Make api name editable and add expiry (#6473)

Fixes #6302

---------

Co-authored-by: martmull <martmull@hotmail.fr>
This commit is contained in:
Prateek Jain
2024-08-02 17:01:06 +05:30
committed by GitHub
parent 68120d529c
commit 281bf689fa
13 changed files with 155 additions and 78 deletions

View File

@ -0,0 +1,70 @@
import { useCallback, useEffect } from 'react';
import styled from '@emotion/styled';
import { useDebouncedCallback } from 'use-debounce';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { ApiKey } from '@/settings/developers/types/api-key/ApiKey';
import { TextInput } from '@/ui/input/components/TextInput';
import { isDefined } from '~/utils/isDefined';
const StyledComboInputContainer = styled.div`
display: flex;
flex-direction: row;
> * + * {
margin-left: ${({ theme }) => theme.spacing(4)};
}
`;
type ApiKeyNameInputProps = {
apiKeyName: string;
apiKeyId: string;
disabled: boolean;
onNameUpdate?: (name: string) => void;
};
export const ApiKeyNameInput = ({
apiKeyName,
apiKeyId,
disabled,
onNameUpdate,
}: ApiKeyNameInputProps) => {
const { updateOneRecord: updateApiKey } = useUpdateOneRecord<ApiKey>({
objectNameSingular: CoreObjectNameSingular.ApiKey,
});
// TODO: Enhance this with react-web-hook-form (https://www.react-hook-form.com)
// eslint-disable-next-line react-hooks/exhaustive-deps
const debouncedUpdate = useCallback(
useDebouncedCallback(async (name: string) => {
if (isDefined(onNameUpdate)) {
onNameUpdate(apiKeyName);
}
if (!apiKeyName) {
return;
}
await updateApiKey({
idToUpdate: apiKeyId,
updateOneRecordInput: { name },
});
}, 500),
[updateApiKey, onNameUpdate],
);
useEffect(() => {
debouncedUpdate(apiKeyName);
return debouncedUpdate.cancel;
}, [debouncedUpdate, apiKeyName]);
return (
<StyledComboInputContainer>
<TextInput
placeholder="E.g. backoffice integration"
onChange={onNameUpdate}
fullWidth
value={apiKeyName}
disabled={disabled}
/>
</StyledComboInputContainer>
);
};

View File

@ -1,27 +0,0 @@
import { act, renderHook } from '@testing-library/react';
import { RecoilRoot, RecoilState } from 'recoil';
import { generatedApiKeyFamilyState } from '@/settings/developers/states/generatedApiKeyFamilyState';
import { useGeneratedApiKeys } from '../useGeneratedApiKeys';
describe('useGeneratedApiKeys', () => {
test('should set generatedApiKeyFamilyState correctly', () => {
const { result } = renderHook(() => useGeneratedApiKeys(), {
wrapper: RecoilRoot,
});
const apiKeyId = 'someId';
const apiKey = 'someKey';
act(() => {
result.current(apiKeyId, apiKey);
});
const recoilState: RecoilState<string | null | undefined> =
generatedApiKeyFamilyState(apiKeyId);
const stateValue = recoilState.key;
expect(stateValue).toContain(apiKeyId);
});
});

View File

@ -1,13 +0,0 @@
import { useRecoilCallback } from 'recoil';
import { generatedApiKeyFamilyState } from '@/settings/developers/states/generatedApiKeyFamilyState';
export const useGeneratedApiKeys = () => {
return useRecoilCallback(
({ set }) =>
(apiKeyId: string, apiKey: string | null) => {
set(generatedApiKeyFamilyState(apiKeyId), apiKey);
},
[],
);
};

View File

@ -1,9 +0,0 @@
import { createFamilyState } from '@/ui/utilities/state/utils/createFamilyState';
export const generatedApiKeyFamilyState = createFamilyState<
string | null | undefined,
string
>({
key: 'generatedApiKeyFamilyState',
defaultValue: null,
});

View File

@ -0,0 +1,6 @@
import { createState } from 'twenty-ui';
export const apiKeyTokenState = createState<string | null>({
key: 'apiKeyTokenState',
defaultValue: null,
});