From fc4075b3722109ea799ee2e25eda621077c9ab07 Mon Sep 17 00:00:00 2001 From: martmull Date: Thu, 26 Oct 2023 11:32:44 +0200 Subject: [PATCH] 2062 view edit an api key (#2231) * Add query to get api keys * Add a link to apiKey detail page * Reset generatedApiKey when leaving page * Simplify stuff * Regenerate key when clicking on button * Simplify * Fix test * Refetch apiKeys when delete or create one * Add test for utils * Create utils function * Enable null expiration dates * Update formatExpiration * Fix display * Fix noteCard * Fix errors * Fix reset * Fix display * Fix renaming * Fix tests * Fix ci * Fix mocked data * Fix test * Update coverage requiremeents * Rename folder * Code review returns * Symplify sht code --- front/nyc.config.js | 8 +- front/src/generated/graphql.tsx | 62 ++++-- .../activities/notes/components/NoteCard.tsx | 5 +- .../developers/components/ApiKeyInput.tsx | 13 +- .../SettingsApiKeysFieldItemTableRow.tsx | 9 +- .../__stories__/ApiKeyInput.stories.tsx | 1 - .../developers/constants/expirationDates.ts | 4 +- .../developers/constants/mockObjects.ts | 36 ---- .../developers/graphql/queries/getApiKey.ts | 1 + .../developers/graphql/queries/getApiKeys.ts | 12 ++ .../developers/hooks/useGeneratedApiKeys.ts | 12 ++ .../states/generatedApiKeyFamilyState.ts | 9 + .../developers/states/generatedApiKeyState.ts | 6 - .../{ApisFieldItem.ts => ApiFieldItem.ts} | 2 +- .../compute-new-expiration-date.test.ts | 23 ++ .../utils/__tests__/format-expiration.test.ts | 34 +++ .../utils/compute-new-expiration-date.ts | 14 ++ .../developers/utils/format-expiration.ts | 31 +++ front/src/modules/ui/display/icon/index.ts | 1 + .../modules/ui/input/components/Select.tsx | 4 +- .../modules/ui/input/components/TextInput.tsx | 10 - .../components/__stories__/Select.stories.tsx | 4 +- .../__stories__/TextInput.stories.tsx | 4 - .../SettingsDevelopersApiKeyDetail.tsx | 200 +++++++++++++----- .../api-keys/SettingsDevelopersApiKeys.tsx | 10 +- .../api-keys/SettingsDevelopersApiKeysNew.tsx | 31 ++- ...ettingsDevelopersApiKeysDetail.stories.tsx | 2 - .../src/testing/decorators/PageDecorator.tsx | 13 +- front/src/testing/graphqlMocks.ts | 10 +- front/src/testing/mock-data/api-keys.ts | 18 +- front/src/utils/__tests__/date-utils.test.ts | 17 +- front/src/utils/date-utils.ts | 7 +- server/.env.example | 2 +- .../environment/environment.service.ts | 2 +- 34 files changed, 434 insertions(+), 183 deletions(-) delete mode 100644 front/src/modules/settings/developers/constants/mockObjects.ts create mode 100644 front/src/modules/settings/developers/graphql/queries/getApiKeys.ts create mode 100644 front/src/modules/settings/developers/hooks/useGeneratedApiKeys.ts create mode 100644 front/src/modules/settings/developers/states/generatedApiKeyFamilyState.ts delete mode 100644 front/src/modules/settings/developers/states/generatedApiKeyState.ts rename front/src/modules/settings/developers/types/{ApisFieldItem.ts => ApiFieldItem.ts} (74%) create mode 100644 front/src/modules/settings/developers/utils/__tests__/compute-new-expiration-date.test.ts create mode 100644 front/src/modules/settings/developers/utils/__tests__/format-expiration.test.ts create mode 100644 front/src/modules/settings/developers/utils/compute-new-expiration-date.ts create mode 100644 front/src/modules/settings/developers/utils/format-expiration.ts diff --git a/front/nyc.config.js b/front/nyc.config.js index 43799fe88..28b9d3da9 100644 --- a/front/nyc.config.js +++ b/front/nyc.config.js @@ -17,9 +17,9 @@ const modulesCoverage = { }; const pagesCoverage = { - "statements": 60, - "lines": 60, - "functions": 55, + "statements": 50, + "lines": 50, + "functions": 45, "exclude": [ "src/generated/**/*", "src/modules/**/*", @@ -32,4 +32,4 @@ const storybookStoriesFolders = process.env.STORYBOOK_SCOPE; module.exports = storybookStoriesFolders === 'pages' ? pagesCoverage : storybookStoriesFolders === 'modules' ? modulesCoverage - : globalCoverage; \ No newline at end of file + : globalCoverage; diff --git a/front/src/generated/graphql.tsx b/front/src/generated/graphql.tsx index 54859b2f4..add5635d7 100644 --- a/front/src/generated/graphql.tsx +++ b/front/src/generated/graphql.tsx @@ -3807,22 +3807,7 @@ export type GetActivitiesQueryVariables = Exact<{ }>; -export type GetActivitiesQuery = { - __typename?: 'Query', - findManyActivities: Array<{ - __typename?: 'Activity'; - id: string; - createdAt: string, - title?: string | null, - body?: string | null, - type: ActivityType, - completedAt?: string | null, - dueAt?: string | null, - assignee?: { __typename?: 'User', id: string, firstName?: string | null, lastName?: string | null, displayName: string, avatarUrl?: string | null } | null, - author: { __typename?: 'User', id: string, firstName?: string | null, lastName?: string | null, displayName: string }, - comments?: Array, - activityTargets?: Array<{ __typename?: 'ActivityTarget', id: string, companyId?: string | null, personId?: string | null, company?: { __typename?: 'Company', id: string, name: string, domainName: string } | null, person?: { __typename?: 'Person', id: string, displayName: string, avatarUrl?: string | null } | null }> | null -}> }; +export type GetActivitiesQuery = { __typename?: 'Query', findManyActivities: Array<{ __typename?: 'Activity', id: string, createdAt: string, title?: string | null, body?: string | null, type: ActivityType, completedAt?: string | null, dueAt?: string | null, assignee?: { __typename?: 'User', id: string, firstName?: string | null, lastName?: string | null, displayName: string, avatarUrl?: string | null } | null, author: { __typename?: 'User', id: string, firstName?: string | null, lastName?: string | null, displayName: string }, comments?: Array<{ __typename?: 'Comment', id: string, body: string, createdAt: string, updatedAt: string, author: { __typename?: 'User', id: string, displayName: string, firstName?: string | null, lastName?: string | null, avatarUrl?: string | null } }> | null, activityTargets?: Array<{ __typename?: 'ActivityTarget', id: string, companyId?: string | null, personId?: string | null, company?: { __typename?: 'Company', id: string, name: string, domainName: string } | null, person?: { __typename?: 'Person', id: string, displayName: string, avatarUrl?: string | null } | null }> | null }> }; export type GetActivitiesByTargetsQueryVariables = Exact<{ activityTargetIds: Array | Scalars['String']; @@ -4225,7 +4210,12 @@ export type GetApiKeyQueryVariables = Exact<{ }>; -export type GetApiKeyQuery = { __typename?: 'Query', findManyApiKey: Array<{ __typename?: 'ApiKey', id: string, name: string, expiresAt?: string | null }> }; +export type GetApiKeyQuery = { __typename?: 'Query', findManyApiKey: Array<{ __typename?: 'ApiKey', id: string, name: string, expiresAt?: string | null, createdAt: string }> }; + +export type GetApiKeysQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetApiKeysQuery = { __typename?: 'Query', findManyApiKey: Array<{ __typename?: 'ApiKey', id: string, name: string, expiresAt?: string | null, createdAt: string }> }; export type UserFieldsFragmentFragment = { __typename?: 'User', id: string, email: string, displayName: string, firstName?: string | null, lastName?: string | null }; @@ -6954,6 +6944,7 @@ export const GetApiKeyDocument = gql` id name expiresAt + createdAt } } `; @@ -6985,6 +6976,43 @@ export function useGetApiKeyLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions< export type GetApiKeyQueryHookResult = ReturnType; export type GetApiKeyLazyQueryHookResult = ReturnType; export type GetApiKeyQueryResult = Apollo.QueryResult; +export const GetApiKeysDocument = gql` + query GetApiKeys { + findManyApiKey { + id + name + expiresAt + createdAt + } +} + `; + +/** + * __useGetApiKeysQuery__ + * + * To run a query within a React component, call `useGetApiKeysQuery` and pass it any options that fit your needs. + * When your component renders, `useGetApiKeysQuery` 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 } = useGetApiKeysQuery({ + * variables: { + * }, + * }); + */ +export function useGetApiKeysQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(GetApiKeysDocument, options); + } +export function useGetApiKeysLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(GetApiKeysDocument, options); + } +export type GetApiKeysQueryHookResult = ReturnType; +export type GetApiKeysLazyQueryHookResult = ReturnType; +export type GetApiKeysQueryResult = Apollo.QueryResult; export const DeleteUserAccountDocument = gql` mutation DeleteUserAccount { deleteUserAccount { diff --git a/front/src/modules/activities/notes/components/NoteCard.tsx b/front/src/modules/activities/notes/components/NoteCard.tsx index b93e41aea..9089713c2 100644 --- a/front/src/modules/activities/notes/components/NoteCard.tsx +++ b/front/src/modules/activities/notes/components/NoteCard.tsx @@ -9,7 +9,7 @@ import { GenericFieldContextType, } from '@/ui/data/field/contexts/FieldContext'; import { IconComment } from '@/ui/display/icon'; -import { Activity, ActivityTarget } from '~/generated/graphql'; +import { Activity, ActivityTarget, Comment } from '~/generated/graphql'; const StyledCard = styled.div` align-items: flex-start; @@ -76,9 +76,10 @@ export const NoteCard = ({ }: { note: Pick< Activity, - 'id' | 'title' | 'body' | 'type' | 'completedAt' | 'dueAt' | 'comments' + 'id' | 'title' | 'body' | 'type' | 'completedAt' | 'dueAt' > & { activityTargets?: Array> | null; + comments?: Array> | null; }; }) => { const theme = useTheme(); diff --git a/front/src/modules/settings/developers/components/ApiKeyInput.tsx b/front/src/modules/settings/developers/components/ApiKeyInput.tsx index 36639f35f..e727c055b 100644 --- a/front/src/modules/settings/developers/components/ApiKeyInput.tsx +++ b/front/src/modules/settings/developers/components/ApiKeyInput.tsx @@ -5,7 +5,6 @@ import { IconCopy } from '@/ui/display/icon'; import { useSnackBar } from '@/ui/feedback/snack-bar/hooks/useSnackBar'; import { Button } from '@/ui/input/button/components/Button'; import { TextInput } from '@/ui/input/components/TextInput'; -import { beautifyDateDiff } from '~/utils/date-utils'; const StyledContainer = styled.div` display: flex; @@ -17,22 +16,16 @@ const StyledLinkContainer = styled.div` margin-right: ${({ theme }) => theme.spacing(2)}; `; -type ApiKeyInputProps = { expiresAt?: string | null; apiKey: string }; +type ApiKeyInputProps = { apiKey: string }; -export const ApiKeyInput = ({ expiresAt, apiKey }: ApiKeyInputProps) => { +export const ApiKeyInput = ({ apiKey }: ApiKeyInputProps) => { const theme = useTheme(); - const computeInfo = () => { - if (!expiresAt) { - return ''; - } - return `This key will expire in ${beautifyDateDiff(expiresAt)}`; - }; const { enqueueSnackBar } = useSnackBar(); return ( - +