Serverless function UI (#6388)
https://www.figma.com/design/xt8O9mFeLl46C5InWwoMrN/Twenty?node-id=36235-120877 Did not do the file manager part. A Function is defined using one unique file at the moment Feature protected by featureFlag `IS_FUNCTION_SETTINGS_ENABLED` ## Demo https://github.com/user-attachments/assets/0acb8291-47b4-4521-a6fa-a88b9198609b
This commit is contained in:
@ -0,0 +1,34 @@
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { useServerlessFunctionUpdateFormState } from '@/settings/serverless-functions/hooks/useServerlessFunctionUpdateFormState';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
jest.mock(
|
||||
'@/settings/serverless-functions/hooks/useGetOneServerlessFunction',
|
||||
() => ({
|
||||
useGetOneServerlessFunction: jest.fn(),
|
||||
}),
|
||||
);
|
||||
|
||||
describe('useServerlessFunctionUpdateFormState', () => {
|
||||
test('should return a form', () => {
|
||||
const serverlessFunctionId = 'serverlessFunctionId';
|
||||
const useGetOneServerlessFunctionMock = jest.requireMock(
|
||||
'@/settings/serverless-functions/hooks/useGetOneServerlessFunction',
|
||||
);
|
||||
useGetOneServerlessFunctionMock.useGetOneServerlessFunction.mockReturnValue(
|
||||
{
|
||||
serverlessFunction: { sourceCodeFullPath: undefined },
|
||||
},
|
||||
);
|
||||
const { result } = renderHook(
|
||||
() => useServerlessFunctionUpdateFormState(serverlessFunctionId),
|
||||
{
|
||||
wrapper: RecoilRoot,
|
||||
},
|
||||
);
|
||||
|
||||
const [formValues] = result.current;
|
||||
|
||||
expect(formValues).toEqual({ name: '', description: '', code: '' });
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,35 @@
|
||||
import { ApolloClient, useMutation } from '@apollo/client';
|
||||
|
||||
import { useApolloMetadataClient } from '@/object-metadata/hooks/useApolloMetadataClient';
|
||||
import {
|
||||
CreateServerlessFunctionInput,
|
||||
CreateOneServerlessFunctionItemMutation,
|
||||
CreateOneServerlessFunctionItemMutationVariables,
|
||||
} from '~/generated-metadata/graphql';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
import { FIND_MANY_SERVERLESS_FUNCTIONS } from '@/settings/serverless-functions/graphql/queries/findManyServerlessFunctions';
|
||||
import { CREATE_ONE_SERVERLESS_FUNCTION } from '@/settings/serverless-functions/graphql/mutations/createOneServerlessFunction';
|
||||
|
||||
export const useCreateOneServerlessFunction = () => {
|
||||
const apolloMetadataClient = useApolloMetadataClient();
|
||||
const [mutate] = useMutation<
|
||||
CreateOneServerlessFunctionItemMutation,
|
||||
CreateOneServerlessFunctionItemMutationVariables
|
||||
>(CREATE_ONE_SERVERLESS_FUNCTION, {
|
||||
client: apolloMetadataClient ?? ({} as ApolloClient<any>),
|
||||
});
|
||||
|
||||
const createOneServerlessFunction = async (
|
||||
input: CreateServerlessFunctionInput,
|
||||
) => {
|
||||
return await mutate({
|
||||
variables: {
|
||||
input,
|
||||
},
|
||||
awaitRefetchQueries: true,
|
||||
refetchQueries: [getOperationName(FIND_MANY_SERVERLESS_FUNCTIONS) ?? ''],
|
||||
});
|
||||
};
|
||||
|
||||
return { createOneServerlessFunction };
|
||||
};
|
||||
@ -0,0 +1,34 @@
|
||||
import { useApolloMetadataClient } from '@/object-metadata/hooks/useApolloMetadataClient';
|
||||
import { ApolloClient, useMutation } from '@apollo/client';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
import { FIND_MANY_SERVERLESS_FUNCTIONS } from '@/settings/serverless-functions/graphql/queries/findManyServerlessFunctions';
|
||||
import { DELETE_ONE_SERVERLESS_FUNCTION } from '@/settings/serverless-functions/graphql/mutations/deleteOneServerlessFunction';
|
||||
import {
|
||||
DeleteServerlessFunctionInput,
|
||||
DeleteOneServerlessFunctionMutation,
|
||||
DeleteOneServerlessFunctionMutationVariables,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const useDeleteOneServerlessFunction = () => {
|
||||
const apolloMetadataClient = useApolloMetadataClient();
|
||||
const [mutate] = useMutation<
|
||||
DeleteOneServerlessFunctionMutation,
|
||||
DeleteOneServerlessFunctionMutationVariables
|
||||
>(DELETE_ONE_SERVERLESS_FUNCTION, {
|
||||
client: apolloMetadataClient ?? ({} as ApolloClient<any>),
|
||||
});
|
||||
|
||||
const deleteOneServerlessFunction = async (
|
||||
input: DeleteServerlessFunctionInput,
|
||||
) => {
|
||||
return await mutate({
|
||||
variables: {
|
||||
input,
|
||||
},
|
||||
awaitRefetchQueries: true,
|
||||
refetchQueries: [getOperationName(FIND_MANY_SERVERLESS_FUNCTIONS) ?? ''],
|
||||
});
|
||||
};
|
||||
|
||||
return { deleteOneServerlessFunction };
|
||||
};
|
||||
@ -0,0 +1,30 @@
|
||||
import { useApolloMetadataClient } from '@/object-metadata/hooks/useApolloMetadataClient';
|
||||
import { ApolloClient, useMutation } from '@apollo/client';
|
||||
import { EXECUTE_ONE_SERVERLESS_FUNCTION } from '@/settings/serverless-functions/graphql/mutations/executeOneServerlessFunction';
|
||||
import {
|
||||
ExecuteOneServerlessFunctionMutation,
|
||||
ExecuteOneServerlessFunctionMutationVariables,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const useExecuteOneServerlessFunction = () => {
|
||||
const apolloMetadataClient = useApolloMetadataClient();
|
||||
const [mutate] = useMutation<
|
||||
ExecuteOneServerlessFunctionMutation,
|
||||
ExecuteOneServerlessFunctionMutationVariables
|
||||
>(EXECUTE_ONE_SERVERLESS_FUNCTION, {
|
||||
client: apolloMetadataClient ?? ({} as ApolloClient<any>),
|
||||
});
|
||||
|
||||
const executeOneServerlessFunction = async (
|
||||
id: string,
|
||||
payload: object = {},
|
||||
) => {
|
||||
return await mutate({
|
||||
variables: {
|
||||
id,
|
||||
payload,
|
||||
},
|
||||
});
|
||||
};
|
||||
return { executeOneServerlessFunction };
|
||||
};
|
||||
@ -0,0 +1,21 @@
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { FIND_MANY_SERVERLESS_FUNCTIONS } from '@/settings/serverless-functions/graphql/queries/findManyServerlessFunctions';
|
||||
import { useApolloMetadataClient } from '@/object-metadata/hooks/useApolloMetadataClient';
|
||||
import {
|
||||
GetManyServerlessFunctionsQuery,
|
||||
GetManyServerlessFunctionsQueryVariables,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const useGetManyServerlessFunctions = () => {
|
||||
const apolloMetadataClient = useApolloMetadataClient();
|
||||
const { data } = useQuery<
|
||||
GetManyServerlessFunctionsQuery,
|
||||
GetManyServerlessFunctionsQueryVariables
|
||||
>(FIND_MANY_SERVERLESS_FUNCTIONS, {
|
||||
client: apolloMetadataClient ?? undefined,
|
||||
});
|
||||
return {
|
||||
serverlessFunctions:
|
||||
data?.serverlessFunctions?.edges.map(({ node }) => node) || [],
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,23 @@
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { useApolloMetadataClient } from '@/object-metadata/hooks/useApolloMetadataClient';
|
||||
import { FIND_ONE_SERVERLESS_FUNCTION } from '@/settings/serverless-functions/graphql/queries/findOneServerlessFunction';
|
||||
import {
|
||||
GetOneServerlessFunctionQuery,
|
||||
GetOneServerlessFunctionQueryVariables,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const useGetOneServerlessFunction = (id: string) => {
|
||||
const apolloMetadataClient = useApolloMetadataClient();
|
||||
const { data } = useQuery<
|
||||
GetOneServerlessFunctionQuery,
|
||||
GetOneServerlessFunctionQueryVariables
|
||||
>(FIND_ONE_SERVERLESS_FUNCTION, {
|
||||
client: apolloMetadataClient ?? undefined,
|
||||
variables: {
|
||||
id,
|
||||
},
|
||||
});
|
||||
return {
|
||||
serverlessFunction: data?.serverlessFunction || null,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,57 @@
|
||||
import { Dispatch, SetStateAction, useEffect, useState } from 'react';
|
||||
import { getFileAbsoluteURI } from '~/utils/file/getFileAbsoluteURI';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
import { useGetOneServerlessFunction } from '@/settings/serverless-functions/hooks/useGetOneServerlessFunction';
|
||||
|
||||
export type ServerlessFunctionNewFormValues = {
|
||||
name: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
export type ServerlessFunctionFormValues = ServerlessFunctionNewFormValues & {
|
||||
code: string;
|
||||
};
|
||||
|
||||
type SetServerlessFunctionFormValues = Dispatch<
|
||||
SetStateAction<ServerlessFunctionFormValues>
|
||||
>;
|
||||
|
||||
export const useServerlessFunctionUpdateFormState = (
|
||||
serverlessFunctionId: string,
|
||||
): [ServerlessFunctionFormValues, SetServerlessFunctionFormValues] => {
|
||||
const [formValues, setFormValues] = useState<ServerlessFunctionFormValues>({
|
||||
name: '',
|
||||
description: '',
|
||||
code: '',
|
||||
});
|
||||
|
||||
const { serverlessFunction } =
|
||||
useGetOneServerlessFunction(serverlessFunctionId);
|
||||
|
||||
useEffect(() => {
|
||||
const getFileContent = async () => {
|
||||
const resp = await fetch(
|
||||
getFileAbsoluteURI(serverlessFunction?.sourceCodeFullPath),
|
||||
);
|
||||
if (resp.status !== 200) {
|
||||
throw new Error('Network response was not ok');
|
||||
} else {
|
||||
const result = await resp.text();
|
||||
const newState = {
|
||||
code: result,
|
||||
name: serverlessFunction?.name || '',
|
||||
description: serverlessFunction?.description || '',
|
||||
};
|
||||
setFormValues((prevState) => ({
|
||||
...prevState,
|
||||
...newState,
|
||||
}));
|
||||
}
|
||||
};
|
||||
if (isDefined(serverlessFunction?.sourceCodeFullPath)) {
|
||||
getFileContent();
|
||||
}
|
||||
}, [serverlessFunction, setFormValues]);
|
||||
|
||||
return [formValues, setFormValues];
|
||||
};
|
||||
@ -0,0 +1,34 @@
|
||||
import { ApolloClient, useMutation } from '@apollo/client';
|
||||
import { useApolloMetadataClient } from '@/object-metadata/hooks/useApolloMetadataClient';
|
||||
import { UPDATE_ONE_SERVERLESS_FUNCTION } from '@/settings/serverless-functions/graphql/mutations/updateOneServerlessFunction';
|
||||
import {
|
||||
UpdateServerlessFunctionInput,
|
||||
UpdateOneServerlessFunctionMutation,
|
||||
UpdateOneServerlessFunctionMutationVariables,
|
||||
} from '~/generated-metadata/graphql';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
import { FIND_MANY_SERVERLESS_FUNCTIONS } from '@/settings/serverless-functions/graphql/queries/findManyServerlessFunctions';
|
||||
|
||||
export const useUpdateOneServerlessFunction = () => {
|
||||
const apolloMetadataClient = useApolloMetadataClient();
|
||||
const [mutate] = useMutation<
|
||||
UpdateOneServerlessFunctionMutation,
|
||||
UpdateOneServerlessFunctionMutationVariables
|
||||
>(UPDATE_ONE_SERVERLESS_FUNCTION, {
|
||||
client: apolloMetadataClient ?? ({} as ApolloClient<any>),
|
||||
});
|
||||
|
||||
const updateOneServerlessFunction = async (
|
||||
input: UpdateServerlessFunctionInput,
|
||||
) => {
|
||||
return await mutate({
|
||||
variables: {
|
||||
input,
|
||||
},
|
||||
awaitRefetchQueries: true,
|
||||
refetchQueries: [getOperationName(FIND_MANY_SERVERLESS_FUNCTIONS) ?? ''],
|
||||
});
|
||||
};
|
||||
|
||||
return { updateOneServerlessFunction };
|
||||
};
|
||||
Reference in New Issue
Block a user