From 8c685c70d3e843500ae5618730f902ca596168a9 Mon Sep 17 00:00:00 2001 From: Marcin Maciaszczyk Date: Tue, 29 Oct 2024 15:07:02 +0100 Subject: [PATCH 01/12] oauth integrations --- .../integrations/OAuthIntegrations.tsx | 7 +- .../components/integrations/OauthCreator.tsx | 14 +-- .../components/integrations/queries.ts | 18 ---- www/src/generated/graphql.ts | 86 +++++++++++++++++++ www/src/graph/integrations.graphql | 12 +++ 5 files changed, 109 insertions(+), 28 deletions(-) diff --git a/www/src/_deprecated/components/integrations/OAuthIntegrations.tsx b/www/src/_deprecated/components/integrations/OAuthIntegrations.tsx index 66d9d5c42..804195fa0 100644 --- a/www/src/_deprecated/components/integrations/OAuthIntegrations.tsx +++ b/www/src/_deprecated/components/integrations/OAuthIntegrations.tsx @@ -1,10 +1,9 @@ -import { useQuery } from '@apollo/client' import { Box, Text } from 'grommet' import { Check as Checkmark } from 'forge-core' import { ZOOM_ICON, ZOOM_INSTALL_URL } from './constants' -import { OAUTH_Q } from './queries' import { OAuthService } from './types' +import { useOauthIntegrationsQuery } from '../../../generated/graphql' function redirectUrl(format, service) { const location = `${ @@ -66,7 +65,9 @@ function Integration({ } export function OAuthIntegrations() { - const { data } = useQuery(OAUTH_Q, { fetchPolicy: 'cache-and-network' }) + const { data } = useOauthIntegrationsQuery({ + fetchPolicy: 'cache-and-network', + }) if (!data) return null diff --git a/www/src/_deprecated/components/integrations/OauthCreator.tsx b/www/src/_deprecated/components/integrations/OauthCreator.tsx index 3635d906b..6e1185455 100644 --- a/www/src/_deprecated/components/integrations/OauthCreator.tsx +++ b/www/src/_deprecated/components/integrations/OauthCreator.tsx @@ -1,14 +1,13 @@ import { useEffect, useMemo } from 'react' import { Errors } from 'forge-core' import { useLocation, useNavigate, useParams } from 'react-router-dom' -import { useMutation } from '@apollo/client' import { Box, Text } from 'grommet' import { LoopingLogo } from '../../../components/utils/AnimatedLogo' -import { CREATE_OAUTH } from './queries' import { ParamToService } from './types' +import { useCreateOauthIntegrationMutation } from '../../../generated/graphql' function OauthError({ error, service }: any) { return ( @@ -40,11 +39,12 @@ export function OauthCreator() { redirectUri: `${window.location.origin}${window.location.pathname}`, } }, [location]) - const [mutation, { loading, data, error }] = useMutation(CREATE_OAUTH, { - variables: { - attributes: { code, redirectUri, service: ParamToService[service] }, - }, - }) + const [mutation, { loading, data, error }] = + useCreateOauthIntegrationMutation({ + variables: { + attributes: { code, redirectUri, service: ParamToService[service] }, + }, + }) useEffect(() => { mutation() diff --git a/www/src/_deprecated/components/integrations/queries.ts b/www/src/_deprecated/components/integrations/queries.ts index d3f534d89..7f8ae0bc5 100644 --- a/www/src/_deprecated/components/integrations/queries.ts +++ b/www/src/_deprecated/components/integrations/queries.ts @@ -71,21 +71,3 @@ export const DELETE_WEBHOOK = gql` } ${IntegrationWebhookFragment} ` - -export const OAUTH_Q = gql` - query { - oauthIntegrations { - ...OauthIntegration - } - } - ${OauthIntegration} -` - -export const CREATE_OAUTH = gql` - mutation Create($attributes: OauthIntegrationAttributes!) { - createOauthIntegration(attributes: $attributes) { - ...OauthIntegration - } - } - ${OauthIntegration} -` diff --git a/www/src/generated/graphql.ts b/www/src/generated/graphql.ts index 65d978673..5f3d75836 100644 --- a/www/src/generated/graphql.ts +++ b/www/src/generated/graphql.ts @@ -5521,6 +5521,18 @@ export type OauthIntegrationFragment = { __typename?: 'OauthIntegration', id: st export type ZoomMeetingFragment = { __typename?: 'ZoomMeeting', joinUrl: string, password?: string | null }; +export type OauthIntegrationsQueryVariables = Exact<{ [key: string]: never; }>; + + +export type OauthIntegrationsQuery = { __typename?: 'RootQueryType', oauthIntegrations?: Array<{ __typename?: 'OauthIntegration', id: string, service: OauthService, insertedAt?: Date | null } | null> | null }; + +export type CreateOauthIntegrationMutationVariables = Exact<{ + attributes: OauthAttributes; +}>; + + +export type CreateOauthIntegrationMutation = { __typename?: 'RootMutationType', createOauthIntegration?: { __typename?: 'OauthIntegration', id: string, service: OauthService, insertedAt?: Date | null } | null }; + export type SignupInviteMutationVariables = Exact<{ attributes: UserAttributes; inviteId: Scalars['String']['input']; @@ -8610,6 +8622,78 @@ export type GroupsQueryHookResult = ReturnType; export type GroupsLazyQueryHookResult = ReturnType; export type GroupsSuspenseQueryHookResult = ReturnType; export type GroupsQueryResult = Apollo.QueryResult; +export const OauthIntegrationsDocument = gql` + query OauthIntegrations { + oauthIntegrations { + ...OauthIntegration + } +} + ${OauthIntegrationFragmentDoc}`; + +/** + * __useOauthIntegrationsQuery__ + * + * To run a query within a React component, call `useOauthIntegrationsQuery` and pass it any options that fit your needs. + * When your component renders, `useOauthIntegrationsQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useOauthIntegrationsQuery({ + * variables: { + * }, + * }); + */ +export function useOauthIntegrationsQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(OauthIntegrationsDocument, options); + } +export function useOauthIntegrationsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(OauthIntegrationsDocument, options); + } +export function useOauthIntegrationsSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(OauthIntegrationsDocument, options); + } +export type OauthIntegrationsQueryHookResult = ReturnType; +export type OauthIntegrationsLazyQueryHookResult = ReturnType; +export type OauthIntegrationsSuspenseQueryHookResult = ReturnType; +export type OauthIntegrationsQueryResult = Apollo.QueryResult; +export const CreateOauthIntegrationDocument = gql` + mutation CreateOauthIntegration($attributes: OauthAttributes!) { + createOauthIntegration(attributes: $attributes) { + ...OauthIntegration + } +} + ${OauthIntegrationFragmentDoc}`; +export type CreateOauthIntegrationMutationFn = Apollo.MutationFunction; + +/** + * __useCreateOauthIntegrationMutation__ + * + * To run a mutation, you first call `useCreateOauthIntegrationMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useCreateOauthIntegrationMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [createOauthIntegrationMutation, { data, loading, error }] = useCreateOauthIntegrationMutation({ + * variables: { + * attributes: // value for 'attributes' + * }, + * }); + */ +export function useCreateOauthIntegrationMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(CreateOauthIntegrationDocument, options); + } +export type CreateOauthIntegrationMutationHookResult = ReturnType; +export type CreateOauthIntegrationMutationResult = Apollo.MutationResult; +export type CreateOauthIntegrationMutationOptions = Apollo.BaseMutationOptions; export const SignupInviteDocument = gql` mutation SignupInvite($attributes: UserAttributes!, $inviteId: String!) { signup(attributes: $attributes, inviteId: $inviteId) { @@ -11973,6 +12057,7 @@ export const namedOperations = { GetDnsRecords: 'GetDnsRecords', GroupMembers: 'GroupMembers', Groups: 'Groups', + OauthIntegrations: 'OauthIntegrations', Invite: 'Invite', KeyBackups: 'KeyBackups', KeyBackup: 'KeyBackup', @@ -12020,6 +12105,7 @@ export const namedOperations = { CreateGroup: 'CreateGroup', UpdateGroup: 'UpdateGroup', DeleteGroup: 'DeleteGroup', + CreateOauthIntegration: 'CreateOauthIntegration', SignupInvite: 'SignupInvite', RealizeInvite: 'RealizeInvite', CreateInvite: 'CreateInvite', diff --git a/www/src/graph/integrations.graphql b/www/src/graph/integrations.graphql index 9e0d57fef..59ac63fcd 100644 --- a/www/src/graph/integrations.graphql +++ b/www/src/graph/integrations.graphql @@ -25,3 +25,15 @@ fragment ZoomMeeting on ZoomMeeting { joinUrl password } + +query OauthIntegrations { + oauthIntegrations { + ...OauthIntegration + } +} + +mutation CreateOauthIntegration($attributes: OauthAttributes!) { + createOauthIntegration(attributes: $attributes) { + ...OauthIntegration + } +} From f8f97ff60d3deedb7ba94a5b56fde0a43ce8b653 Mon Sep 17 00:00:00 2001 From: Marcin Maciaszczyk Date: Wed, 30 Oct 2024 15:06:08 +0100 Subject: [PATCH 02/12] service account impersonation --- www/src/components/account/User.tsx | 25 +++++++------------ www/src/components/account/queries.ts | 8 ------ www/src/generated/graphql.ts | 6 +++-- www/src/graph/users.graphql | 4 +-- .../hooks/useImpersonatedServiceAccount.tsx | 14 +++-------- 5 files changed, 19 insertions(+), 38 deletions(-) diff --git a/www/src/components/account/User.tsx b/www/src/components/account/User.tsx index 9701784da..7b414f938 100644 --- a/www/src/components/account/User.tsx +++ b/www/src/components/account/User.tsx @@ -10,7 +10,11 @@ import { Button, Span } from 'honorable' import { useContext, useMemo, useState } from 'react' import CurrentUserContext from '../../contexts/CurrentUserContext' -import { Permission, useUpdateUserMutation } from '../../generated/graphql' +import { + Permission, + useImpersonateServiceAccountMutation, + useUpdateUserMutation, +} from '../../generated/graphql' import { fetchToken, setPreviousUserData, @@ -23,7 +27,6 @@ import DeleteUserModal from '../utils/user/DeleteUserModal' import { EditServiceAccount } from './CreateServiceAccount' import { MoreMenu } from './MoreMenu' -import { IMPERSONATE_SERVICE_ACCOUNT } from './queries' import { hasRbac } from './utils' export function UserInfo({ @@ -185,21 +188,11 @@ export function User({ user, update }: any) { export function ServiceAccount({ user, update }: any) { const me = useContext(CurrentUserContext) const editable = canEdit(me, me.account) || hasRbac(me, Permission.Users) - const [mutation, { error }] = useMutation(IMPERSONATE_SERVICE_ACCOUNT, { + const [mutation, { error }] = useImpersonateServiceAccountMutation({ variables: { id: user.id }, - update: ( - _cache, - { - data: { - impersonateServiceAccount: { jwt }, - }, - } - ) => { - setPreviousUserData({ - me, - jwt: fetchToken(), - }) - setToken(jwt) + update: (_cache, { data }) => { + setPreviousUserData({ me, jwt: fetchToken() }) + setToken(data?.impersonateServiceAccount?.jwt) ;(window as Window).location = '/' }, }) diff --git a/www/src/components/account/queries.ts b/www/src/components/account/queries.ts index 0aaa27b75..6b1cc44ce 100644 --- a/www/src/components/account/queries.ts +++ b/www/src/components/account/queries.ts @@ -177,14 +177,6 @@ export const AUDITS_Q = gql` ${AuditFragment} ` -export const IMPERSONATE_SERVICE_ACCOUNT = gql` - mutation Impersonate($id: ID) { - impersonateServiceAccount(id: $id) { - jwt - } - } -` - export const DNS_DOMAINS = gql` query Domains($cursor: String) { dnsDomains(after: $cursor, first: 50) { diff --git a/www/src/generated/graphql.ts b/www/src/generated/graphql.ts index 5f3d75836..699ed5f8d 100644 --- a/www/src/generated/graphql.ts +++ b/www/src/generated/graphql.ts @@ -6156,6 +6156,7 @@ export type LoginMutationVariables = Exact<{ export type LoginMutation = { __typename?: 'RootMutationType', login?: { __typename?: 'User', jwt?: string | null } | null }; export type ImpersonateServiceAccountMutationVariables = Exact<{ + id?: InputMaybe; email?: InputMaybe; }>; @@ -11362,8 +11363,8 @@ export type LoginMutationHookResult = ReturnType; export type LoginMutationResult = Apollo.MutationResult; export type LoginMutationOptions = Apollo.BaseMutationOptions; export const ImpersonateServiceAccountDocument = gql` - mutation ImpersonateServiceAccount($email: String) { - impersonateServiceAccount(email: $email) { + mutation ImpersonateServiceAccount($id: ID, $email: String) { + impersonateServiceAccount(id: $id, email: $email) { jwt email } @@ -11384,6 +11385,7 @@ export type ImpersonateServiceAccountMutationFn = Apollo.MutationFunction - mutation().then( - ({ - data: { - impersonateServiceAccount: { jwt }, - }, - }) => jwt - ) + mutation().then(({ data }) => data?.impersonateServiceAccount?.jwt) ) // Cache clients with impersonated service account tokens as keys. @@ -26,7 +20,7 @@ export default function useImpersonatedServiceAccount( ) { const [client, setClient] = useState | undefined>() const [token, setToken] = useState() - const [mutation, { error }] = useMutation(IMPERSONATE_SERVICE_ACCOUNT, { + const [mutation, { error }] = useImpersonateServiceAccountMutation({ variables: { id }, }) From e71c93e80a5232297bcac10250a3ba9e65139962 Mon Sep 17 00:00:00 2001 From: Marcin Maciaszczyk Date: Wed, 30 Oct 2024 15:31:04 +0100 Subject: [PATCH 03/12] account, users, roles and audits --- www/src/components/account/CreateRole.tsx | 9 +- .../account/CreateServiceAccount.tsx | 14 +- www/src/components/account/EditRole.tsx | 6 +- www/src/components/account/InviteUser.tsx | 7 +- www/src/components/account/Invites.tsx | 7 +- www/src/components/account/Roles.tsx | 10 +- www/src/components/account/queries.ts | 84 --- www/src/components/audits/Audits.tsx | 5 +- www/src/generated/graphql.ts | 599 +++++++++++++----- www/src/graph/account.graphql | 46 -- www/src/graph/audit.graphql | 48 ++ www/src/graph/invite.graphql | 34 +- www/src/graph/role.graphql | 38 ++ www/src/graph/users.graphql | 30 +- 14 files changed, 580 insertions(+), 357 deletions(-) create mode 100644 www/src/graph/audit.graphql create mode 100644 www/src/graph/role.graphql diff --git a/www/src/components/account/CreateRole.tsx b/www/src/components/account/CreateRole.tsx index d2e5b17d2..84c927adc 100644 --- a/www/src/components/account/CreateRole.tsx +++ b/www/src/components/account/CreateRole.tsx @@ -9,12 +9,13 @@ import { appendConnection, updateCache } from '../../utils/graphql' import SubscriptionContext from '../../contexts/SubscriptionContext' -import { CREATE_ROLE, ROLES_Q } from './queries' +import { ROLES_Q } from './queries' import { Actions } from './Actions' import { sanitize } from './utils' import { RoleForm } from './RoleForm' import BillingFeatureBlockModal from './billing/BillingFeatureBlockModal' +import { useCreateRoleMutation } from '../../generated/graphql' const defaultAttributes = { name: '', @@ -42,15 +43,15 @@ export function CreateRole({ q }: any) { setCreateModalVisible(false) }, []) - const [mutation, { loading, error }] = useMutation(CREATE_ROLE, { + const [mutation, { loading, error }] = useCreateRoleMutation({ variables: { attributes: { ...attributes, roleBindings: roleBindings.map(sanitize) }, }, - update: (cache, { data: { createRole } }) => + update: (cache, { data }) => updateCache(cache, { query: ROLES_Q, variables: { q }, - update: (prev) => appendConnection(prev, createRole, 'roles'), + update: (prev) => appendConnection(prev, data?.createRole, 'roles'), }), onCompleted: () => resetAndClose(), }) diff --git a/www/src/components/account/CreateServiceAccount.tsx b/www/src/components/account/CreateServiceAccount.tsx index b93c6ab57..f2b377eea 100644 --- a/www/src/components/account/CreateServiceAccount.tsx +++ b/www/src/components/account/CreateServiceAccount.tsx @@ -20,17 +20,14 @@ import SubscriptionContext from '../../contexts/SubscriptionContext' import { Confirm } from '../utils/Confirm' -import { - CREATE_SERVICE_ACCOUNT, - UPDATE_SERVICE_ACCOUNT, - USERS_Q, -} from './queries' +import { UPDATE_SERVICE_ACCOUNT, USERS_Q } from './queries' import { MoreMenu } from './MoreMenu' import { BindingInput } from './Typeaheads' import { sanitize } from './utils' import BillingFeatureBlockModal from './billing/BillingFeatureBlockModal' +import { useCreateServiceAccountMutation } from '../../generated/graphql' function ServiceAccountForm({ error, @@ -274,18 +271,19 @@ export function CreateServiceAccount({ q }: any) { setCreateModalVisible(false) }, []) - const [mutation, { loading, error }] = useMutation(CREATE_SERVICE_ACCOUNT, { + const [mutation, { loading, error }] = useCreateServiceAccountMutation({ variables: { attributes: { ...attributes, impersonationPolicy: { bindings: bindings.map(sanitize) }, }, }, - update: (cache, { data: { createServiceAccount } }) => + update: (cache, { data }) => updateCache(cache, { query: USERS_Q, variables: { q, serviceAccount: true }, - update: (prev) => appendConnection(prev, createServiceAccount, 'users'), + update: (prev) => + appendConnection(prev, data?.createServiceAccount, 'users'), }), onCompleted: () => { resetAndClose() diff --git a/www/src/components/account/EditRole.tsx b/www/src/components/account/EditRole.tsx index 57d30a3f7..744ded5e0 100644 --- a/www/src/components/account/EditRole.tsx +++ b/www/src/components/account/EditRole.tsx @@ -1,15 +1,13 @@ -import { useMutation } from '@apollo/client' import { Button } from 'honorable' import { Modal } from '@pluralsh/design-system' import { useMemo, useState } from 'react' import uniqWith from 'lodash/uniqWith' import isEqual from 'lodash/isEqual' -import { UPDATE_ROLE } from './queries' - import { Actions } from './Actions' import { sanitize } from './utils' import { RoleForm } from './RoleForm' +import { useUpdateRoleMutation } from '../../generated/graphql' export function EditRole({ role }: any) { const [open, setOpen] = useState(false) @@ -25,7 +23,7 @@ export function EditRole({ role }: any) { [roleBindings] ) - const [mutation, { loading, error }] = useMutation(UPDATE_ROLE, { + const [mutation, { loading, error }] = useUpdateRoleMutation({ variables: { id: role.id, attributes: { ...attributes, roleBindings: roleBindings.map(sanitize) }, diff --git a/www/src/components/account/InviteUser.tsx b/www/src/components/account/InviteUser.tsx index 119c90db4..a889fd869 100644 --- a/www/src/components/account/InviteUser.tsx +++ b/www/src/components/account/InviteUser.tsx @@ -1,4 +1,3 @@ -import { useMutation } from '@apollo/client' import { Codeline, MailIcon, @@ -15,8 +14,8 @@ import { useCurrentUser } from '../../contexts/CurrentUserContext' import SubscriptionContext from '../../contexts/SubscriptionContext' import { GqlError } from '../utils/Alert' -import { CREATE_INVITE } from './queries' import { inviteLink } from './utils' +import { useCreateInviteMutation } from '../../generated/graphql' const MAX_OPEN_SOURCE_USERS = 5 @@ -27,10 +26,10 @@ export function InviteUser({ refetch }: { refetch?: (() => void) | null }) { const [invite, setInvite] = useState(null) const { account } = useCurrentUser() const { isGrandfathered, isPaidPlan } = useContext(SubscriptionContext) - const [mutation, { loading, error, reset }] = useMutation(CREATE_INVITE, { + const [mutation, { loading, error, reset }] = useCreateInviteMutation({ variables: { attributes: { email } }, onCompleted: (data) => { - setInvite(data && data.createInvite) + setInvite(data?.createInvite) refetch?.() }, }) diff --git a/www/src/components/account/Invites.tsx b/www/src/components/account/Invites.tsx index 81b86cf40..ff1ef6ed3 100644 --- a/www/src/components/account/Invites.tsx +++ b/www/src/components/account/Invites.tsx @@ -1,4 +1,4 @@ -import { useMutation, useQuery } from '@apollo/client' +import { useQuery } from '@apollo/client' import moment from 'moment' import { useEffect, useState } from 'react' import { Div, Flex, Text } from 'honorable' @@ -23,12 +23,13 @@ import LoadingIndicator from '../utils/LoadingIndicator' import { Confirm } from '../utils/Confirm' -import { DELETE_INVITE, INVITES_Q } from './queries' +import { INVITES_Q } from './queries' import { inviteLink } from './utils' +import { useDeleteInviteMutation } from '../../generated/graphql' function DeleteInvite({ invite }: any) { const [confirm, setConfirm] = useState(false) - const [mutation, { loading, error }] = useMutation(DELETE_INVITE, { + const [mutation, { loading, error }] = useDeleteInviteMutation({ variables: { id: invite.id }, onCompleted: () => setConfirm(false), update: (cache, { data: { deleteInvite } }) => diff --git a/www/src/components/account/Roles.tsx b/www/src/components/account/Roles.tsx index b8e01212e..4dbd31b25 100644 --- a/www/src/components/account/Roles.tsx +++ b/www/src/components/account/Roles.tsx @@ -1,4 +1,4 @@ -import { useMutation, useQuery } from '@apollo/client' +import { useQuery } from '@apollo/client' import { Box } from 'grommet' import isEmpty from 'lodash/isEmpty' import { Flex } from 'honorable' @@ -16,7 +16,7 @@ import { } from '../../utils/graphql' import { DeleteIconButton } from '../utils/IconButtons' import { StandardScroller } from '../utils/SmoothScroller' -import { Permission } from '../../generated/graphql' +import { Permission, useDeleteRoleMutation } from '../../generated/graphql' import { canEdit } from '../../utils/account' import LoadingIndicator from '../utils/LoadingIndicator' @@ -26,7 +26,7 @@ import { Confirm } from '../utils/Confirm' import BillingTrialBanner from './billing/BillingTrialBanner' -import { DELETE_ROLE, ROLES_Q } from './queries' +import { ROLES_Q } from './queries' import { hasRbac } from './utils' import { Info } from './Info' import { EditRole } from './EditRole' @@ -51,13 +51,13 @@ function Role({ role, q }: any) { const [confirm, setConfirm] = useState(false) const me = useContext(CurrentUserContext) const editable = canEdit(me, me.account) || hasRbac(me, Permission.Users) - const [mutation, { loading, error }] = useMutation(DELETE_ROLE, { + const [mutation, { loading, error }] = useDeleteRoleMutation({ variables: { id: role.id }, update: (cache, { data }) => updateCache(cache, { query: ROLES_Q, variables: { q }, - update: (prev) => removeConnection(prev, data.deleteRole, 'roles'), + update: (prev) => removeConnection(prev, data?.deleteRole, 'roles'), }), onCompleted: () => setConfirm(false), }) diff --git a/www/src/components/account/queries.ts b/www/src/components/account/queries.ts index 6b1cc44ce..5abfe2ad3 100644 --- a/www/src/components/account/queries.ts +++ b/www/src/components/account/queries.ts @@ -81,55 +81,6 @@ export const SEARCH_GROUPS = gql` ${GroupFragment} ` -export const CREATE_INVITE = gql` - mutation CreateInvite($attributes: InviteAttributes!) { - createInvite(attributes: $attributes) { - ...InviteFragment - } - } - ${InviteFragment} -` - -export const CREATE_ROLE = gql` - mutation CreateRole($attributes: RoleAttributes!) { - createRole(attributes: $attributes) { - ...RoleFragment - } - } - ${RoleFragment} -` - -export const UPDATE_ROLE = gql` - mutation UpdateRole($id: ID!, $attributes: RoleAttributes!) { - updateRole(id: $id, attributes: $attributes) { - ...RoleFragment - } - } - ${RoleFragment} -` - -export const DELETE_ROLE = gql` - mutation DeleteRow($id: ID!) { - deleteRole(id: $id) { - ...RoleFragment - } - } - ${RoleFragment} -` - -export const CREATE_SERVICE_ACCOUNT = gql` - mutation Create($attributes: ServiceAccountAttributes!) { - createServiceAccount(attributes: $attributes) { - ...UserFragment - impersonationPolicy { - ...ImpersonationPolicy - } - } - } - ${ImpersonationPolicy} - ${UserFragment} -` - export const UPDATE_SERVICE_ACCOUNT = gql` mutation Create($id: ID!, $attributes: ServiceAccountAttributes!) { updateServiceAccount(id: $id, attributes: $attributes) { @@ -160,23 +111,6 @@ export const ROLES_Q = gql` ${RoleFragment} ` -export const AUDITS_Q = gql` - query Audits($cursor: String) { - audits(first: 50, after: $cursor) { - pageInfo { - ...PageInfo - } - edges { - node { - ...AuditFragment - } - } - } - } - ${PageInfo} - ${AuditFragment} -` - export const DNS_DOMAINS = gql` query Domains($cursor: String) { dnsDomains(after: $cursor, first: 50) { @@ -215,15 +149,6 @@ export const DNS_RECORDS = gql` ${DnsRecordFragment} ` -export const CREATE_DOMAIN = gql` - mutation Create($attributes: DnsDomainAttributes!) { - createDomain(attributes: $attributes) { - ...DnsDomainFragment - } - } - ${DnsDomainFragment} -` - export const UPDATE_DOMAIN = gql` mutation Update($id: ID!, $attributes: DnsDomainAttributes!) { updateDomain(id: $id, attributes: $attributes) { @@ -267,12 +192,3 @@ export const INVITES_Q = gql` ${PageInfo} ${InviteFragment} ` - -export const DELETE_INVITE = gql` - mutation Delete($id: ID!) { - deleteInvite(id: $id) { - ...InviteFragment - } - } - ${InviteFragment} -` diff --git a/www/src/components/audits/Audits.tsx b/www/src/components/audits/Audits.tsx index 98cdac38b..35286f289 100644 --- a/www/src/components/audits/Audits.tsx +++ b/www/src/components/audits/Audits.tsx @@ -1,18 +1,17 @@ import { memo, useCallback, useMemo } from 'react' import { Box } from 'grommet' import { Link } from 'react-router-dom' -import { useQuery } from '@apollo/client' import { A, Div } from 'honorable' import { Date, PageTitle, Table } from '@pluralsh/design-system' import { createColumnHelper } from '@tanstack/react-table' import isEmpty from 'lodash/isEmpty' import { extendConnection } from '../../utils/graphql' -import { AUDITS_Q } from '../account/queries' import LoadingIndicator from '../utils/LoadingIndicator' import { AuditUser } from './AuditUser' import { Location } from './Location' +import { useAuditsQuery } from '../../generated/graphql' const FETCH_MARGIN = 30 @@ -133,7 +132,7 @@ const AuditsTable = memo(({ audits, fetchMoreOnBottomReached }: any) => ) export function Audits() { - const { data, loading, fetchMore } = useQuery(AUDITS_Q, { + const { data, loading, fetchMore } = useAuditsQuery({ fetchPolicy: 'cache-and-network', }) const pageInfo = data?.audits?.pageInfo diff --git a/www/src/generated/graphql.ts b/www/src/generated/graphql.ts index 699ed5f8d..61faafe50 100644 --- a/www/src/generated/graphql.ts +++ b/www/src/generated/graphql.ts @@ -5286,14 +5286,10 @@ export type ZoomMeeting = { password?: Maybe; }; -export type AuditFragment = { __typename?: 'Audit', id: string, action: string, ip?: string | null, country?: string | null, city?: string | null, latitude?: string | null, longitude?: string | null, insertedAt?: Date | null, actor?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, repository?: { __typename?: 'Repository', id: string, name: string, notes?: string | null, description?: string | null, documentation?: string | null, icon?: string | null, darkIcon?: string | null, private?: boolean | null, trending?: boolean | null, verified?: boolean | null, category?: Category | null, docs?: Array<{ __typename?: 'FileContent', content: string, path: string } | null> | null, oauthSettings?: { __typename?: 'OauthSettings', uriFormat: string, authMethod: OidcAuthMethod } | null, publisher?: { __typename?: 'Publisher', id?: string | null, name: string, phone?: string | null, avatar?: string | null, description?: string | null, backgroundColor?: string | null, owner?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, address?: { __typename?: 'Address', line1?: string | null, line2?: string | null, city?: string | null, country?: string | null, state?: string | null, zip?: string | null } | null } | null, recipes?: Array<{ __typename?: 'Recipe', name: string, provider?: Provider | null, description?: string | null } | null> | null } | null, group?: { __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null, integrationWebhook?: { __typename?: 'IntegrationWebhook', id: string, name: string, url: string, secret: string, actions?: Array | null } | null, role?: { __typename?: 'Role', id: string, name: string, description?: string | null, repositories?: Array | null, permissions?: Array | null, roleBindings?: Array<{ __typename?: 'RoleBinding', id: string, user?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, group?: { __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null } | null> | null } | null, version?: { __typename?: 'Version', id: string, helm?: Map | null, readme?: string | null, valuesTemplate?: string | null, version: string, insertedAt?: Date | null, package?: string | null, crds?: Array<{ __typename?: 'Crd', id: string, name: string, blob?: string | null } | null> | null, chart?: { __typename?: 'Chart', id?: string | null, name: string, description?: string | null, latestVersion?: string | null, insertedAt?: Date | null, dependencies?: { __typename?: 'Dependencies', wait?: boolean | null, application?: boolean | null, providers?: Array | null, secrets?: Array | null, providerWirings?: Map | null, outputs?: Map | null, dependencies?: Array<{ __typename?: 'Dependency', name?: string | null, repo?: string | null, type?: DependencyType | null, version?: string | null, optional?: boolean | null } | null> | null, wirings?: { __typename?: 'Wirings', terraform?: Map | null, helm?: Map | null } | null } | null } | null, terraform?: { __typename?: 'Terraform', id?: string | null, name?: string | null } | null, dependencies?: { __typename?: 'Dependencies', wait?: boolean | null, application?: boolean | null, providers?: Array | null, secrets?: Array | null, providerWirings?: Map | null, outputs?: Map | null, dependencies?: Array<{ __typename?: 'Dependency', name?: string | null, repo?: string | null, type?: DependencyType | null, version?: string | null, optional?: boolean | null } | null> | null, wirings?: { __typename?: 'Wirings', terraform?: Map | null, helm?: Map | null } | null } | null } | null, image?: { __typename?: 'DockerImage', id: string, tag?: string | null, dockerRepository?: { __typename?: 'DockerRepository', name: string } | null } | null }; - export type PolicyBindingFragment = { __typename?: 'PolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null }; export type DnsDomainFragment = { __typename?: 'DnsDomain', id: string, name: string, insertedAt?: Date | null, creator?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, accessPolicy?: { __typename?: 'DnsAccessPolicy', id: string, bindings?: Array<{ __typename?: 'PolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null }; -export type InviteFragment = { __typename?: 'Invite', id: string, secureId?: string | null, email?: string | null, insertedAt?: Date | null, user?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null }; - export type OidcLoginFragment = { __typename?: 'OidcLogin', ip?: string | null, country?: string | null, city?: string | null, latitude?: string | null, longitude?: string | null, insertedAt?: Date | null, user?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, owner?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, repository?: { __typename?: 'Repository', id: string, name: string, notes?: string | null, description?: string | null, documentation?: string | null, icon?: string | null, darkIcon?: string | null, private?: boolean | null, trending?: boolean | null, verified?: boolean | null, category?: Category | null, docs?: Array<{ __typename?: 'FileContent', content: string, path: string } | null> | null, oauthSettings?: { __typename?: 'OauthSettings', uriFormat: string, authMethod: OidcAuthMethod } | null, publisher?: { __typename?: 'Publisher', id?: string | null, name: string, phone?: string | null, avatar?: string | null, description?: string | null, backgroundColor?: string | null, owner?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, address?: { __typename?: 'Address', line1?: string | null, line2?: string | null, city?: string | null, country?: string | null, state?: string | null, zip?: string | null } | null } | null, recipes?: Array<{ __typename?: 'Recipe', name: string, provider?: Provider | null, description?: string | null } | null> | null } | null }; export type UpdateAccountMutationVariables = Exact<{ @@ -5330,6 +5326,15 @@ export type CreateArtifactMutationVariables = Exact<{ export type CreateArtifactMutation = { __typename?: 'RootMutationType', createArtifact?: { __typename?: 'Artifact', id?: string | null, name?: string | null, blob?: string | null, type?: ArtifactType | null, platform?: ArtifactPlatform | null, arch?: string | null, filesize?: number | null, sha?: string | null, readme?: string | null, insertedAt?: Date | null, updatedAt?: Date | null } | null }; +export type AuditFragment = { __typename?: 'Audit', id: string, action: string, ip?: string | null, country?: string | null, city?: string | null, latitude?: string | null, longitude?: string | null, insertedAt?: Date | null, actor?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, repository?: { __typename?: 'Repository', id: string, name: string, notes?: string | null, description?: string | null, documentation?: string | null, icon?: string | null, darkIcon?: string | null, private?: boolean | null, trending?: boolean | null, verified?: boolean | null, category?: Category | null, docs?: Array<{ __typename?: 'FileContent', content: string, path: string } | null> | null, oauthSettings?: { __typename?: 'OauthSettings', uriFormat: string, authMethod: OidcAuthMethod } | null, publisher?: { __typename?: 'Publisher', id?: string | null, name: string, phone?: string | null, avatar?: string | null, description?: string | null, backgroundColor?: string | null, owner?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, address?: { __typename?: 'Address', line1?: string | null, line2?: string | null, city?: string | null, country?: string | null, state?: string | null, zip?: string | null } | null } | null, recipes?: Array<{ __typename?: 'Recipe', name: string, provider?: Provider | null, description?: string | null } | null> | null } | null, group?: { __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null, integrationWebhook?: { __typename?: 'IntegrationWebhook', id: string, name: string, url: string, secret: string, actions?: Array | null } | null, role?: { __typename?: 'Role', id: string, name: string, description?: string | null, repositories?: Array | null, permissions?: Array | null, roleBindings?: Array<{ __typename?: 'RoleBinding', id: string, user?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, group?: { __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null } | null> | null } | null, version?: { __typename?: 'Version', id: string, helm?: Map | null, readme?: string | null, valuesTemplate?: string | null, version: string, insertedAt?: Date | null, package?: string | null, crds?: Array<{ __typename?: 'Crd', id: string, name: string, blob?: string | null } | null> | null, chart?: { __typename?: 'Chart', id?: string | null, name: string, description?: string | null, latestVersion?: string | null, insertedAt?: Date | null, dependencies?: { __typename?: 'Dependencies', wait?: boolean | null, application?: boolean | null, providers?: Array | null, secrets?: Array | null, providerWirings?: Map | null, outputs?: Map | null, dependencies?: Array<{ __typename?: 'Dependency', name?: string | null, repo?: string | null, type?: DependencyType | null, version?: string | null, optional?: boolean | null } | null> | null, wirings?: { __typename?: 'Wirings', terraform?: Map | null, helm?: Map | null } | null } | null } | null, terraform?: { __typename?: 'Terraform', id?: string | null, name?: string | null } | null, dependencies?: { __typename?: 'Dependencies', wait?: boolean | null, application?: boolean | null, providers?: Array | null, secrets?: Array | null, providerWirings?: Map | null, outputs?: Map | null, dependencies?: Array<{ __typename?: 'Dependency', name?: string | null, repo?: string | null, type?: DependencyType | null, version?: string | null, optional?: boolean | null } | null> | null, wirings?: { __typename?: 'Wirings', terraform?: Map | null, helm?: Map | null } | null } | null } | null, image?: { __typename?: 'DockerImage', id: string, tag?: string | null, dockerRepository?: { __typename?: 'DockerRepository', name: string } | null } | null }; + +export type AuditsQueryVariables = Exact<{ + cursor?: InputMaybe; +}>; + + +export type AuditsQuery = { __typename?: 'RootQueryType', audits?: { __typename?: 'AuditConnection', pageInfo: { __typename?: 'PageInfo', endCursor?: string | null, hasNextPage: boolean }, edges?: Array<{ __typename?: 'AuditEdge', node?: { __typename?: 'Audit', id: string, action: string, ip?: string | null, country?: string | null, city?: string | null, latitude?: string | null, longitude?: string | null, insertedAt?: Date | null, actor?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, repository?: { __typename?: 'Repository', id: string, name: string, notes?: string | null, description?: string | null, documentation?: string | null, icon?: string | null, darkIcon?: string | null, private?: boolean | null, trending?: boolean | null, verified?: boolean | null, category?: Category | null, docs?: Array<{ __typename?: 'FileContent', content: string, path: string } | null> | null, oauthSettings?: { __typename?: 'OauthSettings', uriFormat: string, authMethod: OidcAuthMethod } | null, publisher?: { __typename?: 'Publisher', id?: string | null, name: string, phone?: string | null, avatar?: string | null, description?: string | null, backgroundColor?: string | null, owner?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, address?: { __typename?: 'Address', line1?: string | null, line2?: string | null, city?: string | null, country?: string | null, state?: string | null, zip?: string | null } | null } | null, recipes?: Array<{ __typename?: 'Recipe', name: string, provider?: Provider | null, description?: string | null } | null> | null } | null, group?: { __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null, integrationWebhook?: { __typename?: 'IntegrationWebhook', id: string, name: string, url: string, secret: string, actions?: Array | null } | null, role?: { __typename?: 'Role', id: string, name: string, description?: string | null, repositories?: Array | null, permissions?: Array | null, roleBindings?: Array<{ __typename?: 'RoleBinding', id: string, user?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, group?: { __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null } | null> | null } | null, version?: { __typename?: 'Version', id: string, helm?: Map | null, readme?: string | null, valuesTemplate?: string | null, version: string, insertedAt?: Date | null, package?: string | null, crds?: Array<{ __typename?: 'Crd', id: string, name: string, blob?: string | null } | null> | null, chart?: { __typename?: 'Chart', id?: string | null, name: string, description?: string | null, latestVersion?: string | null, insertedAt?: Date | null, dependencies?: { __typename?: 'Dependencies', wait?: boolean | null, application?: boolean | null, providers?: Array | null, secrets?: Array | null, providerWirings?: Map | null, outputs?: Map | null, dependencies?: Array<{ __typename?: 'Dependency', name?: string | null, repo?: string | null, type?: DependencyType | null, version?: string | null, optional?: boolean | null } | null> | null, wirings?: { __typename?: 'Wirings', terraform?: Map | null, helm?: Map | null } | null } | null } | null, terraform?: { __typename?: 'Terraform', id?: string | null, name?: string | null } | null, dependencies?: { __typename?: 'Dependencies', wait?: boolean | null, application?: boolean | null, providers?: Array | null, secrets?: Array | null, providerWirings?: Map | null, outputs?: Map | null, dependencies?: Array<{ __typename?: 'Dependency', name?: string | null, repo?: string | null, type?: DependencyType | null, version?: string | null, optional?: boolean | null } | null> | null, wirings?: { __typename?: 'Wirings', terraform?: Map | null, helm?: Map | null } | null } | null } | null, image?: { __typename?: 'DockerImage', id: string, tag?: string | null, dockerRepository?: { __typename?: 'DockerRepository', name: string } | null } | null } | null } | null> | null } | null }; + export type ChartFragment = { __typename?: 'Chart', id?: string | null, name: string, description?: string | null, latestVersion?: string | null, insertedAt?: Date | null, dependencies?: { __typename?: 'Dependencies', wait?: boolean | null, application?: boolean | null, providers?: Array | null, secrets?: Array | null, providerWirings?: Map | null, outputs?: Map | null, dependencies?: Array<{ __typename?: 'Dependency', name?: string | null, repo?: string | null, type?: DependencyType | null, version?: string | null, optional?: boolean | null } | null> | null, wirings?: { __typename?: 'Wirings', terraform?: Map | null, helm?: Map | null } | null } | null }; export type CrdFragment = { __typename?: 'Crd', id: string, name: string, blob?: string | null }; @@ -5533,6 +5538,22 @@ export type CreateOauthIntegrationMutationVariables = Exact<{ export type CreateOauthIntegrationMutation = { __typename?: 'RootMutationType', createOauthIntegration?: { __typename?: 'OauthIntegration', id: string, service: OauthService, insertedAt?: Date | null } | null }; +export type InviteFragment = { __typename?: 'Invite', id: string, secureId?: string | null, email?: string | null, insertedAt?: Date | null, user?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null }; + +export type InviteQueryVariables = Exact<{ + id: Scalars['String']['input']; +}>; + + +export type InviteQuery = { __typename?: 'RootQueryType', invite?: { __typename?: 'Invite', id: string, email?: string | null, existing: boolean, account?: { __typename?: 'Account', id: string, name?: string | null, billingCustomerId?: string | null, backgroundColor?: string | null, userCount?: string | null, trialed?: boolean | null } | null, user?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, account: { __typename?: 'Account', id: string, name?: string | null, billingCustomerId?: string | null, backgroundColor?: string | null, userCount?: string | null, trialed?: boolean | null }, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null } | null }; + +export type CreateInviteMutationVariables = Exact<{ + attributes: InviteAttributes; +}>; + + +export type CreateInviteMutation = { __typename?: 'RootMutationType', createInvite?: { __typename?: 'Invite', id: string, secureId?: string | null, email?: string | null, insertedAt?: Date | null, user?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null } | null }; + export type SignupInviteMutationVariables = Exact<{ attributes: UserAttributes; inviteId: Scalars['String']['input']; @@ -5548,19 +5569,12 @@ export type RealizeInviteMutationVariables = Exact<{ export type RealizeInviteMutation = { __typename?: 'RootMutationType', realizeInvite?: { __typename?: 'User', jwt?: string | null } | null }; -export type InviteQueryVariables = Exact<{ - id: Scalars['String']['input']; -}>; - - -export type InviteQuery = { __typename?: 'RootQueryType', invite?: { __typename?: 'Invite', id: string, email?: string | null, existing: boolean, account?: { __typename?: 'Account', id: string, name?: string | null, billingCustomerId?: string | null, backgroundColor?: string | null, userCount?: string | null, trialed?: boolean | null } | null, user?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, account: { __typename?: 'Account', id: string, name?: string | null, billingCustomerId?: string | null, backgroundColor?: string | null, userCount?: string | null, trialed?: boolean | null }, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null } | null }; - -export type CreateInviteMutationVariables = Exact<{ - attributes: InviteAttributes; +export type DeleteInviteMutationVariables = Exact<{ + id: Scalars['ID']['input']; }>; -export type CreateInviteMutation = { __typename?: 'RootMutationType', createInvite?: { __typename?: 'Invite', id: string, secureId?: string | null, email?: string | null, insertedAt?: Date | null, user?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null } | null }; +export type DeleteInviteMutation = { __typename?: 'RootMutationType', deleteInvite?: { __typename?: 'Invite', id: string, secureId?: string | null, email?: string | null, insertedAt?: Date | null, user?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null } | null }; export type KeyBackupUserFragment = { __typename?: 'User', email: string }; @@ -5975,6 +5989,32 @@ export type ReleaseMutationVariables = Exact<{ export type ReleaseMutation = { __typename?: 'RootMutationType', release?: boolean | null }; +export type RoleFragment = { __typename?: 'Role', id: string, name: string, description?: string | null, repositories?: Array | null, permissions?: Array | null, roleBindings?: Array<{ __typename?: 'RoleBinding', id: string, user?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, group?: { __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null } | null> | null }; + +export type RoleBindingFragment = { __typename?: 'RoleBinding', id: string, user?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, group?: { __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null }; + +export type CreateRoleMutationVariables = Exact<{ + attributes: RoleAttributes; +}>; + + +export type CreateRoleMutation = { __typename?: 'RootMutationType', createRole?: { __typename?: 'Role', id: string, name: string, description?: string | null, repositories?: Array | null, permissions?: Array | null, roleBindings?: Array<{ __typename?: 'RoleBinding', id: string, user?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, group?: { __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null } | null> | null } | null }; + +export type UpdateRoleMutationVariables = Exact<{ + id: Scalars['ID']['input']; + attributes: RoleAttributes; +}>; + + +export type UpdateRoleMutation = { __typename?: 'RootMutationType', updateRole?: { __typename?: 'Role', id: string, name: string, description?: string | null, repositories?: Array | null, permissions?: Array | null, roleBindings?: Array<{ __typename?: 'RoleBinding', id: string, user?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, group?: { __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null } | null> | null } | null }; + +export type DeleteRoleMutationVariables = Exact<{ + id: Scalars['ID']['input']; +}>; + + +export type DeleteRoleMutation = { __typename?: 'RootMutationType', deleteRole?: { __typename?: 'Role', id: string, name: string, description?: string | null, repositories?: Array | null, permissions?: Array | null, roleBindings?: Array<{ __typename?: 'RoleBinding', id: string, user?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, group?: { __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null } | null> | null } | null }; + export type GetTfProvidersQueryVariables = Exact<{ [key: string]: never; }>; @@ -6100,10 +6140,6 @@ export type PublisherFragment = { __typename?: 'Publisher', id?: string | null, export type WebhookFragment = { __typename?: 'Webhook', id?: string | null, url?: string | null, secret?: string | null, insertedAt?: Date | null }; -export type RoleBindingFragment = { __typename?: 'RoleBinding', id: string, user?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, group?: { __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null }; - -export type RoleFragment = { __typename?: 'Role', id: string, name: string, description?: string | null, repositories?: Array | null, permissions?: Array | null, roleBindings?: Array<{ __typename?: 'RoleBinding', id: string, user?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, group?: { __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null } | null> | null }; - export type PublicKeyFragment = { __typename?: 'PublicKey', id: string, name: string, digest: string, insertedAt?: Date | null, content: string, user: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } }; export type EabCredentialFragment = { __typename?: 'EabCredential', id: string, keyId: string, hmacKey: string, cluster: string, provider: Provider, insertedAt?: Date | null }; @@ -6155,6 +6191,13 @@ export type LoginMutationVariables = Exact<{ export type LoginMutation = { __typename?: 'RootMutationType', login?: { __typename?: 'User', jwt?: string | null } | null }; +export type CreateServiceAccountMutationVariables = Exact<{ + attributes: ServiceAccountAttributes; +}>; + + +export type CreateServiceAccountMutation = { __typename?: 'RootMutationType', createServiceAccount?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null } | null }; + export type ImpersonateServiceAccountMutationVariables = Exact<{ id?: InputMaybe; email?: InputMaybe; @@ -6364,6 +6407,37 @@ export const UserFragmentDoc = gql` } ${GroupFragmentDoc} ${ImpersonationPolicyFragmentDoc}`; +export const PolicyBindingFragmentDoc = gql` + fragment PolicyBinding on PolicyBinding { + id + group { + id + name + } + user { + id + name + email + } +} + `; +export const DnsDomainFragmentDoc = gql` + fragment DnsDomain on DnsDomain { + id + name + creator { + ...User + } + accessPolicy { + id + bindings { + ...PolicyBinding + } + } + insertedAt +} + ${UserFragmentDoc} +${PolicyBindingFragmentDoc}`; export const FileContentFragmentDoc = gql` fragment FileContent on FileContent { content @@ -6428,6 +6502,41 @@ export const RepoFragmentDoc = gql` } ${FileContentFragmentDoc} ${PublisherFragmentDoc}`; +export const OidcLoginFragmentDoc = gql` + fragment OidcLogin on OidcLogin { + ip + country + city + latitude + longitude + user { + ...User + } + owner { + ...User + } + repository { + ...Repo + } + insertedAt +} + ${UserFragmentDoc} +${RepoFragmentDoc}`; +export const ArtifactFragmentDoc = gql` + fragment Artifact on Artifact { + id + name + blob + type + platform + arch + filesize + sha + readme + insertedAt + updatedAt +} + `; export const IntegrationWebhookFragmentDoc = gql` fragment IntegrationWebhook on IntegrationWebhook { id @@ -6569,83 +6678,6 @@ ${GroupFragmentDoc} ${IntegrationWebhookFragmentDoc} ${RoleFragmentDoc} ${VersionFragmentDoc}`; -export const PolicyBindingFragmentDoc = gql` - fragment PolicyBinding on PolicyBinding { - id - group { - id - name - } - user { - id - name - email - } -} - `; -export const DnsDomainFragmentDoc = gql` - fragment DnsDomain on DnsDomain { - id - name - creator { - ...User - } - accessPolicy { - id - bindings { - ...PolicyBinding - } - } - insertedAt -} - ${UserFragmentDoc} -${PolicyBindingFragmentDoc}`; -export const InviteFragmentDoc = gql` - fragment Invite on Invite { - id - secureId - email - insertedAt - user { - ...User - } -} - ${UserFragmentDoc}`; -export const OidcLoginFragmentDoc = gql` - fragment OidcLogin on OidcLogin { - ip - country - city - latitude - longitude - user { - ...User - } - owner { - ...User - } - repository { - ...Repo - } - insertedAt -} - ${UserFragmentDoc} -${RepoFragmentDoc}`; -export const ArtifactFragmentDoc = gql` - fragment Artifact on Artifact { - id - name - blob - type - platform - arch - filesize - sha - readme - insertedAt - updatedAt -} - `; export const ChartInstallationFragmentDoc = gql` fragment ChartInstallation on ChartInstallation { id @@ -7121,6 +7153,17 @@ export const ZoomMeetingFragmentDoc = gql` password } `; +export const InviteFragmentDoc = gql` + fragment Invite on Invite { + id + secureId + email + insertedAt + user { + ...User + } +} + ${UserFragmentDoc}`; export const KeyBackupUserFragmentDoc = gql` fragment KeyBackupUser on User { email @@ -7910,6 +7953,54 @@ export function useCreateArtifactMutation(baseOptions?: Apollo.MutationHookOptio export type CreateArtifactMutationHookResult = ReturnType; export type CreateArtifactMutationResult = Apollo.MutationResult; export type CreateArtifactMutationOptions = Apollo.BaseMutationOptions; +export const AuditsDocument = gql` + query Audits($cursor: String) { + audits(first: 50, after: $cursor) { + pageInfo { + ...PageInfo + } + edges { + node { + ...Audit + } + } + } +} + ${PageInfoFragmentDoc} +${AuditFragmentDoc}`; + +/** + * __useAuditsQuery__ + * + * To run a query within a React component, call `useAuditsQuery` and pass it any options that fit your needs. + * When your component renders, `useAuditsQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useAuditsQuery({ + * variables: { + * cursor: // value for 'cursor' + * }, + * }); + */ +export function useAuditsQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(AuditsDocument, options); + } +export function useAuditsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(AuditsDocument, options); + } +export function useAuditsSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(AuditsDocument, options); + } +export type AuditsQueryHookResult = ReturnType; +export type AuditsLazyQueryHookResult = ReturnType; +export type AuditsSuspenseQueryHookResult = ReturnType; +export type AuditsQueryResult = Apollo.QueryResult; export const GetChartsDocument = gql` query GetCharts($id: ID!) { charts(repositoryId: $id, first: 100) { @@ -8695,6 +8786,91 @@ export function useCreateOauthIntegrationMutation(baseOptions?: Apollo.MutationH export type CreateOauthIntegrationMutationHookResult = ReturnType; export type CreateOauthIntegrationMutationResult = Apollo.MutationResult; export type CreateOauthIntegrationMutationOptions = Apollo.BaseMutationOptions; +export const InviteDocument = gql` + query Invite($id: String!) { + invite(id: $id) { + id + email + existing + account { + ...Account + } + user { + ...User + account { + ...Account + } + } + } +} + ${AccountFragmentDoc} +${UserFragmentDoc}`; + +/** + * __useInviteQuery__ + * + * To run a query within a React component, call `useInviteQuery` and pass it any options that fit your needs. + * When your component renders, `useInviteQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useInviteQuery({ + * variables: { + * id: // value for 'id' + * }, + * }); + */ +export function useInviteQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(InviteDocument, options); + } +export function useInviteLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(InviteDocument, options); + } +export function useInviteSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(InviteDocument, options); + } +export type InviteQueryHookResult = ReturnType; +export type InviteLazyQueryHookResult = ReturnType; +export type InviteSuspenseQueryHookResult = ReturnType; +export type InviteQueryResult = Apollo.QueryResult; +export const CreateInviteDocument = gql` + mutation CreateInvite($attributes: InviteAttributes!) { + createInvite(attributes: $attributes) { + ...Invite + } +} + ${InviteFragmentDoc}`; +export type CreateInviteMutationFn = Apollo.MutationFunction; + +/** + * __useCreateInviteMutation__ + * + * To run a mutation, you first call `useCreateInviteMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useCreateInviteMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [createInviteMutation, { data, loading, error }] = useCreateInviteMutation({ + * variables: { + * attributes: // value for 'attributes' + * }, + * }); + */ +export function useCreateInviteMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(CreateInviteDocument, options); + } +export type CreateInviteMutationHookResult = ReturnType; +export type CreateInviteMutationResult = Apollo.MutationResult; +export type CreateInviteMutationOptions = Apollo.BaseMutationOptions; export const SignupInviteDocument = gql` mutation SignupInvite($attributes: UserAttributes!, $inviteId: String!) { signup(attributes: $attributes, inviteId: $inviteId) { @@ -8762,91 +8938,39 @@ export function useRealizeInviteMutation(baseOptions?: Apollo.MutationHookOption export type RealizeInviteMutationHookResult = ReturnType; export type RealizeInviteMutationResult = Apollo.MutationResult; export type RealizeInviteMutationOptions = Apollo.BaseMutationOptions; -export const InviteDocument = gql` - query Invite($id: String!) { - invite(id: $id) { - id - email - existing - account { - ...Account - } - user { - ...User - account { - ...Account - } - } - } -} - ${AccountFragmentDoc} -${UserFragmentDoc}`; - -/** - * __useInviteQuery__ - * - * To run a query within a React component, call `useInviteQuery` and pass it any options that fit your needs. - * When your component renders, `useInviteQuery` returns an object from Apollo Client that contains loading, error, and data properties - * you can use to render your UI. - * - * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; - * - * @example - * const { data, loading, error } = useInviteQuery({ - * variables: { - * id: // value for 'id' - * }, - * }); - */ -export function useInviteQuery(baseOptions: Apollo.QueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(InviteDocument, options); - } -export function useInviteLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(InviteDocument, options); - } -export function useInviteSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { - const options = {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(InviteDocument, options); - } -export type InviteQueryHookResult = ReturnType; -export type InviteLazyQueryHookResult = ReturnType; -export type InviteSuspenseQueryHookResult = ReturnType; -export type InviteQueryResult = Apollo.QueryResult; -export const CreateInviteDocument = gql` - mutation CreateInvite($attributes: InviteAttributes!) { - createInvite(attributes: $attributes) { +export const DeleteInviteDocument = gql` + mutation DeleteInvite($id: ID!) { + deleteInvite(id: $id) { ...Invite } } ${InviteFragmentDoc}`; -export type CreateInviteMutationFn = Apollo.MutationFunction; +export type DeleteInviteMutationFn = Apollo.MutationFunction; /** - * __useCreateInviteMutation__ + * __useDeleteInviteMutation__ * - * To run a mutation, you first call `useCreateInviteMutation` within a React component and pass it any options that fit your needs. - * When your component renders, `useCreateInviteMutation` returns a tuple that includes: + * To run a mutation, you first call `useDeleteInviteMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useDeleteInviteMutation` returns a tuple that includes: * - A mutate function that you can call at any time to execute the mutation * - An object with fields that represent the current status of the mutation's execution * * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; * * @example - * const [createInviteMutation, { data, loading, error }] = useCreateInviteMutation({ + * const [deleteInviteMutation, { data, loading, error }] = useDeleteInviteMutation({ * variables: { - * attributes: // value for 'attributes' + * id: // value for 'id' * }, * }); */ -export function useCreateInviteMutation(baseOptions?: Apollo.MutationHookOptions) { +export function useDeleteInviteMutation(baseOptions?: Apollo.MutationHookOptions) { const options = {...defaultOptions, ...baseOptions} - return Apollo.useMutation(CreateInviteDocument, options); + return Apollo.useMutation(DeleteInviteDocument, options); } -export type CreateInviteMutationHookResult = ReturnType; -export type CreateInviteMutationResult = Apollo.MutationResult; -export type CreateInviteMutationOptions = Apollo.BaseMutationOptions; +export type DeleteInviteMutationHookResult = ReturnType; +export type DeleteInviteMutationResult = Apollo.MutationResult; +export type DeleteInviteMutationOptions = Apollo.BaseMutationOptions; export const KeyBackupsDocument = gql` query KeyBackups { keyBackups(first: 1000) { @@ -10600,6 +10724,106 @@ export function useReleaseMutation(baseOptions?: Apollo.MutationHookOptions; export type ReleaseMutationResult = Apollo.MutationResult; export type ReleaseMutationOptions = Apollo.BaseMutationOptions; +export const CreateRoleDocument = gql` + mutation CreateRole($attributes: RoleAttributes!) { + createRole(attributes: $attributes) { + ...Role + } +} + ${RoleFragmentDoc}`; +export type CreateRoleMutationFn = Apollo.MutationFunction; + +/** + * __useCreateRoleMutation__ + * + * To run a mutation, you first call `useCreateRoleMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useCreateRoleMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [createRoleMutation, { data, loading, error }] = useCreateRoleMutation({ + * variables: { + * attributes: // value for 'attributes' + * }, + * }); + */ +export function useCreateRoleMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(CreateRoleDocument, options); + } +export type CreateRoleMutationHookResult = ReturnType; +export type CreateRoleMutationResult = Apollo.MutationResult; +export type CreateRoleMutationOptions = Apollo.BaseMutationOptions; +export const UpdateRoleDocument = gql` + mutation UpdateRole($id: ID!, $attributes: RoleAttributes!) { + updateRole(id: $id, attributes: $attributes) { + ...Role + } +} + ${RoleFragmentDoc}`; +export type UpdateRoleMutationFn = Apollo.MutationFunction; + +/** + * __useUpdateRoleMutation__ + * + * To run a mutation, you first call `useUpdateRoleMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useUpdateRoleMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [updateRoleMutation, { data, loading, error }] = useUpdateRoleMutation({ + * variables: { + * id: // value for 'id' + * attributes: // value for 'attributes' + * }, + * }); + */ +export function useUpdateRoleMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(UpdateRoleDocument, options); + } +export type UpdateRoleMutationHookResult = ReturnType; +export type UpdateRoleMutationResult = Apollo.MutationResult; +export type UpdateRoleMutationOptions = Apollo.BaseMutationOptions; +export const DeleteRoleDocument = gql` + mutation DeleteRole($id: ID!) { + deleteRole(id: $id) { + ...Role + } +} + ${RoleFragmentDoc}`; +export type DeleteRoleMutationFn = Apollo.MutationFunction; + +/** + * __useDeleteRoleMutation__ + * + * To run a mutation, you first call `useDeleteRoleMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useDeleteRoleMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [deleteRoleMutation, { data, loading, error }] = useDeleteRoleMutation({ + * variables: { + * id: // value for 'id' + * }, + * }); + */ +export function useDeleteRoleMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(DeleteRoleDocument, options); + } +export type DeleteRoleMutationHookResult = ReturnType; +export type DeleteRoleMutationResult = Apollo.MutationResult; +export type DeleteRoleMutationOptions = Apollo.BaseMutationOptions; export const GetTfProvidersDocument = gql` query GetTfProviders { terraformProviders @@ -11362,6 +11586,43 @@ export function useLoginMutation(baseOptions?: Apollo.MutationHookOptions; export type LoginMutationResult = Apollo.MutationResult; export type LoginMutationOptions = Apollo.BaseMutationOptions; +export const CreateServiceAccountDocument = gql` + mutation CreateServiceAccount($attributes: ServiceAccountAttributes!) { + createServiceAccount(attributes: $attributes) { + ...User + impersonationPolicy { + ...ImpersonationPolicy + } + } +} + ${UserFragmentDoc} +${ImpersonationPolicyFragmentDoc}`; +export type CreateServiceAccountMutationFn = Apollo.MutationFunction; + +/** + * __useCreateServiceAccountMutation__ + * + * To run a mutation, you first call `useCreateServiceAccountMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useCreateServiceAccountMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [createServiceAccountMutation, { data, loading, error }] = useCreateServiceAccountMutation({ + * variables: { + * attributes: // value for 'attributes' + * }, + * }); + */ +export function useCreateServiceAccountMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(CreateServiceAccountDocument, options); + } +export type CreateServiceAccountMutationHookResult = ReturnType; +export type CreateServiceAccountMutationResult = Apollo.MutationResult; +export type CreateServiceAccountMutationOptions = Apollo.BaseMutationOptions; export const ImpersonateServiceAccountDocument = gql` mutation ImpersonateServiceAccount($id: ID, $email: String) { impersonateServiceAccount(id: $id, email: $email) { @@ -12051,6 +12312,7 @@ export type UpdateVersionMutationOptions = Apollo.BaseMutationOptions Date: Wed, 30 Oct 2024 15:57:32 +0100 Subject: [PATCH 04/12] type fixes --- www/src/components/account/Invites.tsx | 5 +++-- www/src/components/audits/Audits.tsx | 9 ++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/www/src/components/account/Invites.tsx b/www/src/components/account/Invites.tsx index ff1ef6ed3..6d7b435ef 100644 --- a/www/src/components/account/Invites.tsx +++ b/www/src/components/account/Invites.tsx @@ -32,11 +32,12 @@ function DeleteInvite({ invite }: any) { const [mutation, { loading, error }] = useDeleteInviteMutation({ variables: { id: invite.id }, onCompleted: () => setConfirm(false), - update: (cache, { data: { deleteInvite } }) => + update: (cache, { data }) => updateCache(cache, { query: INVITES_Q, variables: {}, - update: (invites) => removeConnection(invites, deleteInvite, 'invites'), + update: (invites) => + removeConnection(invites, data?.deleteInvite, 'invites'), }), }) diff --git a/www/src/components/audits/Audits.tsx b/www/src/components/audits/Audits.tsx index 35286f289..96e5995f8 100644 --- a/www/src/components/audits/Audits.tsx +++ b/www/src/components/audits/Audits.tsx @@ -6,7 +6,7 @@ import { Date, PageTitle, Table } from '@pluralsh/design-system' import { createColumnHelper } from '@tanstack/react-table' import isEmpty from 'lodash/isEmpty' -import { extendConnection } from '../../utils/graphql' +import { extendConnection, mapExistingNodes } from '../../utils/graphql' import LoadingIndicator from '../utils/LoadingIndicator' import { AuditUser } from './AuditUser' @@ -136,8 +136,7 @@ export function Audits() { fetchPolicy: 'cache-and-network', }) const pageInfo = data?.audits?.pageInfo - const edges = data?.audits?.edges - const audits = useMemo(() => edges?.map(({ node }) => node) || [], [edges]) + const audits = useMemo(() => mapExistingNodes(data?.audits), [data?.audits]) const fetchMoreOnBottomReached = useCallback( (element?: HTMLDivElement | undefined) => { @@ -149,10 +148,10 @@ export function Audits() { if ( scrollHeight - scrollTop - clientHeight < FETCH_MARGIN && !loading && - pageInfo.hasNextPage + pageInfo?.hasNextPage ) { fetchMore({ - variables: { cursor: pageInfo.endCursor }, + variables: { cursor: pageInfo?.endCursor }, updateQuery: (prev, { fetchMoreResult: { audits } }) => extendConnection(prev, audits, 'audits'), }) From 59b8544ddd1aa8873dd50b4869058b3fe8a93e19 Mon Sep 17 00:00:00 2001 From: Marcin Maciaszczyk Date: Wed, 30 Oct 2024 16:19:31 +0100 Subject: [PATCH 05/12] audits --- .../components/audits/AuditChloropleth.tsx | 15 +- www/src/components/audits/LoginAudits.tsx | 17 +- www/src/components/audits/queries.ts | 39 ----- www/src/generated/graphql.ts | 148 ++++++++++++++++++ www/src/graph/audit.graphql | 27 ++++ 5 files changed, 192 insertions(+), 54 deletions(-) delete mode 100644 www/src/components/audits/queries.ts diff --git a/www/src/components/audits/AuditChloropleth.tsx b/www/src/components/audits/AuditChloropleth.tsx index 6258b00ba..bade5f842 100644 --- a/www/src/components/audits/AuditChloropleth.tsx +++ b/www/src/components/audits/AuditChloropleth.tsx @@ -1,4 +1,3 @@ -import { useQuery } from '@apollo/client' import { useRef, useState } from 'react' import lookup from 'country-code-lookup' @@ -8,7 +7,10 @@ import { Card, PageTitle, SubTab, TabList } from '@pluralsh/design-system' import { Chloropleth } from '../utils/Chloropleth' -import { AUDIT_METRICS, LOGIN_METRICS } from './queries' +import { + useAuditMetricsQuery, + useLoginMetricsQuery, +} from '../../generated/graphql' const DIRECTORY = [ { key: 'audit-logs', label: 'Audit logs' }, @@ -19,14 +21,13 @@ export function AuditChloropleth() { const [selectedKey, setSelectedKey] = useState('audit-logs') const tabStateRef = useRef(null) - const { data } = useQuery( - selectedKey === 'logins' ? LOGIN_METRICS : AUDIT_METRICS, - { fetchPolicy: 'cache-and-network' } - ) + const query = + selectedKey === 'logins' ? useLoginMetricsQuery : useAuditMetricsQuery + const { data } = query({ fetchPolicy: 'cache-and-network' }) if (!data) return null - const results = data.auditMetrics || data.loginMetrics + const results = data['auditMetrics'] || data['loginMetrics'] const metrics = results.map(({ country, count }) => ({ // @ts-expect-error id: lookup.byIso(country).iso3, diff --git a/www/src/components/audits/LoginAudits.tsx b/www/src/components/audits/LoginAudits.tsx index dd0e1efe0..5a0b6ad45 100644 --- a/www/src/components/audits/LoginAudits.tsx +++ b/www/src/components/audits/LoginAudits.tsx @@ -1,4 +1,3 @@ -import { useQuery } from '@apollo/client' import { Box } from 'grommet' import { memo, useCallback, useMemo } from 'react' import { Date, IconFrame, PageTitle, Table } from '@pluralsh/design-system' @@ -6,12 +5,12 @@ import { createColumnHelper } from '@tanstack/react-table' import isEmpty from 'lodash/isEmpty' import { Flex } from 'honorable' -import { extendConnection } from '../../utils/graphql' +import { extendConnection, mapExistingNodes } from '../../utils/graphql' import LoadingIndicator from '../utils/LoadingIndicator' import { AuditUser } from './AuditUser' import { Location } from './Location' -import { LOGINS_Q } from './queries' +import { useLoginsQuery } from '../../generated/graphql' const FETCH_MARGIN = 30 @@ -87,12 +86,14 @@ const LoginAuditsTable = memo(({ logins, fetchMoreOnBottomReached }: any) => ) export function LoginAudits() { - const { data, loading, fetchMore } = useQuery(LOGINS_Q, { + const { data, loading, fetchMore } = useLoginsQuery({ fetchPolicy: 'cache-and-network', }) const pageInfo = data?.oidcLogins?.pageInfo - const edges = data?.oidcLogins?.edges - const logins = useMemo(() => edges?.map(({ node }) => node) || [], [edges]) + const logins = useMemo( + () => mapExistingNodes(data?.oidcLogins) || [], + [data?.oidcLogins] + ) const fetchMoreOnBottomReached = useCallback( (element?: HTMLDivElement | undefined) => { @@ -104,10 +105,10 @@ export function LoginAudits() { if ( scrollHeight - scrollTop - clientHeight < FETCH_MARGIN && !loading && - pageInfo.hasNextPage + pageInfo?.hasNextPage ) { fetchMore({ - variables: { cursor: pageInfo.endCursor }, + variables: { cursor: pageInfo?.endCursor }, updateQuery: (prev, { fetchMoreResult: { oidcLogins } }) => extendConnection(prev, oidcLogins, 'oidcLogins'), }) diff --git a/www/src/components/audits/queries.ts b/www/src/components/audits/queries.ts deleted file mode 100644 index 0c7e1996c..000000000 --- a/www/src/components/audits/queries.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { gql } from '@apollo/client' - -import { OidcLoginFragment } from '../../models/account' -import { PageInfo } from '../../models/misc' - -export const LOGINS_Q = gql` - query Logins($cursor: String) { - oidcLogins(first: 50, after: $cursor) { - pageInfo { - ...PageInfo - } - edges { - node { - ...OidcLoginFragment - } - } - } - } - ${PageInfo} - ${OidcLoginFragment} -` - -export const AUDIT_METRICS = gql` - query { - auditMetrics { - country - count - } - } -` - -export const LOGIN_METRICS = gql` - query { - loginMetrics { - country - count - } - } -` diff --git a/www/src/generated/graphql.ts b/www/src/generated/graphql.ts index 61faafe50..79f702f50 100644 --- a/www/src/generated/graphql.ts +++ b/www/src/generated/graphql.ts @@ -5335,6 +5335,23 @@ export type AuditsQueryVariables = Exact<{ export type AuditsQuery = { __typename?: 'RootQueryType', audits?: { __typename?: 'AuditConnection', pageInfo: { __typename?: 'PageInfo', endCursor?: string | null, hasNextPage: boolean }, edges?: Array<{ __typename?: 'AuditEdge', node?: { __typename?: 'Audit', id: string, action: string, ip?: string | null, country?: string | null, city?: string | null, latitude?: string | null, longitude?: string | null, insertedAt?: Date | null, actor?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, repository?: { __typename?: 'Repository', id: string, name: string, notes?: string | null, description?: string | null, documentation?: string | null, icon?: string | null, darkIcon?: string | null, private?: boolean | null, trending?: boolean | null, verified?: boolean | null, category?: Category | null, docs?: Array<{ __typename?: 'FileContent', content: string, path: string } | null> | null, oauthSettings?: { __typename?: 'OauthSettings', uriFormat: string, authMethod: OidcAuthMethod } | null, publisher?: { __typename?: 'Publisher', id?: string | null, name: string, phone?: string | null, avatar?: string | null, description?: string | null, backgroundColor?: string | null, owner?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, address?: { __typename?: 'Address', line1?: string | null, line2?: string | null, city?: string | null, country?: string | null, state?: string | null, zip?: string | null } | null } | null, recipes?: Array<{ __typename?: 'Recipe', name: string, provider?: Provider | null, description?: string | null } | null> | null } | null, group?: { __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null, integrationWebhook?: { __typename?: 'IntegrationWebhook', id: string, name: string, url: string, secret: string, actions?: Array | null } | null, role?: { __typename?: 'Role', id: string, name: string, description?: string | null, repositories?: Array | null, permissions?: Array | null, roleBindings?: Array<{ __typename?: 'RoleBinding', id: string, user?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, group?: { __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null } | null> | null } | null, version?: { __typename?: 'Version', id: string, helm?: Map | null, readme?: string | null, valuesTemplate?: string | null, version: string, insertedAt?: Date | null, package?: string | null, crds?: Array<{ __typename?: 'Crd', id: string, name: string, blob?: string | null } | null> | null, chart?: { __typename?: 'Chart', id?: string | null, name: string, description?: string | null, latestVersion?: string | null, insertedAt?: Date | null, dependencies?: { __typename?: 'Dependencies', wait?: boolean | null, application?: boolean | null, providers?: Array | null, secrets?: Array | null, providerWirings?: Map | null, outputs?: Map | null, dependencies?: Array<{ __typename?: 'Dependency', name?: string | null, repo?: string | null, type?: DependencyType | null, version?: string | null, optional?: boolean | null } | null> | null, wirings?: { __typename?: 'Wirings', terraform?: Map | null, helm?: Map | null } | null } | null } | null, terraform?: { __typename?: 'Terraform', id?: string | null, name?: string | null } | null, dependencies?: { __typename?: 'Dependencies', wait?: boolean | null, application?: boolean | null, providers?: Array | null, secrets?: Array | null, providerWirings?: Map | null, outputs?: Map | null, dependencies?: Array<{ __typename?: 'Dependency', name?: string | null, repo?: string | null, type?: DependencyType | null, version?: string | null, optional?: boolean | null } | null> | null, wirings?: { __typename?: 'Wirings', terraform?: Map | null, helm?: Map | null } | null } | null } | null, image?: { __typename?: 'DockerImage', id: string, tag?: string | null, dockerRepository?: { __typename?: 'DockerRepository', name: string } | null } | null } | null } | null> | null } | null }; +export type LoginsQueryVariables = Exact<{ + cursor?: InputMaybe; +}>; + + +export type LoginsQuery = { __typename?: 'RootQueryType', oidcLogins?: { __typename?: 'OidcLoginConnection', pageInfo: { __typename?: 'PageInfo', endCursor?: string | null, hasNextPage: boolean }, edges?: Array<{ __typename?: 'OidcLoginEdge', node?: { __typename?: 'OidcLogin', ip?: string | null, country?: string | null, city?: string | null, latitude?: string | null, longitude?: string | null, insertedAt?: Date | null, user?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, owner?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, repository?: { __typename?: 'Repository', id: string, name: string, notes?: string | null, description?: string | null, documentation?: string | null, icon?: string | null, darkIcon?: string | null, private?: boolean | null, trending?: boolean | null, verified?: boolean | null, category?: Category | null, docs?: Array<{ __typename?: 'FileContent', content: string, path: string } | null> | null, oauthSettings?: { __typename?: 'OauthSettings', uriFormat: string, authMethod: OidcAuthMethod } | null, publisher?: { __typename?: 'Publisher', id?: string | null, name: string, phone?: string | null, avatar?: string | null, description?: string | null, backgroundColor?: string | null, owner?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, address?: { __typename?: 'Address', line1?: string | null, line2?: string | null, city?: string | null, country?: string | null, state?: string | null, zip?: string | null } | null } | null, recipes?: Array<{ __typename?: 'Recipe', name: string, provider?: Provider | null, description?: string | null } | null> | null } | null } | null } | null> | null } | null }; + +export type AuditMetricsQueryVariables = Exact<{ [key: string]: never; }>; + + +export type AuditMetricsQuery = { __typename?: 'RootQueryType', auditMetrics?: Array<{ __typename?: 'GeoMetric', country?: string | null, count?: number | null } | null> | null }; + +export type LoginMetricsQueryVariables = Exact<{ [key: string]: never; }>; + + +export type LoginMetricsQuery = { __typename?: 'RootQueryType', loginMetrics?: Array<{ __typename?: 'GeoMetric', country?: string | null, count?: number | null } | null> | null }; + export type ChartFragment = { __typename?: 'Chart', id?: string | null, name: string, description?: string | null, latestVersion?: string | null, insertedAt?: Date | null, dependencies?: { __typename?: 'Dependencies', wait?: boolean | null, application?: boolean | null, providers?: Array | null, secrets?: Array | null, providerWirings?: Map | null, outputs?: Map | null, dependencies?: Array<{ __typename?: 'Dependency', name?: string | null, repo?: string | null, type?: DependencyType | null, version?: string | null, optional?: boolean | null } | null> | null, wirings?: { __typename?: 'Wirings', terraform?: Map | null, helm?: Map | null } | null } | null }; export type CrdFragment = { __typename?: 'Crd', id: string, name: string, blob?: string | null }; @@ -8001,6 +8018,134 @@ export type AuditsQueryHookResult = ReturnType; export type AuditsLazyQueryHookResult = ReturnType; export type AuditsSuspenseQueryHookResult = ReturnType; export type AuditsQueryResult = Apollo.QueryResult; +export const LoginsDocument = gql` + query Logins($cursor: String) { + oidcLogins(first: 50, after: $cursor) { + pageInfo { + ...PageInfo + } + edges { + node { + ...OidcLogin + } + } + } +} + ${PageInfoFragmentDoc} +${OidcLoginFragmentDoc}`; + +/** + * __useLoginsQuery__ + * + * To run a query within a React component, call `useLoginsQuery` and pass it any options that fit your needs. + * When your component renders, `useLoginsQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useLoginsQuery({ + * variables: { + * cursor: // value for 'cursor' + * }, + * }); + */ +export function useLoginsQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(LoginsDocument, options); + } +export function useLoginsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(LoginsDocument, options); + } +export function useLoginsSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(LoginsDocument, options); + } +export type LoginsQueryHookResult = ReturnType; +export type LoginsLazyQueryHookResult = ReturnType; +export type LoginsSuspenseQueryHookResult = ReturnType; +export type LoginsQueryResult = Apollo.QueryResult; +export const AuditMetricsDocument = gql` + query AuditMetrics { + auditMetrics { + country + count + } +} + `; + +/** + * __useAuditMetricsQuery__ + * + * To run a query within a React component, call `useAuditMetricsQuery` and pass it any options that fit your needs. + * When your component renders, `useAuditMetricsQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useAuditMetricsQuery({ + * variables: { + * }, + * }); + */ +export function useAuditMetricsQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(AuditMetricsDocument, options); + } +export function useAuditMetricsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(AuditMetricsDocument, options); + } +export function useAuditMetricsSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(AuditMetricsDocument, options); + } +export type AuditMetricsQueryHookResult = ReturnType; +export type AuditMetricsLazyQueryHookResult = ReturnType; +export type AuditMetricsSuspenseQueryHookResult = ReturnType; +export type AuditMetricsQueryResult = Apollo.QueryResult; +export const LoginMetricsDocument = gql` + query LoginMetrics { + loginMetrics { + country + count + } +} + `; + +/** + * __useLoginMetricsQuery__ + * + * To run a query within a React component, call `useLoginMetricsQuery` and pass it any options that fit your needs. + * When your component renders, `useLoginMetricsQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useLoginMetricsQuery({ + * variables: { + * }, + * }); + */ +export function useLoginMetricsQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(LoginMetricsDocument, options); + } +export function useLoginMetricsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(LoginMetricsDocument, options); + } +export function useLoginMetricsSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(LoginMetricsDocument, options); + } +export type LoginMetricsQueryHookResult = ReturnType; +export type LoginMetricsLazyQueryHookResult = ReturnType; +export type LoginMetricsSuspenseQueryHookResult = ReturnType; +export type LoginMetricsQueryResult = Apollo.QueryResult; export const GetChartsDocument = gql` query GetCharts($id: ID!) { charts(repositoryId: $id, first: 100) { @@ -12313,6 +12458,9 @@ export const namedOperations = { Query: { ListArtifacts: 'ListArtifacts', Audits: 'Audits', + Logins: 'Logins', + AuditMetrics: 'AuditMetrics', + LoginMetrics: 'LoginMetrics', GetCharts: 'GetCharts', GetVersions: 'GetVersions', GetChartInstallations: 'GetChartInstallations', diff --git a/www/src/graph/audit.graphql b/www/src/graph/audit.graphql index d774217d3..348e191b8 100644 --- a/www/src/graph/audit.graphql +++ b/www/src/graph/audit.graphql @@ -45,4 +45,31 @@ query Audits($cursor: String) { } } } +} + +query Logins($cursor: String) { + oidcLogins(first: 50, after: $cursor) { + pageInfo { + ...PageInfo + } + edges { + node { + ...OidcLogin + } + } + } +} + +query AuditMetrics { + auditMetrics { + country + count + } +} + +query LoginMetrics { + loginMetrics { + country + count + } } \ No newline at end of file From b3c72450432bce78595399f3a3b3b8a79db7c925 Mon Sep 17 00:00:00 2001 From: Marcin Maciaszczyk Date: Mon, 4 Nov 2024 14:41:58 +0100 Subject: [PATCH 06/12] cluster apps --- www/src/components/cluster/ClusterApp.tsx | 4 +- www/src/components/cluster/ClusterApps.tsx | 19 ++--- www/src/components/cluster/queries.ts | 27 ------- www/src/generated/graphql.ts | 90 +++++++++++++++++++--- www/src/graph/oauth.graphql | 10 +-- www/src/graph/repos.graphql | 25 ++++++ 6 files changed, 118 insertions(+), 57 deletions(-) delete mode 100644 www/src/components/cluster/queries.ts diff --git a/www/src/components/cluster/ClusterApp.tsx b/www/src/components/cluster/ClusterApp.tsx index 7ec7d5f5c..2fcf6a0dc 100644 --- a/www/src/components/cluster/ClusterApp.tsx +++ b/www/src/components/cluster/ClusterApp.tsx @@ -12,11 +12,11 @@ import { useNavigate, useParams } from 'react-router-dom' import { useTheme } from 'styled-components' -import { Repository } from '../../generated/graphql' +import { Repository, RepositoryFragment } from '../../generated/graphql' import { MoreMenu } from '../account/MoreMenu' type ClusterAppProps = { - app: Repository + app: RepositoryFragment consoleUrl?: string | null last: boolean } diff --git a/www/src/components/cluster/ClusterApps.tsx b/www/src/components/cluster/ClusterApps.tsx index 651bd5929..d8b62022e 100644 --- a/www/src/components/cluster/ClusterApps.tsx +++ b/www/src/components/cluster/ClusterApps.tsx @@ -4,15 +4,15 @@ import Fuse from 'fuse.js' import { Input, MagnifyingGlassIcon } from '@pluralsh/design-system' import ListCard from '../utils/ListCard' -import usePaginatedQuery from '../../hooks/usePaginatedQuery' import LoadingIndicator from '../utils/LoadingIndicator' import { EmptyListMessage } from '../overview/clusters/misc' import InfiniteScroller from '../utils/InfiniteScroller' -import { Cluster } from '../../generated/graphql' +import { Cluster, useRepositoriesQuery } from '../../generated/graphql' import { ensureURLValidity } from '../../utils/url' import { ClusterApp } from './ClusterApp' -import { REPOSITORIES_Q } from './queries' +import { useFetchPaginatedData } from '../utils/useFetchPaginatedData' +import { mapExistingNodes } from '../../utils/graphql' const searchOptions = { keys: ['name'], @@ -25,12 +25,13 @@ export function ClusterApps({ cluster: { consoleUrl }, }: ClusterAppsProps): ReactElement { const [search, setSearch] = useState('') - const [apps, loading, hasMore, loadMore] = usePaginatedQuery( - REPOSITORIES_Q, - { variables: { installed: true } }, - (data) => data.repositories + const { data, loading, pageInfo, fetchNextPage } = useFetchPaginatedData( + { queryHook: useRepositoriesQuery, keyPath: ['repositories'] }, + { installed: true } ) + const apps = useMemo(() => mapExistingNodes(data?.repositories) ?? [], [data]) + const fuse = useMemo(() => new Fuse(apps, searchOptions), [apps]) const filteredApps = useMemo( () => (search ? fuse.search(search).map(({ item }) => item) : apps), @@ -59,8 +60,8 @@ export function ClusterApps({ {!isEmpty(apps) ? ( ; @@ -5902,6 +5900,8 @@ export type FileContentFragment = { __typename?: 'FileContent', content: string, export type RepoFragment = { __typename?: 'Repository', id: string, name: string, notes?: string | null, description?: string | null, documentation?: string | null, icon?: string | null, darkIcon?: string | null, private?: boolean | null, trending?: boolean | null, verified?: boolean | null, category?: Category | null, docs?: Array<{ __typename?: 'FileContent', content: string, path: string } | null> | null, oauthSettings?: { __typename?: 'OauthSettings', uriFormat: string, authMethod: OidcAuthMethod } | null, publisher?: { __typename?: 'Publisher', id?: string | null, name: string, phone?: string | null, avatar?: string | null, description?: string | null, backgroundColor?: string | null, owner?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, address?: { __typename?: 'Address', line1?: string | null, line2?: string | null, city?: string | null, country?: string | null, state?: string | null, zip?: string | null } | null } | null, recipes?: Array<{ __typename?: 'Recipe', name: string, provider?: Provider | null, description?: string | null } | null> | null }; +export type RepositoryFragment = { __typename?: 'Repository', id: string, name: string, icon?: string | null, darkIcon?: string | null, installation?: { __typename?: 'Installation', pingedAt?: Date | null, synced?: boolean | null, locked?: boolean | null } | null }; + export type MarketplaceRepositoryFragment = { __typename?: 'Repository', id: string, name: string, description?: string | null, releaseStatus?: ReleaseStatus | null, documentation?: string | null, icon?: string | null, darkIcon?: string | null, private?: boolean | null, trending?: boolean | null, verified?: boolean | null, category?: Category | null, oauthSettings?: { __typename?: 'OauthSettings', uriFormat: string, authMethod: OidcAuthMethod } | null, publisher?: { __typename?: 'Publisher', id?: string | null, name: string, phone?: string | null, avatar?: string | null, description?: string | null, backgroundColor?: string | null, owner?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, address?: { __typename?: 'Address', line1?: string | null, line2?: string | null, city?: string | null, country?: string | null, state?: string | null, zip?: string | null } | null } | null, installation?: { __typename?: 'Installation', id: string } | null, tags?: Array<{ __typename?: 'Tag', tag: string } | null> | null }; export type DependenciesFragment = { __typename?: 'Dependencies', wait?: boolean | null, application?: boolean | null, providers?: Array | null, secrets?: Array | null, providerWirings?: Map | null, outputs?: Map | null, dependencies?: Array<{ __typename?: 'Dependency', name?: string | null, repo?: string | null, type?: DependencyType | null, version?: string | null, optional?: boolean | null } | null> | null, wirings?: { __typename?: 'Wirings', terraform?: Map | null, helm?: Map | null } | null }; @@ -5971,6 +5971,14 @@ export type UnlockRepositoryMutationVariables = Exact<{ export type UnlockRepositoryMutation = { __typename?: 'RootMutationType', unlockRepository?: number | null }; +export type RepositoriesQueryVariables = Exact<{ + cursor?: InputMaybe; + installed?: InputMaybe; +}>; + + +export type RepositoriesQuery = { __typename?: 'RootQueryType', repositories?: { __typename?: 'RepositoryConnection', pageInfo: { __typename?: 'PageInfo', endCursor?: string | null, hasNextPage: boolean }, edges?: Array<{ __typename?: 'RepositoryEdge', node?: { __typename?: 'Repository', id: string, name: string, icon?: string | null, darkIcon?: string | null, installation?: { __typename?: 'Installation', pingedAt?: Date | null, synced?: boolean | null, locked?: boolean | null } | null } | null } | null> | null } | null }; + export type MarketplaceRepositoriesQueryVariables = Exact<{ publisherId?: InputMaybe; tag?: InputMaybe; @@ -7255,13 +7263,6 @@ export const OAuthInfoFragmentDoc = gql` authorizeUrl } `; -export const RepositoryFragmentDoc = gql` - fragment Repository on Repository { - name - icon - darkIcon -} - `; export const SubscriptionFragmentDoc = gql` fragment Subscription on RepositorySubscription { id @@ -7590,6 +7591,19 @@ export const CategoryFragmentDoc = gql` count } `; +export const RepositoryFragmentDoc = gql` + fragment Repository on Repository { + id + name + icon + darkIcon + installation { + pingedAt + synced + locked + } +} + `; export const MarketplaceRepositoryFragmentDoc = gql` fragment MarketplaceRepository on Repository { id @@ -9319,7 +9333,9 @@ export const OidcConsentDocument = gql` query OIDCConsent($challenge: String!) { oidcConsent(challenge: $challenge) { repository { - ...Repository + name + icon + darkIcon } consent { requestedScope @@ -9327,7 +9343,7 @@ export const OidcConsentDocument = gql` } } } - ${RepositoryFragmentDoc}`; + `; /** * __useOidcConsentQuery__ @@ -10703,6 +10719,55 @@ export function useUnlockRepositoryMutation(baseOptions?: Apollo.MutationHookOpt export type UnlockRepositoryMutationHookResult = ReturnType; export type UnlockRepositoryMutationResult = Apollo.MutationResult; export type UnlockRepositoryMutationOptions = Apollo.BaseMutationOptions; +export const RepositoriesDocument = gql` + query Repositories($cursor: String, $installed: Boolean) { + repositories(after: $cursor, first: 200, installed: $installed) { + pageInfo { + ...PageInfo + } + edges { + node { + ...Repository + } + } + } +} + ${PageInfoFragmentDoc} +${RepositoryFragmentDoc}`; + +/** + * __useRepositoriesQuery__ + * + * To run a query within a React component, call `useRepositoriesQuery` and pass it any options that fit your needs. + * When your component renders, `useRepositoriesQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useRepositoriesQuery({ + * variables: { + * cursor: // value for 'cursor' + * installed: // value for 'installed' + * }, + * }); + */ +export function useRepositoriesQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(RepositoriesDocument, options); + } +export function useRepositoriesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(RepositoriesDocument, options); + } +export function useRepositoriesSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(RepositoriesDocument, options); + } +export type RepositoriesQueryHookResult = ReturnType; +export type RepositoriesLazyQueryHookResult = ReturnType; +export type RepositoriesSuspenseQueryHookResult = ReturnType; +export type RepositoriesQueryResult = Apollo.QueryResult; export const MarketplaceRepositoriesDocument = gql` query MarketplaceRepositories($publisherId: ID, $tag: String, $cursor: String) { repositories(publisherId: $publisherId, tag: $tag, after: $cursor, first: 200) { @@ -12486,6 +12551,7 @@ export const namedOperations = { GetStack: 'GetStack', ListStacks: 'ListStacks', Repository: 'Repository', + Repositories: 'Repositories', MarketplaceRepositories: 'MarketplaceRepositories', Scaffolds: 'Scaffolds', GetTfProviders: 'GetTfProviders', @@ -12620,7 +12686,6 @@ export const namedOperations = { NotificationFragment: 'NotificationFragment', OIDCProvider: 'OIDCProvider', OAuthInfo: 'OAuthInfo', - Repository: 'Repository', Limit: 'Limit', LineItem: 'LineItem', ServiceLevel: 'ServiceLevel', @@ -12646,6 +12711,7 @@ export const namedOperations = { Category: 'Category', FileContent: 'FileContent', Repo: 'Repo', + Repository: 'Repository', MarketplaceRepository: 'MarketplaceRepository', Dependencies: 'Dependencies', Integration: 'Integration', diff --git a/www/src/graph/oauth.graphql b/www/src/graph/oauth.graphql index 585bb48c0..82c0a6022 100644 --- a/www/src/graph/oauth.graphql +++ b/www/src/graph/oauth.graphql @@ -33,16 +33,12 @@ fragment OAuthInfo on OauthInfo { authorizeUrl } -fragment Repository on Repository { - name - icon - darkIcon -} - query OIDCConsent($challenge: String!) { oidcConsent(challenge: $challenge) { repository { - ...Repository + name + icon + darkIcon } consent { requestedScope diff --git a/www/src/graph/repos.graphql b/www/src/graph/repos.graphql index e1f7b842a..7c2a0b1ea 100644 --- a/www/src/graph/repos.graphql +++ b/www/src/graph/repos.graphql @@ -42,6 +42,18 @@ fragment Repo on Repository { } } +fragment Repository on Repository { + id + name + icon + darkIcon + installation { + pingedAt + synced + locked + } +} + fragment MarketplaceRepository on Repository { id name @@ -195,6 +207,19 @@ mutation UnlockRepository($name: String!) { unlockRepository(name: $name) } +query Repositories($cursor: String, $installed: Boolean) { + repositories(after: $cursor, first: 200, installed: $installed) { + pageInfo { + ...PageInfo + } + edges { + node { + ...Repository + } + } + } +} + query MarketplaceRepositories($publisherId: ID, $tag: String, $cursor: String) { repositories( publisherId: $publisherId From 08b83b3b34d0ee2a9ca49e08e7486e0a96a0bc6a Mon Sep 17 00:00:00 2001 From: Marcin Maciaszczyk Date: Mon, 4 Nov 2024 15:11:02 +0100 Subject: [PATCH 07/12] dns --- www/src/components/account/DnsRecords.tsx | 11 +- www/src/components/account/Domains.tsx | 19 ++-- www/src/components/account/queries.ts | 27 ----- www/src/generated/graphql.ts | 122 ++++++++++++++++++---- www/src/graph/dns.graphql | 29 ++++- 5 files changed, 149 insertions(+), 59 deletions(-) diff --git a/www/src/components/account/DnsRecords.tsx b/www/src/components/account/DnsRecords.tsx index 9f75f951e..daebd4f13 100644 --- a/www/src/components/account/DnsRecords.tsx +++ b/www/src/components/account/DnsRecords.tsx @@ -1,4 +1,4 @@ -import { useMutation, useQuery } from '@apollo/client' +import { useQuery } from '@apollo/client' import { Box } from 'grommet' import { Button, Div, Flex, Span } from 'honorable' import moment from 'moment' @@ -18,19 +18,20 @@ import { Table, TableData, TableRow } from '../utils/Table' import { ProviderIcon } from '../utils/ProviderIcon' import { Confirm } from '../utils/Confirm' -import { DELETE_DNS_RECORD, DNS_RECORDS } from './queries' +import { DNS_RECORDS } from './queries' +import { useDeleteDnsRecordMutation } from '../../generated/graphql' function DeleteRecord({ record, domain }: any) { const [confirm, setConfirm] = useState(false) - const [mutation, { loading, error }] = useMutation(DELETE_DNS_RECORD, { + const [mutation, { loading, error }] = useDeleteDnsRecordMutation({ variables: { name: record.name, type: record.type }, - update: (cache, { data: { deleteDnsRecord } }) => + update: (cache, { data }) => updateCache(cache, { query: DNS_RECORDS, variables: { id: domain.id }, update: (prev) => deepUpdate(prev, 'dnsDomain', (domain) => - removeConnection(domain, deleteDnsRecord, 'dnsRecords') + removeConnection(domain, data?.deleteDnsRecord, 'dnsRecords') ), }), onCompleted: () => setConfirm(false), diff --git a/www/src/components/account/Domains.tsx b/www/src/components/account/Domains.tsx index cb6ed254e..6b2e30b39 100644 --- a/www/src/components/account/Domains.tsx +++ b/www/src/components/account/Domains.tsx @@ -1,4 +1,4 @@ -import { useMutation, useQuery } from '@apollo/client' +import { useQuery } from '@apollo/client' import { Box } from 'grommet' import { Flex, Span } from 'honorable' import moment from 'moment' @@ -25,11 +25,15 @@ import { Table, TableData, TableRow } from '../utils/Table' import ListInput from '../utils/ListInput' import { List } from '../utils/List' import { Confirm } from '../utils/Confirm' -import { DnsRecordFragment } from '../../generated/graphql' +import { + DnsRecordFragment, + useDeleteDomainMutation, + useUpdateDomainMutation, +} from '../../generated/graphql' import LoadingIndicator from '../utils/LoadingIndicator' -import { DELETE_DOMAIN, DNS_DOMAINS, UPDATE_DOMAIN } from './queries' +import { DNS_DOMAINS } from './queries' import { Actions } from './Actions' import { MoreMenu } from './MoreMenu' import { BindingInput } from './Typeaheads' @@ -52,12 +56,13 @@ function Header({ q, setQ }: any) { function DomainOptions({ domain, setDomain }: any) { const [confirm, setConfirm] = useState(false) const [edit, setEdit] = useState(false) - const [mutation, { loading, error }] = useMutation(DELETE_DOMAIN, { + const [mutation, { loading, error }] = useDeleteDomainMutation({ variables: { id: domain.id }, - update: (cache, { data: { deleteDomain } }) => { + update: (cache, { data }) => { updateCache(cache, { query: DNS_DOMAINS, - update: (prev) => removeConnection(prev, deleteDomain, 'dnsDomains'), + update: (prev) => + removeConnection(prev, data?.deleteDomain, 'dnsDomains'), variables: {}, }) }, @@ -124,7 +129,7 @@ function AccessPolicy({ domain: { id, accessPolicy }, edit, setEdit }: any) { accessPolicy ? accessPolicy.bindings : [] ) const uniqueBindings = useMemo(() => uniqWith(bindings, isEqual), [bindings]) - const [mutation, { loading, error }] = useMutation(UPDATE_DOMAIN, { + const [mutation, { loading, error }] = useUpdateDomainMutation({ variables: { id, attributes: { diff --git a/www/src/components/account/queries.ts b/www/src/components/account/queries.ts index 5abfe2ad3..26047b4de 100644 --- a/www/src/components/account/queries.ts +++ b/www/src/components/account/queries.ts @@ -149,33 +149,6 @@ export const DNS_RECORDS = gql` ${DnsRecordFragment} ` -export const UPDATE_DOMAIN = gql` - mutation Update($id: ID!, $attributes: DnsDomainAttributes!) { - updateDomain(id: $id, attributes: $attributes) { - ...DnsDomainFragment - } - } - ${DnsDomainFragment} -` - -export const DELETE_DOMAIN = gql` - mutation Delete($id: ID!) { - deleteDomain(id: $id) { - ...DnsDomainFragment - } - } - ${DnsDomainFragment} -` - -export const DELETE_DNS_RECORD = gql` - mutation Delete($name: String!, $type: DnsRecordType!) { - deleteDnsRecord(name: $name, type: $type) { - ...DnsRecordFragment - } - } - ${DnsRecordFragment} -` - export const INVITES_Q = gql` query Invites($cursor: String) { invites(first: 50, after: $cursor) { diff --git a/www/src/generated/graphql.ts b/www/src/generated/graphql.ts index eb94c5e74..db9d44ca7 100644 --- a/www/src/generated/graphql.ts +++ b/www/src/generated/graphql.ts @@ -5419,13 +5419,13 @@ export type ClustersQuery = { __typename?: 'RootQueryType', clusters?: { __typen export type DnsRecordFragment = { __typename?: 'DnsRecord', id: string, name: string, type: DnsRecordType, records?: Array | null, cluster: string, provider: Provider, insertedAt?: Date | null, creator?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null }; -export type GetDnsRecordsQueryVariables = Exact<{ +export type DnsRecordsQueryVariables = Exact<{ cluster: Scalars['String']['input']; provider: Provider; }>; -export type GetDnsRecordsQuery = { __typename?: 'RootQueryType', dnsRecords?: { __typename?: 'DnsRecordConnection', edges?: Array<{ __typename?: 'DnsRecordEdge', node?: { __typename?: 'DnsRecord', id: string, name: string, type: DnsRecordType, records?: Array | null, cluster: string, provider: Provider, insertedAt?: Date | null, creator?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null } | null } | null> | null } | null }; +export type DnsRecordsQuery = { __typename?: 'RootQueryType', dnsRecords?: { __typename?: 'DnsRecordConnection', edges?: Array<{ __typename?: 'DnsRecordEdge', node?: { __typename?: 'DnsRecord', id: string, name: string, type: DnsRecordType, records?: Array | null, cluster: string, provider: Provider, insertedAt?: Date | null, creator?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null } | null } | null> | null } | null }; export type CreateDnsRecordMutationVariables = Exact<{ cluster: Scalars['String']['input']; @@ -5444,6 +5444,21 @@ export type DeleteDnsRecordMutationVariables = Exact<{ export type DeleteDnsRecordMutation = { __typename?: 'RootMutationType', deleteDnsRecord?: { __typename?: 'DnsRecord', id: string, name: string, type: DnsRecordType, records?: Array | null, cluster: string, provider: Provider, insertedAt?: Date | null, creator?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null } | null }; +export type UpdateDomainMutationVariables = Exact<{ + id: Scalars['ID']['input']; + attributes: DnsDomainAttributes; +}>; + + +export type UpdateDomainMutation = { __typename?: 'RootMutationType', updateDomain?: { __typename?: 'DnsDomain', id: string, name: string, insertedAt?: Date | null, creator?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, accessPolicy?: { __typename?: 'DnsAccessPolicy', id: string, bindings?: Array<{ __typename?: 'PolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null }; + +export type DeleteDomainMutationVariables = Exact<{ + id: Scalars['ID']['input']; +}>; + + +export type DeleteDomainMutation = { __typename?: 'RootMutationType', deleteDomain?: { __typename?: 'DnsDomain', id: string, name: string, insertedAt?: Date | null, creator?: { __typename?: 'User', id: string, name: string, email: string, avatar?: string | null, provider?: Provider | null, demoed?: boolean | null, onboarding?: OnboardingState | null, emailConfirmed?: boolean | null, emailConfirmBy?: Date | null, backgroundColor?: string | null, serviceAccount?: boolean | null, hasInstallations?: boolean | null, hasShell?: boolean | null, onboardingChecklist?: { __typename?: 'OnboardingChecklist', dismissed?: boolean | null, status?: OnboardingChecklistState | null } | null, invites?: Array<{ __typename?: 'Invite', id: string, email?: string | null } | null> | null, roles?: { __typename?: 'Roles', admin?: boolean | null } | null, groups?: Array<{ __typename?: 'Group', id: string, name: string, global?: boolean | null, description?: string | null } | null> | null, impersonationPolicy?: { __typename?: 'ImpersonationPolicy', id: string, bindings?: Array<{ __typename?: 'ImpersonationPolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null, accessPolicy?: { __typename?: 'DnsAccessPolicy', id: string, bindings?: Array<{ __typename?: 'PolicyBinding', id: string, group?: { __typename?: 'Group', id: string, name: string } | null, user?: { __typename?: 'User', id: string, name: string, email: string } | null } | null> | null } | null } | null }; + export type DockerRepoFragment = { __typename?: 'DockerRepository', id: string, name: string, public?: boolean | null, insertedAt?: Date | null, updatedAt?: Date | null, repository?: { __typename?: 'Repository', id: string, name: string } | null }; export type DockerRepositoryFragment = { __typename?: 'DockerRepository', id: string, name: string, public?: boolean | null, insertedAt?: Date | null, updatedAt?: Date | null, repository?: { __typename?: 'Repository', id: string, name: string, editable?: boolean | null } | null }; @@ -8460,8 +8475,8 @@ export type ClustersQueryHookResult = ReturnType; export type ClustersLazyQueryHookResult = ReturnType; export type ClustersSuspenseQueryHookResult = ReturnType; export type ClustersQueryResult = Apollo.QueryResult; -export const GetDnsRecordsDocument = gql` - query GetDnsRecords($cluster: String!, $provider: Provider!) { +export const DnsRecordsDocument = gql` + query DnsRecords($cluster: String!, $provider: Provider!) { dnsRecords(cluster: $cluster, provider: $provider, first: 500) { edges { node { @@ -8473,38 +8488,38 @@ export const GetDnsRecordsDocument = gql` ${DnsRecordFragmentDoc}`; /** - * __useGetDnsRecordsQuery__ + * __useDnsRecordsQuery__ * - * To run a query within a React component, call `useGetDnsRecordsQuery` and pass it any options that fit your needs. - * When your component renders, `useGetDnsRecordsQuery` returns an object from Apollo Client that contains loading, error, and data properties + * To run a query within a React component, call `useDnsRecordsQuery` and pass it any options that fit your needs. + * When your component renders, `useDnsRecordsQuery` returns an object from Apollo Client that contains loading, error, and data properties * you can use to render your UI. * * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; * * @example - * const { data, loading, error } = useGetDnsRecordsQuery({ + * const { data, loading, error } = useDnsRecordsQuery({ * variables: { * cluster: // value for 'cluster' * provider: // value for 'provider' * }, * }); */ -export function useGetDnsRecordsQuery(baseOptions: Apollo.QueryHookOptions) { +export function useDnsRecordsQuery(baseOptions: Apollo.QueryHookOptions) { const options = {...defaultOptions, ...baseOptions} - return Apollo.useQuery(GetDnsRecordsDocument, options); + return Apollo.useQuery(DnsRecordsDocument, options); } -export function useGetDnsRecordsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { +export function useDnsRecordsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { const options = {...defaultOptions, ...baseOptions} - return Apollo.useLazyQuery(GetDnsRecordsDocument, options); + return Apollo.useLazyQuery(DnsRecordsDocument, options); } -export function useGetDnsRecordsSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { +export function useDnsRecordsSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { const options = {...defaultOptions, ...baseOptions} - return Apollo.useSuspenseQuery(GetDnsRecordsDocument, options); + return Apollo.useSuspenseQuery(DnsRecordsDocument, options); } -export type GetDnsRecordsQueryHookResult = ReturnType; -export type GetDnsRecordsLazyQueryHookResult = ReturnType; -export type GetDnsRecordsSuspenseQueryHookResult = ReturnType; -export type GetDnsRecordsQueryResult = Apollo.QueryResult; +export type DnsRecordsQueryHookResult = ReturnType; +export type DnsRecordsLazyQueryHookResult = ReturnType; +export type DnsRecordsSuspenseQueryHookResult = ReturnType; +export type DnsRecordsQueryResult = Apollo.QueryResult; export const CreateDnsRecordDocument = gql` mutation CreateDnsRecord($cluster: String!, $provider: Provider!, $attributes: DnsRecordAttributes!) { createDnsRecord(cluster: $cluster, provider: $provider, attributes: $attributes) { @@ -8574,6 +8589,73 @@ export function useDeleteDnsRecordMutation(baseOptions?: Apollo.MutationHookOpti export type DeleteDnsRecordMutationHookResult = ReturnType; export type DeleteDnsRecordMutationResult = Apollo.MutationResult; export type DeleteDnsRecordMutationOptions = Apollo.BaseMutationOptions; +export const UpdateDomainDocument = gql` + mutation UpdateDomain($id: ID!, $attributes: DnsDomainAttributes!) { + updateDomain(id: $id, attributes: $attributes) { + ...DnsDomain + } +} + ${DnsDomainFragmentDoc}`; +export type UpdateDomainMutationFn = Apollo.MutationFunction; + +/** + * __useUpdateDomainMutation__ + * + * To run a mutation, you first call `useUpdateDomainMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useUpdateDomainMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [updateDomainMutation, { data, loading, error }] = useUpdateDomainMutation({ + * variables: { + * id: // value for 'id' + * attributes: // value for 'attributes' + * }, + * }); + */ +export function useUpdateDomainMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(UpdateDomainDocument, options); + } +export type UpdateDomainMutationHookResult = ReturnType; +export type UpdateDomainMutationResult = Apollo.MutationResult; +export type UpdateDomainMutationOptions = Apollo.BaseMutationOptions; +export const DeleteDomainDocument = gql` + mutation DeleteDomain($id: ID!) { + deleteDomain(id: $id) { + ...DnsDomain + } +} + ${DnsDomainFragmentDoc}`; +export type DeleteDomainMutationFn = Apollo.MutationFunction; + +/** + * __useDeleteDomainMutation__ + * + * To run a mutation, you first call `useDeleteDomainMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useDeleteDomainMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [deleteDomainMutation, { data, loading, error }] = useDeleteDomainMutation({ + * variables: { + * id: // value for 'id' + * }, + * }); + */ +export function useDeleteDomainMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(DeleteDomainDocument, options); + } +export type DeleteDomainMutationHookResult = ReturnType; +export type DeleteDomainMutationResult = Apollo.MutationResult; +export type DeleteDomainMutationOptions = Apollo.BaseMutationOptions; export const CreateDomainDocument = gql` mutation CreateDomain($name: String!) { provisionDomain(name: $name) { @@ -12531,7 +12613,7 @@ export const namedOperations = { GetChartInstallations: 'GetChartInstallations', GetPackageInstallations: 'GetPackageInstallations', Clusters: 'Clusters', - GetDnsRecords: 'GetDnsRecords', + DnsRecords: 'DnsRecords', GroupMembers: 'GroupMembers', Groups: 'Groups', OauthIntegrations: 'OauthIntegrations', @@ -12577,6 +12659,8 @@ export const namedOperations = { UninstallChart: 'UninstallChart', CreateDnsRecord: 'CreateDnsRecord', DeleteDnsRecord: 'DeleteDnsRecord', + UpdateDomain: 'UpdateDomain', + DeleteDomain: 'DeleteDomain', CreateDomain: 'CreateDomain', CreateGroupMember: 'CreateGroupMember', DeleteGroupMember: 'DeleteGroupMember', diff --git a/www/src/graph/dns.graphql b/www/src/graph/dns.graphql index 801f0882b..45e977a2f 100644 --- a/www/src/graph/dns.graphql +++ b/www/src/graph/dns.graphql @@ -11,7 +11,22 @@ fragment DnsRecord on DnsRecord { insertedAt } -query GetDnsRecords($cluster: String!, $provider: Provider!) { +fragment DnsDomain on DnsDomain { + id + name + creator { + ...User + } + accessPolicy { + id + bindings { + ...PolicyBinding + } + } + insertedAt +} + +query DnsRecords($cluster: String!, $provider: Provider!) { dnsRecords(cluster: $cluster, provider: $provider, first: 500) { edges { node { @@ -40,3 +55,15 @@ mutation DeleteDnsRecord($name: String!, $type: DnsRecordType!) { ...DnsRecord } } + +mutation UpdateDomain($id: ID!, $attributes: DnsDomainAttributes!) { + updateDomain(id: $id, attributes: $attributes) { + ...DnsDomain + } +} + +mutation DeleteDomain($id: ID!) { + deleteDomain(id: $id) { + ...DnsDomain + } +} From d6777ad055fec56ca4d8b21830ff0dd7778f45c8 Mon Sep 17 00:00:00 2001 From: Marcin Maciaszczyk Date: Mon, 4 Nov 2024 15:22:26 +0100 Subject: [PATCH 08/12] marketplace --- .../marketplace/MarketplaceSidebar.tsx | 26 ++-- www/src/components/marketplace/queries.ts | 5 - www/src/generated/graphql.ts | 119 ++++++++++++++++++ www/src/graph/marketplace.graphql | 29 +++++ 4 files changed, 165 insertions(+), 14 deletions(-) create mode 100644 www/src/graph/marketplace.graphql diff --git a/www/src/components/marketplace/MarketplaceSidebar.tsx b/www/src/components/marketplace/MarketplaceSidebar.tsx index b30e463de..3735e5769 100644 --- a/www/src/components/marketplace/MarketplaceSidebar.tsx +++ b/www/src/components/marketplace/MarketplaceSidebar.tsx @@ -11,6 +11,13 @@ import styled from 'styled-components' import usePaginatedQuery from '../../hooks/usePaginatedQuery' import { CATEGORIES_QUERY, TAGS_QUERY } from './queries' +import { + useCategoriesQuery, + useOidcProvidersQuery, + useTagsQuery, +} from '../../generated/graphql' +import { useFetchPaginatedData } from '../utils/useFetchPaginatedData' +import { mapExistingNodes } from '../../utils/graphql' const SIDEBAR_WIDTH = 256 - 32 @@ -241,17 +248,18 @@ const SidebarWrapper = styled(Card)<{ $isOpen: boolean }>( ) function MarketplaceSidebar({ isOpen }: { isOpen: boolean }) { - const { data: categoriesData } = useQuery(CATEGORIES_QUERY) - const [tags, , hasMoreTags, fetchMoreTags] = usePaginatedQuery( - TAGS_QUERY, - {}, - (data) => data.tags + const { data: categoriesData } = useCategoriesQuery() + const { data, pageInfo, fetchNextPage } = useFetchPaginatedData( + { queryHook: useTagsQuery, keyPath: ['tags'] }, + {} ) + const [search, setSearch] = useState('') if (!categoriesData) return null + const filteredCategories = categoriesData.categories?.filter( - (c) => !!c.category + (c) => !!c?.category ) return ( @@ -259,9 +267,9 @@ function MarketplaceSidebar({ isOpen }: { isOpen: boolean }) {
diff --git a/www/src/components/marketplace/queries.ts b/www/src/components/marketplace/queries.ts index c053de396..67230e6e3 100644 --- a/www/src/components/marketplace/queries.ts +++ b/www/src/components/marketplace/queries.ts @@ -4,11 +4,6 @@ import { CategoryFragment } from '../../models/repo' import { PageInfo } from '../../models/misc' export const CATEGORIES_QUERY = gql` - query { - categories { - ...CategoryFragment - } - } ${CategoryFragment} ` diff --git a/www/src/generated/graphql.ts b/www/src/generated/graphql.ts index db9d44ca7..320c33ccd 100644 --- a/www/src/generated/graphql.ts +++ b/www/src/generated/graphql.ts @@ -5638,6 +5638,22 @@ export type CreateKeyBackupMutationVariables = Exact<{ export type CreateKeyBackupMutation = { __typename?: 'RootMutationType', createKeyBackup?: { __typename?: 'KeyBackup', digest: string, id: string, insertedAt?: Date | null, name: string, repositories?: Array | null, updatedAt?: Date | null, value: string, user: { __typename?: 'User', email: string } } | null }; +export type CategoryInfoFragment = { __typename?: 'CategoryInfo', category?: Category | null, count?: number | null }; + +export type GroupedTagFragment = { __typename?: 'GroupedTag', tag: string, count: number }; + +export type CategoriesQueryVariables = Exact<{ [key: string]: never; }>; + + +export type CategoriesQuery = { __typename?: 'RootQueryType', categories?: Array<{ __typename?: 'CategoryInfo', category?: Category | null, count?: number | null } | null> | null }; + +export type TagsQueryVariables = Exact<{ + cursor?: InputMaybe; +}>; + + +export type TagsQuery = { __typename?: 'RootQueryType', tags?: { __typename?: 'GroupedTagConnection', pageInfo: { __typename?: 'PageInfo', endCursor?: string | null, hasNextPage: boolean }, edges?: Array<{ __typename?: 'GroupedTagEdge', node?: { __typename?: 'GroupedTag', tag: string, count: number } | null } | null> | null } | null }; + export type MetricFragment = { __typename?: 'Metric', name: string, tags?: Array<{ __typename?: 'MetricTag', name: string, value: string } | null> | null, values?: Array<{ __typename?: 'MetricValue', time?: Date | null, value?: number | null } | null> | null }; export type PageInfoFragment = { __typename?: 'PageInfo', endCursor?: string | null, hasNextPage: boolean }; @@ -7223,6 +7239,18 @@ export const KeyBackupFragmentDoc = gql` value } ${KeyBackupUserFragmentDoc}`; +export const CategoryInfoFragmentDoc = gql` + fragment CategoryInfo on CategoryInfo { + category + count +} + `; +export const GroupedTagFragmentDoc = gql` + fragment GroupedTag on GroupedTag { + tag + count +} + `; export const MetricFragmentDoc = gql` fragment Metric on Metric { name @@ -9361,6 +9389,93 @@ export function useCreateKeyBackupMutation(baseOptions?: Apollo.MutationHookOpti export type CreateKeyBackupMutationHookResult = ReturnType; export type CreateKeyBackupMutationResult = Apollo.MutationResult; export type CreateKeyBackupMutationOptions = Apollo.BaseMutationOptions; +export const CategoriesDocument = gql` + query Categories { + categories { + ...CategoryInfo + } +} + ${CategoryInfoFragmentDoc}`; + +/** + * __useCategoriesQuery__ + * + * To run a query within a React component, call `useCategoriesQuery` and pass it any options that fit your needs. + * When your component renders, `useCategoriesQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useCategoriesQuery({ + * variables: { + * }, + * }); + */ +export function useCategoriesQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(CategoriesDocument, options); + } +export function useCategoriesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(CategoriesDocument, options); + } +export function useCategoriesSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(CategoriesDocument, options); + } +export type CategoriesQueryHookResult = ReturnType; +export type CategoriesLazyQueryHookResult = ReturnType; +export type CategoriesSuspenseQueryHookResult = ReturnType; +export type CategoriesQueryResult = Apollo.QueryResult; +export const TagsDocument = gql` + query Tags($cursor: String) { + tags(type: REPOSITORIES, first: 200, after: $cursor) { + pageInfo { + ...PageInfo + } + edges { + node { + ...GroupedTag + } + } + } +} + ${PageInfoFragmentDoc} +${GroupedTagFragmentDoc}`; + +/** + * __useTagsQuery__ + * + * To run a query within a React component, call `useTagsQuery` and pass it any options that fit your needs. + * When your component renders, `useTagsQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useTagsQuery({ + * variables: { + * cursor: // value for 'cursor' + * }, + * }); + */ +export function useTagsQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(TagsDocument, options); + } +export function useTagsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(TagsDocument, options); + } +export function useTagsSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useSuspenseQuery(TagsDocument, options); + } +export type TagsQueryHookResult = ReturnType; +export type TagsLazyQueryHookResult = ReturnType; +export type TagsSuspenseQueryHookResult = ReturnType; +export type TagsQueryResult = Apollo.QueryResult; export const NotificationsDocument = gql` query Notifications($incidentId: ID, $first: Int = 50, $cursor: String) { notifications(incidentId: $incidentId, first: $first, after: $cursor) { @@ -12620,6 +12735,8 @@ export const namedOperations = { Invite: 'Invite', KeyBackups: 'KeyBackups', KeyBackup: 'KeyBackup', + Categories: 'Categories', + Tags: 'Tags', Notifications: 'Notifications', OIDCConsent: 'OIDCConsent', OIDCProviders: 'OIDCProviders', @@ -12765,6 +12882,8 @@ export const namedOperations = { Invite: 'Invite', KeyBackupUser: 'KeyBackupUser', KeyBackup: 'KeyBackup', + CategoryInfo: 'CategoryInfo', + GroupedTag: 'GroupedTag', Metric: 'Metric', PageInfo: 'PageInfo', NotificationFragment: 'NotificationFragment', diff --git a/www/src/graph/marketplace.graphql b/www/src/graph/marketplace.graphql new file mode 100644 index 000000000..d290e6f25 --- /dev/null +++ b/www/src/graph/marketplace.graphql @@ -0,0 +1,29 @@ + +fragment CategoryInfo on CategoryInfo { + category + count +} + +fragment GroupedTag on GroupedTag { + tag + count +} + +query Categories{ + categories { + ...CategoryInfo + } +} + +query Tags($cursor: String) { + tags(type: REPOSITORIES, first: 200, after: $cursor) { + pageInfo { + ...PageInfo + } + edges { + node { + ...GroupedTag + } + } + } +} \ No newline at end of file From 063d60cf88d413acc0fc76cf4ef2d61c84193041 Mon Sep 17 00:00:00 2001 From: Marcin Maciaszczyk Date: Mon, 4 Nov 2024 15:25:43 +0100 Subject: [PATCH 09/12] lint --- www/src/components/account/CreateRole.tsx | 4 +- .../account/CreateServiceAccount.tsx | 3 +- www/src/components/account/DnsRecords.tsx | 3 +- www/src/components/account/EditRole.tsx | 3 +- www/src/components/account/InviteUser.tsx | 3 +- www/src/components/account/Invites.tsx | 3 +- www/src/components/account/User.tsx | 1 - www/src/components/account/queries.ts | 1 - .../components/audits/AuditChloropleth.tsx | 2 +- www/src/components/audits/Audits.tsx | 3 +- www/src/components/audits/LoginAudits.tsx | 3 +- www/src/components/cluster/ClusterApp.tsx | 2 +- www/src/components/cluster/ClusterApps.tsx | 3 +- .../marketplace/MarketplaceSidebar.tsx | 11 +- www/src/components/marketplace/queries.ts | 25 ---- .../plural-cloud/EditPluralOIDCClient.tsx | 2 +- www/src/graph/audit.graphql | 116 +++++++++--------- www/src/graph/marketplace.graphql | 37 +++--- www/src/graph/role.graphql | 50 ++++---- 19 files changed, 123 insertions(+), 152 deletions(-) delete mode 100644 www/src/components/marketplace/queries.ts diff --git a/www/src/components/account/CreateRole.tsx b/www/src/components/account/CreateRole.tsx index 84c927adc..9b3264feb 100644 --- a/www/src/components/account/CreateRole.tsx +++ b/www/src/components/account/CreateRole.tsx @@ -1,5 +1,4 @@ import { useCallback, useContext, useMemo, useState } from 'react' -import { useMutation } from '@apollo/client' import { Button } from 'honorable' import { Modal } from '@pluralsh/design-system' import uniqWith from 'lodash/uniqWith' @@ -9,13 +8,14 @@ import { appendConnection, updateCache } from '../../utils/graphql' import SubscriptionContext from '../../contexts/SubscriptionContext' +import { useCreateRoleMutation } from '../../generated/graphql' + import { ROLES_Q } from './queries' import { Actions } from './Actions' import { sanitize } from './utils' import { RoleForm } from './RoleForm' import BillingFeatureBlockModal from './billing/BillingFeatureBlockModal' -import { useCreateRoleMutation } from '../../generated/graphql' const defaultAttributes = { name: '', diff --git a/www/src/components/account/CreateServiceAccount.tsx b/www/src/components/account/CreateServiceAccount.tsx index f2b377eea..5b34f5ff7 100644 --- a/www/src/components/account/CreateServiceAccount.tsx +++ b/www/src/components/account/CreateServiceAccount.tsx @@ -20,6 +20,8 @@ import SubscriptionContext from '../../contexts/SubscriptionContext' import { Confirm } from '../utils/Confirm' +import { useCreateServiceAccountMutation } from '../../generated/graphql' + import { UPDATE_SERVICE_ACCOUNT, USERS_Q } from './queries' import { MoreMenu } from './MoreMenu' @@ -27,7 +29,6 @@ import { MoreMenu } from './MoreMenu' import { BindingInput } from './Typeaheads' import { sanitize } from './utils' import BillingFeatureBlockModal from './billing/BillingFeatureBlockModal' -import { useCreateServiceAccountMutation } from '../../generated/graphql' function ServiceAccountForm({ error, diff --git a/www/src/components/account/DnsRecords.tsx b/www/src/components/account/DnsRecords.tsx index daebd4f13..f6c1c3732 100644 --- a/www/src/components/account/DnsRecords.tsx +++ b/www/src/components/account/DnsRecords.tsx @@ -18,9 +18,10 @@ import { Table, TableData, TableRow } from '../utils/Table' import { ProviderIcon } from '../utils/ProviderIcon' import { Confirm } from '../utils/Confirm' -import { DNS_RECORDS } from './queries' import { useDeleteDnsRecordMutation } from '../../generated/graphql' +import { DNS_RECORDS } from './queries' + function DeleteRecord({ record, domain }: any) { const [confirm, setConfirm] = useState(false) const [mutation, { loading, error }] = useDeleteDnsRecordMutation({ diff --git a/www/src/components/account/EditRole.tsx b/www/src/components/account/EditRole.tsx index 744ded5e0..0d02320e4 100644 --- a/www/src/components/account/EditRole.tsx +++ b/www/src/components/account/EditRole.tsx @@ -4,10 +4,11 @@ import { useMemo, useState } from 'react' import uniqWith from 'lodash/uniqWith' import isEqual from 'lodash/isEqual' +import { useUpdateRoleMutation } from '../../generated/graphql' + import { Actions } from './Actions' import { sanitize } from './utils' import { RoleForm } from './RoleForm' -import { useUpdateRoleMutation } from '../../generated/graphql' export function EditRole({ role }: any) { const [open, setOpen] = useState(false) diff --git a/www/src/components/account/InviteUser.tsx b/www/src/components/account/InviteUser.tsx index a889fd869..197e8b04e 100644 --- a/www/src/components/account/InviteUser.tsx +++ b/www/src/components/account/InviteUser.tsx @@ -14,9 +14,10 @@ import { useCurrentUser } from '../../contexts/CurrentUserContext' import SubscriptionContext from '../../contexts/SubscriptionContext' import { GqlError } from '../utils/Alert' -import { inviteLink } from './utils' import { useCreateInviteMutation } from '../../generated/graphql' +import { inviteLink } from './utils' + const MAX_OPEN_SOURCE_USERS = 5 export function InviteUser({ refetch }: { refetch?: (() => void) | null }) { diff --git a/www/src/components/account/Invites.tsx b/www/src/components/account/Invites.tsx index 6d7b435ef..9a4d7eb2d 100644 --- a/www/src/components/account/Invites.tsx +++ b/www/src/components/account/Invites.tsx @@ -23,9 +23,10 @@ import LoadingIndicator from '../utils/LoadingIndicator' import { Confirm } from '../utils/Confirm' +import { useDeleteInviteMutation } from '../../generated/graphql' + import { INVITES_Q } from './queries' import { inviteLink } from './utils' -import { useDeleteInviteMutation } from '../../generated/graphql' function DeleteInvite({ invite }: any) { const [confirm, setConfirm] = useState(false) diff --git a/www/src/components/account/User.tsx b/www/src/components/account/User.tsx index 7b414f938..d6439a49c 100644 --- a/www/src/components/account/User.tsx +++ b/www/src/components/account/User.tsx @@ -1,4 +1,3 @@ -import { useMutation } from '@apollo/client' import { AppIcon, Chip, diff --git a/www/src/components/account/queries.ts b/www/src/components/account/queries.ts index 26047b4de..4959cc1f8 100644 --- a/www/src/components/account/queries.ts +++ b/www/src/components/account/queries.ts @@ -1,7 +1,6 @@ import { gql } from '@apollo/client' import { - AuditFragment, DnsDomainFragment, DnsRecordFragment, InviteFragment, diff --git a/www/src/components/audits/AuditChloropleth.tsx b/www/src/components/audits/AuditChloropleth.tsx index bade5f842..7d2118c36 100644 --- a/www/src/components/audits/AuditChloropleth.tsx +++ b/www/src/components/audits/AuditChloropleth.tsx @@ -27,7 +27,7 @@ export function AuditChloropleth() { if (!data) return null - const results = data['auditMetrics'] || data['loginMetrics'] + const results = data.auditMetrics || data.loginMetrics const metrics = results.map(({ country, count }) => ({ // @ts-expect-error id: lookup.byIso(country).iso3, diff --git a/www/src/components/audits/Audits.tsx b/www/src/components/audits/Audits.tsx index 96e5995f8..ab910693a 100644 --- a/www/src/components/audits/Audits.tsx +++ b/www/src/components/audits/Audits.tsx @@ -9,9 +9,10 @@ import isEmpty from 'lodash/isEmpty' import { extendConnection, mapExistingNodes } from '../../utils/graphql' import LoadingIndicator from '../utils/LoadingIndicator' +import { useAuditsQuery } from '../../generated/graphql' + import { AuditUser } from './AuditUser' import { Location } from './Location' -import { useAuditsQuery } from '../../generated/graphql' const FETCH_MARGIN = 30 diff --git a/www/src/components/audits/LoginAudits.tsx b/www/src/components/audits/LoginAudits.tsx index 5a0b6ad45..b2b48240a 100644 --- a/www/src/components/audits/LoginAudits.tsx +++ b/www/src/components/audits/LoginAudits.tsx @@ -8,9 +8,10 @@ import { Flex } from 'honorable' import { extendConnection, mapExistingNodes } from '../../utils/graphql' import LoadingIndicator from '../utils/LoadingIndicator' +import { useLoginsQuery } from '../../generated/graphql' + import { AuditUser } from './AuditUser' import { Location } from './Location' -import { useLoginsQuery } from '../../generated/graphql' const FETCH_MARGIN = 30 diff --git a/www/src/components/cluster/ClusterApp.tsx b/www/src/components/cluster/ClusterApp.tsx index 2fcf6a0dc..9791e467e 100644 --- a/www/src/components/cluster/ClusterApp.tsx +++ b/www/src/components/cluster/ClusterApp.tsx @@ -12,7 +12,7 @@ import { useNavigate, useParams } from 'react-router-dom' import { useTheme } from 'styled-components' -import { Repository, RepositoryFragment } from '../../generated/graphql' +import { RepositoryFragment } from '../../generated/graphql' import { MoreMenu } from '../account/MoreMenu' type ClusterAppProps = { diff --git a/www/src/components/cluster/ClusterApps.tsx b/www/src/components/cluster/ClusterApps.tsx index d8b62022e..cea2ce45d 100644 --- a/www/src/components/cluster/ClusterApps.tsx +++ b/www/src/components/cluster/ClusterApps.tsx @@ -10,10 +10,11 @@ import InfiniteScroller from '../utils/InfiniteScroller' import { Cluster, useRepositoriesQuery } from '../../generated/graphql' import { ensureURLValidity } from '../../utils/url' -import { ClusterApp } from './ClusterApp' import { useFetchPaginatedData } from '../utils/useFetchPaginatedData' import { mapExistingNodes } from '../../utils/graphql' +import { ClusterApp } from './ClusterApp' + const searchOptions = { keys: ['name'], threshold: 0.25, diff --git a/www/src/components/marketplace/MarketplaceSidebar.tsx b/www/src/components/marketplace/MarketplaceSidebar.tsx index 3735e5769..3e9855778 100644 --- a/www/src/components/marketplace/MarketplaceSidebar.tsx +++ b/www/src/components/marketplace/MarketplaceSidebar.tsx @@ -1,5 +1,4 @@ import { useCallback, useMemo, useState } from 'react' -import { useQuery } from '@apollo/client' import { useSearchParams } from 'react-router-dom' import { A, Accordion, Div } from 'honorable' import { Card, Checkbox, CloseIcon, Input } from '@pluralsh/design-system' @@ -8,16 +7,8 @@ import capitalize from 'lodash/capitalize' import styled from 'styled-components' -import usePaginatedQuery from '../../hooks/usePaginatedQuery' - -import { CATEGORIES_QUERY, TAGS_QUERY } from './queries' -import { - useCategoriesQuery, - useOidcProvidersQuery, - useTagsQuery, -} from '../../generated/graphql' +import { useCategoriesQuery, useTagsQuery } from '../../generated/graphql' import { useFetchPaginatedData } from '../utils/useFetchPaginatedData' -import { mapExistingNodes } from '../../utils/graphql' const SIDEBAR_WIDTH = 256 - 32 diff --git a/www/src/components/marketplace/queries.ts b/www/src/components/marketplace/queries.ts deleted file mode 100644 index 67230e6e3..000000000 --- a/www/src/components/marketplace/queries.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { gql } from '@apollo/client' - -import { CategoryFragment } from '../../models/repo' -import { PageInfo } from '../../models/misc' - -export const CATEGORIES_QUERY = gql` - ${CategoryFragment} -` - -export const TAGS_QUERY = gql` - query Tags($cursor: String) { - tags(type: REPOSITORIES, first: 200, after: $cursor) { - pageInfo { - ...PageInfo - } - edges { - node { - tag - count - } - } - } - } - ${PageInfo} -` diff --git a/www/src/components/overview/clusters/plural-cloud/EditPluralOIDCClient.tsx b/www/src/components/overview/clusters/plural-cloud/EditPluralOIDCClient.tsx index 1a309b738..af3e1c9b8 100644 --- a/www/src/components/overview/clusters/plural-cloud/EditPluralOIDCClient.tsx +++ b/www/src/components/overview/clusters/plural-cloud/EditPluralOIDCClient.tsx @@ -171,7 +171,7 @@ function EditPluralOIDCClient({ onEdit() onClose() } - }, [onClose, onCreate, onEdit, refetch]) + }, [createMode, onClose, onCreate, onEdit, refetch]) const [create, { data, loading: creating, error: createError }] = useCreateProviderMutation({ diff --git a/www/src/graph/audit.graphql b/www/src/graph/audit.graphql index 348e191b8..67bef1502 100644 --- a/www/src/graph/audit.graphql +++ b/www/src/graph/audit.graphql @@ -1,75 +1,75 @@ fragment Audit on Audit { + id + action + ip + country + city + latitude + longitude + actor { + ...User + } + repository { + ...Repo + } + group { + ...Group + } + integrationWebhook { + ...IntegrationWebhook + } + role { + ...Role + } + version { + ...Version + } + image { id - action - ip - country - city - latitude - longitude - actor { - ...User - } - repository { - ...Repo - } - group { - ...Group - } - integrationWebhook { - ...IntegrationWebhook - } - role { - ...Role - } - version { - ...Version - } - image { - id - tag - dockerRepository { - name - } + tag + dockerRepository { + name } - insertedAt + } + insertedAt } query Audits($cursor: String) { - audits(first: 50, after: $cursor) { - pageInfo { - ...PageInfo - } - edges { - node { - ...Audit - } - } + audits(first: 50, after: $cursor) { + pageInfo { + ...PageInfo } + edges { + node { + ...Audit + } + } + } } query Logins($cursor: String) { - oidcLogins(first: 50, after: $cursor) { - pageInfo { - ...PageInfo - } - edges { - node { - ...OidcLogin - } - } + oidcLogins(first: 50, after: $cursor) { + pageInfo { + ...PageInfo + } + edges { + node { + ...OidcLogin + } } + } } query AuditMetrics { - auditMetrics { - country - count - } + auditMetrics { + country + count + } } query LoginMetrics { - loginMetrics { - country - count - } -} \ No newline at end of file + loginMetrics { + country + count + } +} diff --git a/www/src/graph/marketplace.graphql b/www/src/graph/marketplace.graphql index d290e6f25..3ea1d0288 100644 --- a/www/src/graph/marketplace.graphql +++ b/www/src/graph/marketplace.graphql @@ -1,29 +1,28 @@ - fragment CategoryInfo on CategoryInfo { - category - count + category + count } fragment GroupedTag on GroupedTag { - tag - count + tag + count } -query Categories{ - categories { - ...CategoryInfo - } +query Categories { + categories { + ...CategoryInfo + } } query Tags($cursor: String) { - tags(type: REPOSITORIES, first: 200, after: $cursor) { - pageInfo { - ...PageInfo - } - edges { - node { - ...GroupedTag - } - } + tags(type: REPOSITORIES, first: 200, after: $cursor) { + pageInfo { + ...PageInfo } -} \ No newline at end of file + edges { + node { + ...GroupedTag + } + } + } +} diff --git a/www/src/graph/role.graphql b/www/src/graph/role.graphql index d52c23933..fb003a5f2 100644 --- a/www/src/graph/role.graphql +++ b/www/src/graph/role.graphql @@ -1,38 +1,38 @@ fragment Role on Role { - id - name - description - repositories - permissions - roleBindings { - ...RoleBinding - } + id + name + description + repositories + permissions + roleBindings { + ...RoleBinding + } } fragment RoleBinding on RoleBinding { - id - user { - ...User - } - group { - ...Group - } + id + user { + ...User + } + group { + ...Group + } } mutation CreateRole($attributes: RoleAttributes!) { - createRole(attributes: $attributes) { - ...Role - } + createRole(attributes: $attributes) { + ...Role + } } mutation UpdateRole($id: ID!, $attributes: RoleAttributes!) { - updateRole(id: $id, attributes: $attributes) { - ...Role - } + updateRole(id: $id, attributes: $attributes) { + ...Role + } } mutation DeleteRole($id: ID!) { - deleteRole(id: $id) { - ...Role - } -} \ No newline at end of file + deleteRole(id: $id) { + ...Role + } +} From 9ee61a7d563b7323c282b3929a4a7684466153d6 Mon Sep 17 00:00:00 2001 From: Marcin Maciaszczyk Date: Mon, 4 Nov 2024 15:32:51 +0100 Subject: [PATCH 10/12] post-lint fix --- www/src/components/audits/AuditChloropleth.tsx | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/www/src/components/audits/AuditChloropleth.tsx b/www/src/components/audits/AuditChloropleth.tsx index 7d2118c36..b4a164902 100644 --- a/www/src/components/audits/AuditChloropleth.tsx +++ b/www/src/components/audits/AuditChloropleth.tsx @@ -1,4 +1,4 @@ -import { useRef, useState } from 'react' +import { useMemo, useRef, useState } from 'react' import lookup from 'country-code-lookup' import { Box } from 'grommet' @@ -8,6 +8,7 @@ import { Card, PageTitle, SubTab, TabList } from '@pluralsh/design-system' import { Chloropleth } from '../utils/Chloropleth' import { + LoginMetricsQueryResult, useAuditMetricsQuery, useLoginMetricsQuery, } from '../../generated/graphql' @@ -21,9 +22,14 @@ export function AuditChloropleth() { const [selectedKey, setSelectedKey] = useState('audit-logs') const tabStateRef = useRef(null) - const query = - selectedKey === 'logins' ? useLoginMetricsQuery : useAuditMetricsQuery - const { data } = query({ fetchPolicy: 'cache-and-network' }) + const query = useMemo( + () => + selectedKey === 'logins' ? useLoginMetricsQuery : useAuditMetricsQuery, + [selectedKey] + ) + const { data }: { data: any } = query({ + fetchPolicy: 'cache-and-network', + }) if (!data) return null From 0c7eaf877ee227d6b720f3728f0b2692555ba307 Mon Sep 17 00:00:00 2001 From: Marcin Maciaszczyk Date: Mon, 4 Nov 2024 15:33:06 +0100 Subject: [PATCH 11/12] lint --- www/src/components/audits/AuditChloropleth.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/www/src/components/audits/AuditChloropleth.tsx b/www/src/components/audits/AuditChloropleth.tsx index b4a164902..8b9bff9b1 100644 --- a/www/src/components/audits/AuditChloropleth.tsx +++ b/www/src/components/audits/AuditChloropleth.tsx @@ -8,7 +8,6 @@ import { Card, PageTitle, SubTab, TabList } from '@pluralsh/design-system' import { Chloropleth } from '../utils/Chloropleth' import { - LoginMetricsQueryResult, useAuditMetricsQuery, useLoginMetricsQuery, } from '../../generated/graphql' From b770151f19448bae73162f76fae1328f3d9cea5e Mon Sep 17 00:00:00 2001 From: Marcin Maciaszczyk Date: Mon, 4 Nov 2024 16:44:11 +0100 Subject: [PATCH 12/12] fix tags --- www/src/components/marketplace/MarketplaceSidebar.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/www/src/components/marketplace/MarketplaceSidebar.tsx b/www/src/components/marketplace/MarketplaceSidebar.tsx index 3e9855778..ebcc400e4 100644 --- a/www/src/components/marketplace/MarketplaceSidebar.tsx +++ b/www/src/components/marketplace/MarketplaceSidebar.tsx @@ -9,6 +9,7 @@ import styled from 'styled-components' import { useCategoriesQuery, useTagsQuery } from '../../generated/graphql' import { useFetchPaginatedData } from '../utils/useFetchPaginatedData' +import { mapExistingNodes } from '../../utils/graphql' const SIDEBAR_WIDTH = 256 - 32 @@ -247,6 +248,8 @@ function MarketplaceSidebar({ isOpen }: { isOpen: boolean }) { const [search, setSearch] = useState('') + const tags = useMemo(() => mapExistingNodes(data?.tags) ?? [], [data]) + if (!categoriesData) return null const filteredCategories = categoriesData.categories?.filter( @@ -258,7 +261,7 @@ function MarketplaceSidebar({ isOpen }: { isOpen: boolean }) {