mirror of
https://github.com/lingble/twenty.git
synced 2025-11-02 05:37:56 +00:00
Feat/metadata datatable types (#2175)
* Handled new url v2 type * Fixed refetch queries * wip * Ok delete but views bug * Fix lint --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@@ -28,7 +28,7 @@ import { SettingsWorkspaceMembers } from '~/pages/settings/SettingsWorkspaceMemb
|
||||
import { Tasks } from '~/pages/tasks/Tasks';
|
||||
import { getPageTitleFromPath } from '~/utils/title-utils';
|
||||
|
||||
import { ObjectTablePage } from './pages/companies/ObjectsTable';
|
||||
import { ObjectTablePage } from './modules/metadata/components/ObjectTablePage';
|
||||
import { SettingsObjectNewFieldStep1 } from './pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep1';
|
||||
import { SettingsObjectNewFieldStep2 } from './pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2';
|
||||
import { SettingsApis } from './pages/settings/SettingsApis';
|
||||
|
||||
@@ -19,6 +19,7 @@ import MainNavbar from '@/ui/navigation/navbar/components/MainNavbar';
|
||||
import NavItem from '@/ui/navigation/navbar/components/NavItem';
|
||||
import NavTitle from '@/ui/navigation/navbar/components/NavTitle';
|
||||
|
||||
import { useGetClientConfigQuery } from './generated/graphql';
|
||||
import { measureTotalFrameLoad } from './utils/measureTotalFrameLoad';
|
||||
|
||||
export const AppNavbar = () => {
|
||||
@@ -30,6 +31,10 @@ export const AppNavbar = () => {
|
||||
const isInSubMenu = useIsSubMenuNavbarDisplayed();
|
||||
const { currentUserDueTaskCount } = useCurrentUserTaskCount();
|
||||
|
||||
const { data } = useGetClientConfigQuery();
|
||||
|
||||
const isFlexibleBackendEnabled = data?.clientConfig?.flexibleBackendEnabled;
|
||||
|
||||
return (
|
||||
<>
|
||||
{!isInSubMenu ? (
|
||||
@@ -90,7 +95,7 @@ export const AppNavbar = () => {
|
||||
Icon={IconTargetArrow}
|
||||
active={currentPath === '/opportunities'}
|
||||
/>
|
||||
<MetadataObjectNavItems />
|
||||
{isFlexibleBackendEnabled && <MetadataObjectNavItems />}
|
||||
</MainNavbar>
|
||||
) : (
|
||||
<SettingsNavbar />
|
||||
|
||||
@@ -13,10 +13,12 @@ import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/
|
||||
* Therefore it is highly recommended to use the babel or swc plugin for production.
|
||||
*/
|
||||
const documents = {
|
||||
"\n mutation CreateOneMetadataObject($input: CreateOneObjectInput!) {\n createOneObject(input: $input) {\n id\n }\n }\n": types.CreateOneMetadataObjectDocument,
|
||||
"\n mutation CreateOneMetadataObject($input: CreateOneObjectInput!) {\n createOneObject(input: $input) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n }\n }\n": types.CreateOneMetadataObjectDocument,
|
||||
"\n mutation CreateOneMetadataField($input: CreateOneFieldInput!) {\n createOneField(input: $input) {\n id\n type\n name\n label\n description\n icon\n placeholder\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n }\n }\n": types.CreateOneMetadataFieldDocument,
|
||||
"\n mutation UpdateOneMetadataField(\n $idToUpdate: ID!\n $updatePayload: UpdateFieldInput!\n ) {\n updateOneField(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n }\n }\n": types.UpdateOneMetadataFieldDocument,
|
||||
"\n mutation UpdateOneMetadataObject(\n $idToUpdate: ID!\n $updatePayload: UpdateObjectInput!\n ) {\n updateOneObject(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n }\n }\n": types.UpdateOneMetadataObjectDocument,
|
||||
"\n mutation UpdateOneMetadataField(\n $idToUpdate: ID!\n $updatePayload: UpdateFieldInput!\n ) {\n updateOneField(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n type\n name\n label\n description\n icon\n placeholder\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n }\n }\n": types.UpdateOneMetadataFieldDocument,
|
||||
"\n mutation UpdateOneMetadataObject(\n $idToUpdate: ID!\n $updatePayload: UpdateObjectInput!\n ) {\n updateOneObject(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n }\n }\n": types.UpdateOneMetadataObjectDocument,
|
||||
"\n mutation DeleteOneMetadataObject($idToDelete: ID!) {\n deleteOneObject(input: { id: $idToDelete }) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n }\n }\n": types.DeleteOneMetadataObjectDocument,
|
||||
"\n mutation DeleteOneMetadataField($idToDelete: ID!) {\n deleteOneField(input: { id: $idToDelete }) {\n id\n type\n name\n label\n description\n icon\n placeholder\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n }\n }\n": types.DeleteOneMetadataFieldDocument,
|
||||
"\n query MetadataObjects {\n objects {\n edges {\n node {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n fields {\n edges {\n node {\n id\n type\n name\n label\n description\n icon\n placeholder\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n totalCount\n }\n }\n }\n pageInfo {\n hasNextPage\n hasPreviousPage\n startCursor\n endCursor\n }\n totalCount\n }\n }\n": types.MetadataObjectsDocument,
|
||||
};
|
||||
|
||||
@@ -37,7 +39,7 @@ export function graphql(source: string): unknown;
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n mutation CreateOneMetadataObject($input: CreateOneObjectInput!) {\n createOneObject(input: $input) {\n id\n }\n }\n"): (typeof documents)["\n mutation CreateOneMetadataObject($input: CreateOneObjectInput!) {\n createOneObject(input: $input) {\n id\n }\n }\n"];
|
||||
export function graphql(source: "\n mutation CreateOneMetadataObject($input: CreateOneObjectInput!) {\n createOneObject(input: $input) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n }\n }\n"): (typeof documents)["\n mutation CreateOneMetadataObject($input: CreateOneObjectInput!) {\n createOneObject(input: $input) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -45,11 +47,19 @@ export function graphql(source: "\n mutation CreateOneMetadataField($input: Cre
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n mutation UpdateOneMetadataField(\n $idToUpdate: ID!\n $updatePayload: UpdateFieldInput!\n ) {\n updateOneField(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n }\n }\n"): (typeof documents)["\n mutation UpdateOneMetadataField(\n $idToUpdate: ID!\n $updatePayload: UpdateFieldInput!\n ) {\n updateOneField(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n }\n }\n"];
|
||||
export function graphql(source: "\n mutation UpdateOneMetadataField(\n $idToUpdate: ID!\n $updatePayload: UpdateFieldInput!\n ) {\n updateOneField(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n type\n name\n label\n description\n icon\n placeholder\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n }\n }\n"): (typeof documents)["\n mutation UpdateOneMetadataField(\n $idToUpdate: ID!\n $updatePayload: UpdateFieldInput!\n ) {\n updateOneField(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n type\n name\n label\n description\n icon\n placeholder\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n mutation UpdateOneMetadataObject(\n $idToUpdate: ID!\n $updatePayload: UpdateObjectInput!\n ) {\n updateOneObject(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n }\n }\n"): (typeof documents)["\n mutation UpdateOneMetadataObject(\n $idToUpdate: ID!\n $updatePayload: UpdateObjectInput!\n ) {\n updateOneObject(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n }\n }\n"];
|
||||
export function graphql(source: "\n mutation UpdateOneMetadataObject(\n $idToUpdate: ID!\n $updatePayload: UpdateObjectInput!\n ) {\n updateOneObject(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n }\n }\n"): (typeof documents)["\n mutation UpdateOneMetadataObject(\n $idToUpdate: ID!\n $updatePayload: UpdateObjectInput!\n ) {\n updateOneObject(input: { id: $idToUpdate, update: $updatePayload }) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n mutation DeleteOneMetadataObject($idToDelete: ID!) {\n deleteOneObject(input: { id: $idToDelete }) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n }\n }\n"): (typeof documents)["\n mutation DeleteOneMetadataObject($idToDelete: ID!) {\n deleteOneObject(input: { id: $idToDelete }) {\n id\n dataSourceId\n nameSingular\n namePlural\n labelSingular\n labelPlural\n description\n icon\n isCustom\n isActive\n createdAt\n updatedAt\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n mutation DeleteOneMetadataField($idToDelete: ID!) {\n deleteOneField(input: { id: $idToDelete }) {\n id\n type\n name\n label\n description\n icon\n placeholder\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n }\n }\n"): (typeof documents)["\n mutation DeleteOneMetadataField($idToDelete: ID!) {\n deleteOneField(input: { id: $idToDelete }) {\n id\n type\n name\n label\n description\n icon\n placeholder\n isCustom\n isActive\n isNullable\n createdAt\n updatedAt\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
|
||||
@@ -635,18 +635,15 @@ export type UpdateFieldInput = {
|
||||
description?: InputMaybe<Scalars['String']['input']>;
|
||||
icon?: InputMaybe<Scalars['String']['input']>;
|
||||
isActive?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
label: Scalars['String']['input'];
|
||||
name: Scalars['String']['input'];
|
||||
label?: InputMaybe<Scalars['String']['input']>;
|
||||
};
|
||||
|
||||
export type UpdateObjectInput = {
|
||||
description?: InputMaybe<Scalars['String']['input']>;
|
||||
icon?: InputMaybe<Scalars['String']['input']>;
|
||||
isActive?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
labelPlural: Scalars['String']['input'];
|
||||
labelSingular: Scalars['String']['input'];
|
||||
namePlural: Scalars['String']['input'];
|
||||
nameSingular: Scalars['String']['input'];
|
||||
labelPlural?: InputMaybe<Scalars['String']['input']>;
|
||||
labelSingular?: InputMaybe<Scalars['String']['input']>;
|
||||
};
|
||||
|
||||
export type UpdateOneFieldInput = {
|
||||
@@ -868,7 +865,7 @@ export type CreateOneMetadataObjectMutationVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type CreateOneMetadataObjectMutation = { __typename?: 'Mutation', createOneObject: { __typename?: 'object', id: string } };
|
||||
export type CreateOneMetadataObjectMutation = { __typename?: 'Mutation', createOneObject: { __typename?: 'object', id: string, dataSourceId: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isActive: boolean, createdAt: any, updatedAt: any } };
|
||||
|
||||
export type CreateOneMetadataFieldMutationVariables = Exact<{
|
||||
input: CreateOneFieldInput;
|
||||
@@ -883,7 +880,7 @@ export type UpdateOneMetadataFieldMutationVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type UpdateOneMetadataFieldMutation = { __typename?: 'Mutation', updateOneField: { __typename?: 'field', id: string } };
|
||||
export type UpdateOneMetadataFieldMutation = { __typename?: 'Mutation', updateOneField: { __typename?: 'field', id: string, type: string, name: string, label: string, description?: string | null, icon?: string | null, placeholder?: string | null, isCustom: boolean, isActive: boolean, isNullable: boolean, createdAt: any, updatedAt: any } };
|
||||
|
||||
export type UpdateOneMetadataObjectMutationVariables = Exact<{
|
||||
idToUpdate: Scalars['ID']['input'];
|
||||
@@ -891,7 +888,21 @@ export type UpdateOneMetadataObjectMutationVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type UpdateOneMetadataObjectMutation = { __typename?: 'Mutation', updateOneObject: { __typename?: 'object', id: string } };
|
||||
export type UpdateOneMetadataObjectMutation = { __typename?: 'Mutation', updateOneObject: { __typename?: 'object', id: string, dataSourceId: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isActive: boolean, createdAt: any, updatedAt: any } };
|
||||
|
||||
export type DeleteOneMetadataObjectMutationVariables = Exact<{
|
||||
idToDelete: Scalars['ID']['input'];
|
||||
}>;
|
||||
|
||||
|
||||
export type DeleteOneMetadataObjectMutation = { __typename?: 'Mutation', deleteOneObject: { __typename?: 'ObjectDeleteResponse', id?: string | null, dataSourceId?: string | null, nameSingular?: string | null, namePlural?: string | null, labelSingular?: string | null, labelPlural?: string | null, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, createdAt?: any | null, updatedAt?: any | null } };
|
||||
|
||||
export type DeleteOneMetadataFieldMutationVariables = Exact<{
|
||||
idToDelete: Scalars['ID']['input'];
|
||||
}>;
|
||||
|
||||
|
||||
export type DeleteOneMetadataFieldMutation = { __typename?: 'Mutation', deleteOneField: { __typename?: 'FieldDeleteResponse', id?: string | null, type?: string | null, name?: string | null, label?: string | null, description?: string | null, icon?: string | null, placeholder?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isNullable?: boolean | null, createdAt?: any | null, updatedAt?: any | null } };
|
||||
|
||||
export type MetadataObjectsQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
@@ -899,8 +910,10 @@ export type MetadataObjectsQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
export type MetadataObjectsQuery = { __typename?: 'Query', objects: { __typename?: 'ObjectConnection', totalCount: number, edges: Array<{ __typename?: 'objectEdge', node: { __typename?: 'object', id: string, dataSourceId: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isActive: boolean, createdAt: any, updatedAt: any, fields: { __typename?: 'ObjectFieldsConnection', totalCount: number, edges: Array<{ __typename?: 'fieldEdge', node: { __typename?: 'field', id: string, type: string, name: string, label: string, description?: string | null, icon?: string | null, placeholder?: string | null, isCustom: boolean, isActive: boolean, isNullable: boolean, createdAt: any, updatedAt: any } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage?: boolean | null, hasPreviousPage?: boolean | null, startCursor?: any | null, endCursor?: any | null } } } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage?: boolean | null, hasPreviousPage?: boolean | null, startCursor?: any | null, endCursor?: any | null } } };
|
||||
|
||||
|
||||
export const CreateOneMetadataObjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOneMetadataObject"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateOneObjectInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOneObject"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode<CreateOneMetadataObjectMutation, CreateOneMetadataObjectMutationVariables>;
|
||||
export const CreateOneMetadataObjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOneMetadataObject"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateOneObjectInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOneObject"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"dataSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]} as unknown as DocumentNode<CreateOneMetadataObjectMutation, CreateOneMetadataObjectMutationVariables>;
|
||||
export const CreateOneMetadataFieldDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOneMetadataField"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateOneFieldInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOneField"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"placeholder"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isNullable"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]} as unknown as DocumentNode<CreateOneMetadataFieldMutation, CreateOneMetadataFieldMutationVariables>;
|
||||
export const UpdateOneMetadataFieldDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateOneMetadataField"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"idToUpdate"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"updatePayload"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateFieldInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateOneField"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"idToUpdate"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"update"},"value":{"kind":"Variable","name":{"kind":"Name","value":"updatePayload"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode<UpdateOneMetadataFieldMutation, UpdateOneMetadataFieldMutationVariables>;
|
||||
export const UpdateOneMetadataObjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateOneMetadataObject"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"idToUpdate"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"updatePayload"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateObjectInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateOneObject"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"idToUpdate"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"update"},"value":{"kind":"Variable","name":{"kind":"Name","value":"updatePayload"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode<UpdateOneMetadataObjectMutation, UpdateOneMetadataObjectMutationVariables>;
|
||||
export const UpdateOneMetadataFieldDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateOneMetadataField"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"idToUpdate"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"updatePayload"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateFieldInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateOneField"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"idToUpdate"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"update"},"value":{"kind":"Variable","name":{"kind":"Name","value":"updatePayload"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"placeholder"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isNullable"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]} as unknown as DocumentNode<UpdateOneMetadataFieldMutation, UpdateOneMetadataFieldMutationVariables>;
|
||||
export const UpdateOneMetadataObjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateOneMetadataObject"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"idToUpdate"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"updatePayload"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateObjectInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateOneObject"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"idToUpdate"}}},{"kind":"ObjectField","name":{"kind":"Name","value":"update"},"value":{"kind":"Variable","name":{"kind":"Name","value":"updatePayload"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"dataSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]} as unknown as DocumentNode<UpdateOneMetadataObjectMutation, UpdateOneMetadataObjectMutationVariables>;
|
||||
export const DeleteOneMetadataObjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteOneMetadataObject"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"idToDelete"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteOneObject"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"idToDelete"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"dataSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]} as unknown as DocumentNode<DeleteOneMetadataObjectMutation, DeleteOneMetadataObjectMutationVariables>;
|
||||
export const DeleteOneMetadataFieldDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteOneMetadataField"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"idToDelete"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteOneField"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"ObjectValue","fields":[{"kind":"ObjectField","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"idToDelete"}}}]}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"placeholder"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isNullable"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}}]} as unknown as DocumentNode<DeleteOneMetadataFieldMutation, DeleteOneMetadataFieldMutationVariables>;
|
||||
export const MetadataObjectsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"MetadataObjects"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"objects"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"dataSourceId"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"fields"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"edges"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"node"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"placeholder"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isNullable"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"pageInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}},{"kind":"Field","name":{"kind":"Name","value":"hasPreviousPage"}},{"kind":"Field","name":{"kind":"Name","value":"startCursor"}},{"kind":"Field","name":{"kind":"Name","value":"endCursor"}}]}},{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"pageInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"hasNextPage"}},{"kind":"Field","name":{"kind":"Name","value":"hasPreviousPage"}},{"kind":"Field","name":{"kind":"Name","value":"startCursor"}},{"kind":"Field","name":{"kind":"Name","value":"endCursor"}}]}},{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}}]}}]} as unknown as DocumentNode<MetadataObjectsQuery, MetadataObjectsQueryVariables>;
|
||||
@@ -17,7 +17,6 @@ import '@emotion/react';
|
||||
|
||||
import { PageChangeEffect } from './effect-components/PageChangeEffect';
|
||||
import { ApolloMetadataClientProvider } from './modules/metadata/components/ApolloMetadataClientProvider';
|
||||
import { FetchMetadataEffect } from './modules/metadata/components/FetchMetadataEffect';
|
||||
import { App } from './App';
|
||||
|
||||
import './index.css';
|
||||
@@ -36,7 +35,6 @@ root.render(
|
||||
<ClientConfigProvider>
|
||||
<UserProvider>
|
||||
<ApolloMetadataClientProvider>
|
||||
<FetchMetadataEffect />
|
||||
<PageChangeEffect />
|
||||
<AppThemeProvider>
|
||||
<SnackBarProvider>
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { isFlexibleBackendEnabledState } from '@/client-config/states/isFlexibleBackendEnabledState';
|
||||
import { MetadataObjectsQuery } from '~/generated-metadata/graphql';
|
||||
|
||||
import { FIND_MANY_METADATA_OBJECTS } from '../graphql/queries';
|
||||
import { useApolloMetadataClient } from '../hooks/useApolloMetadataClient';
|
||||
import { useCreateOneObject } from '../hooks/useCreateOneObject';
|
||||
import { useFindManyObjects } from '../hooks/useFindManyObjects';
|
||||
import { useSeedCustomObjectsTemp } from '../hooks/useSeedCustomObjectsTemp';
|
||||
import { metadataObjectsState } from '../states/metadataObjectsState';
|
||||
import { MetadataObject } from '../types/MetadataObject';
|
||||
|
||||
export const FetchMetadataEffect = () => {
|
||||
const [metadataObjects, setMetadataObjects] =
|
||||
useRecoilState(metadataObjectsState);
|
||||
const [isFlexibleBackendEnabled] = useRecoilState(
|
||||
isFlexibleBackendEnabledState,
|
||||
);
|
||||
const apolloMetadataClient = useApolloMetadataClient();
|
||||
|
||||
const seedCustomObjectsTemp = useSeedCustomObjectsTemp();
|
||||
|
||||
const { createOneObject } = useCreateOneObject({
|
||||
objectNamePlural: 'suppliers',
|
||||
});
|
||||
|
||||
const { objects: suppliers, loading } = useFindManyObjects({
|
||||
objectNamePlural: 'suppliers',
|
||||
});
|
||||
|
||||
const [created, setCreated] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (!created && !loading && suppliers.length === 0 && createOneObject) {
|
||||
createOneObject({
|
||||
name: 'Supplier 1',
|
||||
city: 'City 1',
|
||||
});
|
||||
|
||||
createOneObject({
|
||||
name: 'Supplier 2',
|
||||
city: 'City 2',
|
||||
});
|
||||
|
||||
createOneObject({
|
||||
name: 'Supplier 3',
|
||||
city: 'City 3',
|
||||
});
|
||||
|
||||
setCreated(true);
|
||||
}
|
||||
}, [suppliers, createOneObject, loading, created]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isFlexibleBackendEnabled) return;
|
||||
|
||||
(async () => {
|
||||
if (apolloMetadataClient && metadataObjects.length === 0) {
|
||||
const objects = await apolloMetadataClient.query<MetadataObjectsQuery>({
|
||||
query: FIND_MANY_METADATA_OBJECTS,
|
||||
});
|
||||
|
||||
if (
|
||||
objects.data.objects.edges.length > 0 &&
|
||||
metadataObjects.length === 0
|
||||
) {
|
||||
const formattedObjects: MetadataObject[] =
|
||||
objects.data.objects.edges.map((object) => ({
|
||||
...object.node,
|
||||
fields: object.node.fields.edges.map((field) => field.node),
|
||||
}));
|
||||
setMetadataObjects(formattedObjects);
|
||||
} else if (
|
||||
objects.data.objects.edges.length === 0 &&
|
||||
metadataObjects.length === 0
|
||||
) {
|
||||
try {
|
||||
await seedCustomObjectsTemp();
|
||||
|
||||
const objects =
|
||||
await apolloMetadataClient.query<MetadataObjectsQuery>({
|
||||
query: FIND_MANY_METADATA_OBJECTS,
|
||||
});
|
||||
|
||||
const formattedObjects: MetadataObject[] =
|
||||
objects.data.objects.edges.map((object) => ({
|
||||
...object.node,
|
||||
fields: object.node.fields.edges.map((field) => field.node),
|
||||
}));
|
||||
|
||||
setMetadataObjects(formattedObjects);
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
}, [
|
||||
isFlexibleBackendEnabled,
|
||||
metadataObjects,
|
||||
setMetadataObjects,
|
||||
apolloMetadataClient,
|
||||
seedCustomObjectsTemp,
|
||||
]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
@@ -1,29 +1,58 @@
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
|
||||
import { IconArchive } from '@/ui/display/icon';
|
||||
import { IconBuildingSkyscraper } from '@/ui/display/icon';
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { IconButton } from '@/ui/input/button/components/IconButton';
|
||||
import NavItem from '@/ui/navigation/navbar/components/NavItem';
|
||||
import { useGetClientConfigQuery } from '~/generated/graphql';
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
import { useCreateNewTempsCustomObject } from '../hooks/useCreateNewTempCustomObject';
|
||||
import { useDeleteOneMetadataObject } from '../hooks/useDeleteOneMetadataObject';
|
||||
import { useFindManyMetadataObjects } from '../hooks/useFindManyMetadataObjects';
|
||||
|
||||
export const MetadataObjectNavItems = () => {
|
||||
const { data } = useGetClientConfigQuery();
|
||||
|
||||
const { metadataObjects } = useFindManyMetadataObjects();
|
||||
|
||||
const isFlexibleBackendEnabled = data?.clientConfig?.flexibleBackendEnabled;
|
||||
// eslint-disable-next-line no-console
|
||||
console.log({
|
||||
metadataObjects,
|
||||
});
|
||||
|
||||
if (!isFlexibleBackendEnabled) return <></>;
|
||||
const createNewTempCustomObject = useCreateNewTempsCustomObject();
|
||||
|
||||
const { deleteOneMetadataObject } = useDeleteOneMetadataObject();
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<>
|
||||
{metadataObjects.map((metadataObject) => (
|
||||
<NavItem
|
||||
key={metadataObject.id}
|
||||
label={capitalize(metadataObject.namePlural)}
|
||||
to={`/objects/${metadataObject.namePlural}`}
|
||||
Icon={IconBuildingSkyscraper}
|
||||
/>
|
||||
))}
|
||||
<Button
|
||||
title="+ Create new object"
|
||||
variant="secondary"
|
||||
onClick={createNewTempCustomObject}
|
||||
/>
|
||||
{metadataObjects
|
||||
.filter((metadataObject) => !!metadataObject.isActive)
|
||||
.map((metadataObject) => (
|
||||
<div style={{ display: 'flex', flexDirection: 'row', width: '60%' }}>
|
||||
<IconButton
|
||||
Icon={IconArchive}
|
||||
onClick={() => {
|
||||
deleteOneMetadataObject(metadataObject.id);
|
||||
}}
|
||||
/>
|
||||
<NavItem
|
||||
key={metadataObject.id}
|
||||
label={capitalize(metadataObject.namePlural)}
|
||||
to={`/objects/${metadataObject.namePlural}`}
|
||||
Icon={IconBuildingSkyscraper}
|
||||
onClick={() => {
|
||||
navigate(`/objects/${metadataObject.namePlural}`);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -21,15 +21,17 @@ export const ObjectDataTableEffect = ({
|
||||
}: ObjectDataTableEffectProps) => {
|
||||
const setDataTableData = useSetObjectDataTableData();
|
||||
|
||||
const { objects } = useFindManyObjects({
|
||||
const { objects, loading } = useFindManyObjects({
|
||||
objectNamePlural,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const entities = objects ?? [];
|
||||
if (!loading) {
|
||||
const entities = objects ?? [];
|
||||
|
||||
setDataTableData(entities);
|
||||
}, [objects, setDataTableData]);
|
||||
setDataTableData(entities);
|
||||
}
|
||||
}, [objects, setDataTableData, loading]);
|
||||
|
||||
const [searchParams] = useSearchParams();
|
||||
const tableRecoilScopeId = useRecoilScopeId(TableRecoilScopeContext);
|
||||
@@ -61,8 +63,10 @@ export const ObjectDataTableEffect = ({
|
||||
const viewId = searchParams.get('view');
|
||||
if (viewId) {
|
||||
handleViewSelect(viewId);
|
||||
} else {
|
||||
handleViewSelect(objectNamePlural);
|
||||
}
|
||||
}, [handleViewSelect, searchParams]);
|
||||
}, [handleViewSelect, searchParams, objectNamePlural]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { suppliersAvailableColumnDefinitions } from '@/companies/constants/companiesAvailableColumnDefinitions';
|
||||
import { DataTable } from '@/ui/data/data-table/components/DataTable';
|
||||
import { TableContext } from '@/ui/data/data-table/contexts/TableContext';
|
||||
import { TableRecoilScopeContext } from '@/ui/data/data-table/states/recoil-scope-contexts/TableRecoilScopeContext';
|
||||
import { ViewBarContext } from '@/ui/data/view-bar/contexts/ViewBarContext';
|
||||
import { useTableViews } from '@/views/hooks/useTableViews';
|
||||
|
||||
import { useMetadataTableViews } from '../hooks/useMetadataTableViews';
|
||||
import { useUpdateOneObject } from '../hooks/useUpdateOneObject';
|
||||
import { MetadataObjectIdentifier } from '../types/MetadataObjectIdentifier';
|
||||
|
||||
@@ -14,10 +13,7 @@ export type ObjectTableProps = MetadataObjectIdentifier;
|
||||
|
||||
export const ObjectTable = ({ objectNamePlural }: ObjectTableProps) => {
|
||||
const { createView, deleteView, submitCurrentView, updateView } =
|
||||
useTableViews({
|
||||
objectId: 'company',
|
||||
columnDefinitions: suppliersAvailableColumnDefinitions,
|
||||
});
|
||||
useMetadataTableViews();
|
||||
|
||||
const { updateOneObject } = useUpdateOneObject({
|
||||
objectNamePlural,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { useEffect } from 'react';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { ObjectTable } from '@/metadata/components/ObjectTable';
|
||||
@@ -14,6 +15,10 @@ import { PageHeader } from '@/ui/layout/page/PageHeader';
|
||||
import { PageHotkeysEffect } from '@/ui/layout/page/PageHotkeysEffect';
|
||||
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
|
||||
|
||||
import { useCreateOneObject } from '../hooks/useCreateOneObject';
|
||||
import { useFindOneMetadataObject } from '../hooks/useFindOneMetadataObject';
|
||||
import { MetadataObjectScope } from '../scopes/MetadataObjectScope';
|
||||
|
||||
const StyledTableContainer = styled.div`
|
||||
display: flex;
|
||||
width: 100%;
|
||||
@@ -24,8 +29,26 @@ export type ObjectTablePageProps = MetadataObjectIdentifier;
|
||||
export const ObjectTablePage = () => {
|
||||
const objectNamePlural = useParams().objectNamePlural ?? '';
|
||||
|
||||
const { objectNotFoundInMetadata, loading } = useFindOneMetadataObject({
|
||||
objectNamePlural,
|
||||
});
|
||||
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
if (!loading && objectNotFoundInMetadata) {
|
||||
navigate('/');
|
||||
}
|
||||
}, [objectNotFoundInMetadata, loading, navigate]);
|
||||
|
||||
const { createOneObject } = useCreateOneObject({
|
||||
objectNamePlural,
|
||||
});
|
||||
|
||||
const handleAddButtonClick = async () => {
|
||||
//
|
||||
createOneObject?.({
|
||||
name: 'Test',
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -36,11 +59,13 @@ export const ObjectTablePage = () => {
|
||||
</PageHeader>
|
||||
<PageBody>
|
||||
<RecoilScope
|
||||
scopeId="objects"
|
||||
scopeId={objectNamePlural}
|
||||
CustomRecoilScopeContext={TableRecoilScopeContext}
|
||||
>
|
||||
<StyledTableContainer>
|
||||
<ObjectTable objectNamePlural={objectNamePlural} />
|
||||
<MetadataObjectScope metadataObjectNamePlural={objectNamePlural}>
|
||||
<ObjectTable objectNamePlural={objectNamePlural} />
|
||||
</MetadataObjectScope>
|
||||
</StyledTableContainer>
|
||||
<DataTableActionBar />
|
||||
<DataTableContextMenu />
|
||||
@@ -4,6 +4,17 @@ export const CREATE_ONE_METADATA_OBJECT = gql`
|
||||
mutation CreateOneMetadataObject($input: CreateOneObjectInput!) {
|
||||
createOneObject(input: $input) {
|
||||
id
|
||||
dataSourceId
|
||||
nameSingular
|
||||
namePlural
|
||||
labelSingular
|
||||
labelPlural
|
||||
description
|
||||
icon
|
||||
isCustom
|
||||
isActive
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -34,6 +45,17 @@ export const UPDATE_ONE_METADATA_FIELD = gql`
|
||||
) {
|
||||
updateOneField(input: { id: $idToUpdate, update: $updatePayload }) {
|
||||
id
|
||||
type
|
||||
name
|
||||
label
|
||||
description
|
||||
icon
|
||||
placeholder
|
||||
isCustom
|
||||
isActive
|
||||
isNullable
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -45,6 +67,55 @@ export const UPDATE_ONE_METADATA_OBJECT = gql`
|
||||
) {
|
||||
updateOneObject(input: { id: $idToUpdate, update: $updatePayload }) {
|
||||
id
|
||||
dataSourceId
|
||||
nameSingular
|
||||
namePlural
|
||||
labelSingular
|
||||
labelPlural
|
||||
description
|
||||
icon
|
||||
isCustom
|
||||
isActive
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const DELETE_ONE_METADATA_OBJECT = gql`
|
||||
mutation DeleteOneMetadataObject($idToDelete: ID!) {
|
||||
deleteOneObject(input: { id: $idToDelete }) {
|
||||
id
|
||||
dataSourceId
|
||||
nameSingular
|
||||
namePlural
|
||||
labelSingular
|
||||
labelPlural
|
||||
description
|
||||
icon
|
||||
isCustom
|
||||
isActive
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const DELETE_ONE_METADATA_FIELD = gql`
|
||||
mutation DeleteOneMetadataField($idToDelete: ID!) {
|
||||
deleteOneField(input: { id: $idToDelete }) {
|
||||
id
|
||||
type
|
||||
name
|
||||
label
|
||||
description
|
||||
icon
|
||||
placeholder
|
||||
isCustom
|
||||
isActive
|
||||
isNullable
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
160
front/src/modules/metadata/hooks/useCreateNewTempCustomObject.ts
Normal file
160
front/src/modules/metadata/hooks/useCreateNewTempCustomObject.ts
Normal file
@@ -0,0 +1,160 @@
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
|
||||
import { ColumnDefinition } from '@/ui/data/data-table/types/ColumnDefinition';
|
||||
import { FieldMetadata } from '@/ui/data/field/types/FieldMetadata';
|
||||
import { FieldType } from '@/ui/data/field/types/FieldType';
|
||||
import { IconBrandLinkedin } from '@/ui/display/icon';
|
||||
import { GET_VIEW_FIELDS } from '@/views/graphql/queries/getViewFields';
|
||||
import { GET_VIEWS } from '@/views/graphql/queries/getViews';
|
||||
import { toViewFieldInput } from '@/views/hooks/useTableViewFields';
|
||||
import {
|
||||
useCreateViewFieldsMutation,
|
||||
useCreateViewMutation,
|
||||
ViewType,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
import { useCreateOneMetadataField } from './useCreateOneMetadataField';
|
||||
import { useCreateOneMetadataObject } from './useCreateOneMetadataObject';
|
||||
import { useUpdateOneMetadataField } from './useUpdateOneMetadataField';
|
||||
import { useUpdateOneMetadataObject } from './useUpdateOneMetadataObject';
|
||||
|
||||
export const useCreateNewTempsCustomObject = () => {
|
||||
const { createOneMetadataObject } = useCreateOneMetadataObject();
|
||||
const { createOneMetadataField } = useCreateOneMetadataField();
|
||||
|
||||
const { updateOneMetadataObject } = useUpdateOneMetadataObject();
|
||||
const { updateOneMetadataField } = useUpdateOneMetadataField();
|
||||
|
||||
const [createViewMutation] = useCreateViewMutation();
|
||||
const [createViewFieldsMutation] = useCreateViewFieldsMutation();
|
||||
|
||||
return async () => {
|
||||
const date = new Date().toISOString().replace(/[\/:\.\-\_]/g, '');
|
||||
|
||||
const { data: createdMetadataObject } = await createOneMetadataObject({
|
||||
labelPlural: 'Suppliers' + date,
|
||||
labelSingular: 'Supplier' + date,
|
||||
nameSingular: 'supplier' + date,
|
||||
namePlural: 'suppliers' + date,
|
||||
description: 'Suppliers' + date,
|
||||
icon: 'IconBuilding',
|
||||
});
|
||||
|
||||
const supplierObjectId = createdMetadataObject?.createOneObject?.id ?? '';
|
||||
|
||||
if (!createdMetadataObject) {
|
||||
throw new Error('Could not create metadata object');
|
||||
}
|
||||
|
||||
await updateOneMetadataObject({
|
||||
idToUpdate: supplierObjectId,
|
||||
updatePayload: {
|
||||
isActive: true,
|
||||
},
|
||||
});
|
||||
|
||||
const { data: nameFieldData } = await createOneMetadataField({
|
||||
objectId: supplierObjectId,
|
||||
name: 'name',
|
||||
type: 'text',
|
||||
description: 'Name',
|
||||
label: 'Name',
|
||||
icon: 'IconBuilding',
|
||||
});
|
||||
|
||||
if (!nameFieldData || !nameFieldData.createOneField.name) {
|
||||
throw new Error('Could not create metadata field');
|
||||
}
|
||||
|
||||
await updateOneMetadataField({
|
||||
fieldIdToUpdate: nameFieldData?.createOneField?.id ?? '',
|
||||
updatePayload: {
|
||||
isActive: true,
|
||||
},
|
||||
});
|
||||
|
||||
const { data: cityFieldData } = await createOneMetadataField({
|
||||
objectId: supplierObjectId,
|
||||
label: 'City',
|
||||
name: 'city',
|
||||
type: 'text',
|
||||
description: 'City',
|
||||
icon: 'IconMap',
|
||||
});
|
||||
|
||||
if (!cityFieldData || !cityFieldData.createOneField.name) {
|
||||
throw new Error('Could not create metadata field');
|
||||
}
|
||||
|
||||
await updateOneMetadataField({
|
||||
fieldIdToUpdate: cityFieldData?.createOneField?.id ?? '',
|
||||
updatePayload: {
|
||||
isActive: true,
|
||||
},
|
||||
});
|
||||
|
||||
const { data: emailFieldData } = await createOneMetadataField({
|
||||
objectId: supplierObjectId,
|
||||
label: 'Email',
|
||||
name: 'email',
|
||||
type: 'url',
|
||||
description: 'Email',
|
||||
icon: 'IconMap',
|
||||
});
|
||||
|
||||
if (!emailFieldData || !emailFieldData.createOneField.name) {
|
||||
throw new Error('Could not create metadata field');
|
||||
}
|
||||
|
||||
await updateOneMetadataField({
|
||||
fieldIdToUpdate: emailFieldData?.createOneField?.id ?? '',
|
||||
updatePayload: {
|
||||
isActive: true,
|
||||
},
|
||||
});
|
||||
|
||||
const objectId = 'suppliers' + date;
|
||||
|
||||
const { data: newView } = await createViewMutation({
|
||||
variables: {
|
||||
data: {
|
||||
name: 'Default',
|
||||
objectId: objectId,
|
||||
type: ViewType.Table,
|
||||
},
|
||||
},
|
||||
refetchQueries: [getOperationName(GET_VIEWS) ?? ''],
|
||||
});
|
||||
|
||||
const createdFields = [
|
||||
emailFieldData.createOneField,
|
||||
nameFieldData.createOneField,
|
||||
cityFieldData.createOneField,
|
||||
];
|
||||
|
||||
const tempColumnDefinitions: ColumnDefinition<FieldMetadata>[] =
|
||||
createdFields.map((field, index) => ({
|
||||
index,
|
||||
key: field.name,
|
||||
name: field.label,
|
||||
size: 100,
|
||||
type: field.type as FieldType,
|
||||
metadata: {
|
||||
fieldName: field.name,
|
||||
placeHolder: field.label,
|
||||
},
|
||||
Icon: IconBrandLinkedin,
|
||||
isVisible: true,
|
||||
})) ?? [];
|
||||
|
||||
await createViewFieldsMutation({
|
||||
variables: {
|
||||
data: tempColumnDefinitions.map((column) => ({
|
||||
...toViewFieldInput(objectId, column),
|
||||
viewId: newView?.view.id ?? '',
|
||||
})),
|
||||
},
|
||||
refetchQueries: [getOperationName(GET_VIEW_FIELDS) ?? ''],
|
||||
});
|
||||
};
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ApolloClient, useMutation } from '@apollo/client';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
|
||||
import { FieldType } from '@/ui/data/field/types/FieldType';
|
||||
import {
|
||||
CreateOneMetadataFieldMutation,
|
||||
CreateOneMetadataFieldMutationVariables,
|
||||
@@ -11,6 +12,11 @@ import { FIND_MANY_METADATA_OBJECTS } from '../graphql/queries';
|
||||
|
||||
import { useApolloMetadataClient } from './useApolloMetadataClient';
|
||||
|
||||
type CreateOneMetadataFieldArgs =
|
||||
CreateOneMetadataFieldMutationVariables['input']['field'] & {
|
||||
type: FieldType;
|
||||
};
|
||||
|
||||
export const useCreateOneMetadataField = () => {
|
||||
const apolloMetadataClient = useApolloMetadataClient();
|
||||
|
||||
@@ -21,10 +27,8 @@ export const useCreateOneMetadataField = () => {
|
||||
client: apolloMetadataClient ?? ({} as ApolloClient<any>),
|
||||
});
|
||||
|
||||
const createOneMetadataField = (
|
||||
input: CreateOneMetadataFieldMutationVariables['input']['field'],
|
||||
) =>
|
||||
mutate({
|
||||
const createOneMetadataField = async (input: CreateOneMetadataFieldArgs) => {
|
||||
return await mutate({
|
||||
variables: {
|
||||
input: {
|
||||
field: {
|
||||
@@ -32,8 +36,10 @@ export const useCreateOneMetadataField = () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
awaitRefetchQueries: true,
|
||||
refetchQueries: [getOperationName(FIND_MANY_METADATA_OBJECTS) ?? ''],
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
createOneMetadataField,
|
||||
|
||||
@@ -21,10 +21,10 @@ export const useCreateOneMetadataObject = () => {
|
||||
client: apolloMetadataClient ?? ({} as ApolloClient<any>),
|
||||
});
|
||||
|
||||
const createOneMetadataObject = (
|
||||
const createOneMetadataObject = async (
|
||||
input: CreateOneMetadataObjectMutationVariables['input']['object'],
|
||||
) =>
|
||||
mutate({
|
||||
) => {
|
||||
return await mutate({
|
||||
variables: {
|
||||
input: {
|
||||
object: {
|
||||
@@ -32,8 +32,10 @@ export const useCreateOneMetadataObject = () => {
|
||||
},
|
||||
},
|
||||
},
|
||||
awaitRefetchQueries: true,
|
||||
refetchQueries: [getOperationName(FIND_MANY_METADATA_OBJECTS) ?? ''],
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
createOneMetadataObject,
|
||||
|
||||
@@ -1,30 +1,24 @@
|
||||
import { gql, useMutation } from '@apollo/client';
|
||||
import { useMutation } from '@apollo/client';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
|
||||
import { MetadataObjectIdentifier } from '../types/MetadataObjectIdentifier';
|
||||
import { generateCreateOneObjectMutation } from '../utils/generateCreateOneObjectMutation';
|
||||
|
||||
import { useFindOneMetadataObject } from './useFindOneMetadataObject';
|
||||
|
||||
export const useCreateOneObject = ({
|
||||
objectNamePlural,
|
||||
}: MetadataObjectIdentifier) => {
|
||||
const { foundMetadataObject, objectNotFoundInMetadata } =
|
||||
useFindOneMetadataObject({
|
||||
objectNamePlural,
|
||||
});
|
||||
|
||||
const generatedMutation = foundMetadataObject
|
||||
? generateCreateOneObjectMutation({
|
||||
metadataObject: foundMetadataObject,
|
||||
})
|
||||
: gql`
|
||||
mutation EmptyMutation {
|
||||
empty
|
||||
}
|
||||
`;
|
||||
const {
|
||||
foundMetadataObject,
|
||||
objectNotFoundInMetadata,
|
||||
findManyQuery,
|
||||
createOneMutation,
|
||||
} = useFindOneMetadataObject({
|
||||
objectNamePlural,
|
||||
});
|
||||
|
||||
// TODO: type this with a minimal type at least with Record<string, any>
|
||||
const [mutate] = useMutation(generatedMutation);
|
||||
const [mutate] = useMutation(createOneMutation);
|
||||
|
||||
const createOneObject = foundMetadataObject
|
||||
? (input: Record<string, any>) => {
|
||||
@@ -34,6 +28,7 @@ export const useCreateOneObject = ({
|
||||
...input,
|
||||
},
|
||||
},
|
||||
refetchQueries: [getOperationName(findManyQuery) ?? ''],
|
||||
});
|
||||
}
|
||||
: undefined;
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import { ApolloClient, useMutation } from '@apollo/client';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
|
||||
import {
|
||||
DeleteOneMetadataFieldMutation,
|
||||
DeleteOneMetadataFieldMutationVariables,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
import { DELETE_ONE_METADATA_FIELD } from '../graphql/mutations';
|
||||
import { FIND_MANY_METADATA_OBJECTS } from '../graphql/queries';
|
||||
|
||||
import { useApolloMetadataClient } from './useApolloMetadataClient';
|
||||
|
||||
export const useDeleteOneMetadataField = () => {
|
||||
const apolloMetadataClient = useApolloMetadataClient();
|
||||
|
||||
const [mutate] = useMutation<
|
||||
DeleteOneMetadataFieldMutation,
|
||||
DeleteOneMetadataFieldMutationVariables
|
||||
>(DELETE_ONE_METADATA_FIELD, {
|
||||
client: apolloMetadataClient ?? ({} as ApolloClient<any>),
|
||||
});
|
||||
|
||||
const deleteOneMetadataField = async (
|
||||
idToDelete: DeleteOneMetadataFieldMutationVariables['idToDelete'],
|
||||
) => {
|
||||
return await mutate({
|
||||
variables: {
|
||||
idToDelete,
|
||||
},
|
||||
awaitRefetchQueries: true,
|
||||
refetchQueries: [getOperationName(FIND_MANY_METADATA_OBJECTS) ?? ''],
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
deleteOneMetadataField,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
import { ApolloClient, useMutation } from '@apollo/client';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
|
||||
import {
|
||||
DeleteOneMetadataObjectMutation,
|
||||
DeleteOneMetadataObjectMutationVariables,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
import { DELETE_ONE_METADATA_OBJECT } from '../graphql/mutations';
|
||||
import { FIND_MANY_METADATA_OBJECTS } from '../graphql/queries';
|
||||
|
||||
import { useApolloMetadataClient } from './useApolloMetadataClient';
|
||||
|
||||
export const useDeleteOneMetadataObject = () => {
|
||||
const apolloMetadataClient = useApolloMetadataClient();
|
||||
|
||||
const [mutate] = useMutation<
|
||||
DeleteOneMetadataObjectMutation,
|
||||
DeleteOneMetadataObjectMutationVariables
|
||||
>(DELETE_ONE_METADATA_OBJECT, {
|
||||
client: apolloMetadataClient ?? ({} as ApolloClient<any>),
|
||||
});
|
||||
|
||||
const deleteOneMetadataObject = async (
|
||||
idToDelete: DeleteOneMetadataObjectMutationVariables['idToDelete'],
|
||||
) => {
|
||||
return await mutate({
|
||||
variables: {
|
||||
idToDelete,
|
||||
},
|
||||
awaitRefetchQueries: true,
|
||||
refetchQueries: [getOperationName(FIND_MANY_METADATA_OBJECTS) ?? ''],
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
deleteOneMetadataObject,
|
||||
};
|
||||
};
|
||||
40
front/src/modules/metadata/hooks/useDeleteOneObject.ts
Normal file
40
front/src/modules/metadata/hooks/useDeleteOneObject.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { useMutation } from '@apollo/client';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
|
||||
import { MetadataObjectIdentifier } from '../types/MetadataObjectIdentifier';
|
||||
|
||||
import { useFindOneMetadataObject } from './useFindOneMetadataObject';
|
||||
|
||||
export const useDeleteOneObject = ({
|
||||
objectNamePlural,
|
||||
}: MetadataObjectIdentifier) => {
|
||||
const {
|
||||
foundMetadataObject,
|
||||
objectNotFoundInMetadata,
|
||||
findManyQuery,
|
||||
deleteOneMutation,
|
||||
} = useFindOneMetadataObject({
|
||||
objectNamePlural,
|
||||
});
|
||||
|
||||
// TODO: type this with a minimal type at least with Record<string, any>
|
||||
const [mutate] = useMutation(deleteOneMutation);
|
||||
|
||||
const deleteOneObject = foundMetadataObject
|
||||
? (input: Record<string, any>) => {
|
||||
return mutate({
|
||||
variables: {
|
||||
input: {
|
||||
...input,
|
||||
},
|
||||
},
|
||||
refetchQueries: [getOperationName(findManyQuery) ?? ''],
|
||||
});
|
||||
}
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
deleteOneObject,
|
||||
objectNotFoundInMetadata,
|
||||
};
|
||||
};
|
||||
@@ -15,13 +15,17 @@ import { useApolloMetadataClient } from './useApolloMetadataClient';
|
||||
export const useFindManyMetadataObjects = () => {
|
||||
const apolloMetadataClient = useApolloMetadataClient();
|
||||
|
||||
const { data, fetchMore: fetchMoreInternal } = useQuery<
|
||||
MetadataObjectsQuery,
|
||||
MetadataObjectsQueryVariables
|
||||
>(FIND_MANY_METADATA_OBJECTS, {
|
||||
client: apolloMetadataClient ?? undefined,
|
||||
skip: !apolloMetadataClient,
|
||||
});
|
||||
const {
|
||||
data,
|
||||
fetchMore: fetchMoreInternal,
|
||||
loading,
|
||||
} = useQuery<MetadataObjectsQuery, MetadataObjectsQueryVariables>(
|
||||
FIND_MANY_METADATA_OBJECTS,
|
||||
{
|
||||
client: apolloMetadataClient ?? undefined,
|
||||
skip: !apolloMetadataClient,
|
||||
},
|
||||
);
|
||||
|
||||
const hasMore = data?.objects?.pageInfo?.hasNextPage;
|
||||
|
||||
@@ -38,23 +42,10 @@ export const useFindManyMetadataObjects = () => {
|
||||
});
|
||||
}, [data]);
|
||||
|
||||
const getMetadataObjectsFromCache = () => {
|
||||
const queryResult = apolloMetadataClient?.readQuery<
|
||||
MetadataObjectsQuery,
|
||||
MetadataObjectsQueryVariables
|
||||
>({
|
||||
query: FIND_MANY_METADATA_OBJECTS,
|
||||
});
|
||||
|
||||
return formatPagedMetadataObjectsToMetadataObjects({
|
||||
pagedMetadataObjects: queryResult ?? undefined,
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
metadataObjects,
|
||||
hasMore,
|
||||
fetchMore,
|
||||
getMetadataObjectsFromCache,
|
||||
loading,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { useMemo } from 'react';
|
||||
import { gql, useQuery } from '@apollo/client';
|
||||
import { useQuery } from '@apollo/client';
|
||||
|
||||
import { MetadataObjectIdentifier } from '../types/MetadataObjectIdentifier';
|
||||
import { PaginatedObjectType } from '../types/PaginatedObjectType';
|
||||
import { formatPagedObjectsToObjects } from '../utils/formatPagedObjectsToObjects';
|
||||
import { generateFindManyCustomObjectsQuery } from '../utils/generateFindManyCustomObjectsQuery';
|
||||
|
||||
import { useFindOneMetadataObject } from './useFindOneMetadataObject';
|
||||
|
||||
@@ -15,23 +14,13 @@ export const useFindManyObjects = <
|
||||
>({
|
||||
objectNamePlural,
|
||||
}: MetadataObjectIdentifier) => {
|
||||
const { foundMetadataObject, objectNotFoundInMetadata } =
|
||||
const { foundMetadataObject, objectNotFoundInMetadata, findManyQuery } =
|
||||
useFindOneMetadataObject({
|
||||
objectNamePlural,
|
||||
});
|
||||
|
||||
const generatedQuery = foundMetadataObject
|
||||
? generateFindManyCustomObjectsQuery({
|
||||
metadataObject: foundMetadataObject,
|
||||
})
|
||||
: gql`
|
||||
query EmptyQuery {
|
||||
empty
|
||||
}
|
||||
`;
|
||||
|
||||
const { data, loading, error } = useQuery<PaginatedObjectType<ObjectType>>(
|
||||
generatedQuery,
|
||||
findManyQuery,
|
||||
{
|
||||
skip: !foundMetadataObject,
|
||||
},
|
||||
|
||||
@@ -1,21 +1,80 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
import { ColumnDefinition } from '@/ui/data/data-table/types/ColumnDefinition';
|
||||
import { FieldMetadata } from '@/ui/data/field/types/FieldMetadata';
|
||||
|
||||
import { MetadataObjectIdentifier } from '../types/MetadataObjectIdentifier';
|
||||
import { formatMetadataFieldAsColumnDefinition } from '../utils/formatMetadataFieldAsColumnDefinition';
|
||||
import { generateCreateOneObjectMutation } from '../utils/generateCreateOneObjectMutation';
|
||||
import { generateFindManyCustomObjectsQuery } from '../utils/generateFindManyCustomObjectsQuery';
|
||||
|
||||
import { useFindManyMetadataObjects } from './useFindManyMetadataObjects';
|
||||
|
||||
export const useFindOneMetadataObject = ({
|
||||
objectNamePlural,
|
||||
}: MetadataObjectIdentifier) => {
|
||||
const { metadataObjects } = useFindManyMetadataObjects();
|
||||
const { metadataObjects, loading } = useFindManyMetadataObjects();
|
||||
|
||||
const foundMetadataObject = metadataObjects.find(
|
||||
(object) => object.namePlural === objectNamePlural,
|
||||
);
|
||||
|
||||
const objectNotFoundInMetadata =
|
||||
metadataObjects.length > 0 && !foundMetadataObject;
|
||||
metadataObjects.length === 0 ||
|
||||
(metadataObjects.length > 0 && !foundMetadataObject);
|
||||
|
||||
const columnDefinitions: ColumnDefinition<FieldMetadata>[] =
|
||||
foundMetadataObject?.fields.map((field, index) =>
|
||||
formatMetadataFieldAsColumnDefinition({
|
||||
index,
|
||||
field,
|
||||
}),
|
||||
) ?? [];
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log({
|
||||
foundMetadataObject,
|
||||
columnDefinitions,
|
||||
});
|
||||
|
||||
const findManyQuery = foundMetadataObject
|
||||
? generateFindManyCustomObjectsQuery({
|
||||
metadataObject: foundMetadataObject,
|
||||
})
|
||||
: gql`
|
||||
query EmptyQuery {
|
||||
empty
|
||||
}
|
||||
`;
|
||||
|
||||
const createOneMutation = foundMetadataObject
|
||||
? generateCreateOneObjectMutation({
|
||||
metadataObject: foundMetadataObject,
|
||||
})
|
||||
: gql`
|
||||
mutation EmptyMutation {
|
||||
empty
|
||||
}
|
||||
`;
|
||||
|
||||
// TODO: implement backend delete
|
||||
const deleteOneMutation = foundMetadataObject
|
||||
? generateCreateOneObjectMutation({
|
||||
metadataObject: foundMetadataObject,
|
||||
})
|
||||
: gql`
|
||||
mutation EmptyMutation {
|
||||
empty
|
||||
}
|
||||
`;
|
||||
|
||||
return {
|
||||
foundMetadataObject,
|
||||
objectNotFoundInMetadata,
|
||||
columnDefinitions,
|
||||
findManyQuery,
|
||||
createOneMutation,
|
||||
deleteOneMutation,
|
||||
loading,
|
||||
};
|
||||
};
|
||||
|
||||
18
front/src/modules/metadata/hooks/useMetadataObject.ts
Normal file
18
front/src/modules/metadata/hooks/useMetadataObject.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||
|
||||
import { MetadataObjectScopeInternalContext } from '../scopes/scope-internal-context/MetadataObjectScopeInternalContext';
|
||||
|
||||
type UseMetadataObjectProps = {
|
||||
metadataObjectNamePlural?: string;
|
||||
};
|
||||
|
||||
export const useMetadataObject = (props?: UseMetadataObjectProps) => {
|
||||
const scopeId = useAvailableScopeIdOrThrow(
|
||||
MetadataObjectScopeInternalContext,
|
||||
props?.metadataObjectNamePlural,
|
||||
);
|
||||
|
||||
return {
|
||||
scopeId,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
import { useContext } from 'react';
|
||||
|
||||
import { MetadataObjectScopeInternalContext } from '../scopes/scope-internal-context/MetadataObjectScopeInternalContext';
|
||||
|
||||
import { useFindOneMetadataObject } from './useFindOneMetadataObject';
|
||||
|
||||
export const useMetadataObjectInContext = () => {
|
||||
const context = useContext(MetadataObjectScopeInternalContext);
|
||||
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
'Could not find MetadataObjectScopeInternalContext while in useMetadataObjectInContext',
|
||||
);
|
||||
}
|
||||
|
||||
const { foundMetadataObject, loading, columnDefinitions } =
|
||||
useFindOneMetadataObject({
|
||||
objectNamePlural: context.objectNamePlural,
|
||||
});
|
||||
|
||||
return {
|
||||
...context,
|
||||
foundMetadataObject,
|
||||
loading,
|
||||
columnDefinitions,
|
||||
};
|
||||
};
|
||||
81
front/src/modules/metadata/hooks/useMetadataTableViews.ts
Normal file
81
front/src/modules/metadata/hooks/useMetadataTableViews.ts
Normal file
@@ -0,0 +1,81 @@
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
|
||||
import { TableRecoilScopeContext } from '@/ui/data/data-table/states/recoil-scope-contexts/TableRecoilScopeContext';
|
||||
import { tableColumnsScopedState } from '@/ui/data/data-table/states/tableColumnsScopedState';
|
||||
import { filtersScopedState } from '@/ui/data/view-bar/states/filtersScopedState';
|
||||
import { sortsScopedState } from '@/ui/data/view-bar/states/sortsScopedState';
|
||||
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
|
||||
import { useTableViewFields } from '@/views/hooks/useTableViewFields';
|
||||
import { useViewFilters } from '@/views/hooks/useViewFilters';
|
||||
import { useViews } from '@/views/hooks/useViews';
|
||||
import { useViewSorts } from '@/views/hooks/useViewSorts';
|
||||
import { ViewType } from '~/generated/graphql';
|
||||
|
||||
import { useMetadataObjectInContext } from './useMetadataObjectInContext';
|
||||
|
||||
export const useMetadataTableViews = () => {
|
||||
const { objectNamePlural, columnDefinitions } = useMetadataObjectInContext();
|
||||
|
||||
const tableColumns = useRecoilScopedValue(
|
||||
tableColumnsScopedState,
|
||||
TableRecoilScopeContext,
|
||||
);
|
||||
const filters = useRecoilScopedValue(
|
||||
filtersScopedState,
|
||||
TableRecoilScopeContext,
|
||||
);
|
||||
const sorts = useRecoilScopedValue(sortsScopedState, TableRecoilScopeContext);
|
||||
|
||||
const [_, setSearchParams] = useSearchParams();
|
||||
|
||||
const handleViewCreate = async (viewId: string) => {
|
||||
await createViewFields(tableColumns, viewId);
|
||||
await createViewFilters(filters, viewId);
|
||||
await createViewSorts(sorts, viewId);
|
||||
setSearchParams({ view: viewId });
|
||||
};
|
||||
|
||||
const objectId = objectNamePlural;
|
||||
|
||||
const { createView, deleteView, isFetchingViews, updateView } = useViews({
|
||||
objectId,
|
||||
onViewCreate: handleViewCreate,
|
||||
type: ViewType.Table,
|
||||
RecoilScopeContext: TableRecoilScopeContext,
|
||||
});
|
||||
|
||||
const { createViewFields, persistColumns } = useTableViewFields({
|
||||
objectId,
|
||||
columnDefinitions,
|
||||
skipFetch: isFetchingViews,
|
||||
});
|
||||
|
||||
const createDefaultViewFields = async () => {
|
||||
await createViewFields(tableColumns);
|
||||
};
|
||||
|
||||
const { createViewFilters, persistFilters } = useViewFilters({
|
||||
RecoilScopeContext: TableRecoilScopeContext,
|
||||
skipFetch: isFetchingViews,
|
||||
});
|
||||
|
||||
const { createViewSorts, persistSorts } = useViewSorts({
|
||||
RecoilScopeContext: TableRecoilScopeContext,
|
||||
skipFetch: isFetchingViews,
|
||||
});
|
||||
|
||||
const submitCurrentView = async () => {
|
||||
await persistFilters();
|
||||
await persistSorts();
|
||||
};
|
||||
|
||||
return {
|
||||
createView,
|
||||
deleteView,
|
||||
persistColumns,
|
||||
submitCurrentView,
|
||||
updateView,
|
||||
createDefaultViewFields,
|
||||
isFetchingViews,
|
||||
};
|
||||
};
|
||||
@@ -2,16 +2,11 @@ import { isNonEmptyArray } from '~/utils/isNonEmptyArray';
|
||||
|
||||
import { useCreateOneMetadataField } from './useCreateOneMetadataField';
|
||||
import { useCreateOneMetadataObject } from './useCreateOneMetadataObject';
|
||||
import { useUpdateOneMetadataField } from './useUpdateOneMetadataField';
|
||||
import { useUpdateOneMetadataObject } from './useUpdateOneMetadataObject';
|
||||
|
||||
export const useSeedCustomObjectsTemp = () => {
|
||||
const { createOneMetadataObject } = useCreateOneMetadataObject();
|
||||
const { createOneMetadataField } = useCreateOneMetadataField();
|
||||
|
||||
const { updateOneMetadataObject } = useUpdateOneMetadataObject();
|
||||
const { updateOneMetadataField } = useUpdateOneMetadataField();
|
||||
|
||||
return async () => {
|
||||
const { data: createdMetadataObject, errors } =
|
||||
await createOneMetadataObject({
|
||||
@@ -26,7 +21,7 @@ export const useSeedCustomObjectsTemp = () => {
|
||||
if (!isNonEmptyArray(errors)) {
|
||||
const supplierObjectId = createdMetadataObject?.createOneObject?.id ?? '';
|
||||
|
||||
const { data: createNameFieldData } = await createOneMetadataField({
|
||||
await createOneMetadataField({
|
||||
objectId: supplierObjectId,
|
||||
name: 'name',
|
||||
type: 'text',
|
||||
@@ -35,9 +30,7 @@ export const useSeedCustomObjectsTemp = () => {
|
||||
icon: 'IconBuilding',
|
||||
});
|
||||
|
||||
const nameFieldId = createNameFieldData?.createOneField.id ?? '';
|
||||
|
||||
const { data: createCityFieldData } = await createOneMetadataField({
|
||||
await createOneMetadataField({
|
||||
objectId: supplierObjectId,
|
||||
label: 'City',
|
||||
name: 'city',
|
||||
@@ -45,31 +38,6 @@ export const useSeedCustomObjectsTemp = () => {
|
||||
description: 'City',
|
||||
icon: 'IconMap',
|
||||
});
|
||||
|
||||
const cityFieldId = createCityFieldData?.createOneField.id ?? '';
|
||||
|
||||
await updateOneMetadataObject({
|
||||
idToUpdate: supplierObjectId,
|
||||
updatePayload: {
|
||||
labelPlural: 'Suppliers 2',
|
||||
},
|
||||
});
|
||||
|
||||
await updateOneMetadataField({
|
||||
objectIdToUpdate: supplierObjectId,
|
||||
fieldIdToUpdate: cityFieldId,
|
||||
updatePayload: {
|
||||
label: 'City 2',
|
||||
},
|
||||
});
|
||||
|
||||
await updateOneMetadataField({
|
||||
objectIdToUpdate: supplierObjectId,
|
||||
fieldIdToUpdate: nameFieldId,
|
||||
updatePayload: {
|
||||
label: 'Name 2',
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -10,13 +10,10 @@ import { UPDATE_ONE_METADATA_FIELD } from '../graphql/mutations';
|
||||
import { FIND_MANY_METADATA_OBJECTS } from '../graphql/queries';
|
||||
|
||||
import { useApolloMetadataClient } from './useApolloMetadataClient';
|
||||
import { useFindManyMetadataObjects } from './useFindManyMetadataObjects';
|
||||
|
||||
export const useUpdateOneMetadataField = () => {
|
||||
const apolloMetadataClient = useApolloMetadataClient();
|
||||
|
||||
const { getMetadataObjectsFromCache } = useFindManyMetadataObjects();
|
||||
|
||||
const [mutate] = useMutation<
|
||||
UpdateOneMetadataFieldMutation,
|
||||
UpdateOneMetadataFieldMutationVariables
|
||||
@@ -24,48 +21,24 @@ export const useUpdateOneMetadataField = () => {
|
||||
client: apolloMetadataClient ?? undefined,
|
||||
});
|
||||
|
||||
const updateOneMetadataField = ({
|
||||
objectIdToUpdate,
|
||||
const updateOneMetadataField = async ({
|
||||
fieldIdToUpdate,
|
||||
updatePayload,
|
||||
}: {
|
||||
objectIdToUpdate: string;
|
||||
fieldIdToUpdate: UpdateOneMetadataFieldMutationVariables['idToUpdate'];
|
||||
updatePayload: Partial<
|
||||
Pick<
|
||||
UpdateOneMetadataFieldMutationVariables['updatePayload'],
|
||||
'description' | 'icon' | 'isActive' | 'label'
|
||||
>
|
||||
updatePayload: Pick<
|
||||
UpdateOneMetadataFieldMutationVariables['updatePayload'],
|
||||
'description' | 'icon' | 'isActive' | 'label'
|
||||
>;
|
||||
}) => {
|
||||
const metadataObjects = getMetadataObjectsFromCache();
|
||||
|
||||
const foundMetadataObject = metadataObjects.find(
|
||||
(metadataObject) => metadataObject.id === objectIdToUpdate,
|
||||
);
|
||||
|
||||
if (!foundMetadataObject)
|
||||
throw new Error(`Metadata object with id ${objectIdToUpdate} not found`);
|
||||
|
||||
const foundMetadataField = foundMetadataObject.fields.find(
|
||||
(metadataField) => metadataField.id === fieldIdToUpdate,
|
||||
);
|
||||
|
||||
if (!foundMetadataField)
|
||||
throw new Error(`Metadata field with id ${fieldIdToUpdate} not found`);
|
||||
|
||||
return mutate({
|
||||
return await mutate({
|
||||
variables: {
|
||||
idToUpdate: fieldIdToUpdate,
|
||||
updatePayload: {
|
||||
name: foundMetadataField.name,
|
||||
description: foundMetadataField.description,
|
||||
icon: foundMetadataField.icon,
|
||||
isActive: foundMetadataField.isActive,
|
||||
label: foundMetadataField.label,
|
||||
...updatePayload,
|
||||
label: updatePayload.label ?? undefined,
|
||||
},
|
||||
},
|
||||
awaitRefetchQueries: true,
|
||||
refetchQueries: [getOperationName(FIND_MANY_METADATA_OBJECTS) ?? ''],
|
||||
});
|
||||
};
|
||||
|
||||
@@ -10,14 +10,11 @@ import { UPDATE_ONE_METADATA_OBJECT } from '../graphql/mutations';
|
||||
import { FIND_MANY_METADATA_OBJECTS } from '../graphql/queries';
|
||||
|
||||
import { useApolloMetadataClient } from './useApolloMetadataClient';
|
||||
import { useFindManyMetadataObjects } from './useFindManyMetadataObjects';
|
||||
|
||||
// TODO: Slice the Apollo store synchronously in the update function instead of subscribing, so we can use update after read in the same function call
|
||||
export const useUpdateOneMetadataObject = () => {
|
||||
const apolloClientMetadata = useApolloMetadataClient();
|
||||
|
||||
const { getMetadataObjectsFromCache } = useFindManyMetadataObjects();
|
||||
|
||||
const [mutate] = useMutation<
|
||||
UpdateOneMetadataObjectMutation,
|
||||
UpdateOneMetadataObjectMutationVariables
|
||||
@@ -25,41 +22,22 @@ export const useUpdateOneMetadataObject = () => {
|
||||
client: apolloClientMetadata ?? undefined,
|
||||
});
|
||||
|
||||
const updateOneMetadataObject = ({
|
||||
const updateOneMetadataObject = async ({
|
||||
idToUpdate,
|
||||
updatePayload,
|
||||
}: {
|
||||
idToUpdate: UpdateOneMetadataObjectMutationVariables['idToUpdate'];
|
||||
updatePayload: Partial<
|
||||
Pick<
|
||||
UpdateOneMetadataObjectMutationVariables['updatePayload'],
|
||||
'description' | 'icon' | 'isActive' | 'labelPlural' | 'labelSingular'
|
||||
>
|
||||
updatePayload: Pick<
|
||||
UpdateOneMetadataObjectMutationVariables['updatePayload'],
|
||||
'description' | 'icon' | 'isActive' | 'labelPlural' | 'labelSingular'
|
||||
>;
|
||||
}) => {
|
||||
const metadataObjects = getMetadataObjectsFromCache();
|
||||
|
||||
const foundMetadataObject = metadataObjects.find(
|
||||
(metadataObject) => metadataObject.id === idToUpdate,
|
||||
);
|
||||
|
||||
if (!foundMetadataObject)
|
||||
throw new Error(`Metadata object with id ${idToUpdate} not found`);
|
||||
|
||||
return mutate({
|
||||
return await mutate({
|
||||
variables: {
|
||||
idToUpdate,
|
||||
updatePayload: {
|
||||
namePlural: foundMetadataObject.namePlural,
|
||||
nameSingular: foundMetadataObject.nameSingular,
|
||||
description: foundMetadataObject.description,
|
||||
icon: foundMetadataObject.icon,
|
||||
isActive: foundMetadataObject.isActive,
|
||||
labelPlural: foundMetadataObject.labelPlural,
|
||||
labelSingular: foundMetadataObject.labelSingular,
|
||||
...updatePayload,
|
||||
},
|
||||
updatePayload,
|
||||
},
|
||||
awaitRefetchQueries: true,
|
||||
refetchQueries: [getOperationName(FIND_MANY_METADATA_OBJECTS) ?? ''],
|
||||
});
|
||||
};
|
||||
|
||||
24
front/src/modules/metadata/scopes/MetadataObjectScope.tsx
Normal file
24
front/src/modules/metadata/scopes/MetadataObjectScope.tsx
Normal file
@@ -0,0 +1,24 @@
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
import { MetadataObjectScopeInternalContext } from './scope-internal-context/MetadataObjectScopeInternalContext';
|
||||
|
||||
type MetadataObjectScopeProps = {
|
||||
children: ReactNode;
|
||||
metadataObjectNamePlural: string;
|
||||
};
|
||||
|
||||
export const MetadataObjectScope = ({
|
||||
children,
|
||||
metadataObjectNamePlural,
|
||||
}: MetadataObjectScopeProps) => {
|
||||
return (
|
||||
<MetadataObjectScopeInternalContext.Provider
|
||||
value={{
|
||||
scopeId: metadataObjectNamePlural,
|
||||
objectNamePlural: metadataObjectNamePlural,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</MetadataObjectScopeInternalContext.Provider>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
import { ScopedStateKey } from '@/ui/utilities/recoil-scope/scopes-internal/types/ScopedStateKey';
|
||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
||||
|
||||
type MetadataObjectScopeInternalContextProps = ScopedStateKey & {
|
||||
objectNamePlural: string;
|
||||
};
|
||||
|
||||
export const MetadataObjectScopeInternalContext =
|
||||
createScopeInternalContext<MetadataObjectScopeInternalContextProps>();
|
||||
@@ -2,6 +2,9 @@ import { atom } from 'recoil';
|
||||
|
||||
import { MetadataObject } from '../types/MetadataObject';
|
||||
|
||||
/**
|
||||
* @deprecated Use `useFindManyMetadataObjects` instead.
|
||||
*/
|
||||
export const metadataObjectsState = atom<MetadataObject[]>({
|
||||
key: 'metadataObjectsState',
|
||||
default: [],
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import { ColumnDefinition } from '@/ui/data/data-table/types/ColumnDefinition';
|
||||
import { FieldMetadata } from '@/ui/data/field/types/FieldMetadata';
|
||||
import { FieldType } from '@/ui/data/field/types/FieldType';
|
||||
import { IconBrandLinkedin } from '@/ui/display/icon';
|
||||
|
||||
import { MetadataObject } from '../types/MetadataObject';
|
||||
|
||||
const parseFieldType = (fieldType: string): FieldType => {
|
||||
if (fieldType === 'url') {
|
||||
return 'urlV2';
|
||||
}
|
||||
|
||||
return fieldType as FieldType;
|
||||
};
|
||||
|
||||
export const formatMetadataFieldAsColumnDefinition = ({
|
||||
index,
|
||||
field,
|
||||
}: {
|
||||
index: number;
|
||||
field: MetadataObject['fields'][0];
|
||||
}): ColumnDefinition<FieldMetadata> => ({
|
||||
index,
|
||||
key: field.name,
|
||||
name: field.label,
|
||||
size: 100,
|
||||
type: parseFieldType(field.type),
|
||||
metadata: {
|
||||
fieldName: field.name,
|
||||
placeHolder: field.label,
|
||||
},
|
||||
Icon: IconBrandLinkedin,
|
||||
isVisible: true,
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
import { capitalize } from '~/utils/string/capitalize';
|
||||
|
||||
import { MetadataObject } from '../types/MetadataObject';
|
||||
|
||||
// TODO: implement
|
||||
export const generateDeleteOneObjectMutation = ({
|
||||
metadataObject,
|
||||
}: {
|
||||
metadataObject: MetadataObject;
|
||||
}) => {
|
||||
const capitalizedObjectName = capitalize(metadataObject.nameSingular);
|
||||
|
||||
return gql`
|
||||
mutation DeleteOne${capitalizedObjectName}($input: ${capitalizedObjectName}DeleteInput!) {
|
||||
createOne${capitalizedObjectName}(data: $input) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
};
|
||||
@@ -1,5 +1,7 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
import { FieldType } from '@/ui/data/field/types/FieldType';
|
||||
|
||||
import { MetadataObject } from '../types/MetadataObject';
|
||||
|
||||
export const generateFindManyCustomObjectsQuery = ({
|
||||
@@ -15,7 +17,24 @@ export const generateFindManyCustomObjectsQuery = ({
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
${metadataObject.fields.map((field) => field.name).join('\n')}
|
||||
${metadataObject.fields
|
||||
.map((field) => {
|
||||
// TODO: parse
|
||||
const fieldType = field.type as FieldType;
|
||||
|
||||
if (fieldType === 'text') {
|
||||
return field.name;
|
||||
} else if (fieldType === 'url') {
|
||||
return `
|
||||
${field.name}
|
||||
{
|
||||
text
|
||||
link
|
||||
}
|
||||
`;
|
||||
}
|
||||
})
|
||||
.join('\n')}
|
||||
}
|
||||
cursor
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import { PhoneFieldDisplay } from '../meta-types/display/components/PhoneFieldDi
|
||||
import { RelationFieldDisplay } from '../meta-types/display/components/RelationFieldDisplay';
|
||||
import { TextFieldDisplay } from '../meta-types/display/components/TextFieldDisplay';
|
||||
import { URLFieldDisplay } from '../meta-types/display/components/URLFieldDisplay';
|
||||
import { URLV2FieldDisplay } from '../meta-types/display/components/URLV2FieldDisplay';
|
||||
import { isFieldChip } from '../types/guards/isFieldChip';
|
||||
import { isFieldDate } from '../types/guards/isFieldDate';
|
||||
import { isFieldDoubleText } from '../types/guards/isFieldDoubleText';
|
||||
@@ -23,6 +24,7 @@ import { isFieldPhone } from '../types/guards/isFieldPhone';
|
||||
import { isFieldRelation } from '../types/guards/isFieldRelation';
|
||||
import { isFieldText } from '../types/guards/isFieldText';
|
||||
import { isFieldURL } from '../types/guards/isFieldURL';
|
||||
import { isFieldURLV2 } from '../types/guards/isFieldURLV2';
|
||||
|
||||
export const FieldDisplay = () => {
|
||||
const { fieldDefinition } = useContext(FieldContext);
|
||||
@@ -43,6 +45,8 @@ export const FieldDisplay = () => {
|
||||
<MoneyFieldDisplay />
|
||||
) : isFieldURL(fieldDefinition) ? (
|
||||
<URLFieldDisplay />
|
||||
) : isFieldURLV2(fieldDefinition) ? (
|
||||
<URLV2FieldDisplay />
|
||||
) : isFieldPhone(fieldDefinition) ? (
|
||||
<PhoneFieldDisplay />
|
||||
) : isFieldChip(fieldDefinition) ? (
|
||||
|
||||
@@ -16,6 +16,7 @@ import { ProbabilityFieldInput } from '../meta-types/input/components/Probabilit
|
||||
import { RelationFieldInput } from '../meta-types/input/components/RelationFieldInput';
|
||||
import { TextFieldInput } from '../meta-types/input/components/TextFieldInput';
|
||||
import { URLFieldInput } from '../meta-types/input/components/URLFieldInput';
|
||||
import { URLV2FieldInput } from '../meta-types/input/components/URLV2FieldInput';
|
||||
import { FieldInputEvent } from '../types/FieldInputEvent';
|
||||
import { isFieldBoolean } from '../types/guards/isFieldBoolean';
|
||||
import { isFieldChip } from '../types/guards/isFieldChip';
|
||||
@@ -30,6 +31,7 @@ import { isFieldProbability } from '../types/guards/isFieldProbability';
|
||||
import { isFieldRelation } from '../types/guards/isFieldRelation';
|
||||
import { isFieldText } from '../types/guards/isFieldText';
|
||||
import { isFieldURL } from '../types/guards/isFieldURL';
|
||||
import { isFieldURLV2 } from '../types/guards/isFieldURLV2';
|
||||
|
||||
type FieldInputProps = {
|
||||
onSubmit?: FieldInputEvent;
|
||||
@@ -98,6 +100,14 @@ export const FieldInput = ({
|
||||
onTab={onTab}
|
||||
onShiftTab={onShiftTab}
|
||||
/>
|
||||
) : isFieldURLV2(fieldDefinition) ? (
|
||||
<URLV2FieldInput
|
||||
onEnter={onEnter}
|
||||
onEscape={onEscape}
|
||||
onClickOutside={onClickOutside}
|
||||
onTab={onTab}
|
||||
onShiftTab={onShiftTab}
|
||||
/>
|
||||
) : isFieldPhone(fieldDefinition) ? (
|
||||
<PhoneFieldInput
|
||||
onEnter={onEnter}
|
||||
|
||||
@@ -28,6 +28,8 @@ import { isFieldRelationValue } from '../types/guards/isFieldRelationValue';
|
||||
import { isFieldText } from '../types/guards/isFieldText';
|
||||
import { isFieldTextValue } from '../types/guards/isFieldTextValue';
|
||||
import { isFieldURL } from '../types/guards/isFieldURL';
|
||||
import { isFieldURLV2 } from '../types/guards/isFieldURLV2';
|
||||
import { isFieldURLV2Value } from '../types/guards/isFieldURLV2Value';
|
||||
import { isFieldURLValue } from '../types/guards/isFieldURLValue';
|
||||
|
||||
export const usePersistField = () => {
|
||||
@@ -66,6 +68,9 @@ export const usePersistField = () => {
|
||||
const fieldIsURL =
|
||||
isFieldURL(fieldDefinition) && isFieldURLValue(valueToPersist);
|
||||
|
||||
const fieldIsURLV2 =
|
||||
isFieldURLV2(fieldDefinition) && isFieldURLV2Value(valueToPersist);
|
||||
|
||||
const fieldIsBoolean =
|
||||
isFieldBoolean(fieldDefinition) &&
|
||||
isFieldBooleanValue(valueToPersist);
|
||||
@@ -154,7 +159,8 @@ export const usePersistField = () => {
|
||||
fieldIsNumber ||
|
||||
fieldIsMoney ||
|
||||
fieldIsDate ||
|
||||
fieldIsPhone
|
||||
fieldIsPhone ||
|
||||
fieldIsURLV2
|
||||
) {
|
||||
const fieldName = fieldDefinition.metadata.fieldName;
|
||||
|
||||
@@ -173,7 +179,11 @@ export const usePersistField = () => {
|
||||
});
|
||||
} else {
|
||||
throw new Error(
|
||||
`Invalid value to persist: ${valueToPersist} for type : ${fieldDefinition.type}, type may not be implemented in usePersistField.`,
|
||||
`Invalid value to persist: ${JSON.stringify(
|
||||
valueToPersist,
|
||||
)} for type : ${
|
||||
fieldDefinition.type
|
||||
}, type may not be implemented in usePersistField.`,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { useURLV2Field } from '../../hooks/useURLV2Field';
|
||||
import { URLV2Display } from '../content-display/components/URLDisplayV2';
|
||||
|
||||
export const URLV2FieldDisplay = () => {
|
||||
const { fieldValue } = useURLV2Field();
|
||||
|
||||
return <URLV2Display value={fieldValue} />;
|
||||
};
|
||||
@@ -0,0 +1,73 @@
|
||||
import { MouseEvent } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { FieldURLV2Value } from '@/ui/data/field/types/FieldMetadata';
|
||||
import { RoundedLink } from '@/ui/navigation/link/components/RoundedLink';
|
||||
import {
|
||||
LinkType,
|
||||
SocialLink,
|
||||
} from '@/ui/navigation/link/components/SocialLink';
|
||||
|
||||
import { EllipsisDisplay } from './EllipsisDisplay';
|
||||
|
||||
const StyledRawLink = styled(RoundedLink)`
|
||||
overflow: hidden;
|
||||
|
||||
a {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
`;
|
||||
|
||||
type URLV2DisplayProps = {
|
||||
value?: FieldURLV2Value;
|
||||
};
|
||||
|
||||
const checkUrlType = (url: string) => {
|
||||
if (
|
||||
/^(http|https):\/\/(?:www\.)?linkedin.com(\w+:{0,1}\w*@)?(\S+)(:([0-9])+)?(\/|\/([\w#!:.?+=&%@!\-/]))?/.test(
|
||||
url,
|
||||
)
|
||||
) {
|
||||
return LinkType.LinkedIn;
|
||||
}
|
||||
if (url.match(/^((http|https):\/\/)?(?:www\.)?twitter\.com\/(\w+)?/i)) {
|
||||
return LinkType.Twitter;
|
||||
}
|
||||
|
||||
return LinkType.Url;
|
||||
};
|
||||
|
||||
export const URLV2Display = ({ value }: URLV2DisplayProps) => {
|
||||
const handleClick = (event: MouseEvent<HTMLElement>) => {
|
||||
event.stopPropagation();
|
||||
};
|
||||
|
||||
const absoluteUrl = value?.link
|
||||
? value.link.startsWith('http')
|
||||
? value.link
|
||||
: 'https://' + value.link
|
||||
: '';
|
||||
|
||||
const displayedValue = value?.text ?? '';
|
||||
|
||||
const type = checkUrlType(absoluteUrl);
|
||||
|
||||
if (type === LinkType.LinkedIn || type === LinkType.Twitter) {
|
||||
return (
|
||||
<EllipsisDisplay>
|
||||
<SocialLink href={absoluteUrl} onClick={handleClick} type={type}>
|
||||
{displayedValue}
|
||||
</SocialLink>
|
||||
</EllipsisDisplay>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<EllipsisDisplay>
|
||||
<StyledRawLink href={absoluteUrl} onClick={handleClick}>
|
||||
{displayedValue}
|
||||
</StyledRawLink>
|
||||
</EllipsisDisplay>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
import { useContext } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { FieldContext } from '../../contexts/FieldContext';
|
||||
import { usePersistField } from '../../hooks/usePersistField';
|
||||
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
|
||||
import { FieldURLV2Value } from '../../types/FieldMetadata';
|
||||
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
|
||||
import { isFieldURLV2 } from '../../types/guards/isFieldURLV2';
|
||||
import { isFieldURLV2Value } from '../../types/guards/isFieldURLV2Value';
|
||||
|
||||
export const useURLV2Field = () => {
|
||||
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
|
||||
|
||||
assertFieldMetadata('urlV2', isFieldURLV2, fieldDefinition);
|
||||
|
||||
const fieldName = fieldDefinition.metadata.fieldName;
|
||||
|
||||
const [fieldValue, setFieldValue] = useRecoilState<FieldURLV2Value>(
|
||||
entityFieldsFamilySelector({
|
||||
entityId: entityId,
|
||||
fieldName: fieldName,
|
||||
}),
|
||||
);
|
||||
|
||||
const persistField = usePersistField();
|
||||
|
||||
const persistURLField = (newValue: FieldURLV2Value) => {
|
||||
if (!isFieldURLV2Value(newValue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
persistField(newValue);
|
||||
};
|
||||
|
||||
return {
|
||||
fieldDefinition,
|
||||
fieldValue,
|
||||
setFieldValue,
|
||||
hotkeyScope,
|
||||
persistURLField,
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,89 @@
|
||||
import { FieldDoubleText } from '../../../types/FieldDoubleText';
|
||||
import { useURLV2Field } from '../../hooks/useURLV2Field';
|
||||
|
||||
import { DoubleTextInput } from './internal/DoubleTextInput';
|
||||
import { FieldInputOverlay } from './internal/FieldInputOverlay';
|
||||
import { FieldInputEvent } from './DateFieldInput';
|
||||
|
||||
export type URLV2FieldInputProps = {
|
||||
onClickOutside?: FieldInputEvent;
|
||||
onEnter?: FieldInputEvent;
|
||||
onEscape?: FieldInputEvent;
|
||||
onTab?: FieldInputEvent;
|
||||
onShiftTab?: FieldInputEvent;
|
||||
};
|
||||
|
||||
export const URLV2FieldInput = ({
|
||||
onEnter,
|
||||
onEscape,
|
||||
onClickOutside,
|
||||
onTab,
|
||||
onShiftTab,
|
||||
}: URLV2FieldInputProps) => {
|
||||
const { fieldValue, hotkeyScope, persistURLField } = useURLV2Field();
|
||||
|
||||
const handleEnter = (newURL: FieldDoubleText) => {
|
||||
onEnter?.(() =>
|
||||
persistURLField({
|
||||
link: newURL.firstValue,
|
||||
text: newURL.secondValue,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleEscape = (newURL: FieldDoubleText) => {
|
||||
onEscape?.(() =>
|
||||
persistURLField({
|
||||
link: newURL.firstValue,
|
||||
text: newURL.secondValue,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleClickOutside = (
|
||||
event: MouseEvent | TouchEvent,
|
||||
newURL: FieldDoubleText,
|
||||
) => {
|
||||
onClickOutside?.(() =>
|
||||
persistURLField({
|
||||
link: newURL.firstValue,
|
||||
text: newURL.secondValue,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleTab = (newURL: FieldDoubleText) => {
|
||||
onTab?.(() =>
|
||||
persistURLField({
|
||||
link: newURL.firstValue,
|
||||
text: newURL.secondValue,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
const handleShiftTab = (newURL: FieldDoubleText) => {
|
||||
onShiftTab?.(() =>
|
||||
persistURLField({
|
||||
link: newURL.firstValue,
|
||||
text: newURL.secondValue,
|
||||
}),
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<FieldInputOverlay>
|
||||
<DoubleTextInput
|
||||
firstValue={fieldValue.link}
|
||||
secondValue={fieldValue.text}
|
||||
firstValuePlaceholder={'Link'}
|
||||
secondValuePlaceholder={'Label'}
|
||||
hotkeyScope={hotkeyScope}
|
||||
onClickOutside={handleClickOutside}
|
||||
onEnter={handleEnter}
|
||||
onEscape={handleEscape}
|
||||
onTab={handleTab}
|
||||
onShiftTab={handleShiftTab}
|
||||
/>
|
||||
</FieldInputOverlay>
|
||||
);
|
||||
};
|
||||
@@ -16,6 +16,11 @@ export type FieldURLMetadata = {
|
||||
fieldName: string;
|
||||
};
|
||||
|
||||
export type FieldURLV2Metadata = {
|
||||
placeHolder: string;
|
||||
fieldName: string;
|
||||
};
|
||||
|
||||
export type FieldDateMetadata = {
|
||||
fieldName: string;
|
||||
};
|
||||
@@ -82,6 +87,7 @@ export type FieldMetadata =
|
||||
| FieldDoubleTextMetadata
|
||||
| FieldPhoneMetadata
|
||||
| FieldURLMetadata
|
||||
| FieldURLV2Metadata
|
||||
| FieldNumberMetadata
|
||||
| FieldMoneyMetadata
|
||||
| FieldEmailMetadata
|
||||
@@ -95,6 +101,7 @@ export type FieldChipValue = string;
|
||||
export type FieldDateValue = string | null;
|
||||
export type FieldPhoneValue = string;
|
||||
export type FieldURLValue = string;
|
||||
export type FieldURLV2Value = { link: string; text: string };
|
||||
export type FieldNumberValue = number | null;
|
||||
export type FieldMoneyValue = number | null;
|
||||
export type FieldEmailValue = string;
|
||||
|
||||
@@ -10,5 +10,6 @@ export type FieldType =
|
||||
| 'date'
|
||||
| 'phone'
|
||||
| 'url'
|
||||
| 'urlV2'
|
||||
| 'probability'
|
||||
| 'moneyAmount';
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
FieldRelationMetadata,
|
||||
FieldTextMetadata,
|
||||
FieldURLMetadata,
|
||||
FieldURLV2Metadata,
|
||||
} from '../FieldMetadata';
|
||||
import { FieldType } from '../FieldType';
|
||||
|
||||
@@ -41,6 +42,8 @@ type AssertFieldMetadataFunction = <
|
||||
? FieldPhoneMetadata
|
||||
: E extends 'url'
|
||||
? FieldURLMetadata
|
||||
: E extends 'urlV2'
|
||||
? FieldURLV2Metadata
|
||||
: E extends 'probability'
|
||||
? FieldProbabilityMetadata
|
||||
: E extends 'moneyAmount'
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import { FieldDefinition } from '../FieldDefinition';
|
||||
import { FieldMetadata, FieldURLV2Metadata } from '../FieldMetadata';
|
||||
|
||||
export const isFieldURLV2 = (
|
||||
field: FieldDefinition<FieldMetadata>,
|
||||
): field is FieldDefinition<FieldURLV2Metadata> => field.type === 'urlV2';
|
||||
@@ -0,0 +1,13 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { FieldURLV2Value } from '../FieldMetadata';
|
||||
|
||||
const urlV2Schema = z.object({
|
||||
link: z.string(),
|
||||
text: z.string(),
|
||||
});
|
||||
|
||||
// TODO: add yup
|
||||
export const isFieldURLV2Value = (
|
||||
fieldValue: unknown,
|
||||
): fieldValue is FieldURLV2Value => urlV2Schema.safeParse(fieldValue).success;
|
||||
@@ -23,8 +23,8 @@ import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
import { GET_VIEW_FIELDS } from '../graphql/queries/getViewFields';
|
||||
|
||||
const toViewFieldInput = (
|
||||
objectId: 'company' | 'person',
|
||||
export const toViewFieldInput = (
|
||||
objectId: string,
|
||||
fieldDefinition: ColumnDefinition<FieldMetadata>,
|
||||
) => ({
|
||||
key: fieldDefinition.key,
|
||||
@@ -40,7 +40,7 @@ export const useTableViewFields = ({
|
||||
columnDefinitions,
|
||||
skipFetch,
|
||||
}: {
|
||||
objectId: 'company' | 'person';
|
||||
objectId: string;
|
||||
columnDefinitions: ColumnDefinition<FieldMetadata>[];
|
||||
skipFetch?: boolean;
|
||||
}) => {
|
||||
@@ -110,7 +110,7 @@ export const useTableViewFields = ({
|
||||
);
|
||||
|
||||
useGetViewFieldsQuery({
|
||||
skip: !currentViewId || skipFetch,
|
||||
skip: !currentViewId || skipFetch || columnDefinitions.length === 0,
|
||||
variables: {
|
||||
orderBy: { index: SortOrder.Asc },
|
||||
where: {
|
||||
|
||||
@@ -18,7 +18,7 @@ export const useTableViews = ({
|
||||
objectId,
|
||||
columnDefinitions,
|
||||
}: {
|
||||
objectId: 'company' | 'person';
|
||||
objectId: string;
|
||||
columnDefinitions: ColumnDefinition<FieldMetadata>[];
|
||||
}) => {
|
||||
const tableColumns = useRecoilScopedValue(
|
||||
@@ -52,6 +52,10 @@ export const useTableViews = ({
|
||||
skipFetch: isFetchingViews,
|
||||
});
|
||||
|
||||
const createDefaultViewFields = async () => {
|
||||
await createViewFields(tableColumns);
|
||||
};
|
||||
|
||||
const { createViewFilters, persistFilters } = useViewFilters({
|
||||
RecoilScopeContext: TableRecoilScopeContext,
|
||||
skipFetch: isFetchingViews,
|
||||
@@ -73,5 +77,7 @@ export const useTableViews = ({
|
||||
persistColumns,
|
||||
submitCurrentView,
|
||||
updateView,
|
||||
createDefaultViewFields,
|
||||
isFetchingViews,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -22,7 +22,7 @@ export const useViews = ({
|
||||
RecoilScopeContext,
|
||||
type,
|
||||
}: {
|
||||
objectId: 'company' | 'person';
|
||||
objectId: string;
|
||||
onViewCreate?: (viewId: string) => Promise<void>;
|
||||
RecoilScopeContext: RecoilScopeContext;
|
||||
type: ViewType;
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
import { Field, InputType } from '@nestjs/graphql';
|
||||
|
||||
import { IsBoolean, IsNotEmpty, IsOptional, IsString } from 'class-validator';
|
||||
import { IsBoolean, IsOptional, IsString } from 'class-validator';
|
||||
|
||||
@InputType()
|
||||
export class UpdateFieldInput {
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Field()
|
||||
name: string;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@Field()
|
||||
label: string;
|
||||
@IsOptional()
|
||||
@Field({ nullable: true })
|
||||
label?: string;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
|
||||
@@ -6,23 +6,13 @@ import { IsBoolean, IsOptional, IsString } from 'class-validator';
|
||||
export class UpdateObjectInput {
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@Field()
|
||||
nameSingular: string;
|
||||
@Field({ nullable: true })
|
||||
labelSingular?: string;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@Field()
|
||||
namePlural: string;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@Field()
|
||||
labelSingular: string;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
@Field()
|
||||
labelPlural: string;
|
||||
@Field({ nullable: true })
|
||||
labelPlural?: string;
|
||||
|
||||
@IsString()
|
||||
@IsOptional()
|
||||
|
||||
Reference in New Issue
Block a user