diff --git a/hasura/metadata/tables.yaml b/hasura/metadata/tables.yaml index f55abeb9a..52d066b62 100644 --- a/hasura/metadata/tables.yaml +++ b/hasura/metadata/tables.yaml @@ -643,6 +643,19 @@ - name: Player using: foreign_key_constraint_on: player_id + insert_permissions: + - role: player + permission: + check: + player_id: + _eq: X-Hasura-User-Id + columns: [] + backend_only: false + - role: public + permission: + check: {} + columns: [] + backend_only: false select_permissions: - role: player permission: @@ -658,6 +671,25 @@ - identifier - type filter: {} + update_permissions: + - role: player + permission: + columns: + - identifier + - type + filter: + player_id: + _eq: X-Hasura-User-Id + check: null + - role: public + permission: + columns: [] + filter: {} + check: null + delete_permissions: + - role: public + permission: + filter: {} - table: schema: public name: player_role diff --git a/hasura/migrations/1691747987091_add_dework_to_account_type/down.sql b/hasura/migrations/1691747987091_add_dework_to_account_type/down.sql new file mode 100644 index 000000000..1499d49b3 --- /dev/null +++ b/hasura/migrations/1691747987091_add_dework_to_account_type/down.sql @@ -0,0 +1 @@ +DELETE FROM "AccountType" WHERE type = 'DEWORK'; \ No newline at end of file diff --git a/hasura/migrations/1691747987091_add_dework_to_account_type/up.sql b/hasura/migrations/1691747987091_add_dework_to_account_type/up.sql new file mode 100644 index 000000000..47485cc92 --- /dev/null +++ b/hasura/migrations/1691747987091_add_dework_to_account_type/up.sql @@ -0,0 +1,4 @@ +INSERT INTO "AccountType" + (type) VALUES ('DEWORK') + ON CONFLICT DO NOTHING -- allow multiple runs +; diff --git a/packages/backend/codegen.ts b/packages/backend/codegen.ts index e851dca66..cce3bb3eb 100644 --- a/packages/backend/codegen.ts +++ b/packages/backend/codegen.ts @@ -33,64 +33,64 @@ const config = { immutableTypes: true, scalars: { account_type: - "'ETHEREUM' | 'DISCORD' | 'GITHUB' | 'TWITTER' | 'DISCOURSE'", + "'ETHEREUM' | 'DISCORD' | 'GITHUB' | 'TWITTER' | 'DISCOURSE | DEWORK'", }, dedupeOperationSuffix: true, }, }, - 'src/lib/autogen/daohaus-sdk.ts': { - // DAOHaus v3 API Endpoint - // schema: `https://gateway.thegraph.com/api/${process.env.THE_GRAPH_API_TOKEN}/subgraphs/id/GfHFdFmiSwW1PKtnDhhcxhArwtTjVuMnXxQ5XcETF1bP`, - schema: `https://gateway.thegraph.com/api/${process.env.THE_GRAPH_API_TOKEN}/subgraphs/id/9uvKq57ZiNCdT9uZ6xaFhp3yYczTM4Fgr7CJHM6tdX9H`, - documents: [ - 'src/handlers/remote-schemas/resolvers/daohaus/**/(!(*.d)).ts', - ], - plugins: [ - 'typescript', - 'typescript-operations', - 'typescript-graphql-request', - 'typescript-resolvers', - { add: { content: '/* eslint-disable */' } }, - ], - config: { - avoidOptionals: true, - dedupeOperationSuffix: true, - typesPrefix: 'DaoHaus', - }, - }, - 'src/lib/autogen/seedgraph-sdk.ts': { - schema: 'https://api.thegraph.com/subgraphs/name/tenfinney/polygon-seeds', - documents: [ - 'src/handlers/remote-schemas/resolvers/seedGraph/**/(!(*.d)).ts', - ], - plugins: [ - 'typescript', - 'typescript-operations', - 'typescript-graphql-request', - { add: { content: '/* eslint-disable */' } }, - ], - config: { - avoidOptionals: true, - dedupeOperationSuffix: true, - }, - }, - 'src/lib/autogen/balancerpolygon-sdk.ts': { - schema: - 'https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-polygon-v2', - documents: [ - 'src/handlers/remote-schemas/resolvers/balancerPolygon/**/(!(*.d)).ts', - ], - plugins: [ - 'typescript', - 'typescript-operations', - 'typescript-graphql-request', - { add: { content: '/* eslint-disable */' } }, - ], - config: { - avoidOptionals: true, - dedupeOperationSuffix: true, - }, - }, + // 'src/lib/autogen/daohaus-sdk.ts': { + // // DAOHaus v3 API Endpoint + // // schema: `https://gateway.thegraph.com/api/${process.env.THE_GRAPH_API_TOKEN}/subgraphs/id/GfHFdFmiSwW1PKtnDhhcxhArwtTjVuMnXxQ5XcETF1bP`, + // schema: `https://gateway.thegraph.com/api/${process.env.THE_GRAPH_API_TOKEN}/subgraphs/id/9uvKq57ZiNCdT9uZ6xaFhp3yYczTM4Fgr7CJHM6tdX9H`, + // documents: [ + // 'src/handlers/remote-schemas/resolvers/daohaus/**/(!(*.d)).ts', + // ], + // plugins: [ + // 'typescript', + // 'typescript-operations', + // 'typescript-graphql-request', + // 'typescript-resolvers', + // { add: { content: '/* eslint-disable */' } }, + // ], + // config: { + // avoidOptionals: true, + // dedupeOperationSuffix: true, + // typesPrefix: 'DaoHaus', + // }, + // }, + // 'src/lib/autogen/seedgraph-sdk.ts': { + // schema: 'https://api.thegraph.com/subgraphs/name/tenfinney/polygon-seeds', + // documents: [ + // 'src/handlers/remote-schemas/resolvers/seedGraph/**/(!(*.d)).ts', + // ], + // plugins: [ + // 'typescript', + // 'typescript-operations', + // 'typescript-graphql-request', + // { add: { content: '/* eslint-disable */' } }, + // ], + // config: { + // avoidOptionals: true, + // dedupeOperationSuffix: true, + // }, + // }, + // 'src/lib/autogen/balancerpolygon-sdk.ts': { + // schema: + // 'https://api.thegraph.com/subgraphs/name/balancer-labs/balancer-polygon-v2', + // documents: [ + // 'src/handlers/remote-schemas/resolvers/balancerPolygon/**/(!(*.d)).ts', + // ], + // plugins: [ + // 'typescript', + // 'typescript-operations', + // 'typescript-graphql-request', + // { add: { content: '/* eslint-disable */' } }, + // ], + // config: { + // avoidOptionals: true, + // dedupeOperationSuffix: true, + // }, + // }, }, }; diff --git a/packages/backend/package.json b/packages/backend/package.json index 7c3644c05..a44aa5e8e 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -10,7 +10,7 @@ "scripts": { "start": "node --trace-warnings dist/index.js", "build": "yarn generate && tsc -b", - "dev": "tsc --build && concurrently 'tsc --watch --preserveWatchOutput' nodemon 'yarn generate # --watch'", + "dev": "tsc --build && concurrently 'tsc --watch --preserveWatchOutput' nodemon", "typecheck": "yarn generate && tsc --noEmit --pretty", "precommit": "yarn typecheck && yarn lint-staged", "generate": "graphql-codegen && export OUT=src/lib/autogen/daohaus-sdk.ts && awk '!/MolochVersion = .molochVersion/' $OUT > $OUT.filtered && mv $OUT.filtered $OUT", diff --git a/packages/web/components/Player/Section/PlayerDework.tsx b/packages/web/components/Player/Section/PlayerDework.tsx index 2b2f1bf3b..408dd86ec 100644 --- a/packages/web/components/Player/Section/PlayerDework.tsx +++ b/packages/web/components/Player/Section/PlayerDework.tsx @@ -10,6 +10,7 @@ import { InfoIcon, Input, Spinner, + Link, Text, Tooltip, VStack, @@ -17,7 +18,6 @@ import { WrapItem, } from '@metafam/ds'; import { generateUUID } from '@metafam/utils'; -import { to } from '@react-spring/web'; import DeworkLogo from 'assets/integrationLogos/deworkLogo.png'; import { MetaLink } from 'components/Link'; import { ProfileSection } from 'components/Section/ProfileSection'; @@ -30,6 +30,8 @@ import { processDeworkData, } from 'utils/dework'; import { formatAddress } from 'utils/playerHelpers'; +import { getPlayerDeworkUsername } from 'graphql/getDeworkUsername'; +import { useUpsertDeworkProfileMutation } from 'graphql/autogen/types'; type Props = { player: Player; @@ -85,6 +87,16 @@ export const PlayerDework: React.FC = ({ const connected = addressMatch && !playerDeworkURL; const [loading, setLoading] = useState(true); const noticeRef = useRef(null); + + useEffect(() => { + const getDeworkUsername = async () => { + getPlayerDeworkUsername(player.id).then((res) => res && setPlayerDeworkURL(res as string)) + } + if (player?.id) { + getDeworkUsername() + } + }, [player?.id]) + const getData = useCallback(async (address: string) => { setLoading(true); await getDeworkData(address).then((res: any) => { @@ -146,6 +158,7 @@ export const PlayerDework: React.FC = ({ retryCall()} @@ -167,13 +180,15 @@ export const PlayerDework: React.FC = ({ ); }; -const DeworkProfile: React.FC<{data: any }> = ({ data }) => { +const DeworkProfile: React.FC<{data: any, playerDeworkURL: string }> = ({ data, playerDeworkURL }) => { const processedData = useMemo( () => processDeworkData(data), [data], ); + const deworkURL = `https://app.dework.xyz/` + (playerDeworkURL ? `profile/${playerDeworkURL}` : '') + return ( = ({ data }) => { )} {data && ( - See  complete  profile on Dework - + )} @@ -278,26 +294,48 @@ const DeworkProfile: React.FC<{data: any }> = ({ data }) => { const PlayerDeworkView: React.FC<{ role: string; player: Player; + playerDeworkURL: string; setPlayerDeworkURL: any; profileData: any; retry: () => void; -}> = ({ role, player, setPlayerDeworkURL, retry, profileData }) => { +}> = ({ role, player, setPlayerDeworkURL, retry, profileData, playerDeworkURL }) => { const currentView = { - AddURL: , + AddURL: , Loading: , NoMatch: , - DeworkProfile: , + DeworkProfile: , }[role]; return <>{currentView}; }; -const DeworkLink: React.FC<{ setPlayerDeworkURL: any }> = ({ +const DeworkLink: React.FC<{ setPlayerDeworkURL: any, playerDeworkURL: string }> = ({ setPlayerDeworkURL, + playerDeworkURL, }) => { const [deworkURL, setDeworkURL] = useState(''); + const [upsertPlayerDeworkState, upsertPlayerDework] = useUpsertDeworkProfileMutation(); + const handleSetUserDeworkURL = async (playerId: string, identifier: string) => { + try { + //console.log('in 2') + const response = await upsertPlayerDework({ + playerId: 'f0db18b2-4294-4373-a468-f08f53ab4fbc', + identifier: 'Sero', + type: 'DEWORK' + }); + //console.log(response) + // Handle the response if necessary. + // For example, you might want to update the UI based on the mutation's result: + if (response && response.data) { + //console.log("Successfully upserted:", response.data); + } + } catch (error) { + //console.error("Error upserting the Dework profile:", error); + } + }; + return ( <> @@ -325,13 +363,13 @@ const DeworkLink: React.FC<{ setPlayerDeworkURL: any }> = ({ Enter exactly as written on Dework ); diff --git a/packages/web/graphql/getDeworkUsername.ts b/packages/web/graphql/getDeworkUsername.ts new file mode 100644 index 000000000..416667b59 --- /dev/null +++ b/packages/web/graphql/getDeworkUsername.ts @@ -0,0 +1,16 @@ +import { client } from './client'; + +const playerDeworkUsernameQuery = /* GraphQL */ ` + query GetPlayerDeworkUsername($playerId: uuid!) { + player_account(where: { playerId: {_eq: $playerId}, type: {_eq: DEWORK}}) { + identifier + } + } +` + +export const getPlayerDeworkUsername = async (playerId: string): Promise => { + if (!playerId) return '' + let info = await client.query(playerDeworkUsernameQuery, { playerId }) + const username = info?.data?.player_account[0]?.identifier + return username +} \ No newline at end of file diff --git a/packages/web/graphql/mutations/dework.ts b/packages/web/graphql/mutations/dework.ts new file mode 100644 index 000000000..d75b4e062 --- /dev/null +++ b/packages/web/graphql/mutations/dework.ts @@ -0,0 +1,13 @@ +export const UpsertDeworkUsername = /* GraphQL */ ` + mutation UpsertDeworkProfile( + $playerId: uuid!, + $identifier: String!, + $type: String! + ) { + insert_player_account_one(object: {identifier: $identifier, playerId: $playerId, type: DEWORK}, on_conflict: {constraint: Account_identifier_type_key, update_columns: identifier}) { + identifier + playerId + type + } + } +` \ No newline at end of file diff --git a/schema.graphql b/schema.graphql index 2373f59ea..21b31f813 100644 --- a/schema.graphql +++ b/schema.graphql @@ -64,6 +64,7 @@ enum AccountType_constraint { } enum AccountType_enum { + DEWORK DISCORD DISCOURSE ETHEREUM @@ -1076,6 +1077,14 @@ type DiscordGuildAuthResponse { success: Boolean! } +type DiscordGuildsSyncOutput { + name: String! + numDeleted: Int + numInserted: Int + numSkipped: Int + username: String! +} + type DiscordRole { id: String! name: String! @@ -4072,6 +4081,16 @@ type mutation_root { """ saveGuildLayout(guildLayoutInfo: GuildLayoutInfoInput!): SaveGuildLayoutResponse + """ + perform the action: "syncAllGuildDiscordMembers" + """ + syncAllGuildDiscordMembers: [DiscordGuildsSyncOutput] + + """ + perform the action: "syncSourceCredAccounts" + """ + syncSourceCredAccounts: SourceCredSyncOutput + """ perform the action: "updateExpiredIDXProfiles" """ @@ -10838,6 +10857,13 @@ enum SkillCategory_update_column { name } +type SourceCredSyncOutput { + numInserted: Int! + numSkipped: Int! + numUnclaimed: Int! + numUpdated: Int! +} + """ expression to compare columns of type String. All fields are combined with logical 'AND'. """