[PAGE LAYOUTS] Add widgets validation (#16635)
- Add widget validation - Remove 'None' option for primary axis group by - Fix error message parsing by passing the operation type in `useMetadataErrorHandler`
This commit is contained in:
+6
-3
@@ -21,9 +21,12 @@ export const SaveDashboardSingleRecordAction = () => {
|
||||
const { closeCommandMenu } = useCommandMenu();
|
||||
|
||||
const handleClick = async () => {
|
||||
await savePageLayout();
|
||||
closeCommandMenu();
|
||||
setIsPageLayoutInEditMode(false);
|
||||
const result = await savePageLayout();
|
||||
|
||||
if (result.status === 'successful') {
|
||||
closeCommandMenu();
|
||||
setIsPageLayoutInEditMode(false);
|
||||
}
|
||||
};
|
||||
|
||||
return <Action onClick={handleClick} />;
|
||||
|
||||
+18
-12
@@ -101,6 +101,13 @@ export const ChartGroupByFieldSelectionDropdownContentBase = <
|
||||
|
||||
const { getIcon } = useIcons();
|
||||
|
||||
const isSecondaryAxisGroupBy =
|
||||
fieldMetadataIdKey === 'secondaryAxisGroupByFieldMetadataId';
|
||||
|
||||
const selectableItemIdArray = isSecondaryAxisGroupBy
|
||||
? ['none', ...availableFieldMetadataItems.map((item) => item.id)]
|
||||
: availableFieldMetadataItems.map((item) => item.id);
|
||||
|
||||
if (!isDefined(sourceObjectMetadataItem)) {
|
||||
return null;
|
||||
}
|
||||
@@ -227,19 +234,18 @@ export const ChartGroupByFieldSelectionDropdownContentBase = <
|
||||
<SelectableList
|
||||
selectableListInstanceId={dropdownId}
|
||||
focusId={dropdownId}
|
||||
selectableItemIdArray={[
|
||||
'none',
|
||||
...availableFieldMetadataItems.map((item) => item.id),
|
||||
]}
|
||||
selectableItemIdArray={selectableItemIdArray}
|
||||
>
|
||||
<SelectableListItem itemId="none" onEnter={handleSelectNone}>
|
||||
<MenuItemSelect
|
||||
text={t`None`}
|
||||
selected={!isDefined(currentGroupByFieldMetadataId)}
|
||||
focused={selectedItemId === 'none'}
|
||||
onClick={handleSelectNone}
|
||||
/>
|
||||
</SelectableListItem>
|
||||
{isSecondaryAxisGroupBy && (
|
||||
<SelectableListItem itemId="none" onEnter={handleSelectNone}>
|
||||
<MenuItemSelect
|
||||
text={t`None`}
|
||||
selected={!isDefined(currentGroupByFieldMetadataId)}
|
||||
focused={selectedItemId === 'none'}
|
||||
onClick={handleSelectNone}
|
||||
/>
|
||||
</SelectableListItem>
|
||||
)}
|
||||
|
||||
{availableFieldMetadataItems.map((fieldMetadataItem) => (
|
||||
<SelectableListItem
|
||||
|
||||
+86
-79
@@ -1,6 +1,5 @@
|
||||
import { type ApolloError } from '@apollo/client';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { classifyMetadataError } from '@/metadata-error-handler/utils/classify-metadata-error.util';
|
||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
@@ -8,9 +7,19 @@ import {
|
||||
type AllMetadataName,
|
||||
WorkspaceMigrationV2ExceptionCode,
|
||||
} from 'twenty-shared/metadata';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
|
||||
export const useMetadataErrorHandler = () => {
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
|
||||
const TRANSLATED_OPERATION_TYPE = {
|
||||
[CrudOperationType.CREATE]: t`create`,
|
||||
[CrudOperationType.UPDATE]: t`update`,
|
||||
[CrudOperationType.DELETE]: t`delete`,
|
||||
[CrudOperationType.RESTORE]: t`restore`,
|
||||
[CrudOperationType.DESTROY]: t`destroy`,
|
||||
} as const satisfies Record<CrudOperationType, string>;
|
||||
|
||||
const TRANSLATED_METADATA_NAME = {
|
||||
objectMetadata: t`object`,
|
||||
fieldMetadata: t`field`,
|
||||
@@ -35,85 +44,83 @@ export const useMetadataErrorHandler = () => {
|
||||
viewFilterGroup: t`view filter group`,
|
||||
} as const satisfies Record<AllMetadataName, string>;
|
||||
|
||||
const handleMetadataError = useCallback(
|
||||
(
|
||||
error: ApolloError,
|
||||
options: {
|
||||
primaryMetadataName: AllMetadataName;
|
||||
},
|
||||
) => {
|
||||
const classification = classifyMetadataError({
|
||||
error,
|
||||
primaryMetadataName: options.primaryMetadataName,
|
||||
});
|
||||
|
||||
const translatedMetadataName =
|
||||
TRANSLATED_METADATA_NAME[options.primaryMetadataName];
|
||||
|
||||
switch (classification.type) {
|
||||
case 'v1':
|
||||
enqueueErrorSnackBar({ apolloError: classification.error });
|
||||
break;
|
||||
|
||||
case 'v2-validation': {
|
||||
const {
|
||||
extensions,
|
||||
primaryMetadataName,
|
||||
relatedFailingMetadataNames,
|
||||
} = classification;
|
||||
|
||||
const targetErrors = extensions.errors[primaryMetadataName] ?? [];
|
||||
if (targetErrors.length > 0) {
|
||||
targetErrors.forEach((entityError) => {
|
||||
entityError.errors.forEach((validationError) =>
|
||||
enqueueErrorSnackBar({
|
||||
message:
|
||||
validationError.userFriendlyMessage ??
|
||||
validationError.message,
|
||||
}),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
targetErrors.length === 0 &&
|
||||
relatedFailingMetadataNames.length > 0
|
||||
) {
|
||||
const relatedEntityNames = relatedFailingMetadataNames
|
||||
.map((metadataName) => TRANSLATED_METADATA_NAME[metadataName])
|
||||
.join(', ');
|
||||
|
||||
enqueueErrorSnackBar({
|
||||
message: t`Failed to create ${translatedMetadataName}. Related ${relatedEntityNames} validation failed. Please check your configuration and try again.`,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
targetErrors.length === 0 &&
|
||||
relatedFailingMetadataNames.length === 0
|
||||
) {
|
||||
enqueueErrorSnackBar({
|
||||
message: t`Failed to create ${translatedMetadataName}. Please try again.`,
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'v2-internal': {
|
||||
const { code } = classification;
|
||||
const errorMessage =
|
||||
code ===
|
||||
WorkspaceMigrationV2ExceptionCode.BUILDER_INTERNAL_SERVER_ERROR
|
||||
? t`An internal error occurred while validating your changes. Please contact support.`
|
||||
: t`An internal error occurred while applying your changes. Please contact support and try again later.`;
|
||||
|
||||
enqueueErrorSnackBar({ message: errorMessage });
|
||||
break;
|
||||
}
|
||||
}
|
||||
const handleMetadataError = (
|
||||
error: ApolloError,
|
||||
options: {
|
||||
primaryMetadataName: AllMetadataName;
|
||||
operationType: CrudOperationType;
|
||||
},
|
||||
[enqueueErrorSnackBar, TRANSLATED_METADATA_NAME],
|
||||
);
|
||||
) => {
|
||||
const classification = classifyMetadataError({
|
||||
error,
|
||||
primaryMetadataName: options.primaryMetadataName,
|
||||
});
|
||||
|
||||
const translatedMetadataName =
|
||||
TRANSLATED_METADATA_NAME[options.primaryMetadataName];
|
||||
|
||||
switch (classification.type) {
|
||||
case 'v1':
|
||||
enqueueErrorSnackBar({ apolloError: classification.error });
|
||||
break;
|
||||
|
||||
case 'v2-validation': {
|
||||
const { extensions, primaryMetadataName, relatedFailingMetadataNames } =
|
||||
classification;
|
||||
|
||||
const targetErrors = extensions.errors[primaryMetadataName] ?? [];
|
||||
if (targetErrors.length > 0) {
|
||||
targetErrors.forEach((entityError) => {
|
||||
entityError.errors.forEach((validationError) =>
|
||||
enqueueErrorSnackBar({
|
||||
message:
|
||||
validationError.userFriendlyMessage ??
|
||||
validationError.message,
|
||||
}),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
const translatedOperationType =
|
||||
TRANSLATED_OPERATION_TYPE[options.operationType];
|
||||
|
||||
if (
|
||||
targetErrors.length === 0 &&
|
||||
relatedFailingMetadataNames.length > 0
|
||||
) {
|
||||
const relatedEntityNames = relatedFailingMetadataNames
|
||||
.map((metadataName) => TRANSLATED_METADATA_NAME[metadataName])
|
||||
.join(', ');
|
||||
|
||||
enqueueErrorSnackBar({
|
||||
message: t`Failed to ${translatedOperationType} ${translatedMetadataName}. Related ${relatedEntityNames} validation failed. Please check your configuration and try again.`,
|
||||
});
|
||||
}
|
||||
|
||||
if (
|
||||
targetErrors.length === 0 &&
|
||||
relatedFailingMetadataNames.length === 0
|
||||
) {
|
||||
enqueueErrorSnackBar({
|
||||
message: t`Failed to ${translatedOperationType} ${translatedMetadataName}. Please try again.`,
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'v2-internal': {
|
||||
const { code } = classification;
|
||||
const errorMessage =
|
||||
code ===
|
||||
WorkspaceMigrationV2ExceptionCode.BUILDER_INTERNAL_SERVER_ERROR
|
||||
? t`An internal error occurred while validating your changes. Please contact support.`
|
||||
: t`An internal error occurred while applying your changes. Please contact support and try again later.`;
|
||||
|
||||
enqueueErrorSnackBar({ message: errorMessage });
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
handleMetadataError,
|
||||
|
||||
+2
@@ -10,6 +10,7 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { useRefreshCoreViewsByObjectMetadataId } from '@/views/hooks/useRefreshCoreViewsByObjectMetadataId';
|
||||
import { ApolloError } from '@apollo/client';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
|
||||
export const useCreateOneFieldMetadataItem = () => {
|
||||
const { refreshObjectMetadataItems } =
|
||||
@@ -52,6 +53,7 @@ export const useCreateOneFieldMetadataItem = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'fieldMetadata',
|
||||
operationType: CrudOperationType.CREATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
|
||||
+2
@@ -10,6 +10,7 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { useRefreshCoreViewsByObjectMetadataId } from '@/views/hooks/useRefreshCoreViewsByObjectMetadataId';
|
||||
import { ApolloError } from '@apollo/client';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
export const useCreateOneObjectMetadataItem = () => {
|
||||
@@ -54,6 +55,7 @@ export const useCreateOneObjectMetadataItem = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'objectMetadata',
|
||||
operationType: CrudOperationType.CREATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
|
||||
+2
@@ -13,6 +13,7 @@ import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state
|
||||
import { useRefreshCoreViewsByObjectMetadataId } from '@/views/hooks/useRefreshCoreViewsByObjectMetadataId';
|
||||
import { ApolloError } from '@apollo/client';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
|
||||
export const useDeleteOneFieldMetadataItem = () => {
|
||||
const [deleteOneFieldMetadataItemMutation] =
|
||||
@@ -80,6 +81,7 @@ export const useDeleteOneFieldMetadataItem = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'fieldMetadata',
|
||||
operationType: CrudOperationType.DELETE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
|
||||
+2
@@ -7,6 +7,7 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { useRefreshAllCoreViews } from '@/views/hooks/useRefreshAllCoreViews';
|
||||
import { ApolloError } from '@apollo/client';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
|
||||
export const useDeleteOneObjectMetadataItem = () => {
|
||||
const [deleteOneObjectMetadataItemMutation] =
|
||||
@@ -45,6 +46,7 @@ export const useDeleteOneObjectMetadataItem = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'objectMetadata',
|
||||
operationType: CrudOperationType.DELETE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
|
||||
+2
@@ -10,6 +10,7 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { useRefreshCoreViewsByObjectMetadataId } from '@/views/hooks/useRefreshCoreViewsByObjectMetadataId';
|
||||
import { ApolloError } from '@apollo/client';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
|
||||
export const useUpdateOneFieldMetadataItem = () => {
|
||||
const { refreshObjectMetadataItems } =
|
||||
@@ -67,6 +68,7 @@ export const useUpdateOneFieldMetadataItem = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'fieldMetadata',
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
|
||||
+2
@@ -10,6 +10,7 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { useRefreshCoreViewsByObjectMetadataId } from '@/views/hooks/useRefreshCoreViewsByObjectMetadataId';
|
||||
import { ApolloError } from '@apollo/client';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
|
||||
// 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 useUpdateOneObjectMetadataItem = () => {
|
||||
@@ -55,6 +56,7 @@ export const useUpdateOneObjectMetadataItem = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'objectMetadata',
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { usePageLayoutDraftState } from '@/page-layout/hooks/usePageLayoutDraftState';
|
||||
import { useUpdatePageLayoutWithTabsAndWidgets } from '@/page-layout/hooks/useUpdatePageLayoutWithTabsAndWidgets';
|
||||
import { PageLayoutComponentInstanceContext } from '@/page-layout/states/contexts/PageLayoutComponentInstanceContext';
|
||||
import { pageLayoutCurrentLayoutsComponentState } from '@/page-layout/states/pageLayoutCurrentLayoutsComponentState';
|
||||
import { pageLayoutPersistedComponentState } from '@/page-layout/states/pageLayoutPersistedComponentState';
|
||||
@@ -10,7 +11,6 @@ import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/com
|
||||
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { useUpdatePageLayoutWithTabsAndWidgetsMutation } from '~/generated/graphql';
|
||||
|
||||
export const useSavePageLayout = (pageLayoutIdFromProps: string) => {
|
||||
const pageLayoutId = useAvailableComponentInstanceIdOrThrow(
|
||||
@@ -30,8 +30,8 @@ export const useSavePageLayout = (pageLayoutIdFromProps: string) => {
|
||||
|
||||
const { pageLayoutDraft } = usePageLayoutDraftState(pageLayoutId);
|
||||
|
||||
const [updatePageLayoutWithTabsAndWidgets] =
|
||||
useUpdatePageLayoutWithTabsAndWidgetsMutation();
|
||||
const { updatePageLayoutWithTabsAndWidgets } =
|
||||
useUpdatePageLayoutWithTabsAndWidgets();
|
||||
|
||||
const savePageLayout = useRecoilCallback(
|
||||
({ set }) =>
|
||||
@@ -39,25 +39,28 @@ export const useSavePageLayout = (pageLayoutIdFromProps: string) => {
|
||||
const updateInput =
|
||||
convertPageLayoutDraftToUpdateInput(pageLayoutDraft);
|
||||
|
||||
const { data } = await updatePageLayoutWithTabsAndWidgets({
|
||||
variables: {
|
||||
id: pageLayoutId,
|
||||
input: updateInput,
|
||||
},
|
||||
});
|
||||
const result = await updatePageLayoutWithTabsAndWidgets(
|
||||
pageLayoutId,
|
||||
updateInput,
|
||||
);
|
||||
|
||||
const updatedPageLayout = data?.updatePageLayoutWithTabsAndWidgets;
|
||||
if (result.status === 'successful') {
|
||||
const updatedPageLayout =
|
||||
result.response.data?.updatePageLayoutWithTabsAndWidgets;
|
||||
|
||||
if (isDefined(updatedPageLayout)) {
|
||||
const pageLayoutToPersist: PageLayout =
|
||||
transformPageLayout(updatedPageLayout);
|
||||
if (isDefined(updatedPageLayout)) {
|
||||
const pageLayoutToPersist: PageLayout =
|
||||
transformPageLayout(updatedPageLayout);
|
||||
|
||||
set(pageLayoutPersistedCallbackState, pageLayoutToPersist);
|
||||
set(
|
||||
pageLayoutCurrentLayoutsCallbackState,
|
||||
convertPageLayoutToTabLayouts(pageLayoutToPersist),
|
||||
);
|
||||
set(pageLayoutPersistedCallbackState, pageLayoutToPersist);
|
||||
set(
|
||||
pageLayoutCurrentLayoutsCallbackState,
|
||||
convertPageLayoutToTabLayouts(pageLayoutToPersist),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
[
|
||||
pageLayoutCurrentLayoutsCallbackState,
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
import {
|
||||
type UpdatePageLayoutWithTabsInput,
|
||||
useUpdatePageLayoutWithTabsAndWidgetsMutation,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
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 { ApolloError } from '@apollo/client';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
|
||||
export const useUpdatePageLayoutWithTabsAndWidgets = () => {
|
||||
const [updatePageLayoutWithTabsAndWidgetsMutation] =
|
||||
useUpdatePageLayoutWithTabsAndWidgetsMutation();
|
||||
|
||||
const { handleMetadataError } = useMetadataErrorHandler();
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
|
||||
const updatePageLayoutWithTabsAndWidgets = async (
|
||||
id: string,
|
||||
input: UpdatePageLayoutWithTabsInput,
|
||||
): Promise<
|
||||
MetadataRequestResult<
|
||||
Awaited<ReturnType<typeof updatePageLayoutWithTabsAndWidgetsMutation>>
|
||||
>
|
||||
> => {
|
||||
try {
|
||||
const updatedPageLayout =
|
||||
await updatePageLayoutWithTabsAndWidgetsMutation({
|
||||
variables: {
|
||||
id,
|
||||
input,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: updatedPageLayout,
|
||||
};
|
||||
} catch (error) {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'pageLayout',
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
}
|
||||
|
||||
return {
|
||||
status: 'failed',
|
||||
error,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
updatePageLayoutWithTabsAndWidgets,
|
||||
};
|
||||
};
|
||||
+4
@@ -12,6 +12,7 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { ApolloError, useMutation } from '@apollo/client';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import {
|
||||
type CreateOneServerlessFunctionItemMutation,
|
||||
type CreateOneServerlessFunctionItemMutationVariables,
|
||||
@@ -72,6 +73,7 @@ export const usePersistServerlessFunction = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'serverlessFunction',
|
||||
operationType: CrudOperationType.CREATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
@@ -114,6 +116,7 @@ export const usePersistServerlessFunction = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'serverlessFunction',
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
@@ -157,6 +160,7 @@ export const usePersistServerlessFunction = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'serverlessFunction',
|
||||
operationType: CrudOperationType.DELETE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
|
||||
@@ -6,6 +6,7 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { useViewsSideEffectsOnViewGroups } from '@/views/hooks/useViewsSideEffectsOnViewGroups';
|
||||
import { ApolloError } from '@apollo/client';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
import {
|
||||
@@ -72,6 +73,7 @@ export const usePersistView = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'view',
|
||||
operationType: CrudOperationType.CREATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
@@ -110,6 +112,7 @@ export const usePersistView = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'view',
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
@@ -143,6 +146,7 @@ export const usePersistView = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'view',
|
||||
operationType: CrudOperationType.DELETE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
|
||||
@@ -6,6 +6,7 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { useTriggerViewFieldOptimisticEffect } from '@/views/optimistic-effects/hooks/useTriggerViewFieldOptimisticEffect';
|
||||
import { ApolloError } from '@apollo/client';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
type CreateManyCoreViewFieldsMutationVariables,
|
||||
@@ -71,6 +72,7 @@ export const usePersistViewField = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewField',
|
||||
operationType: CrudOperationType.CREATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
@@ -132,6 +134,7 @@ export const usePersistViewField = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewField',
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
@@ -193,6 +196,7 @@ export const usePersistViewField = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewField',
|
||||
operationType: CrudOperationType.DELETE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
@@ -244,6 +248,7 @@ export const usePersistViewField = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewField',
|
||||
operationType: CrudOperationType.DESTROY,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
|
||||
@@ -6,6 +6,7 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { useTriggerViewFilterOptimisticEffect } from '@/views/optimistic-effects/hooks/useTriggerViewFilterOptimisticEffect';
|
||||
import { ApolloError } from '@apollo/client';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
type CreateCoreViewFilterMutationVariables,
|
||||
@@ -71,6 +72,7 @@ export const usePersistViewFilterRecords = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewFilter',
|
||||
operationType: CrudOperationType.CREATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
@@ -132,6 +134,7 @@ export const usePersistViewFilterRecords = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewFilter',
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
@@ -193,6 +196,7 @@ export const usePersistViewFilterRecords = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewFilter',
|
||||
operationType: CrudOperationType.DELETE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
@@ -244,6 +248,7 @@ export const usePersistViewFilterRecords = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewFilter',
|
||||
operationType: CrudOperationType.DESTROY,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
|
||||
@@ -6,6 +6,7 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { useTriggerViewGroupOptimisticEffect } from '@/views/optimistic-effects/hooks/useTriggerViewGroupOptimisticEffect';
|
||||
import { ApolloError } from '@apollo/client';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
type UpdateCoreViewGroupMutationVariables,
|
||||
@@ -63,6 +64,7 @@ export const usePersistViewGroupRecords = () => {
|
||||
if (error instanceof ApolloError) {
|
||||
handleMetadataError(error, {
|
||||
primaryMetadataName: 'viewGroup',
|
||||
operationType: CrudOperationType.UPDATE,
|
||||
});
|
||||
} else {
|
||||
enqueueErrorSnackBar({ message: t`An error occurred.` });
|
||||
|
||||
Reference in New Issue
Block a user