Sync metadata store after view child entity mutations server response (#23150)
## Summary - View persist hooks (`usePerformView(Sort|Field|Filter|Group|FieldGroup|FilterGroup|)APIPersist`) now write successful mutation results back to the metadata store (`addToDraft` / `updateInDraft` / `removeFromDraft` + `applyChanges`), following the existing pattern from `usePerformViewAPIUpdate`. - Previously the store only updated via SSE, so until that landed, save flows diffed against stale view data and re-sent creates with the same id — failing server-side with a duplicate key error. Fixes TWENTY-SERVER-HQM
This commit is contained in:
File diff suppressed because one or more lines are too long
-11
@@ -1,11 +0,0 @@
|
||||
import { VIEW_FIELD_GROUP_FRAGMENT } from '@/views/graphql/fragments/viewFieldGroupFragment';
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const CREATE_MANY_VIEW_FIELD_GROUPS = gql`
|
||||
${VIEW_FIELD_GROUP_FRAGMENT}
|
||||
mutation CreateManyViewFieldGroups($inputs: [CreateViewFieldGroupInput!]!) {
|
||||
createManyViewFieldGroups(inputs: $inputs) {
|
||||
...ViewFieldGroupFragment
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -1,11 +0,0 @@
|
||||
import { VIEW_FIELD_GROUP_FRAGMENT } from '@/views/graphql/fragments/viewFieldGroupFragment';
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const DELETE_VIEW_FIELD_GROUP = gql`
|
||||
${VIEW_FIELD_GROUP_FRAGMENT}
|
||||
mutation DeleteViewFieldGroup($input: DeleteViewFieldGroupInput!) {
|
||||
deleteViewFieldGroup(input: $input) {
|
||||
...ViewFieldGroupFragment
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -1,11 +0,0 @@
|
||||
import { VIEW_FIELD_GROUP_FRAGMENT } from '@/views/graphql/fragments/viewFieldGroupFragment';
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const UPDATE_VIEW_FIELD_GROUP = gql`
|
||||
${VIEW_FIELD_GROUP_FRAGMENT}
|
||||
mutation UpdateViewFieldGroup($input: UpdateViewFieldGroupInput!) {
|
||||
updateViewFieldGroup(input: $input) {
|
||||
...ViewFieldGroupFragment
|
||||
}
|
||||
}
|
||||
`;
|
||||
+69
-81
@@ -1,21 +1,20 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler';
|
||||
import { type FlatView } from '@/metadata-store/types/FlatView';
|
||||
import { type FlatViewGroup } from '@/metadata-store/types/FlatViewGroup';
|
||||
import { type MetadataRequestResult } from '@/object-metadata/types/MetadataRequestResult.type';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { usePerformViewEntityAPIPersistOperation } from '@/views/hooks/internal/usePerformViewEntityAPIPersistOperation';
|
||||
import { useViewsSideEffectsOnViewGroups } from '@/views/hooks/useViewsSideEffectsOnViewGroups';
|
||||
import { CombinedGraphQLErrors } from '@apollo/client/errors';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useMutation } from '@apollo/client/react';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
import { useMutation } from '@apollo/client/react';
|
||||
import {
|
||||
CreateViewDocument,
|
||||
type CreateViewMutationVariables,
|
||||
DestroyViewDocument,
|
||||
type DestroyViewMutationVariables,
|
||||
ViewType,
|
||||
CreateViewDocument,
|
||||
DestroyViewDocument,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const usePerformViewAPIPersist = () => {
|
||||
@@ -24,8 +23,8 @@ export const usePerformViewAPIPersist = () => {
|
||||
const { triggerViewGroupOptimisticEffectAtViewCreation } =
|
||||
useViewsSideEffectsOnViewGroups();
|
||||
|
||||
const { handleMetadataError } = useMetadataErrorHandler();
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
const { performViewEntityAPIPersistOperation } =
|
||||
usePerformViewEntityAPIPersistOperation('view');
|
||||
|
||||
const performViewAPICreate = useCallback(
|
||||
async (
|
||||
@@ -34,59 +33,64 @@ export const usePerformViewAPIPersist = () => {
|
||||
): Promise<
|
||||
MetadataRequestResult<Awaited<ReturnType<typeof createViewMutation>>>
|
||||
> => {
|
||||
try {
|
||||
const newViewId = variables.input.id ?? v4();
|
||||
if (variables.input.type === ViewType.KANBAN) {
|
||||
triggerViewGroupOptimisticEffectAtViewCreation({
|
||||
objectMetadataItemId: objectMetadataItemId,
|
||||
mainGroupByFieldMetadataId:
|
||||
variables.input.mainGroupByFieldMetadataId,
|
||||
});
|
||||
}
|
||||
const result = await performViewEntityAPIPersistOperation({
|
||||
persist: () => {
|
||||
const newViewId = variables.input.id ?? v4();
|
||||
if (variables.input.type === ViewType.KANBAN) {
|
||||
triggerViewGroupOptimisticEffectAtViewCreation({
|
||||
objectMetadataItemId: objectMetadataItemId,
|
||||
mainGroupByFieldMetadataId:
|
||||
variables.input.mainGroupByFieldMetadataId,
|
||||
});
|
||||
}
|
||||
|
||||
const result = await createViewMutation({
|
||||
variables: {
|
||||
input: {
|
||||
...variables.input,
|
||||
id: newViewId,
|
||||
return createViewMutation({
|
||||
variables: {
|
||||
input: {
|
||||
...variables.input,
|
||||
id: newViewId,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const newView = result.data?.createView;
|
||||
|
||||
if (!isDefined(newView)) {
|
||||
return {
|
||||
status: 'failed',
|
||||
error: new Error('Failed to create view'),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: result,
|
||||
};
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'view',
|
||||
operationType: CrudOperationType.CREATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
},
|
||||
applyResultToDraft: (mutationResult, { addToDraft }) => {
|
||||
const newView = mutationResult.data?.createView;
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
if (!isDefined(newView)) {
|
||||
throw new Error('Failed to create view');
|
||||
}
|
||||
|
||||
const {
|
||||
__typename,
|
||||
viewFields: _viewFields,
|
||||
viewFieldGroups: _viewFieldGroups,
|
||||
viewFilters: _viewFilters,
|
||||
viewFilterGroups: _viewFilterGroups,
|
||||
viewSorts: _viewSorts,
|
||||
viewGroups,
|
||||
...flatView
|
||||
} = newView;
|
||||
|
||||
addToDraft({ key: 'views', items: [flatView as FlatView] });
|
||||
|
||||
// The server auto-creates viewGroups for Kanban views (mainGroupByFieldMetadataId)
|
||||
addToDraft({
|
||||
key: 'viewGroups',
|
||||
items: viewGroups.map(
|
||||
({ __typename: _viewGroupTypename, ...viewGroup }) =>
|
||||
viewGroup as FlatViewGroup,
|
||||
),
|
||||
});
|
||||
},
|
||||
operationType: CrudOperationType.CREATE,
|
||||
});
|
||||
|
||||
return result;
|
||||
},
|
||||
[
|
||||
createViewMutation,
|
||||
triggerViewGroupOptimisticEffectAtViewCreation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
performViewEntityAPIPersistOperation,
|
||||
],
|
||||
);
|
||||
|
||||
@@ -95,33 +99,17 @@ export const usePerformViewAPIPersist = () => {
|
||||
variables: DestroyViewMutationVariables,
|
||||
): Promise<
|
||||
MetadataRequestResult<Awaited<ReturnType<typeof destroyViewMutation>>>
|
||||
> => {
|
||||
try {
|
||||
const result = await destroyViewMutation({
|
||||
variables,
|
||||
});
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: result,
|
||||
};
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'view',
|
||||
operationType: CrudOperationType.DELETE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[destroyViewMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
> =>
|
||||
performViewEntityAPIPersistOperation({
|
||||
persist: () =>
|
||||
destroyViewMutation({
|
||||
variables,
|
||||
}),
|
||||
applyResultToDraft: (_result, { removeFromDraft }) =>
|
||||
removeFromDraft({ key: 'views', itemIds: [variables.id] }),
|
||||
operationType: CrudOperationType.DELETE,
|
||||
}),
|
||||
[destroyViewMutation, performViewEntityAPIPersistOperation],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler';
|
||||
import { useUpdateMetadataStoreDraft } from '@/metadata-store/hooks/useUpdateMetadataStoreDraft';
|
||||
import { type MetadataRequestResult } from '@/object-metadata/types/MetadataRequestResult.type';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { CombinedGraphQLErrors } from '@apollo/client/errors';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { type AllMetadataName } from 'twenty-shared/metadata';
|
||||
import { type CrudOperationType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
type MetadataStoreDraftUtils = Pick<
|
||||
ReturnType<typeof useUpdateMetadataStoreDraft>,
|
||||
'addToDraft' | 'updateInDraft' | 'removeFromDraft'
|
||||
>;
|
||||
|
||||
type PerformViewEntityAPIPersistOperationArgs<TResponse> = {
|
||||
persist: () => Promise<TResponse>;
|
||||
applyResultToDraft: (
|
||||
response: TResponse,
|
||||
draftUtils: MetadataStoreDraftUtils,
|
||||
) => void;
|
||||
operationType: CrudOperationType;
|
||||
};
|
||||
|
||||
type PerformViewEntityAPIPersistBatchOperationArgs<TInput, TResult> = {
|
||||
inputs: TInput[];
|
||||
mutate: (input: TInput) => Promise<TResult>;
|
||||
applyResultToDraft: (
|
||||
fulfilledMutations: { input: TInput; result: TResult }[],
|
||||
draftUtils: MetadataStoreDraftUtils,
|
||||
) => void;
|
||||
operationType: CrudOperationType;
|
||||
};
|
||||
|
||||
export const usePerformViewEntityAPIPersistOperation = (
|
||||
metadataName: AllMetadataName,
|
||||
) => {
|
||||
const { addToDraft, updateInDraft, removeFromDraft, applyChanges } =
|
||||
useUpdateMetadataStoreDraft();
|
||||
|
||||
const { handleMetadataError } = useMetadataErrorHandler();
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
|
||||
const handlePersistError = useCallback(
|
||||
(error: unknown, operationType: CrudOperationType) => {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: metadataName,
|
||||
operationType,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
},
|
||||
[handleMetadataError, enqueueErrorSnackBar, metadataName],
|
||||
);
|
||||
|
||||
const performViewEntityAPIPersistOperation = useCallback(
|
||||
async <TResponse>({
|
||||
persist,
|
||||
applyResultToDraft,
|
||||
operationType,
|
||||
}: PerformViewEntityAPIPersistOperationArgs<TResponse>): Promise<
|
||||
MetadataRequestResult<TResponse>
|
||||
> => {
|
||||
try {
|
||||
const response = await persist();
|
||||
|
||||
applyResultToDraft(response, {
|
||||
addToDraft,
|
||||
updateInDraft,
|
||||
removeFromDraft,
|
||||
});
|
||||
applyChanges();
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response,
|
||||
};
|
||||
} catch (error) {
|
||||
handlePersistError(error, operationType);
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[
|
||||
addToDraft,
|
||||
updateInDraft,
|
||||
removeFromDraft,
|
||||
applyChanges,
|
||||
handlePersistError,
|
||||
],
|
||||
);
|
||||
|
||||
const performViewEntityAPIPersistBatchOperation = useCallback(
|
||||
async <TInput, TResult>({
|
||||
inputs,
|
||||
mutate,
|
||||
applyResultToDraft,
|
||||
operationType,
|
||||
}: PerformViewEntityAPIPersistBatchOperationArgs<TInput, TResult>): Promise<
|
||||
MetadataRequestResult<TResult[]>
|
||||
> => {
|
||||
if (inputs.length === 0) {
|
||||
return {
|
||||
status: 'successful',
|
||||
response: [],
|
||||
};
|
||||
}
|
||||
|
||||
const settledMutations = await Promise.allSettled(inputs.map(mutate));
|
||||
|
||||
const fulfilledMutations = settledMutations.flatMap(
|
||||
(settledMutation, index) =>
|
||||
settledMutation.status === 'fulfilled'
|
||||
? [{ input: inputs[index], result: settledMutation.value }]
|
||||
: [],
|
||||
);
|
||||
|
||||
applyResultToDraft(fulfilledMutations, {
|
||||
addToDraft,
|
||||
updateInDraft,
|
||||
removeFromDraft,
|
||||
});
|
||||
applyChanges();
|
||||
|
||||
const firstRejectedMutation = settledMutations.find(
|
||||
(settledMutation) => settledMutation.status === 'rejected',
|
||||
);
|
||||
|
||||
if (isDefined(firstRejectedMutation)) {
|
||||
const error = firstRejectedMutation.reason;
|
||||
|
||||
handlePersistError(error, operationType);
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: fulfilledMutations.map(({ result }) => result),
|
||||
};
|
||||
},
|
||||
[
|
||||
addToDraft,
|
||||
updateInDraft,
|
||||
removeFromDraft,
|
||||
applyChanges,
|
||||
handlePersistError,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
performViewEntityAPIPersistOperation,
|
||||
performViewEntityAPIPersistBatchOperation,
|
||||
};
|
||||
};
|
||||
+64
-146
@@ -1,12 +1,11 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler';
|
||||
import { type FlatViewField } from '@/metadata-store/types/FlatViewField';
|
||||
import { type MetadataRequestResult } from '@/object-metadata/types/MetadataRequestResult.type';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { CombinedGraphQLErrors } from '@apollo/client/errors';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import { usePerformViewEntityAPIPersistOperation } from '@/views/hooks/internal/usePerformViewEntityAPIPersistOperation';
|
||||
import { useMutation } from '@apollo/client/react';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
type CreateManyViewFieldsMutationVariables,
|
||||
type DeleteViewFieldMutationVariables,
|
||||
@@ -26,8 +25,10 @@ export const usePerformViewFieldAPIPersist = () => {
|
||||
const [deleteViewFieldMutation] = useMutation(DeleteViewFieldDocument);
|
||||
const [destroyViewFieldMutation] = useMutation(DestroyViewFieldDocument);
|
||||
|
||||
const { handleMetadataError } = useMetadataErrorHandler();
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
const {
|
||||
performViewEntityAPIPersistOperation,
|
||||
performViewEntityAPIPersistBatchOperation,
|
||||
} = usePerformViewEntityAPIPersistOperation('viewField');
|
||||
|
||||
const performViewFieldAPICreate = useCallback(
|
||||
async (
|
||||
@@ -47,79 +48,48 @@ export const usePerformViewFieldAPIPersist = () => {
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await createManyViewFieldsMutation({
|
||||
variables: createViewFieldInputs,
|
||||
});
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: result,
|
||||
};
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewField',
|
||||
operationType: CrudOperationType.CREATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
return performViewEntityAPIPersistOperation({
|
||||
persist: () =>
|
||||
createManyViewFieldsMutation({
|
||||
variables: createViewFieldInputs,
|
||||
}),
|
||||
applyResultToDraft: (result, { addToDraft }) =>
|
||||
addToDraft({
|
||||
key: 'viewFields',
|
||||
items: (result.data?.createManyViewFields ?? []).map(
|
||||
({ __typename, ...viewField }) => viewField as FlatViewField,
|
||||
),
|
||||
}),
|
||||
operationType: CrudOperationType.CREATE,
|
||||
});
|
||||
},
|
||||
[createManyViewFieldsMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
[createManyViewFieldsMutation, performViewEntityAPIPersistOperation],
|
||||
);
|
||||
|
||||
const performViewFieldAPIUpdate = useCallback(
|
||||
async (
|
||||
createViewFieldInputs: UpdateViewFieldMutationVariables[],
|
||||
updateViewFieldInputs: UpdateViewFieldMutationVariables[],
|
||||
): Promise<
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof updateViewFieldMutation>>[]
|
||||
>
|
||||
> => {
|
||||
if (createViewFieldInputs.length === 0) {
|
||||
return {
|
||||
status: 'successful',
|
||||
response: [],
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const results = await Promise.all(
|
||||
createViewFieldInputs.map((variables) =>
|
||||
updateViewFieldMutation({
|
||||
variables,
|
||||
}),
|
||||
> =>
|
||||
performViewEntityAPIPersistBatchOperation({
|
||||
inputs: updateViewFieldInputs,
|
||||
mutate: (variables) => updateViewFieldMutation({ variables }),
|
||||
applyResultToDraft: (fulfilledMutations, { updateInDraft }) =>
|
||||
updateInDraft(
|
||||
'viewFields',
|
||||
fulfilledMutations
|
||||
.map(({ result }) => result.data?.updateViewField)
|
||||
.filter(isDefined)
|
||||
.map(
|
||||
({ __typename, ...viewField }) => viewField as FlatViewField,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: results,
|
||||
};
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewField',
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[updateViewFieldMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
}),
|
||||
[updateViewFieldMutation, performViewEntityAPIPersistBatchOperation],
|
||||
);
|
||||
|
||||
const performViewFieldAPIDelete = useCallback(
|
||||
@@ -129,44 +99,18 @@ export const usePerformViewFieldAPIPersist = () => {
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof deleteViewFieldMutation>>[]
|
||||
>
|
||||
> => {
|
||||
if (deleteViewFieldInputs.length === 0) {
|
||||
return {
|
||||
status: 'successful',
|
||||
response: [],
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const results = await Promise.all(
|
||||
deleteViewFieldInputs.map((variables) =>
|
||||
deleteViewFieldMutation({
|
||||
variables,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: results,
|
||||
};
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewField',
|
||||
operationType: CrudOperationType.DELETE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[deleteViewFieldMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
> =>
|
||||
performViewEntityAPIPersistBatchOperation({
|
||||
inputs: deleteViewFieldInputs,
|
||||
mutate: (variables) => deleteViewFieldMutation({ variables }),
|
||||
applyResultToDraft: (fulfilledMutations, { removeFromDraft }) =>
|
||||
removeFromDraft({
|
||||
key: 'viewFields',
|
||||
itemIds: fulfilledMutations.map(({ input }) => input.input.id),
|
||||
}),
|
||||
operationType: CrudOperationType.DELETE,
|
||||
}),
|
||||
[deleteViewFieldMutation, performViewEntityAPIPersistBatchOperation],
|
||||
);
|
||||
|
||||
const performViewFieldAPIDestroy = useCallback(
|
||||
@@ -176,44 +120,18 @@ export const usePerformViewFieldAPIPersist = () => {
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof destroyViewFieldMutation>>[]
|
||||
>
|
||||
> => {
|
||||
if (destroyViewFieldInputs.length === 0) {
|
||||
return {
|
||||
status: 'successful',
|
||||
response: [],
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const results = await Promise.all(
|
||||
destroyViewFieldInputs.map((variables) =>
|
||||
destroyViewFieldMutation({
|
||||
variables,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: results,
|
||||
};
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewField',
|
||||
operationType: CrudOperationType.DESTROY,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[destroyViewFieldMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
> =>
|
||||
performViewEntityAPIPersistBatchOperation({
|
||||
inputs: destroyViewFieldInputs,
|
||||
mutate: (variables) => destroyViewFieldMutation({ variables }),
|
||||
applyResultToDraft: (fulfilledMutations, { removeFromDraft }) =>
|
||||
removeFromDraft({
|
||||
key: 'viewFields',
|
||||
itemIds: fulfilledMutations.map(({ input }) => input.input.id),
|
||||
}),
|
||||
operationType: CrudOperationType.DESTROY,
|
||||
}),
|
||||
[destroyViewFieldMutation, performViewEntityAPIPersistBatchOperation],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
-197
@@ -1,197 +0,0 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler';
|
||||
import { type MetadataRequestResult } from '@/object-metadata/types/MetadataRequestResult.type';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { CREATE_MANY_VIEW_FIELD_GROUPS } from '@/views/graphql/mutations/createManyViewFieldGroups';
|
||||
import { DELETE_VIEW_FIELD_GROUP } from '@/views/graphql/mutations/deleteViewFieldGroup';
|
||||
import { UPDATE_VIEW_FIELD_GROUP } from '@/views/graphql/mutations/updateViewFieldGroup';
|
||||
import { useMutation } from '@apollo/client/react';
|
||||
import { CombinedGraphQLErrors } from '@apollo/client/errors';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
type ViewFieldGroup,
|
||||
type MutationCreateManyViewFieldGroupsArgs,
|
||||
type MutationDeleteViewFieldGroupArgs,
|
||||
type MutationUpdateViewFieldGroupArgs,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
type CreateManyViewFieldGroupsMutationResult = {
|
||||
createManyViewFieldGroups: ViewFieldGroup[];
|
||||
};
|
||||
|
||||
type UpdateViewFieldGroupMutationResult = {
|
||||
updateViewFieldGroup: ViewFieldGroup;
|
||||
};
|
||||
|
||||
type DeleteViewFieldGroupMutationResult = {
|
||||
deleteViewFieldGroup: ViewFieldGroup;
|
||||
};
|
||||
|
||||
export const usePerformViewFieldGroupAPIPersist = () => {
|
||||
const [createManyViewFieldGroupsMutation] = useMutation<
|
||||
CreateManyViewFieldGroupsMutationResult,
|
||||
MutationCreateManyViewFieldGroupsArgs
|
||||
>(CREATE_MANY_VIEW_FIELD_GROUPS);
|
||||
const [updateViewFieldGroupMutation] = useMutation<
|
||||
UpdateViewFieldGroupMutationResult,
|
||||
MutationUpdateViewFieldGroupArgs
|
||||
>(UPDATE_VIEW_FIELD_GROUP);
|
||||
const [deleteViewFieldGroupMutation] = useMutation<
|
||||
DeleteViewFieldGroupMutationResult,
|
||||
MutationDeleteViewFieldGroupArgs
|
||||
>(DELETE_VIEW_FIELD_GROUP);
|
||||
|
||||
const { handleMetadataError } = useMetadataErrorHandler();
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
|
||||
const performViewFieldGroupAPICreate = useCallback(
|
||||
async (
|
||||
createViewFieldGroupInputs: MutationCreateManyViewFieldGroupsArgs,
|
||||
): Promise<
|
||||
MetadataRequestResult<CreateManyViewFieldGroupsMutationResult | null>
|
||||
> => {
|
||||
if (
|
||||
!Array.isArray(createViewFieldGroupInputs.inputs) ||
|
||||
createViewFieldGroupInputs.inputs.length === 0
|
||||
) {
|
||||
return {
|
||||
status: 'successful',
|
||||
response: null,
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await createManyViewFieldGroupsMutation({
|
||||
variables: createViewFieldGroupInputs,
|
||||
});
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: result.data ?? null,
|
||||
};
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewFieldGroup',
|
||||
operationType: CrudOperationType.CREATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[
|
||||
createManyViewFieldGroupsMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
],
|
||||
);
|
||||
|
||||
const performViewFieldGroupAPIUpdate = useCallback(
|
||||
async (
|
||||
updateViewFieldGroupInputs: MutationUpdateViewFieldGroupArgs[],
|
||||
): Promise<
|
||||
MetadataRequestResult<UpdateViewFieldGroupMutationResult[] | null>
|
||||
> => {
|
||||
if (updateViewFieldGroupInputs.length === 0) {
|
||||
return {
|
||||
status: 'successful',
|
||||
response: [],
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const results = await Promise.all(
|
||||
updateViewFieldGroupInputs.map((variables) =>
|
||||
updateViewFieldGroupMutation({
|
||||
variables,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: results
|
||||
.map((r) => r.data)
|
||||
.filter(isDefined) as UpdateViewFieldGroupMutationResult[],
|
||||
};
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewFieldGroup',
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[updateViewFieldGroupMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
);
|
||||
|
||||
const performViewFieldGroupAPIDelete = useCallback(
|
||||
async (
|
||||
deleteViewFieldGroupInputs: MutationDeleteViewFieldGroupArgs[],
|
||||
): Promise<
|
||||
MetadataRequestResult<DeleteViewFieldGroupMutationResult[] | null>
|
||||
> => {
|
||||
if (deleteViewFieldGroupInputs.length === 0) {
|
||||
return {
|
||||
status: 'successful',
|
||||
response: [],
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const results = await Promise.all(
|
||||
deleteViewFieldGroupInputs.map((variables) =>
|
||||
deleteViewFieldGroupMutation({
|
||||
variables,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: results
|
||||
.map((r) => r.data)
|
||||
.filter(isDefined) as DeleteViewFieldGroupMutationResult[],
|
||||
};
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewFieldGroup',
|
||||
operationType: CrudOperationType.DELETE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[deleteViewFieldGroupMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
);
|
||||
|
||||
return {
|
||||
performViewFieldGroupAPICreate,
|
||||
performViewFieldGroupAPIUpdate,
|
||||
performViewFieldGroupAPIDelete,
|
||||
};
|
||||
};
|
||||
+71
-158
@@ -1,31 +1,42 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler';
|
||||
import { type FlatViewFilter } from '@/metadata-store/types/FlatViewFilter';
|
||||
import { type MetadataRequestResult } from '@/object-metadata/types/MetadataRequestResult.type';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { CombinedGraphQLErrors } from '@apollo/client/errors';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import { usePerformViewEntityAPIPersistOperation } from '@/views/hooks/internal/usePerformViewEntityAPIPersistOperation';
|
||||
import { useMutation } from '@apollo/client/react';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import { convertViewFilterValueToString, isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
type CreateViewFilterMutationVariables,
|
||||
type DeleteViewFilterMutationVariables,
|
||||
type DestroyViewFilterMutationVariables,
|
||||
type UpdateViewFilterMutationVariables,
|
||||
type ViewFilterFragmentFragment,
|
||||
CreateViewFilterDocument,
|
||||
DeleteViewFilterDocument,
|
||||
DestroyViewFilterDocument,
|
||||
UpdateViewFilterDocument,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
// Normalize value like the fetch path (splitViewWithRelated) so store
|
||||
// comparisons against string-converted values stay consistent
|
||||
const toFlatViewFilter = ({
|
||||
__typename,
|
||||
...viewFilter
|
||||
}: ViewFilterFragmentFragment): FlatViewFilter =>
|
||||
({
|
||||
...viewFilter,
|
||||
value: convertViewFilterValueToString(viewFilter.value),
|
||||
}) as FlatViewFilter;
|
||||
|
||||
export const usePerformViewFilterAPIPersist = () => {
|
||||
const [createViewFilterMutation] = useMutation(CreateViewFilterDocument);
|
||||
const [updateViewFilterMutation] = useMutation(UpdateViewFilterDocument);
|
||||
const [deleteViewFilterMutation] = useMutation(DeleteViewFilterDocument);
|
||||
const [destroyViewFilterMutation] = useMutation(DestroyViewFilterDocument);
|
||||
|
||||
const { handleMetadataError } = useMetadataErrorHandler();
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
const { performViewEntityAPIPersistBatchOperation } =
|
||||
usePerformViewEntityAPIPersistOperation('viewFilter');
|
||||
|
||||
const performViewFilterAPICreate = useCallback(
|
||||
async (
|
||||
@@ -34,44 +45,21 @@ export const usePerformViewFilterAPIPersist = () => {
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof createViewFilterMutation>>[]
|
||||
>
|
||||
> => {
|
||||
if (createViewFilterInputs.length === 0) {
|
||||
return {
|
||||
status: 'successful',
|
||||
response: [],
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const results = await Promise.all(
|
||||
createViewFilterInputs.map((variables) =>
|
||||
createViewFilterMutation({
|
||||
variables,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: results,
|
||||
};
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewFilter',
|
||||
operationType: CrudOperationType.CREATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[createViewFilterMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
> =>
|
||||
performViewEntityAPIPersistBatchOperation({
|
||||
inputs: createViewFilterInputs,
|
||||
mutate: (variables) => createViewFilterMutation({ variables }),
|
||||
applyResultToDraft: (fulfilledMutations, { addToDraft }) =>
|
||||
addToDraft({
|
||||
key: 'viewFilters',
|
||||
items: fulfilledMutations
|
||||
.map(({ result }) => result.data?.createViewFilter)
|
||||
.filter(isDefined)
|
||||
.map(toFlatViewFilter),
|
||||
}),
|
||||
operationType: CrudOperationType.CREATE,
|
||||
}),
|
||||
[createViewFilterMutation, performViewEntityAPIPersistBatchOperation],
|
||||
);
|
||||
|
||||
const performViewFilterAPIUpdate = useCallback(
|
||||
@@ -81,44 +69,21 @@ export const usePerformViewFilterAPIPersist = () => {
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof updateViewFilterMutation>>[]
|
||||
>
|
||||
> => {
|
||||
if (updateViewFilterInputs.length === 0) {
|
||||
return {
|
||||
status: 'successful',
|
||||
response: [],
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const results = await Promise.all(
|
||||
updateViewFilterInputs.map((variables) =>
|
||||
updateViewFilterMutation({
|
||||
variables,
|
||||
}),
|
||||
> =>
|
||||
performViewEntityAPIPersistBatchOperation({
|
||||
inputs: updateViewFilterInputs,
|
||||
mutate: (variables) => updateViewFilterMutation({ variables }),
|
||||
applyResultToDraft: (fulfilledMutations, { updateInDraft }) =>
|
||||
updateInDraft(
|
||||
'viewFilters',
|
||||
fulfilledMutations
|
||||
.map(({ result }) => result.data?.updateViewFilter)
|
||||
.filter(isDefined)
|
||||
.map(toFlatViewFilter),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: results,
|
||||
};
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewFilter',
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[updateViewFilterMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
}),
|
||||
[updateViewFilterMutation, performViewEntityAPIPersistBatchOperation],
|
||||
);
|
||||
|
||||
const performViewFilterAPIDelete = useCallback(
|
||||
@@ -128,44 +93,18 @@ export const usePerformViewFilterAPIPersist = () => {
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof deleteViewFilterMutation>>[]
|
||||
>
|
||||
> => {
|
||||
if (deleteViewFilterInputs.length === 0) {
|
||||
return {
|
||||
status: 'successful',
|
||||
response: [],
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const results = await Promise.all(
|
||||
deleteViewFilterInputs.map((variables) =>
|
||||
deleteViewFilterMutation({
|
||||
variables,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: results,
|
||||
};
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewFilter',
|
||||
operationType: CrudOperationType.DELETE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[deleteViewFilterMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
> =>
|
||||
performViewEntityAPIPersistBatchOperation({
|
||||
inputs: deleteViewFilterInputs,
|
||||
mutate: (variables) => deleteViewFilterMutation({ variables }),
|
||||
applyResultToDraft: (fulfilledMutations, { removeFromDraft }) =>
|
||||
removeFromDraft({
|
||||
key: 'viewFilters',
|
||||
itemIds: fulfilledMutations.map(({ input }) => input.input.id),
|
||||
}),
|
||||
operationType: CrudOperationType.DELETE,
|
||||
}),
|
||||
[deleteViewFilterMutation, performViewEntityAPIPersistBatchOperation],
|
||||
);
|
||||
|
||||
const performViewFilterAPIDestroy = useCallback(
|
||||
@@ -175,44 +114,18 @@ export const usePerformViewFilterAPIPersist = () => {
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof destroyViewFilterMutation>>[]
|
||||
>
|
||||
> => {
|
||||
if (destroyViewFilterInputs.length === 0) {
|
||||
return {
|
||||
status: 'successful',
|
||||
response: [],
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const results = await Promise.all(
|
||||
destroyViewFilterInputs.map((variables) =>
|
||||
destroyViewFilterMutation({
|
||||
variables,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: results,
|
||||
};
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewFilter',
|
||||
operationType: CrudOperationType.DESTROY,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[destroyViewFilterMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
> =>
|
||||
performViewEntityAPIPersistBatchOperation({
|
||||
inputs: destroyViewFilterInputs,
|
||||
mutate: (variables) => destroyViewFilterMutation({ variables }),
|
||||
applyResultToDraft: (fulfilledMutations, { removeFromDraft }) =>
|
||||
removeFromDraft({
|
||||
key: 'viewFilters',
|
||||
itemIds: fulfilledMutations.map(({ input }) => input.input.id),
|
||||
}),
|
||||
operationType: CrudOperationType.DESTROY,
|
||||
}),
|
||||
[destroyViewFilterMutation, performViewEntityAPIPersistBatchOperation],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
+95
-55
@@ -1,23 +1,38 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { CREATE_VIEW_FILTER_GROUP } from '@/views/graphql/mutations/createViewFilterGroup';
|
||||
import { DESTROY_VIEW_FILTER_GROUP } from '@/views/graphql/mutations/destroyViewFilterGroup';
|
||||
import { UPDATE_VIEW_FILTER_GROUP } from '@/views/graphql/mutations/updateViewFilterGroup';
|
||||
import { type FlatViewFilterGroup } from '@/metadata-store/types/FlatViewFilterGroup';
|
||||
import { type MetadataRequestResult } from '@/object-metadata/types/MetadataRequestResult.type';
|
||||
import { usePerformViewEntityAPIPersistOperation } from '@/views/hooks/internal/usePerformViewEntityAPIPersistOperation';
|
||||
import { type GraphQLView } from '@/views/types/GraphQLView';
|
||||
import { type ViewFilterGroup } from '@/views/types/ViewFilterGroup';
|
||||
import { useApolloClient } from '@apollo/client/react';
|
||||
import { useMutation } from '@apollo/client/react';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type ViewFilterGroup as GqlViewFilterGroup } from '~/generated-metadata/graphql';
|
||||
import {
|
||||
CreateViewFilterGroupDocument,
|
||||
DestroyViewFilterGroupDocument,
|
||||
UpdateViewFilterGroupDocument,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const usePerformViewFilterGroupAPIPersist = () => {
|
||||
const apolloClient = useApolloClient();
|
||||
const [createViewFilterGroupMutation] = useMutation(
|
||||
CreateViewFilterGroupDocument,
|
||||
);
|
||||
const [updateViewFilterGroupMutation] = useMutation(
|
||||
UpdateViewFilterGroupDocument,
|
||||
);
|
||||
const [destroyViewFilterGroupMutation] = useMutation(
|
||||
DestroyViewFilterGroupDocument,
|
||||
);
|
||||
|
||||
const {
|
||||
performViewEntityAPIPersistOperation,
|
||||
performViewEntityAPIPersistBatchOperation,
|
||||
} = usePerformViewEntityAPIPersistOperation('viewFilterGroup');
|
||||
|
||||
const createViewFilterGroupRecord = useCallback(
|
||||
async (viewFilterGroup: ViewFilterGroup, view: Pick<GraphQLView, 'id'>) => {
|
||||
const result = await apolloClient.mutate<{
|
||||
createViewFilterGroup: ViewFilterGroup;
|
||||
}>({
|
||||
mutation: CREATE_VIEW_FILTER_GROUP,
|
||||
const result = await createViewFilterGroupMutation({
|
||||
variables: {
|
||||
input: {
|
||||
id: viewFilterGroup.id,
|
||||
@@ -26,27 +41,26 @@ export const usePerformViewFilterGroupAPIPersist = () => {
|
||||
logicalOperator: viewFilterGroup.logicalOperator,
|
||||
positionInViewFilterGroup:
|
||||
viewFilterGroup.positionInViewFilterGroup,
|
||||
} satisfies Partial<GqlViewFilterGroup>,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!result.data) {
|
||||
if (!isDefined(result.data)) {
|
||||
throw new Error('Failed to create view filter group');
|
||||
}
|
||||
|
||||
return { newRecordId: result.data.createViewFilterGroup.id };
|
||||
return { newRecord: result.data.createViewFilterGroup };
|
||||
},
|
||||
[apolloClient],
|
||||
[createViewFilterGroupMutation],
|
||||
);
|
||||
|
||||
const performViewFilterGroupAPICreate = useCallback(
|
||||
async (
|
||||
viewFilterGroupsToCreate: ViewFilterGroup[],
|
||||
view: Pick<GraphQLView, 'id'>,
|
||||
) => {
|
||||
if (!viewFilterGroupsToCreate.length) return [];
|
||||
|
||||
): Promise<MetadataRequestResult<string[]>> => {
|
||||
const oldToNewId = new Map<string, string>();
|
||||
const newRecordIds: string[] = [];
|
||||
|
||||
for (const viewFilterGroupToCreate of viewFilterGroupsToCreate) {
|
||||
const newParentViewFilterGroupId = isDefined(
|
||||
@@ -56,37 +70,50 @@ export const usePerformViewFilterGroupAPIPersist = () => {
|
||||
viewFilterGroupToCreate.parentViewFilterGroupId)
|
||||
: undefined;
|
||||
|
||||
const { newRecordId } = await createViewFilterGroupRecord(
|
||||
{
|
||||
...viewFilterGroupToCreate,
|
||||
parentViewFilterGroupId: newParentViewFilterGroupId,
|
||||
const result = await performViewEntityAPIPersistOperation({
|
||||
persist: () =>
|
||||
createViewFilterGroupRecord(
|
||||
{
|
||||
...viewFilterGroupToCreate,
|
||||
parentViewFilterGroupId: newParentViewFilterGroupId,
|
||||
},
|
||||
view,
|
||||
),
|
||||
applyResultToDraft: ({ newRecord }, { addToDraft }) => {
|
||||
const { __typename, ...viewFilterGroup } = newRecord;
|
||||
return addToDraft({
|
||||
key: 'viewFilterGroups',
|
||||
items: [viewFilterGroup as FlatViewFilterGroup],
|
||||
});
|
||||
},
|
||||
view,
|
||||
);
|
||||
operationType: CrudOperationType.CREATE,
|
||||
});
|
||||
|
||||
oldToNewId.set(viewFilterGroupToCreate.id, newRecordId);
|
||||
if (result.status === 'failed') {
|
||||
return result;
|
||||
}
|
||||
|
||||
oldToNewId.set(
|
||||
viewFilterGroupToCreate.id,
|
||||
result.response.newRecord.id,
|
||||
);
|
||||
newRecordIds.push(result.response.newRecord.id);
|
||||
}
|
||||
|
||||
const newRecordIds = viewFilterGroupsToCreate.map((viewFilterGroup) => {
|
||||
const newId = oldToNewId.get(viewFilterGroup.id);
|
||||
if (!newId) {
|
||||
throw new Error('Failed to create view filter group');
|
||||
}
|
||||
return newId;
|
||||
});
|
||||
|
||||
return newRecordIds;
|
||||
return {
|
||||
status: 'successful',
|
||||
response: newRecordIds,
|
||||
};
|
||||
},
|
||||
[createViewFilterGroupRecord],
|
||||
[createViewFilterGroupRecord, performViewEntityAPIPersistOperation],
|
||||
);
|
||||
|
||||
const performViewFilterGroupAPIUpdate = useCallback(
|
||||
(viewFilterGroupsToUpdate: ViewFilterGroup[]) => {
|
||||
if (!viewFilterGroupsToUpdate.length) return;
|
||||
return Promise.all(
|
||||
viewFilterGroupsToUpdate.map((viewFilterGroup) =>
|
||||
apolloClient.mutate<{ updateViewFilterGroup: ViewFilterGroup }>({
|
||||
mutation: UPDATE_VIEW_FILTER_GROUP,
|
||||
(viewFilterGroupsToUpdate: ViewFilterGroup[]) =>
|
||||
performViewEntityAPIPersistBatchOperation({
|
||||
inputs: viewFilterGroupsToUpdate,
|
||||
mutate: (viewFilterGroup) =>
|
||||
updateViewFilterGroupMutation({
|
||||
variables: {
|
||||
id: viewFilterGroup.id,
|
||||
input: {
|
||||
@@ -95,30 +122,43 @@ export const usePerformViewFilterGroupAPIPersist = () => {
|
||||
logicalOperator: viewFilterGroup.logicalOperator,
|
||||
positionInViewFilterGroup:
|
||||
viewFilterGroup.positionInViewFilterGroup,
|
||||
} satisfies Partial<GqlViewFilterGroup>,
|
||||
},
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
},
|
||||
[apolloClient],
|
||||
applyResultToDraft: (fulfilledMutations, { updateInDraft }) =>
|
||||
updateInDraft(
|
||||
'viewFilterGroups',
|
||||
fulfilledMutations
|
||||
.map(({ result }) => result.data?.updateViewFilterGroup)
|
||||
.filter(isDefined)
|
||||
.map(
|
||||
({ __typename, ...viewFilterGroup }) =>
|
||||
viewFilterGroup as FlatViewFilterGroup,
|
||||
),
|
||||
),
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
}),
|
||||
[updateViewFilterGroupMutation, performViewEntityAPIPersistBatchOperation],
|
||||
);
|
||||
|
||||
const performViewFilterGroupAPIDestroy = useCallback(
|
||||
(viewFilterGroupIdsToDestroy: string[]) => {
|
||||
if (!viewFilterGroupIdsToDestroy.length) return;
|
||||
return Promise.all(
|
||||
viewFilterGroupIdsToDestroy.map((viewFilterGroupId) =>
|
||||
apolloClient.mutate<{ destroyViewFilterGroup: ViewFilterGroup }>({
|
||||
mutation: DESTROY_VIEW_FILTER_GROUP,
|
||||
(viewFilterGroupIdsToDestroy: string[]) =>
|
||||
performViewEntityAPIPersistBatchOperation({
|
||||
inputs: viewFilterGroupIdsToDestroy,
|
||||
mutate: (viewFilterGroupId) =>
|
||||
destroyViewFilterGroupMutation({
|
||||
variables: {
|
||||
id: viewFilterGroupId,
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
},
|
||||
[apolloClient],
|
||||
applyResultToDraft: (fulfilledMutations, { removeFromDraft }) =>
|
||||
removeFromDraft({
|
||||
key: 'viewFilterGroups',
|
||||
itemIds: fulfilledMutations.map(({ input }) => input),
|
||||
}),
|
||||
operationType: CrudOperationType.DESTROY,
|
||||
}),
|
||||
[destroyViewFilterGroupMutation, performViewEntityAPIPersistBatchOperation],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
+34
-56
@@ -1,11 +1,9 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler';
|
||||
import { type FlatViewGroup } from '@/metadata-store/types/FlatViewGroup';
|
||||
import { type MetadataRequestResult } from '@/object-metadata/types/MetadataRequestResult.type';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { CombinedGraphQLErrors } from '@apollo/client/errors';
|
||||
import { usePerformViewEntityAPIPersistOperation } from '@/views/hooks/internal/usePerformViewEntityAPIPersistOperation';
|
||||
import { useMutation } from '@apollo/client/react';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { isNonEmptyArray } from '@sniptt/guards';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import {
|
||||
@@ -24,8 +22,8 @@ export const usePerformViewGroupAPIPersist = () => {
|
||||
CreateManyViewGroupsDocument,
|
||||
);
|
||||
|
||||
const { handleMetadataError } = useMetadataErrorHandler();
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
const { performViewEntityAPIPersistOperation } =
|
||||
usePerformViewEntityAPIPersistOperation('viewGroup');
|
||||
|
||||
const performViewGroupAPIUpdate = useCallback(
|
||||
async (
|
||||
@@ -42,32 +40,22 @@ export const usePerformViewGroupAPIPersist = () => {
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await updateManyViewGroupsMutation({
|
||||
variables: updateViewGroupInputs,
|
||||
});
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: result,
|
||||
};
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewGroup',
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
return performViewEntityAPIPersistOperation({
|
||||
persist: () =>
|
||||
updateManyViewGroupsMutation({
|
||||
variables: updateViewGroupInputs,
|
||||
}),
|
||||
applyResultToDraft: (result, { updateInDraft }) =>
|
||||
updateInDraft(
|
||||
'viewGroups',
|
||||
(result.data?.updateManyViewGroups ?? []).map(
|
||||
({ __typename, ...viewGroup }) => viewGroup as FlatViewGroup,
|
||||
),
|
||||
),
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
});
|
||||
},
|
||||
[updateManyViewGroupsMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
[updateManyViewGroupsMutation, performViewEntityAPIPersistOperation],
|
||||
);
|
||||
|
||||
const performViewGroupAPICreate = useCallback(
|
||||
@@ -85,32 +73,22 @@ export const usePerformViewGroupAPIPersist = () => {
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await createManyViewGroupsMutation({
|
||||
variables: createViewGroupInputs,
|
||||
});
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: result,
|
||||
};
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewGroup',
|
||||
operationType: CrudOperationType.CREATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
return performViewEntityAPIPersistOperation({
|
||||
persist: () =>
|
||||
createManyViewGroupsMutation({
|
||||
variables: createViewGroupInputs,
|
||||
}),
|
||||
applyResultToDraft: (result, { addToDraft }) =>
|
||||
addToDraft({
|
||||
key: 'viewGroups',
|
||||
items: (result.data?.createManyViewGroups ?? []).map(
|
||||
({ __typename, ...viewGroup }) => viewGroup as FlatViewGroup,
|
||||
),
|
||||
}),
|
||||
operationType: CrudOperationType.CREATE,
|
||||
});
|
||||
},
|
||||
[createManyViewGroupsMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
[createManyViewGroupsMutation, performViewEntityAPIPersistOperation],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
+59
-157
@@ -1,12 +1,11 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useMetadataErrorHandler } from '@/metadata-error-handler/hooks/useMetadataErrorHandler';
|
||||
import { type FlatViewSort } from '@/metadata-store/types/FlatViewSort';
|
||||
import { type MetadataRequestResult } from '@/object-metadata/types/MetadataRequestResult.type';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { CombinedGraphQLErrors } from '@apollo/client/errors';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import { usePerformViewEntityAPIPersistOperation } from '@/views/hooks/internal/usePerformViewEntityAPIPersistOperation';
|
||||
import { useMutation } from '@apollo/client/react';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
type CreateViewSortMutationVariables,
|
||||
type DeleteViewSortMutationVariables,
|
||||
@@ -24,8 +23,8 @@ export const usePerformViewSortAPIPersist = () => {
|
||||
const [deleteViewSortMutation] = useMutation(DeleteViewSortDocument);
|
||||
const [destroyViewSortMutation] = useMutation(DestroyViewSortDocument);
|
||||
|
||||
const { handleMetadataError } = useMetadataErrorHandler();
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
const { performViewEntityAPIPersistBatchOperation } =
|
||||
usePerformViewEntityAPIPersistOperation('viewSort');
|
||||
|
||||
const performViewSortAPICreate = useCallback(
|
||||
async (
|
||||
@@ -34,43 +33,21 @@ export const usePerformViewSortAPIPersist = () => {
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof createViewSortMutation>>[]
|
||||
>
|
||||
> => {
|
||||
if (createViewSortInputs.length === 0) {
|
||||
return {
|
||||
status: 'successful',
|
||||
response: [],
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const results = await Promise.all(
|
||||
createViewSortInputs.map((variables) =>
|
||||
createViewSortMutation({
|
||||
variables,
|
||||
}),
|
||||
),
|
||||
);
|
||||
return {
|
||||
status: 'successful',
|
||||
response: results,
|
||||
};
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewSort',
|
||||
operationType: CrudOperationType.CREATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[createViewSortMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
> =>
|
||||
performViewEntityAPIPersistBatchOperation({
|
||||
inputs: createViewSortInputs,
|
||||
mutate: (variables) => createViewSortMutation({ variables }),
|
||||
applyResultToDraft: (fulfilledMutations, { addToDraft }) =>
|
||||
addToDraft({
|
||||
key: 'viewSorts',
|
||||
items: fulfilledMutations
|
||||
.map(({ result }) => result.data?.createViewSort)
|
||||
.filter(isDefined)
|
||||
.map(({ __typename, ...viewSort }) => viewSort as FlatViewSort),
|
||||
}),
|
||||
operationType: CrudOperationType.CREATE,
|
||||
}),
|
||||
[createViewSortMutation, performViewEntityAPIPersistBatchOperation],
|
||||
);
|
||||
|
||||
const performViewSortAPIUpdate = useCallback(
|
||||
@@ -80,44 +57,21 @@ export const usePerformViewSortAPIPersist = () => {
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof updateViewSortMutation>>[]
|
||||
>
|
||||
> => {
|
||||
if (updateViewSortInputs.length === 0) {
|
||||
return {
|
||||
status: 'successful',
|
||||
response: [],
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const results = await Promise.all(
|
||||
updateViewSortInputs.map((variables) =>
|
||||
updateViewSortMutation({
|
||||
variables,
|
||||
}),
|
||||
> =>
|
||||
performViewEntityAPIPersistBatchOperation({
|
||||
inputs: updateViewSortInputs,
|
||||
mutate: (variables) => updateViewSortMutation({ variables }),
|
||||
applyResultToDraft: (fulfilledMutations, { updateInDraft }) =>
|
||||
updateInDraft(
|
||||
'viewSorts',
|
||||
fulfilledMutations
|
||||
.map(({ result }) => result.data?.updateViewSort)
|
||||
.filter(isDefined)
|
||||
.map(({ __typename, ...viewSort }) => viewSort as FlatViewSort),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: results,
|
||||
};
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewSort',
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[updateViewSortMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
}),
|
||||
[updateViewSortMutation, performViewEntityAPIPersistBatchOperation],
|
||||
);
|
||||
|
||||
const performViewSortAPIDelete = useCallback(
|
||||
@@ -127,44 +81,18 @@ export const usePerformViewSortAPIPersist = () => {
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof deleteViewSortMutation>>[]
|
||||
>
|
||||
> => {
|
||||
if (deleteViewSortInputs.length === 0) {
|
||||
return {
|
||||
status: 'successful',
|
||||
response: [],
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const results = await Promise.all(
|
||||
deleteViewSortInputs.map((variables) =>
|
||||
deleteViewSortMutation({
|
||||
variables,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: results,
|
||||
};
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewSort',
|
||||
operationType: CrudOperationType.DELETE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[deleteViewSortMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
> =>
|
||||
performViewEntityAPIPersistBatchOperation({
|
||||
inputs: deleteViewSortInputs,
|
||||
mutate: (variables) => deleteViewSortMutation({ variables }),
|
||||
applyResultToDraft: (fulfilledMutations, { removeFromDraft }) =>
|
||||
removeFromDraft({
|
||||
key: 'viewSorts',
|
||||
itemIds: fulfilledMutations.map(({ input }) => input.input.id),
|
||||
}),
|
||||
operationType: CrudOperationType.DELETE,
|
||||
}),
|
||||
[deleteViewSortMutation, performViewEntityAPIPersistBatchOperation],
|
||||
);
|
||||
|
||||
const performViewSortAPIDestroy = useCallback(
|
||||
@@ -174,44 +102,18 @@ export const usePerformViewSortAPIPersist = () => {
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof destroyViewSortMutation>>[]
|
||||
>
|
||||
> => {
|
||||
if (destroyViewSortInputs.length === 0) {
|
||||
return {
|
||||
status: 'successful',
|
||||
response: [],
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
const results = await Promise.all(
|
||||
destroyViewSortInputs.map((variables) =>
|
||||
destroyViewSortMutation({
|
||||
variables,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: results,
|
||||
};
|
||||
} catch (error) {
|
||||
if (CombinedGraphQLErrors.is(error)) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewSort',
|
||||
operationType: CrudOperationType.DESTROY,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
},
|
||||
[destroyViewSortMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
> =>
|
||||
performViewEntityAPIPersistBatchOperation({
|
||||
inputs: destroyViewSortInputs,
|
||||
mutate: (variables) => destroyViewSortMutation({ variables }),
|
||||
applyResultToDraft: (fulfilledMutations, { removeFromDraft }) =>
|
||||
removeFromDraft({
|
||||
key: 'viewSorts',
|
||||
itemIds: fulfilledMutations.map(({ input }) => input.input.id),
|
||||
}),
|
||||
operationType: CrudOperationType.DESTROY,
|
||||
}),
|
||||
[destroyViewSortMutation, performViewEntityAPIPersistBatchOperation],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -207,9 +207,16 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
|
||||
id: v4(),
|
||||
}));
|
||||
|
||||
await performViewFilterGroupAPICreate(viewFilterGroupsToCreate, {
|
||||
id: newViewId,
|
||||
});
|
||||
const filterGroupResult = await performViewFilterGroupAPICreate(
|
||||
viewFilterGroupsToCreate,
|
||||
{
|
||||
id: newViewId,
|
||||
},
|
||||
);
|
||||
|
||||
if (filterGroupResult.status === 'failed') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const createViewFilterInputs = viewFiltersToCreate.map(
|
||||
(viewFilter) => ({
|
||||
|
||||
+17
-3
@@ -84,11 +84,20 @@ export const useSaveRecordFiltersAndGroupFiltersToViewFiltersAndGroupFilters =
|
||||
(viewFilterGroup) => viewFilterGroup.id,
|
||||
);
|
||||
|
||||
await performViewFilterGroupAPICreate(
|
||||
const createFilterGroupResult = await performViewFilterGroupAPICreate(
|
||||
viewFilterGroupsToCreate,
|
||||
currentView,
|
||||
);
|
||||
await performViewFilterGroupAPIUpdate(viewFilterGroupsToUpdate);
|
||||
if (createFilterGroupResult.status === 'failed') {
|
||||
return;
|
||||
}
|
||||
|
||||
const updateFilterGroupResult = await performViewFilterGroupAPIUpdate(
|
||||
viewFilterGroupsToUpdate,
|
||||
);
|
||||
if (updateFilterGroupResult.status === 'failed') {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentViewFilters = currentView.viewFilters ?? [];
|
||||
const currentRecordFilters = store.get(
|
||||
@@ -181,7 +190,12 @@ export const useSaveRecordFiltersAndGroupFiltersToViewFiltersAndGroupFilters =
|
||||
return;
|
||||
}
|
||||
|
||||
await performViewFilterGroupAPIDestroy(viewFilterGroupIdsToDestroy);
|
||||
const destroyFilterGroupResult = await performViewFilterGroupAPIDestroy(
|
||||
viewFilterGroupIdsToDestroy,
|
||||
);
|
||||
if (destroyFilterGroupResult.status === 'failed') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Mirror the DB cascade: remove cascade-deleted viewFilters from the store
|
||||
if (viewFilterGroupIdsToDestroy.length > 0) {
|
||||
|
||||
Reference in New Issue
Block a user