refactor: metadata store cleanup, SSE unification, mock metadata loading & login redirect fix (#18651)
## Summary - **SSE unification**: Replaced 11 individual SSE effect components with a single generic `MetadataStoreSSEEffect` - **Metadata store cleanup**: Merged `metadataCollectionHashesState` into `metadataStoreState` (currentCollectionHash / draftCollectionHash per entity), moved `objectMetadataItemsSelector` to `object-metadata` domain, converted `navigationMenuItemsState` to a derived selector - **Naming clarity**: Renamed `isAppMetadataReadyState` → `isMinimalMetadataReadyState`, `MetadataGater` → `MinimalMetadataGater`, `useIsLogged` → `useHasAccessTokenPair`, `patchMetadataStoreFromSSEEvent` now takes named object params - **Mock metadata loading**: Added `generate-navigation-menu-items.ts` script, rewrote `useLoadMockedMinimalMetadata` to load full objects/fields/indexes/views/navItems from generated mock data, enabling proper sign-in background rendering (table columns, view picker, navigation) - **Login/logout transitions**: `MinimalMetadataLoadEffect` manages mocked↔real metadata transitions based on auth state, `MainContextStoreProvider` computes context on auth pages for view picker support - **Login redirect fix**: `handleLoadWorkspaceAfterAuthentication` now re-enables `isAppEffectRedirectEnabled` after `loadCurrentUser()` completes, fixing the blocked post-login navigation - **Dead code removal**: Deleted `useRefreshPageLayouts`, `useApplyPageLayouts`, `useStaleMetadataEntities`, `metadataCollectionHashesState`, and all individual SSE effects ## Test plan - [x] Login from welcome page redirects to companies page - [x] Logout transitions cleanly to mocked metadata on welcome page - [x] Sign-in background shows table columns, view picker, and navigation items - [x] SSE events still update metadata store entries correctly - [x] Navigation menu items persist across page refreshes - [ ] CI: lint, typecheck, tests pass
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import { styled } from '@linaria/react';
|
||||
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
|
||||
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
|
||||
@@ -17,7 +16,6 @@ import { useAreViewSortsDifferentFromRecordSorts } from '@/views/hooks/useAreVie
|
||||
import { useCanPersistViewChanges } from '@/views/hooks/useCanPersistViewChanges';
|
||||
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
|
||||
import { useIsViewAnyFieldFilterDifferentFromCurrentAnyFieldFilter } from '@/views/hooks/useIsViewAnyFieldFilterDifferentFromCurrentAnyFieldFilter';
|
||||
import { useRefreshCoreViewsByObjectMetadataId } from '@/views/hooks/useRefreshCoreViewsByObjectMetadataId';
|
||||
import { useSaveCurrentViewFiltersAndSorts } from '@/views/hooks/useSaveCurrentViewFiltersAndSorts';
|
||||
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
|
||||
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
|
||||
@@ -39,11 +37,6 @@ export const UpdateViewButtonGroup = () => {
|
||||
const { saveCurrentViewFilterAndSorts } = useSaveCurrentViewFiltersAndSorts();
|
||||
const { canPersistChanges } = useCanPersistViewChanges();
|
||||
|
||||
const { refreshCoreViewsByObjectMetadataId } =
|
||||
useRefreshCoreViewsByObjectMetadataId();
|
||||
|
||||
const { objectMetadataItem } = useRecordIndexContextOrThrow();
|
||||
|
||||
const { setViewPickerMode } = useViewPickerMode();
|
||||
|
||||
const contextStoreCurrentViewId = useAtomComponentStateValue(
|
||||
@@ -83,7 +76,6 @@ export const UpdateViewButtonGroup = () => {
|
||||
const handleUpdateViewClick = async () => {
|
||||
if (!canPersistChanges) return;
|
||||
await saveCurrentViewFilterAndSorts();
|
||||
await refreshCoreViewsByObjectMetadataId(objectMetadataItem.id);
|
||||
};
|
||||
|
||||
const { hasFiltersQueryParams } = useHasFiltersInQueryParams();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { type ReactNode } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { ObjectSortDropdownButton } from '@/object-record/object-sort-dropdown/components/ObjectSortDropdownButton';
|
||||
import { TopBar } from '@/ui/layout/top-bar/components/TopBar';
|
||||
import { QueryParamsFiltersEffect } from '@/views/components/QueryParamsFiltersEffect';
|
||||
@@ -26,19 +26,27 @@ type ViewBarProps = {
|
||||
viewBarId: string;
|
||||
className?: string;
|
||||
optionsDropdownButton: ReactNode;
|
||||
isReadOnly?: boolean;
|
||||
};
|
||||
|
||||
export const ViewBar = ({
|
||||
viewBarId,
|
||||
className,
|
||||
optionsDropdownButton,
|
||||
isReadOnly = false,
|
||||
}: ViewBarProps) => {
|
||||
const { objectNamePlural } = useParams();
|
||||
const { objectNamePlural } = useRecordIndexContextOrThrow();
|
||||
|
||||
if (!objectNamePlural) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isReadOnly) {
|
||||
return (
|
||||
<TopBar className={className} leftComponent={<ViewPickerDropdown />} />
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<ObjectSortDropdownComponentInstanceContext.Provider
|
||||
value={{ instanceId: VIEW_SORT_DROPDOWN_ID }}
|
||||
|
||||
+4
-7
@@ -3,22 +3,21 @@ import { useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural';
|
||||
import { CoreObjectNameSingular } from 'twenty-shared/types';
|
||||
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
|
||||
import { RecordIndexContextProvider } from '@/object-record/record-index/contexts/RecordIndexContext';
|
||||
import { RecordTableComponentInstanceContext } from '@/object-record/record-table/states/context/RecordTableComponentInstanceContext';
|
||||
import { useSetAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useSetAtomComponentState';
|
||||
import { ViewBarFilterDropdown } from '@/views/components/ViewBarFilterDropdown';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
import { CoreObjectNameSingular } from 'twenty-shared/types';
|
||||
|
||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
||||
import { RecordComponentInstanceContextsWrapper } from '@/object-record/components/RecordComponentInstanceContextsWrapper';
|
||||
import { currentRecordFieldsComponentState } from '@/object-record/record-field/states/currentRecordFieldsComponentState';
|
||||
import { type RecordField } from '@/object-record/record-field/types/RecordField';
|
||||
import { useRecordIndexFieldMetadataDerivedStates } from '@/object-record/record-index/hooks/useRecordIndexFieldMetadataDerivedStates';
|
||||
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
|
||||
import { ViewBarFilterDropdownIds } from '@/views/constants/ViewBarFilterDropdownIds';
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { userEvent, within } from 'storybook/test';
|
||||
import { ComponentDecorator } from 'twenty-ui/testing';
|
||||
import { ContextStoreDecorator } from '~/testing/decorators/ContextStoreDecorator';
|
||||
@@ -27,6 +26,7 @@ import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadat
|
||||
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
|
||||
import { mockedCoreViews } from '~/testing/mock-data/generated/metadata/views/mock-views-data';
|
||||
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
|
||||
import { setTestCoreViewsInMetadataStore } from '~/testing/utils/setTestCoreViewsInMetadataStore';
|
||||
|
||||
const meta: Meta<typeof ViewBarFilterDropdown> = {
|
||||
title: 'Modules/Views/ViewBarFilterDropdown',
|
||||
@@ -43,8 +43,6 @@ const meta: Meta<typeof ViewBarFilterDropdown> = {
|
||||
instanceId,
|
||||
);
|
||||
|
||||
const setCoreViews = useSetAtomState(coreViewsState);
|
||||
|
||||
const mockCoreView = mockedCoreViews.find(
|
||||
(v) => v.name === 'All Companies',
|
||||
)!;
|
||||
@@ -72,12 +70,11 @@ const meta: Meta<typeof ViewBarFilterDropdown> = {
|
||||
const [isLoaded, setIsLoaded] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
setCoreViews([mockCoreView]);
|
||||
setTestCoreViewsInMetadataStore(jotaiStore, [mockCoreView]);
|
||||
setContextStoreCurrentViewId(mockCoreView.id);
|
||||
setCurrentRecordFields(columns);
|
||||
setIsLoaded(true);
|
||||
}, [
|
||||
setCoreViews,
|
||||
setContextStoreCurrentViewId,
|
||||
setCurrentRecordFields,
|
||||
mockCoreView,
|
||||
|
||||
+3
-3
@@ -6,7 +6,6 @@ import { type RecordFilterGroup } from '@/object-record/record-filter-group/type
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
import { resetJotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
|
||||
import { useApplyCurrentViewFilterGroupsToCurrentRecordFilterGroups } from '@/views/hooks/useApplyCurrentViewFilterGroupsToCurrentRecordFilterGroups';
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations';
|
||||
import { type View } from '@/views/types/View';
|
||||
import { type ViewFilterGroup } from '@/views/types/ViewFilterGroup';
|
||||
@@ -18,6 +17,7 @@ import { type CoreViewFilterGroup } from '~/generated-metadata/graphql';
|
||||
import { getJestMetadataAndApolloMocksAndCommandMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndCommandMenuWrapper';
|
||||
import { mockedCoreViews } from '~/testing/mock-data/generated/metadata/views/mock-views-data';
|
||||
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
|
||||
import { setTestCoreViewsInMetadataStore } from '~/testing/utils/setTestCoreViewsInMetadataStore';
|
||||
|
||||
const mockObjectMetadataItemNameSingular = 'company';
|
||||
|
||||
@@ -94,7 +94,7 @@ describe('useApplyCurrentViewFilterGroupsToCurrentRecordFilterGroups', () => {
|
||||
contextStoreCurrentObjectMetadataNameSingular:
|
||||
mockObjectMetadataItemNameSingular,
|
||||
onInitializeJotaiStore: (store) => {
|
||||
store.set(coreViewsState.atom, [mockCoreView]);
|
||||
setTestCoreViewsInMetadataStore(store, [mockCoreView]);
|
||||
},
|
||||
}),
|
||||
},
|
||||
@@ -186,7 +186,7 @@ describe('useApplyCurrentViewFilterGroupsToCurrentRecordFilterGroups', () => {
|
||||
contextStoreCurrentObjectMetadataNameSingular:
|
||||
mockObjectMetadataItemNameSingular,
|
||||
onInitializeJotaiStore: (store) => {
|
||||
store.set(coreViewsState.atom, [
|
||||
setTestCoreViewsInMetadataStore(store, [
|
||||
{ ...mockCoreView, viewFilterGroups: [] },
|
||||
]);
|
||||
store.set(
|
||||
|
||||
+4
-4
@@ -5,7 +5,7 @@ import { currentRecordFiltersComponentState } from '@/object-record/record-filte
|
||||
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
import { resetJotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { useApplyCurrentViewFiltersToCurrentRecordFilters } from '@/views/hooks/useApplyCurrentViewFiltersToCurrentRecordFilters';
|
||||
import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations';
|
||||
import { type View } from '@/views/types/View';
|
||||
import { type ViewFilter } from '@/views/types/ViewFilter';
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
import { getJestMetadataAndApolloMocksAndCommandMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndCommandMenuWrapper';
|
||||
import { mockedCoreViews } from '~/testing/mock-data/generated/metadata/views/mock-views-data';
|
||||
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
|
||||
import { useApplyCurrentViewFiltersToCurrentRecordFilters } from '@/views/hooks/useApplyCurrentViewFiltersToCurrentRecordFilters';
|
||||
import { setTestCoreViewsInMetadataStore } from '~/testing/utils/setTestCoreViewsInMetadataStore';
|
||||
|
||||
const mockObjectMetadataItemNameSingular = 'company';
|
||||
|
||||
@@ -105,7 +105,7 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
|
||||
mockObjectMetadataItemNameSingular,
|
||||
contextStoreCurrentViewId: mockView.id,
|
||||
onInitializeJotaiStore: (store) => {
|
||||
store.set(coreViewsState.atom, [mockCoreView]);
|
||||
setTestCoreViewsInMetadataStore(store, [mockCoreView]);
|
||||
},
|
||||
}),
|
||||
},
|
||||
@@ -195,7 +195,7 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
|
||||
contextStoreCurrentObjectMetadataNameSingular:
|
||||
mockObjectMetadataItemNameSingular,
|
||||
onInitializeJotaiStore: (store) => {
|
||||
store.set(coreViewsState.atom, [
|
||||
setTestCoreViewsInMetadataStore(store, [
|
||||
{ ...mockCoreView, viewFilters: [] },
|
||||
]);
|
||||
store.set(
|
||||
|
||||
+5
-5
@@ -6,17 +6,17 @@ import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/use
|
||||
|
||||
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
|
||||
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { useApplyCurrentViewSortsToCurrentRecordSorts } from '@/views/hooks/useApplyCurrentViewSortsToCurrentRecordSorts';
|
||||
import { type CoreViewSortEssential } from '@/views/types/CoreViewSortEssential';
|
||||
import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations';
|
||||
import { type View } from '@/views/types/View';
|
||||
import { type ViewSort } from '@/views/types/ViewSort';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { ViewSortDirection } from '~/generated-metadata/graphql';
|
||||
import { getJestMetadataAndApolloMocksAndCommandMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndCommandMenuWrapper';
|
||||
import { mockedCoreViews } from '~/testing/mock-data/generated/metadata/views/mock-views-data';
|
||||
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
|
||||
import { useApplyCurrentViewSortsToCurrentRecordSorts } from '@/views/hooks/useApplyCurrentViewSortsToCurrentRecordSorts';
|
||||
import { type ViewSort } from '@/views/types/ViewSort';
|
||||
import { setTestCoreViewsInMetadataStore } from '~/testing/utils/setTestCoreViewsInMetadataStore';
|
||||
|
||||
const mockObjectMetadataItemNameSingular = 'company';
|
||||
|
||||
@@ -93,7 +93,7 @@ describe('useApplyCurrentViewSortsToCurrentRecordSorts', () => {
|
||||
mockObjectMetadataItemNameSingular,
|
||||
contextStoreCurrentViewId: mockView.id,
|
||||
onInitializeJotaiStore: (store) => {
|
||||
store.set(coreViewsState.atom, [mockCoreView]);
|
||||
setTestCoreViewsInMetadataStore(store, [mockCoreView]);
|
||||
},
|
||||
}),
|
||||
},
|
||||
@@ -182,7 +182,7 @@ describe('useApplyCurrentViewSortsToCurrentRecordSorts', () => {
|
||||
contextStoreCurrentObjectMetadataNameSingular:
|
||||
mockObjectMetadataItemNameSingular,
|
||||
onInitializeJotaiStore: (store) => {
|
||||
store.set(coreViewsState.atom, [viewWithNoSorts]);
|
||||
setTestCoreViewsInMetadataStore(store, [viewWithNoSorts]);
|
||||
store.set(
|
||||
contextStoreCurrentViewIdComponentState.atomFamily({
|
||||
instanceId: 'instanceId',
|
||||
|
||||
@@ -38,7 +38,6 @@ export const usePerformViewAPIPersist = () => {
|
||||
const newViewId = variables.input.id ?? v4();
|
||||
if (variables.input.type === ViewType.KANBAN) {
|
||||
triggerViewGroupOptimisticEffectAtViewCreation({
|
||||
newViewId,
|
||||
objectMetadataItemId: objectMetadataItemId,
|
||||
mainGroupByFieldMetadataId:
|
||||
variables.input.mainGroupByFieldMetadataId,
|
||||
|
||||
@@ -3,15 +3,11 @@ 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 { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { CombinedGraphQLErrors } from '@apollo/client/errors';
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
import { CrudOperationType } from 'twenty-shared/types';
|
||||
import { upsertPropertiesOfItemIntoArrayOfObjectsComparingId } from 'twenty-shared/utils';
|
||||
import { useMutation } from '@apollo/client/react';
|
||||
import {
|
||||
type CoreView,
|
||||
type UpdateCoreViewMutationVariables,
|
||||
UpdateCoreViewDocument,
|
||||
} from '~/generated-metadata/graphql';
|
||||
@@ -22,8 +18,6 @@ export const usePerformViewAPIUpdate = () => {
|
||||
const { handleMetadataError } = useMetadataErrorHandler();
|
||||
const { enqueueErrorSnackBar } = useSnackBar();
|
||||
|
||||
const setCoreViews = useSetAtomState(coreViewsState);
|
||||
|
||||
const performViewAPIUpdate = useCallback(
|
||||
async (
|
||||
variables: UpdateCoreViewMutationVariables,
|
||||
@@ -31,30 +25,10 @@ export const usePerformViewAPIUpdate = () => {
|
||||
MetadataRequestResult<Awaited<ReturnType<typeof updateCoreViewMutation>>>
|
||||
> => {
|
||||
try {
|
||||
setCoreViews((currentCoreViews) =>
|
||||
upsertPropertiesOfItemIntoArrayOfObjectsComparingId(
|
||||
currentCoreViews,
|
||||
{
|
||||
...variables.input,
|
||||
id: variables.id,
|
||||
} as CoreView,
|
||||
),
|
||||
);
|
||||
|
||||
const result = await updateCoreViewMutation({
|
||||
variables,
|
||||
});
|
||||
|
||||
setCoreViews((currentCoreViews) =>
|
||||
upsertPropertiesOfItemIntoArrayOfObjectsComparingId(
|
||||
currentCoreViews,
|
||||
{
|
||||
...result.data?.updateCoreView,
|
||||
id: variables.id,
|
||||
} as CoreView,
|
||||
),
|
||||
);
|
||||
|
||||
return {
|
||||
status: 'successful',
|
||||
response: result,
|
||||
@@ -75,12 +49,7 @@ export const usePerformViewAPIUpdate = () => {
|
||||
};
|
||||
}
|
||||
},
|
||||
[
|
||||
setCoreViews,
|
||||
updateCoreViewMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
],
|
||||
[updateCoreViewMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
);
|
||||
|
||||
return { performViewAPIUpdate };
|
||||
|
||||
+2
-48
@@ -3,11 +3,9 @@ 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 { useTriggerViewFieldOptimisticEffect } from '@/views/optimistic-effects/hooks/useTriggerViewFieldOptimisticEffect';
|
||||
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 { useMutation } from '@apollo/client/react';
|
||||
import {
|
||||
type CreateManyCoreViewFieldsMutationVariables,
|
||||
@@ -21,9 +19,6 @@ import {
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const usePerformViewFieldAPIPersist = () => {
|
||||
const { triggerViewFieldOptimisticEffect } =
|
||||
useTriggerViewFieldOptimisticEffect();
|
||||
|
||||
const [createManyCoreViewFieldsMutation] = useMutation(
|
||||
CreateManyCoreViewFieldsDocument,
|
||||
);
|
||||
@@ -61,16 +56,6 @@ export const usePerformViewFieldAPIPersist = () => {
|
||||
try {
|
||||
const result = await createManyCoreViewFieldsMutation({
|
||||
variables: createCoreViewFieldInputs,
|
||||
update: (_cache, { data }) => {
|
||||
const createdViewFields = data?.createManyCoreViewFields;
|
||||
if (!isDefined(createdViewFields)) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerViewFieldOptimisticEffect({
|
||||
createdViewFields,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -94,7 +79,6 @@ export const usePerformViewFieldAPIPersist = () => {
|
||||
}
|
||||
},
|
||||
[
|
||||
triggerViewFieldOptimisticEffect,
|
||||
createManyCoreViewFieldsMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
@@ -121,16 +105,6 @@ export const usePerformViewFieldAPIPersist = () => {
|
||||
createCoreViewFieldInputs.map((variables) =>
|
||||
updateCoreViewFieldMutation({
|
||||
variables,
|
||||
update: (_cache, { data }) => {
|
||||
const updatedViewField = data?.updateCoreViewField;
|
||||
if (!isDefined(updatedViewField)) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerViewFieldOptimisticEffect({
|
||||
updatedViewFields: [updatedViewField],
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
@@ -155,12 +129,7 @@ export const usePerformViewFieldAPIPersist = () => {
|
||||
};
|
||||
}
|
||||
},
|
||||
[
|
||||
triggerViewFieldOptimisticEffect,
|
||||
updateCoreViewFieldMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
],
|
||||
[updateCoreViewFieldMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
);
|
||||
|
||||
const performViewFieldAPIDelete = useCallback(
|
||||
@@ -183,16 +152,6 @@ export const usePerformViewFieldAPIPersist = () => {
|
||||
deleteCoreViewFieldInputs.map((variables) =>
|
||||
deleteCoreViewFieldMutation({
|
||||
variables,
|
||||
update: (_cache, { data }) => {
|
||||
const deletedViewField = data?.deleteCoreViewField;
|
||||
if (!isDefined(deletedViewField)) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerViewFieldOptimisticEffect({
|
||||
deletedViewFields: [deletedViewField],
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
@@ -217,12 +176,7 @@ export const usePerformViewFieldAPIPersist = () => {
|
||||
};
|
||||
}
|
||||
},
|
||||
[
|
||||
triggerViewFieldOptimisticEffect,
|
||||
deleteCoreViewFieldMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
],
|
||||
[deleteCoreViewFieldMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
);
|
||||
|
||||
const performViewFieldAPIDestroy = useCallback(
|
||||
|
||||
-37
@@ -6,7 +6,6 @@ import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||
import { CREATE_MANY_CORE_VIEW_FIELD_GROUPS } from '@/views/graphql/mutations/createManyCoreViewFieldGroups';
|
||||
import { DELETE_CORE_VIEW_FIELD_GROUP } from '@/views/graphql/mutations/deleteCoreViewFieldGroup';
|
||||
import { UPDATE_CORE_VIEW_FIELD_GROUP } from '@/views/graphql/mutations/updateCoreViewFieldGroup';
|
||||
import { useTriggerViewFieldGroupOptimisticEffect } from '@/views/optimistic-effects/hooks/useTriggerViewFieldGroupOptimisticEffect';
|
||||
import { useMutation } from '@apollo/client/react';
|
||||
import { CombinedGraphQLErrors } from '@apollo/client/errors';
|
||||
import { t } from '@lingui/core/macro';
|
||||
@@ -32,9 +31,6 @@ type DeleteCoreViewFieldGroupMutationResult = {
|
||||
};
|
||||
|
||||
export const usePerformViewFieldGroupAPIPersist = () => {
|
||||
const { triggerViewFieldGroupOptimisticEffect } =
|
||||
useTriggerViewFieldGroupOptimisticEffect();
|
||||
|
||||
const [createManyCoreViewFieldGroupsMutation] = useMutation<
|
||||
CreateManyCoreViewFieldGroupsMutationResult,
|
||||
MutationCreateManyCoreViewFieldGroupsArgs
|
||||
@@ -70,16 +66,6 @@ export const usePerformViewFieldGroupAPIPersist = () => {
|
||||
try {
|
||||
const result = await createManyCoreViewFieldGroupsMutation({
|
||||
variables: createCoreViewFieldGroupInputs,
|
||||
update: (_cache, { data }) => {
|
||||
const createdViewFieldGroups = data?.createManyCoreViewFieldGroups;
|
||||
if (!isDefined(createdViewFieldGroups)) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerViewFieldGroupOptimisticEffect({
|
||||
createdViewFieldGroups,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -103,7 +89,6 @@ export const usePerformViewFieldGroupAPIPersist = () => {
|
||||
}
|
||||
},
|
||||
[
|
||||
triggerViewFieldGroupOptimisticEffect,
|
||||
createManyCoreViewFieldGroupsMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
@@ -128,16 +113,6 @@ export const usePerformViewFieldGroupAPIPersist = () => {
|
||||
updateCoreViewFieldGroupInputs.map((variables) =>
|
||||
updateCoreViewFieldGroupMutation({
|
||||
variables,
|
||||
update: (_cache, { data }) => {
|
||||
const updatedViewFieldGroup = data?.updateCoreViewFieldGroup;
|
||||
if (!isDefined(updatedViewFieldGroup)) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerViewFieldGroupOptimisticEffect({
|
||||
updatedViewFieldGroups: [updatedViewFieldGroup],
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
@@ -165,7 +140,6 @@ export const usePerformViewFieldGroupAPIPersist = () => {
|
||||
}
|
||||
},
|
||||
[
|
||||
triggerViewFieldGroupOptimisticEffect,
|
||||
updateCoreViewFieldGroupMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
@@ -190,16 +164,6 @@ export const usePerformViewFieldGroupAPIPersist = () => {
|
||||
deleteCoreViewFieldGroupInputs.map((variables) =>
|
||||
deleteCoreViewFieldGroupMutation({
|
||||
variables,
|
||||
update: (_cache, { data }) => {
|
||||
const deletedViewFieldGroup = data?.deleteCoreViewFieldGroup;
|
||||
if (!isDefined(deletedViewFieldGroup)) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerViewFieldGroupOptimisticEffect({
|
||||
deletedViewFieldGroups: [deletedViewFieldGroup],
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
@@ -227,7 +191,6 @@ export const usePerformViewFieldGroupAPIPersist = () => {
|
||||
}
|
||||
},
|
||||
[
|
||||
triggerViewFieldGroupOptimisticEffect,
|
||||
deleteCoreViewFieldGroupMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
|
||||
+3
-52
@@ -3,11 +3,9 @@ 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 { useTriggerViewFilterOptimisticEffect } from '@/views/optimistic-effects/hooks/useTriggerViewFilterOptimisticEffect';
|
||||
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 { useMutation } from '@apollo/client/react';
|
||||
import {
|
||||
type CreateCoreViewFilterMutationVariables,
|
||||
@@ -21,8 +19,6 @@ import {
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const usePerformViewFilterAPIPersist = () => {
|
||||
const { triggerViewFilterOptimisticEffect } =
|
||||
useTriggerViewFilterOptimisticEffect();
|
||||
const [createCoreViewFilterMutation] = useMutation(
|
||||
CreateCoreViewFilterDocument,
|
||||
);
|
||||
@@ -59,16 +55,6 @@ export const usePerformViewFilterAPIPersist = () => {
|
||||
createCoreViewFilterInputs.map((variables) =>
|
||||
createCoreViewFilterMutation({
|
||||
variables,
|
||||
update: (_cache, { data }) => {
|
||||
const createdViewFilter = data?.createCoreViewFilter;
|
||||
if (!isDefined(createdViewFilter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerViewFilterOptimisticEffect({
|
||||
createdViewFilters: [createdViewFilter],
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
@@ -93,12 +79,7 @@ export const usePerformViewFilterAPIPersist = () => {
|
||||
};
|
||||
}
|
||||
},
|
||||
[
|
||||
triggerViewFilterOptimisticEffect,
|
||||
createCoreViewFilterMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
],
|
||||
[createCoreViewFilterMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
);
|
||||
|
||||
const performViewFilterAPIUpdate = useCallback(
|
||||
@@ -121,16 +102,6 @@ export const usePerformViewFilterAPIPersist = () => {
|
||||
updateCoreViewFilterInputs.map((variables) =>
|
||||
updateCoreViewFilterMutation({
|
||||
variables,
|
||||
update: (_cache, { data }) => {
|
||||
const updatedViewFilter = data?.updateCoreViewFilter;
|
||||
if (!isDefined(updatedViewFilter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerViewFilterOptimisticEffect({
|
||||
updatedViewFilters: [updatedViewFilter],
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
@@ -155,12 +126,7 @@ export const usePerformViewFilterAPIPersist = () => {
|
||||
};
|
||||
}
|
||||
},
|
||||
[
|
||||
triggerViewFilterOptimisticEffect,
|
||||
updateCoreViewFilterMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
],
|
||||
[updateCoreViewFilterMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
);
|
||||
|
||||
const performViewFilterAPIDelete = useCallback(
|
||||
@@ -183,16 +149,6 @@ export const usePerformViewFilterAPIPersist = () => {
|
||||
deleteCoreViewFilterInputs.map((variables) =>
|
||||
deleteCoreViewFilterMutation({
|
||||
variables,
|
||||
update: (_cache, { data }) => {
|
||||
const deletedViewFilter = data?.deleteCoreViewFilter;
|
||||
if (!isDefined(deletedViewFilter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerViewFilterOptimisticEffect({
|
||||
deletedViewFilters: [deletedViewFilter],
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
@@ -217,12 +173,7 @@ export const usePerformViewFilterAPIPersist = () => {
|
||||
};
|
||||
}
|
||||
},
|
||||
[
|
||||
triggerViewFilterOptimisticEffect,
|
||||
deleteCoreViewFilterMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
],
|
||||
[deleteCoreViewFilterMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
);
|
||||
|
||||
const performViewFilterAPIDestroy = useCallback(
|
||||
|
||||
+1
-21
@@ -3,11 +3,9 @@ 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 { useTriggerViewGroupOptimisticEffect } from '@/views/optimistic-effects/hooks/useTriggerViewGroupOptimisticEffect';
|
||||
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 { useMutation } from '@apollo/client/react';
|
||||
import {
|
||||
type UpdateCoreViewGroupMutationVariables,
|
||||
@@ -15,9 +13,6 @@ import {
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const usePerformViewGroupAPIPersist = () => {
|
||||
const { triggerViewGroupOptimisticEffect } =
|
||||
useTriggerViewGroupOptimisticEffect();
|
||||
|
||||
const [updateCoreViewGroupMutation] = useMutation(
|
||||
UpdateCoreViewGroupDocument,
|
||||
);
|
||||
@@ -45,16 +40,6 @@ export const usePerformViewGroupAPIPersist = () => {
|
||||
updateCoreViewGroupInputs.map((variables) =>
|
||||
updateCoreViewGroupMutation({
|
||||
variables,
|
||||
update: (_cache, { data }) => {
|
||||
const updatedViewGroup = data?.updateCoreViewGroup;
|
||||
if (!isDefined(updatedViewGroup)) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerViewGroupOptimisticEffect({
|
||||
updatedViewGroups: [updatedViewGroup],
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
@@ -79,12 +64,7 @@ export const usePerformViewGroupAPIPersist = () => {
|
||||
};
|
||||
}
|
||||
},
|
||||
[
|
||||
triggerViewGroupOptimisticEffect,
|
||||
updateCoreViewGroupMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
],
|
||||
[updateCoreViewGroupMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
+3
-57
@@ -3,11 +3,9 @@ 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 { useTriggerViewSortOptimisticEffect } from '@/views/optimistic-effects/hooks/useTriggerViewSortOptimisticEffect';
|
||||
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 { useMutation } from '@apollo/client/react';
|
||||
import {
|
||||
type CreateCoreViewSortMutationVariables,
|
||||
@@ -21,8 +19,6 @@ import {
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const usePerformViewSortAPIPersist = () => {
|
||||
const { triggerViewSortOptimisticEffect } =
|
||||
useTriggerViewSortOptimisticEffect();
|
||||
const [createCoreViewSortMutation] = useMutation(CreateCoreViewSortDocument);
|
||||
const [updateCoreViewSortMutation] = useMutation(UpdateCoreViewSortDocument);
|
||||
const [deleteCoreViewSortMutation] = useMutation(DeleteCoreViewSortDocument);
|
||||
@@ -53,16 +49,6 @@ export const usePerformViewSortAPIPersist = () => {
|
||||
createCoreViewSortInputs.map((variables) =>
|
||||
createCoreViewSortMutation({
|
||||
variables,
|
||||
update: (_cache, { data }) => {
|
||||
const createdViewSort = data?.createCoreViewSort;
|
||||
if (!isDefined(createdViewSort)) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerViewSortOptimisticEffect({
|
||||
createdViewSorts: [createdViewSort],
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
@@ -86,12 +72,7 @@ export const usePerformViewSortAPIPersist = () => {
|
||||
};
|
||||
}
|
||||
},
|
||||
[
|
||||
triggerViewSortOptimisticEffect,
|
||||
createCoreViewSortMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
],
|
||||
[createCoreViewSortMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
);
|
||||
|
||||
const performViewSortAPIUpdate = useCallback(
|
||||
@@ -114,16 +95,6 @@ export const usePerformViewSortAPIPersist = () => {
|
||||
updateCoreViewSortInputs.map((variables) =>
|
||||
updateCoreViewSortMutation({
|
||||
variables,
|
||||
update: (_cache, { data }) => {
|
||||
const updatedViewSort = data?.updateCoreViewSort;
|
||||
if (!isDefined(updatedViewSort)) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerViewSortOptimisticEffect({
|
||||
updatedViewSorts: [updatedViewSort],
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
@@ -148,12 +119,7 @@ export const usePerformViewSortAPIPersist = () => {
|
||||
};
|
||||
}
|
||||
},
|
||||
[
|
||||
triggerViewSortOptimisticEffect,
|
||||
updateCoreViewSortMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
],
|
||||
[updateCoreViewSortMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
);
|
||||
|
||||
const performViewSortAPIDelete = useCallback(
|
||||
@@ -176,21 +142,6 @@ export const usePerformViewSortAPIPersist = () => {
|
||||
deleteCoreViewSortInputs.map((variables) =>
|
||||
deleteCoreViewSortMutation({
|
||||
variables,
|
||||
update: (_cache, { data }) => {
|
||||
const deletedViewSort = data?.deleteCoreViewSort;
|
||||
|
||||
if (!isDefined(deletedViewSort)) {
|
||||
return;
|
||||
}
|
||||
|
||||
triggerViewSortOptimisticEffect({
|
||||
deletedViewSorts: [
|
||||
{
|
||||
id: variables.input.id,
|
||||
},
|
||||
],
|
||||
});
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
@@ -215,12 +166,7 @@ export const usePerformViewSortAPIPersist = () => {
|
||||
};
|
||||
}
|
||||
},
|
||||
[
|
||||
triggerViewSortOptimisticEffect,
|
||||
deleteCoreViewSortMutation,
|
||||
handleMetadataError,
|
||||
enqueueErrorSnackBar,
|
||||
],
|
||||
[deleteCoreViewSortMutation, handleMetadataError, enqueueErrorSnackBar],
|
||||
);
|
||||
|
||||
const performViewSortAPIDestroy = useCallback(
|
||||
|
||||
-173
@@ -1,173 +0,0 @@
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { currentRecordFieldsComponentState } from '@/object-record/record-field/states/currentRecordFieldsComponentState';
|
||||
import { currentRecordFilterGroupsComponentState } from '@/object-record/record-filter-group/states/currentRecordFilterGroupsComponentState';
|
||||
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
|
||||
import { recordIndexShouldHideEmptyRecordGroupsComponentState } from '@/object-record/record-index/states/recordIndexShouldHideEmptyRecordGroupsComponentState';
|
||||
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
|
||||
import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/utils/getRecordIndexIdFromObjectNamePluralAndViewId';
|
||||
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
|
||||
import { coreViewsByObjectMetadataIdFamilySelector } from '@/views/states/selectors/coreViewsByObjectMetadataIdFamilySelector';
|
||||
import { convertCoreViewToView } from '@/views/utils/convertCoreViewToView';
|
||||
import { getFilterableFields } from '@/views/utils/getFilterableFields';
|
||||
import { mapViewFieldToRecordField } from '@/views/utils/mapViewFieldToRecordField';
|
||||
import { mapViewFilterGroupsToRecordFilterGroups } from '@/views/utils/mapViewFilterGroupsToRecordFilterGroups';
|
||||
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
|
||||
import { useCallback } from 'react';
|
||||
import { isDefined, removePropertiesFromRecord } from 'twenty-shared/utils';
|
||||
import { type FindManyCoreViewsQuery } from '~/generated-metadata/graphql';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
export const useApplyCoreViewsForObjectMetadataId = () => {
|
||||
const applyCoreViewsForObjectMetadataId = useCallback(
|
||||
(
|
||||
objectMetadataId: string,
|
||||
coreViewsFromResult: FindManyCoreViewsQuery['getCoreViews'],
|
||||
) => {
|
||||
const objectMetadataItems = jotaiStore.get(objectMetadataItemsState.atom);
|
||||
|
||||
const objectMetadataItem = objectMetadataItems.find(
|
||||
(item) => item.id === objectMetadataId,
|
||||
);
|
||||
|
||||
if (!isDefined(objectMetadataItem)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const coreViewsForObjectMetadataId = jotaiStore.get(
|
||||
coreViewsByObjectMetadataIdFamilySelector.selectorFamily(
|
||||
objectMetadataId,
|
||||
),
|
||||
);
|
||||
|
||||
if (isDeeplyEqual(coreViewsForObjectMetadataId, coreViewsFromResult)) {
|
||||
return;
|
||||
}
|
||||
|
||||
jotaiStore.set(
|
||||
coreViewsByObjectMetadataIdFamilySelector.selectorFamily(
|
||||
objectMetadataId,
|
||||
),
|
||||
coreViewsFromResult,
|
||||
);
|
||||
|
||||
for (const coreView of coreViewsFromResult) {
|
||||
const existingView = coreViewsForObjectMetadataId.find(
|
||||
(coreViewForObjectMetadata) =>
|
||||
coreViewForObjectMetadata.id === coreView.id,
|
||||
);
|
||||
|
||||
if (!isDefined(existingView)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
!isDeeplyEqual(
|
||||
coreView.viewFields.map((viewField) =>
|
||||
removePropertiesFromRecord(viewField, ['updatedAt', 'createdAt']),
|
||||
),
|
||||
existingView.viewFields,
|
||||
)
|
||||
) {
|
||||
const view = convertCoreViewToView(coreView);
|
||||
jotaiStore.set(
|
||||
currentRecordFieldsComponentState.atomFamily({
|
||||
instanceId: getRecordIndexIdFromObjectNamePluralAndViewId(
|
||||
objectMetadataItem.namePlural,
|
||||
view.id,
|
||||
),
|
||||
}),
|
||||
view.viewFields
|
||||
.filter(isDefined)
|
||||
.map((viewField) => mapViewFieldToRecordField(viewField)),
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!isDeeplyEqual(
|
||||
coreView.viewFilters.map((viewFilter) =>
|
||||
removePropertiesFromRecord(viewFilter, [
|
||||
'createdAt',
|
||||
'updatedAt',
|
||||
]),
|
||||
),
|
||||
existingView.viewFilters,
|
||||
)
|
||||
) {
|
||||
const view = convertCoreViewToView(coreView);
|
||||
jotaiStore.set(
|
||||
currentRecordFiltersComponentState.atomFamily({
|
||||
instanceId: getRecordIndexIdFromObjectNamePluralAndViewId(
|
||||
objectMetadataItem.namePlural,
|
||||
view.id,
|
||||
),
|
||||
}),
|
||||
mapViewFiltersToFilters(
|
||||
view.viewFilters,
|
||||
getFilterableFields(objectMetadataItem),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!isDeeplyEqual(
|
||||
coreView.viewFilterGroups,
|
||||
existingView.viewFilterGroups,
|
||||
)
|
||||
) {
|
||||
const view = convertCoreViewToView(coreView);
|
||||
|
||||
jotaiStore.set(
|
||||
currentRecordFilterGroupsComponentState.atomFamily({
|
||||
instanceId: getRecordIndexIdFromObjectNamePluralAndViewId(
|
||||
objectMetadataItem.namePlural,
|
||||
view.id,
|
||||
),
|
||||
}),
|
||||
mapViewFilterGroupsToRecordFilterGroups(
|
||||
view.viewFilterGroups ?? [],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!isDeeplyEqual(
|
||||
coreView.viewSorts.map((viewSort) =>
|
||||
removePropertiesFromRecord(viewSort, ['createdAt', 'updatedAt']),
|
||||
),
|
||||
existingView.viewSorts,
|
||||
)
|
||||
) {
|
||||
const view = convertCoreViewToView(coreView);
|
||||
|
||||
jotaiStore.set(
|
||||
currentRecordSortsComponentState.atomFamily({
|
||||
instanceId: getRecordIndexIdFromObjectNamePluralAndViewId(
|
||||
objectMetadataItem.namePlural,
|
||||
view.id,
|
||||
),
|
||||
}),
|
||||
view.viewSorts,
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
coreView.shouldHideEmptyGroups !== existingView.shouldHideEmptyGroups
|
||||
) {
|
||||
const view = convertCoreViewToView(coreView);
|
||||
jotaiStore.set(
|
||||
recordIndexShouldHideEmptyRecordGroupsComponentState.atomFamily({
|
||||
instanceId: getRecordIndexIdFromObjectNamePluralAndViewId(
|
||||
objectMetadataItem.namePlural,
|
||||
view.id,
|
||||
),
|
||||
}),
|
||||
view.shouldHideEmptyGroups,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
return { applyCoreViewsForObjectMetadataId };
|
||||
};
|
||||
@@ -2,7 +2,6 @@ import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataI
|
||||
import { isHiddenSystemField } from '@/object-metadata/utils/isHiddenSystemField';
|
||||
import { usePerformViewAPIPersist } from '@/views/hooks/internal/usePerformViewAPIPersist';
|
||||
import { usePerformViewFieldAPIPersist } from '@/views/hooks/internal/usePerformViewFieldAPIPersist';
|
||||
import { useRefreshCoreViewsByObjectMetadataId } from '@/views/hooks/useRefreshCoreViewsByObjectMetadataId';
|
||||
import { useCallback } from 'react';
|
||||
import { v4 } from 'uuid';
|
||||
import { ViewType } from '~/generated-metadata/graphql';
|
||||
@@ -16,8 +15,6 @@ const pendingViewCreations = new Set<string>();
|
||||
export const useCreateDefaultViewForObject = () => {
|
||||
const { performViewAPICreate } = usePerformViewAPIPersist();
|
||||
const { performViewFieldAPICreate } = usePerformViewFieldAPIPersist();
|
||||
const { refreshCoreViewsByObjectMetadataId } =
|
||||
useRefreshCoreViewsByObjectMetadataId();
|
||||
|
||||
const createDefaultViewForObject = useCallback(
|
||||
async (objectMetadataItem: ObjectMetadataItem) => {
|
||||
@@ -76,17 +73,11 @@ export const useCreateDefaultViewForObject = () => {
|
||||
}));
|
||||
|
||||
await performViewFieldAPICreate({ inputs: viewFieldInputs });
|
||||
|
||||
await refreshCoreViewsByObjectMetadataId(objectMetadataItem.id);
|
||||
} finally {
|
||||
pendingViewCreations.delete(objectMetadataItem.id);
|
||||
}
|
||||
},
|
||||
[
|
||||
performViewAPICreate,
|
||||
performViewFieldAPICreate,
|
||||
refreshCoreViewsByObjectMetadataId,
|
||||
],
|
||||
[performViewAPICreate, performViewFieldAPICreate],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -11,7 +11,6 @@ import { usePerformViewFieldAPIPersist } from '@/views/hooks/internal/usePerform
|
||||
import { usePerformViewFilterAPIPersist } from '@/views/hooks/internal/usePerformViewFilterAPIPersist';
|
||||
import { usePerformViewFilterGroupAPIPersist } from '@/views/hooks/internal/usePerformViewFilterGroupAPIPersist';
|
||||
import { usePerformViewSortAPIPersist } from '@/views/hooks/internal/usePerformViewSortAPIPersist';
|
||||
import { useRefreshCoreViewsByObjectMetadataId } from '@/views/hooks/useRefreshCoreViewsByObjectMetadataId';
|
||||
import { coreViewFromViewIdFamilySelector } from '@/views/states/selectors/coreViewFromViewIdFamilySelector';
|
||||
import { type GraphQLView } from '@/views/types/GraphQLView';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
@@ -54,9 +53,6 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const { refreshCoreViewsByObjectMetadataId } =
|
||||
useRefreshCoreViewsByObjectMetadataId();
|
||||
|
||||
const currentRecordFilterGroups = useAtomComponentStateValue(
|
||||
currentRecordFilterGroupsComponentState,
|
||||
recordIndexId,
|
||||
@@ -246,8 +242,6 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
|
||||
}
|
||||
}
|
||||
|
||||
await refreshCoreViewsByObjectMetadataId(objectMetadataItem.id);
|
||||
|
||||
return newViewId;
|
||||
},
|
||||
[
|
||||
@@ -256,7 +250,6 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
|
||||
anyFieldFilterValue,
|
||||
objectMetadataItem,
|
||||
performViewFieldAPICreate,
|
||||
refreshCoreViewsByObjectMetadataId,
|
||||
store,
|
||||
currentRecordFilterGroups,
|
||||
currentRecordFilters,
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
import { FIND_ALL_CORE_VIEWS } from '@/views/graphql/queries/findAllCoreViews';
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { type FetchPolicy } from '@apollo/client';
|
||||
import { useApolloClient } from '@apollo/client/react';
|
||||
import { useCallback } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type FindAllCoreViewsQuery } from '~/generated-metadata/graphql';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
import { useStore } from 'jotai';
|
||||
|
||||
export const useRefreshAllCoreViews = (
|
||||
fetchPolicy: FetchPolicy = 'network-only',
|
||||
) => {
|
||||
const store = useStore();
|
||||
const client = useApolloClient();
|
||||
|
||||
const refreshAllCoreViews = useCallback(async () => {
|
||||
const result = await client.query<FindAllCoreViewsQuery>({
|
||||
query: FIND_ALL_CORE_VIEWS,
|
||||
variables: {},
|
||||
fetchPolicy,
|
||||
});
|
||||
|
||||
const currentCoreViews = store.get(coreViewsState.atom);
|
||||
|
||||
const coreViewsFromResult = result.data?.getCoreViews;
|
||||
|
||||
if (
|
||||
isDefined(coreViewsFromResult) &&
|
||||
!isDeeplyEqual(currentCoreViews, coreViewsFromResult)
|
||||
) {
|
||||
store.set(coreViewsState.atom, coreViewsFromResult);
|
||||
}
|
||||
|
||||
return result.data?.getCoreViews;
|
||||
}, [client, fetchPolicy, store]);
|
||||
|
||||
return {
|
||||
refreshAllCoreViews,
|
||||
};
|
||||
};
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
import { useApplyCoreViewsForObjectMetadataId } from '@/views/hooks/useApplyCoreViewsForObjectMetadataId';
|
||||
import { useCallback } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { useApolloClient } from '@apollo/client/react';
|
||||
import { FindManyCoreViewsDocument } from '~/generated-metadata/graphql';
|
||||
|
||||
export const useRefreshCoreViewsByObjectMetadataId = () => {
|
||||
const client = useApolloClient();
|
||||
const { applyCoreViewsForObjectMetadataId } =
|
||||
useApplyCoreViewsForObjectMetadataId();
|
||||
|
||||
const refreshCoreViewsByObjectMetadataId = useCallback(
|
||||
async (objectMetadataId: string) => {
|
||||
const result = await client.query({
|
||||
query: FindManyCoreViewsDocument,
|
||||
variables: {
|
||||
objectMetadataId,
|
||||
},
|
||||
fetchPolicy: 'network-only',
|
||||
});
|
||||
|
||||
if (!isDefined(result.data?.getCoreViews)) {
|
||||
return;
|
||||
}
|
||||
|
||||
applyCoreViewsForObjectMetadataId(
|
||||
objectMetadataId,
|
||||
result.data.getCoreViews,
|
||||
);
|
||||
},
|
||||
[client, applyCoreViewsForObjectMetadataId],
|
||||
);
|
||||
|
||||
return {
|
||||
refreshCoreViewsByObjectMetadataId,
|
||||
};
|
||||
};
|
||||
-32
@@ -1,10 +1,8 @@
|
||||
import { currentRecordFilterGroupsComponentState } from '@/object-record/record-filter-group/states/currentRecordFilterGroupsComponentState';
|
||||
import { useAtomComponentStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateCallbackState';
|
||||
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||
import { usePerformViewFilterGroupAPIPersist } from '@/views/hooks/internal/usePerformViewFilterGroupAPIPersist';
|
||||
import { useCanPersistViewChanges } from '@/views/hooks/useCanPersistViewChanges';
|
||||
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { getViewFilterGroupsToCreate } from '@/views/utils/getViewFilterGroupsToCreate';
|
||||
import { getViewFilterGroupsToDelete } from '@/views/utils/getViewFilterGroupsToDelete';
|
||||
import { getViewFilterGroupsToUpdate } from '@/views/utils/getViewFilterGroupsToUpdate';
|
||||
@@ -28,8 +26,6 @@ export const useSaveRecordFilterGroupsToViewFilterGroups = () => {
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const setCoreViews = useSetAtomState(coreViewsState);
|
||||
|
||||
const saveRecordFilterGroupsToViewFilterGroups = useCallback(async () => {
|
||||
if (!canPersistChanges || !isDefined(currentView)) {
|
||||
return;
|
||||
@@ -59,33 +55,6 @@ export const useSaveRecordFilterGroupsToViewFilterGroups = () => {
|
||||
newViewFilterGroups,
|
||||
);
|
||||
|
||||
const viewFiltersToOptimisticallyCascadeDelete =
|
||||
currentView.viewFilters.filter((viewFilter) =>
|
||||
viewFilterGroupsToDelete.some(
|
||||
(viewFilterGroupToDelete) =>
|
||||
viewFilterGroupToDelete.id === viewFilter.viewFilterGroupId,
|
||||
),
|
||||
);
|
||||
|
||||
for (const viewFilterToCascadeDelete of viewFiltersToOptimisticallyCascadeDelete) {
|
||||
setCoreViews((currentCoreViews) => {
|
||||
const updatedCoreViews = currentCoreViews.map((coreView) => {
|
||||
if (coreView.id !== currentView.id) {
|
||||
return coreView;
|
||||
}
|
||||
|
||||
return {
|
||||
...coreView,
|
||||
viewFilters: coreView.viewFilters.filter(
|
||||
(viewFilter) => viewFilter.id !== viewFilterToCascadeDelete.id,
|
||||
),
|
||||
};
|
||||
});
|
||||
|
||||
return updatedCoreViews;
|
||||
});
|
||||
}
|
||||
|
||||
const viewFilterGroupsToUpdate = getViewFilterGroupsToUpdate(
|
||||
currentViewFilterGroups,
|
||||
newViewFilterGroups,
|
||||
@@ -109,7 +78,6 @@ export const useSaveRecordFilterGroupsToViewFilterGroups = () => {
|
||||
performViewFilterGroupAPICreate,
|
||||
performViewFilterGroupAPIUpdate,
|
||||
performViewFilterGroupAPIDelete,
|
||||
setCoreViews,
|
||||
]);
|
||||
|
||||
return {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useAtomComponentStateCallbackState } from '@/ui/utilities/state/jotai/h
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
import { usePerformViewFilterAPIPersist } from '@/views/hooks/internal/usePerformViewFilterAPIPersist';
|
||||
import { useCanPersistViewChanges } from '@/views/hooks/useCanPersistViewChanges';
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { coreViewsSelector } from '@/views/states/selectors/coreViewsSelector';
|
||||
import { convertCoreViewToView } from '@/views/utils/convertCoreViewToView';
|
||||
import { getViewFiltersToCreate } from '@/views/utils/getViewFiltersToCreate';
|
||||
import { getViewFiltersToDelete } from '@/views/utils/getViewFiltersToDelete';
|
||||
@@ -33,7 +33,7 @@ export const useSaveRecordFiltersToViewFilters = () => {
|
||||
const store = useStore();
|
||||
|
||||
const saveRecordFiltersToViewFilters = useCallback(async () => {
|
||||
const views = store.get(coreViewsState.atom);
|
||||
const views = store.get(coreViewsSelector.atom);
|
||||
|
||||
const currentCoreView = views.find(
|
||||
(view) => view.id === contextStoreCurrentViewId,
|
||||
|
||||
@@ -7,7 +7,6 @@ import { useLoadRecordIndexStates } from '@/object-record/record-index/hooks/use
|
||||
import { recordIndexViewTypeState } from '@/object-record/record-index/states/recordIndexViewTypeState';
|
||||
import { useAtomComponentStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateCallbackState';
|
||||
import { useCanPersistViewChanges } from '@/views/hooks/useCanPersistViewChanges';
|
||||
import { useRefreshCoreViewsByObjectMetadataId } from '@/views/hooks/useRefreshCoreViewsByObjectMetadataId';
|
||||
import { coreViewFromViewIdFamilySelector } from '@/views/states/selectors/coreViewFromViewIdFamilySelector';
|
||||
import { type GraphQLView } from '@/views/types/GraphQLView';
|
||||
import { type View } from '@/views/types/View';
|
||||
@@ -32,8 +31,6 @@ export const useUpdateCurrentView = () => {
|
||||
const store = useStore();
|
||||
|
||||
const [updateOneCoreView] = useMutation(UpdateCoreViewDocument);
|
||||
const { refreshCoreViewsByObjectMetadataId } =
|
||||
useRefreshCoreViewsByObjectMetadataId();
|
||||
|
||||
const getViewGroupsToCreateAtViewUpdate = useMemo(() => {
|
||||
return ({
|
||||
@@ -143,8 +140,6 @@ export const useUpdateCurrentView = () => {
|
||||
if (isDefined(view.type)) {
|
||||
setRecordIndexViewType(view.type);
|
||||
}
|
||||
|
||||
await refreshCoreViewsByObjectMetadataId(currentView.objectMetadataId);
|
||||
}
|
||||
},
|
||||
[
|
||||
@@ -153,7 +148,6 @@ export const useUpdateCurrentView = () => {
|
||||
getViewGroupsToCreateAtViewUpdate,
|
||||
loadRecordIndexStates,
|
||||
objectMetadataItem,
|
||||
refreshCoreViewsByObjectMetadataId,
|
||||
setRecordIndexViewType,
|
||||
store,
|
||||
updateOneCoreView,
|
||||
|
||||
@@ -6,18 +6,12 @@ import { convertExtendedAggregateOperationToAggregateOperation } from '@/object-
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
import { usePerformViewAPIUpdate } from '@/views/hooks/internal/usePerformViewAPIUpdate';
|
||||
import { useCanPersistViewChanges } from '@/views/hooks/useCanPersistViewChanges';
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { convertCoreViewToView } from '@/views/utils/convertCoreViewToView';
|
||||
import { useCallback } from 'react';
|
||||
import {
|
||||
isDefined,
|
||||
upsertIntoArrayOfObjectsComparingId,
|
||||
} from 'twenty-shared/utils';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type CoreView } from '~/generated-metadata/graphql';
|
||||
import { useStore } from 'jotai';
|
||||
|
||||
export const useUpdateViewAggregate = () => {
|
||||
const store = useStore();
|
||||
const { canPersistChanges } = useCanPersistViewChanges();
|
||||
const contextStoreCurrentViewId = useAtomComponentStateValue(
|
||||
contextStoreCurrentViewIdComponentState,
|
||||
@@ -67,13 +61,6 @@ export const useUpdateViewAggregate = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
store.set(coreViewsState.atom, (currentCoreViews) =>
|
||||
upsertIntoArrayOfObjectsComparingId(
|
||||
currentCoreViews,
|
||||
updatedCoreView,
|
||||
),
|
||||
);
|
||||
|
||||
const updatedView = convertCoreViewToView(updatedCoreView);
|
||||
|
||||
loadRecordIndexStates(updatedView, objectMetadataItem);
|
||||
@@ -84,7 +71,6 @@ export const useUpdateViewAggregate = () => {
|
||||
contextStoreCurrentViewId,
|
||||
performViewAPIUpdate,
|
||||
loadRecordIndexStates,
|
||||
store,
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
@@ -1,23 +1,16 @@
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { useTriggerViewGroupOptimisticEffect } from '@/views/optimistic-effects/hooks/useTriggerViewGroupOptimisticEffect';
|
||||
import { type ViewGroup } from '@/views/types/ViewGroup';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { v4 } from 'uuid';
|
||||
import { type CoreViewGroup } from '~/generated-metadata/graphql';
|
||||
|
||||
const useViewsSideEffectsOnViewGroups = () => {
|
||||
const { triggerViewGroupOptimisticEffect } =
|
||||
useTriggerViewGroupOptimisticEffect();
|
||||
|
||||
const objectMetadataItems = useAtomStateValue(objectMetadataItemsState);
|
||||
|
||||
const triggerViewGroupOptimisticEffectAtViewCreation = ({
|
||||
newViewId,
|
||||
mainGroupByFieldMetadataId,
|
||||
objectMetadataItemId,
|
||||
}: {
|
||||
newViewId: string;
|
||||
mainGroupByFieldMetadataId?: string | null;
|
||||
objectMetadataItemId: string;
|
||||
}) => {
|
||||
@@ -63,19 +56,6 @@ const useViewsSideEffectsOnViewGroups = () => {
|
||||
} satisfies ViewGroup);
|
||||
}
|
||||
|
||||
triggerViewGroupOptimisticEffect({
|
||||
createdViewGroups: viewGroupsToCreate.map(
|
||||
({ __typename, ...viewGroup }) =>
|
||||
({
|
||||
...viewGroup,
|
||||
viewId: newViewId,
|
||||
createdAt: new Date().toISOString(),
|
||||
updatedAt: new Date().toISOString(),
|
||||
deletedAt: null,
|
||||
}) as Omit<CoreViewGroup, 'workspaceId'>,
|
||||
),
|
||||
});
|
||||
|
||||
return { viewGroupsToCreate };
|
||||
};
|
||||
|
||||
|
||||
-163
@@ -1,163 +0,0 @@
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations';
|
||||
import { useApolloClient } from '@apollo/client/react';
|
||||
import { useCallback } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type CoreViewFieldGroup } from '~/generated-metadata/graphql';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
import { useStore } from 'jotai';
|
||||
|
||||
type ViewFieldGroupForOptimisticEffect = Omit<
|
||||
CoreViewFieldGroup,
|
||||
'workspaceId'
|
||||
>;
|
||||
|
||||
export const useTriggerViewFieldGroupOptimisticEffect = () => {
|
||||
const store = useStore();
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
const cache = apolloClient.cache;
|
||||
|
||||
const triggerViewFieldGroupOptimisticEffect = useCallback(
|
||||
({
|
||||
createdViewFieldGroups = [],
|
||||
updatedViewFieldGroups = [],
|
||||
deletedViewFieldGroups = [],
|
||||
}: {
|
||||
createdViewFieldGroups?: ViewFieldGroupForOptimisticEffect[];
|
||||
updatedViewFieldGroups?: ViewFieldGroupForOptimisticEffect[];
|
||||
deletedViewFieldGroups?: Pick<CoreViewFieldGroup, 'id' | 'viewId'>[];
|
||||
}) => {
|
||||
const coreViews = store.get(coreViewsState.atom);
|
||||
let newCoreViews = [...coreViews];
|
||||
|
||||
createdViewFieldGroups.forEach((createdViewFieldGroup) => {
|
||||
cache.modify<CoreViewWithRelations>({
|
||||
id: cache.identify({
|
||||
__typename: 'CoreView',
|
||||
id: createdViewFieldGroup.viewId,
|
||||
}),
|
||||
fields: {
|
||||
viewFieldGroups: (existingViewFieldGroups, { toReference }) =>
|
||||
[
|
||||
...(existingViewFieldGroups ?? []),
|
||||
toReference(createdViewFieldGroup),
|
||||
].filter(isDefined),
|
||||
},
|
||||
});
|
||||
const toBeModifiedCoreView = newCoreViews.find(
|
||||
(coreView) => coreView.id === createdViewFieldGroup.viewId,
|
||||
);
|
||||
if (isDefined(toBeModifiedCoreView)) {
|
||||
newCoreViews = [
|
||||
...newCoreViews.filter(
|
||||
(coreView) => coreView.id !== createdViewFieldGroup.viewId,
|
||||
),
|
||||
{
|
||||
...toBeModifiedCoreView,
|
||||
viewFieldGroups: [
|
||||
...(toBeModifiedCoreView.viewFieldGroups ?? []),
|
||||
createdViewFieldGroup,
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
updatedViewFieldGroups.forEach((updatedViewFieldGroup) => {
|
||||
cache.modify<CoreViewWithRelations>({
|
||||
id: cache.identify({
|
||||
__typename: 'CoreView',
|
||||
id: updatedViewFieldGroup.viewId,
|
||||
}),
|
||||
fields: {
|
||||
viewFieldGroups: (
|
||||
existingViewFieldGroups,
|
||||
{ readField, toReference },
|
||||
) =>
|
||||
existingViewFieldGroups
|
||||
?.map((viewFieldGroup) => {
|
||||
const viewFieldGroupId = readField<string>(
|
||||
'id',
|
||||
viewFieldGroup,
|
||||
);
|
||||
if (viewFieldGroupId === updatedViewFieldGroup.id) {
|
||||
return toReference(updatedViewFieldGroup);
|
||||
}
|
||||
return viewFieldGroup;
|
||||
})
|
||||
?.filter(isDefined) ?? [],
|
||||
},
|
||||
});
|
||||
const toBeModifiedCoreView = newCoreViews.find(
|
||||
(coreView) => coreView.id === updatedViewFieldGroup.viewId,
|
||||
);
|
||||
if (isDefined(toBeModifiedCoreView)) {
|
||||
newCoreViews = [
|
||||
...newCoreViews.filter(
|
||||
(coreView) => coreView.id !== updatedViewFieldGroup.viewId,
|
||||
),
|
||||
{
|
||||
...toBeModifiedCoreView,
|
||||
viewFieldGroups: [
|
||||
...(toBeModifiedCoreView.viewFieldGroups ?? []).filter(
|
||||
(viewFieldGroup) =>
|
||||
viewFieldGroup.id !== updatedViewFieldGroup.id,
|
||||
),
|
||||
updatedViewFieldGroup,
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
deletedViewFieldGroups.forEach(
|
||||
(deletedViewFieldGroup: Pick<CoreViewFieldGroup, 'id' | 'viewId'>) => {
|
||||
cache.modify<CoreViewWithRelations>({
|
||||
id: cache.identify({
|
||||
__typename: 'CoreView',
|
||||
id: deletedViewFieldGroup.viewId,
|
||||
}),
|
||||
fields: {
|
||||
viewFieldGroups: (existingViewFieldGroups, { readField }) =>
|
||||
existingViewFieldGroups?.filter(
|
||||
(viewFieldGroup) =>
|
||||
readField('id', viewFieldGroup) !==
|
||||
deletedViewFieldGroup.id,
|
||||
) ?? [],
|
||||
},
|
||||
});
|
||||
const toBeModifiedCoreView = newCoreViews.find(
|
||||
(coreView) => coreView.id === deletedViewFieldGroup.viewId,
|
||||
);
|
||||
|
||||
if (isDefined(toBeModifiedCoreView)) {
|
||||
newCoreViews = [
|
||||
...newCoreViews.filter(
|
||||
(coreView) => coreView.id !== deletedViewFieldGroup.viewId,
|
||||
),
|
||||
{
|
||||
...toBeModifiedCoreView,
|
||||
viewFieldGroups: (
|
||||
toBeModifiedCoreView.viewFieldGroups ?? []
|
||||
).filter(
|
||||
(viewFieldGroup) =>
|
||||
viewFieldGroup.id !== deletedViewFieldGroup.id,
|
||||
),
|
||||
},
|
||||
];
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (!isDeeplyEqual(coreViews, newCoreViews)) {
|
||||
store.set(coreViewsState.atom, newCoreViews);
|
||||
}
|
||||
},
|
||||
[cache, store],
|
||||
);
|
||||
|
||||
return {
|
||||
triggerViewFieldGroupOptimisticEffect,
|
||||
};
|
||||
};
|
||||
-147
@@ -1,147 +0,0 @@
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations';
|
||||
import { useApolloClient } from '@apollo/client/react';
|
||||
import { useCallback } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type CoreViewField } from '~/generated-metadata/graphql';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
import { useStore } from 'jotai';
|
||||
|
||||
export const useTriggerViewFieldOptimisticEffect = () => {
|
||||
const store = useStore();
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
const cache = apolloClient.cache;
|
||||
|
||||
const triggerViewFieldOptimisticEffect = useCallback(
|
||||
({
|
||||
createdViewFields = [],
|
||||
updatedViewFields = [],
|
||||
deletedViewFields = [],
|
||||
}: {
|
||||
createdViewFields?: Omit<CoreViewField, 'workspaceId'>[];
|
||||
updatedViewFields?: Omit<CoreViewField, 'workspaceId'>[];
|
||||
deletedViewFields?: Pick<CoreViewField, 'id' | 'viewId'>[];
|
||||
}) => {
|
||||
const coreViews = store.get(coreViewsState.atom);
|
||||
let newCoreViews = [...coreViews];
|
||||
|
||||
createdViewFields.forEach((createdViewField) => {
|
||||
cache.modify<CoreViewWithRelations>({
|
||||
id: cache.identify({
|
||||
__typename: 'CoreView',
|
||||
id: createdViewField.viewId,
|
||||
}),
|
||||
fields: {
|
||||
viewFields: (existingViewFields, { toReference }) =>
|
||||
[
|
||||
...(existingViewFields ?? []),
|
||||
toReference(createdViewField),
|
||||
].filter(isDefined),
|
||||
},
|
||||
});
|
||||
const toBeModifiedCoreView = newCoreViews.find(
|
||||
(coreView) => coreView.id === createdViewField.viewId,
|
||||
);
|
||||
if (isDefined(toBeModifiedCoreView)) {
|
||||
newCoreViews = [
|
||||
...newCoreViews.filter(
|
||||
(coreView) => coreView.id !== createdViewField.viewId,
|
||||
),
|
||||
{
|
||||
...toBeModifiedCoreView,
|
||||
viewFields: [
|
||||
...toBeModifiedCoreView.viewFields,
|
||||
createdViewField,
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
updatedViewFields.forEach((updatedViewField) => {
|
||||
cache.modify<CoreViewWithRelations>({
|
||||
id: cache.identify({
|
||||
__typename: 'CoreView',
|
||||
id: updatedViewField.viewId,
|
||||
}),
|
||||
fields: {
|
||||
viewFields: (existingViewFields, { readField, toReference }) =>
|
||||
existingViewFields
|
||||
.map((viewField) => {
|
||||
const viewFieldId = readField<string>('id', viewField);
|
||||
if (viewFieldId === updatedViewField.id) {
|
||||
return toReference(updatedViewField);
|
||||
}
|
||||
return viewField;
|
||||
})
|
||||
.filter(isDefined),
|
||||
},
|
||||
});
|
||||
const toBeModifiedCoreView = newCoreViews.find(
|
||||
(coreView) => coreView.id === updatedViewField.viewId,
|
||||
);
|
||||
if (isDefined(toBeModifiedCoreView)) {
|
||||
newCoreViews = [
|
||||
...newCoreViews.filter(
|
||||
(coreView) => coreView.id !== updatedViewField.viewId,
|
||||
),
|
||||
{
|
||||
...toBeModifiedCoreView,
|
||||
viewFields: [
|
||||
...toBeModifiedCoreView.viewFields.filter(
|
||||
(viewField) => viewField.id !== updatedViewField.id,
|
||||
),
|
||||
updatedViewField,
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
deletedViewFields.forEach(
|
||||
(deletedViewField: Pick<CoreViewField, 'id' | 'viewId'>) => {
|
||||
cache.modify<CoreViewWithRelations>({
|
||||
id: cache.identify({
|
||||
__typename: 'CoreView',
|
||||
id: deletedViewField.viewId,
|
||||
}),
|
||||
fields: {
|
||||
viewFields: (existingViewFields, { readField }) =>
|
||||
existingViewFields.filter(
|
||||
(viewField) =>
|
||||
readField('id', viewField) !== deletedViewField.id,
|
||||
),
|
||||
},
|
||||
});
|
||||
const toBeModifiedCoreView = newCoreViews.find(
|
||||
(coreView) => coreView.id === deletedViewField.viewId,
|
||||
);
|
||||
|
||||
if (isDefined(toBeModifiedCoreView)) {
|
||||
newCoreViews = [
|
||||
...newCoreViews.filter(
|
||||
(coreView) => coreView.id !== deletedViewField.viewId,
|
||||
),
|
||||
{
|
||||
...toBeModifiedCoreView,
|
||||
viewFields: toBeModifiedCoreView.viewFields.filter(
|
||||
(viewField) => viewField.id !== deletedViewField.id,
|
||||
),
|
||||
},
|
||||
];
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (!isDeeplyEqual(coreViews, newCoreViews)) {
|
||||
store.set(coreViewsState.atom, newCoreViews);
|
||||
}
|
||||
},
|
||||
[cache, store],
|
||||
);
|
||||
|
||||
return {
|
||||
triggerViewFieldOptimisticEffect,
|
||||
};
|
||||
};
|
||||
-147
@@ -1,147 +0,0 @@
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations';
|
||||
import { useApolloClient } from '@apollo/client/react';
|
||||
import { useCallback } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type CoreViewFilter } from '~/generated-metadata/graphql';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
import { useStore } from 'jotai';
|
||||
type UpdatedDeletedCoreViewFilter = {
|
||||
createdViewFilters?: Omit<CoreViewFilter, 'workspaceId'>[];
|
||||
updatedViewFilters?: Omit<CoreViewFilter, 'workspaceId'>[];
|
||||
deletedViewFilters?: Pick<CoreViewFilter, 'id' | 'viewId'>[];
|
||||
};
|
||||
export const useTriggerViewFilterOptimisticEffect = () => {
|
||||
const store = useStore();
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
const cache = apolloClient.cache;
|
||||
|
||||
const triggerViewFilterOptimisticEffect = useCallback(
|
||||
({
|
||||
createdViewFilters = [],
|
||||
updatedViewFilters = [],
|
||||
deletedViewFilters = [],
|
||||
}: UpdatedDeletedCoreViewFilter) => {
|
||||
const coreViews = store.get(coreViewsState.atom);
|
||||
let newCoreViews = [...coreViews];
|
||||
|
||||
createdViewFilters.forEach((createdViewFilter) => {
|
||||
cache.modify<CoreViewWithRelations>({
|
||||
id: cache.identify({
|
||||
__typename: 'CoreView',
|
||||
id: createdViewFilter.viewId,
|
||||
}),
|
||||
fields: {
|
||||
viewFilters: (existingViewFilters, { toReference }) =>
|
||||
[
|
||||
...(existingViewFilters ?? []),
|
||||
toReference(createdViewFilter),
|
||||
].filter(isDefined),
|
||||
},
|
||||
});
|
||||
const toBeModifiedCoreView = newCoreViews.find(
|
||||
(coreView) => coreView.id === createdViewFilter.viewId,
|
||||
);
|
||||
if (isDefined(toBeModifiedCoreView)) {
|
||||
newCoreViews = [
|
||||
...newCoreViews.filter(
|
||||
(coreView) => coreView.id !== createdViewFilter.viewId,
|
||||
),
|
||||
{
|
||||
...toBeModifiedCoreView,
|
||||
viewFilters: [
|
||||
...toBeModifiedCoreView.viewFilters,
|
||||
createdViewFilter,
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
updatedViewFilters.forEach((updatedViewFilter) => {
|
||||
cache.modify<CoreViewWithRelations>({
|
||||
id: cache.identify({
|
||||
__typename: 'CoreView',
|
||||
id: updatedViewFilter.viewId,
|
||||
}),
|
||||
fields: {
|
||||
viewFilters: (existingViewFilters, { readField, toReference }) =>
|
||||
existingViewFilters
|
||||
.map((viewFilter) => {
|
||||
const viewFilterId = readField<string>('id', viewFilter);
|
||||
if (viewFilterId === updatedViewFilter.id) {
|
||||
return toReference(updatedViewFilter);
|
||||
}
|
||||
return viewFilter;
|
||||
})
|
||||
.filter(isDefined),
|
||||
},
|
||||
});
|
||||
const toBeModifiedCoreView = newCoreViews.find(
|
||||
(coreView) => coreView.id === updatedViewFilter.viewId,
|
||||
);
|
||||
if (isDefined(toBeModifiedCoreView)) {
|
||||
newCoreViews = [
|
||||
...newCoreViews.filter(
|
||||
(coreView) => coreView.id !== updatedViewFilter.viewId,
|
||||
),
|
||||
{
|
||||
...toBeModifiedCoreView,
|
||||
viewFilters: [
|
||||
...toBeModifiedCoreView.viewFilters.filter(
|
||||
(viewFilter) => viewFilter.id !== updatedViewFilter.id,
|
||||
),
|
||||
updatedViewFilter,
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
deletedViewFilters.forEach(
|
||||
(deletedViewFilter: Pick<CoreViewFilter, 'id' | 'viewId'>) => {
|
||||
cache.modify<CoreViewWithRelations>({
|
||||
id: cache.identify({
|
||||
__typename: 'CoreView',
|
||||
id: deletedViewFilter.viewId,
|
||||
}),
|
||||
fields: {
|
||||
viewFilters: (existingViewFilters, { readField }) =>
|
||||
existingViewFilters.filter(
|
||||
(viewFilter) =>
|
||||
readField('id', viewFilter) !== deletedViewFilter.id,
|
||||
),
|
||||
},
|
||||
});
|
||||
const toBeModifiedCoreView = newCoreViews.find(
|
||||
(coreView) => coreView.id === deletedViewFilter.viewId,
|
||||
);
|
||||
|
||||
if (isDefined(toBeModifiedCoreView)) {
|
||||
newCoreViews = [
|
||||
...newCoreViews.filter(
|
||||
(coreView) => coreView.id !== deletedViewFilter.viewId,
|
||||
),
|
||||
{
|
||||
...toBeModifiedCoreView,
|
||||
viewFilters: toBeModifiedCoreView.viewFilters.filter(
|
||||
(viewFilter) => viewFilter.id !== deletedViewFilter.id,
|
||||
),
|
||||
},
|
||||
];
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (!isDeeplyEqual(coreViews, newCoreViews)) {
|
||||
store.set(coreViewsState.atom, newCoreViews);
|
||||
}
|
||||
},
|
||||
[cache, store],
|
||||
);
|
||||
|
||||
return {
|
||||
triggerViewFilterOptimisticEffect,
|
||||
};
|
||||
};
|
||||
-146
@@ -1,146 +0,0 @@
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations';
|
||||
import { useApolloClient } from '@apollo/client/react';
|
||||
import { useCallback } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type CoreViewGroup } from '~/generated-metadata/graphql';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
import { useStore } from 'jotai';
|
||||
|
||||
type UpdatedDeletedCoreViewGroup = {
|
||||
createdViewGroups?: Omit<CoreViewGroup, 'workspaceId'>[];
|
||||
updatedViewGroups?: Omit<CoreViewGroup, 'workspaceId'>[];
|
||||
deletedViewGroups?: Pick<CoreViewGroup, 'id' | 'viewId'>[];
|
||||
};
|
||||
export const useTriggerViewGroupOptimisticEffect = () => {
|
||||
const store = useStore();
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
const cache = apolloClient.cache;
|
||||
|
||||
const triggerViewGroupOptimisticEffect = useCallback(
|
||||
({
|
||||
createdViewGroups = [],
|
||||
updatedViewGroups = [],
|
||||
deletedViewGroups = [],
|
||||
}: UpdatedDeletedCoreViewGroup) => {
|
||||
const coreViews = store.get(coreViewsState.atom);
|
||||
let newCoreViews = [...coreViews];
|
||||
|
||||
createdViewGroups.forEach((createdViewGroup) => {
|
||||
cache.modify<CoreViewWithRelations>({
|
||||
id: cache.identify({
|
||||
__typename: 'CoreView',
|
||||
id: createdViewGroup.viewId,
|
||||
}),
|
||||
fields: {
|
||||
viewGroups: (existingViewGroups, { toReference }) =>
|
||||
[
|
||||
...(existingViewGroups ?? []),
|
||||
toReference(createdViewGroup),
|
||||
].filter(isDefined),
|
||||
},
|
||||
});
|
||||
const toBeModifiedCoreView = newCoreViews.find(
|
||||
(coreView) => coreView.id === createdViewGroup.viewId,
|
||||
);
|
||||
if (isDefined(toBeModifiedCoreView)) {
|
||||
newCoreViews = [
|
||||
...newCoreViews.filter(
|
||||
(coreView) => coreView.id !== createdViewGroup.viewId,
|
||||
),
|
||||
{
|
||||
...toBeModifiedCoreView,
|
||||
viewGroups: [
|
||||
...toBeModifiedCoreView.viewGroups,
|
||||
createdViewGroup,
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
updatedViewGroups.forEach((updatedViewGroup) => {
|
||||
cache.modify<CoreViewWithRelations>({
|
||||
id: cache.identify({
|
||||
__typename: 'CoreView',
|
||||
id: updatedViewGroup.viewId,
|
||||
}),
|
||||
fields: {
|
||||
viewGroups: (existingViewGroups, { readField, toReference }) =>
|
||||
existingViewGroups
|
||||
.map((viewGroup) => {
|
||||
const viewGroupId = readField<string>('id', viewGroup);
|
||||
if (viewGroupId === updatedViewGroup.id) {
|
||||
return toReference(updatedViewGroup);
|
||||
}
|
||||
return viewGroup;
|
||||
})
|
||||
.filter(isDefined),
|
||||
},
|
||||
});
|
||||
const toBeModifiedCoreView = newCoreViews.find(
|
||||
(coreView) => coreView.id === updatedViewGroup.viewId,
|
||||
);
|
||||
if (isDefined(toBeModifiedCoreView)) {
|
||||
newCoreViews = [
|
||||
...newCoreViews.filter(
|
||||
(coreView) => coreView.id !== updatedViewGroup.viewId,
|
||||
),
|
||||
{
|
||||
...toBeModifiedCoreView,
|
||||
viewGroups: [
|
||||
...toBeModifiedCoreView.viewGroups.filter(
|
||||
(viewGroup) => viewGroup.id !== updatedViewGroup.id,
|
||||
),
|
||||
updatedViewGroup,
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
deletedViewGroups.forEach((deletedViewGroup) => {
|
||||
cache.modify<CoreViewWithRelations>({
|
||||
id: cache.identify({
|
||||
__typename: 'CoreView',
|
||||
id: deletedViewGroup.viewId,
|
||||
}),
|
||||
fields: {
|
||||
viewGroups: (existingViewGroups, { readField }) =>
|
||||
existingViewGroups.filter(
|
||||
(viewGroup) =>
|
||||
readField('id', viewGroup) !== deletedViewGroup.id,
|
||||
),
|
||||
},
|
||||
});
|
||||
const toBeModifiedCoreView = newCoreViews.find(
|
||||
(coreView) => coreView.id === deletedViewGroup.viewId,
|
||||
);
|
||||
|
||||
if (isDefined(toBeModifiedCoreView)) {
|
||||
newCoreViews = [
|
||||
...newCoreViews.filter(
|
||||
(coreView) => coreView.id !== deletedViewGroup.viewId,
|
||||
),
|
||||
{
|
||||
...toBeModifiedCoreView,
|
||||
viewGroups: toBeModifiedCoreView.viewGroups.filter(
|
||||
(viewGroup) => viewGroup.id !== deletedViewGroup.id,
|
||||
),
|
||||
},
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
if (!isDeeplyEqual(coreViews, newCoreViews)) {
|
||||
store.set(coreViewsState.atom, newCoreViews);
|
||||
}
|
||||
},
|
||||
[cache, store],
|
||||
);
|
||||
|
||||
return {
|
||||
triggerViewGroupOptimisticEffect,
|
||||
};
|
||||
};
|
||||
-149
@@ -1,149 +0,0 @@
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations';
|
||||
import { useApolloClient } from '@apollo/client/react';
|
||||
import { useStore } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type CoreViewSort } from '~/generated-metadata/graphql';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
export const useTriggerViewSortOptimisticEffect = () => {
|
||||
const store = useStore();
|
||||
const apolloClient = useApolloClient();
|
||||
|
||||
const cache = apolloClient.cache;
|
||||
|
||||
const triggerViewSortOptimisticEffect = useCallback(
|
||||
({
|
||||
createdViewSorts = [],
|
||||
updatedViewSorts = [],
|
||||
deletedViewSorts = [],
|
||||
}: {
|
||||
createdViewSorts?: Omit<CoreViewSort, 'workspaceId'>[];
|
||||
updatedViewSorts?: Omit<CoreViewSort, 'workspaceId'>[];
|
||||
deletedViewSorts?: Pick<CoreViewSort, 'id'>[];
|
||||
}) => {
|
||||
const coreViews = store.get(coreViewsState.atom);
|
||||
let newCoreViews = [...coreViews];
|
||||
|
||||
createdViewSorts.forEach((createdViewSort) => {
|
||||
cache.modify<CoreViewWithRelations>({
|
||||
id: cache.identify({
|
||||
__typename: 'CoreView',
|
||||
id: createdViewSort.viewId,
|
||||
}),
|
||||
fields: {
|
||||
viewSorts: (existingViewSorts, { toReference }) =>
|
||||
[
|
||||
...(existingViewSorts ?? []),
|
||||
toReference(createdViewSort),
|
||||
].filter(isDefined),
|
||||
},
|
||||
});
|
||||
const toBeModifiedCoreView = newCoreViews.find(
|
||||
(coreView) => coreView.id === createdViewSort.viewId,
|
||||
);
|
||||
if (isDefined(toBeModifiedCoreView)) {
|
||||
newCoreViews = [
|
||||
...newCoreViews.filter(
|
||||
(coreView) => coreView.id !== createdViewSort.viewId,
|
||||
),
|
||||
{
|
||||
...toBeModifiedCoreView,
|
||||
viewSorts: [...toBeModifiedCoreView.viewSorts, createdViewSort],
|
||||
},
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
updatedViewSorts.forEach((updatedViewSort) => {
|
||||
cache.modify<CoreViewWithRelations>({
|
||||
id: cache.identify({
|
||||
__typename: 'CoreView',
|
||||
id: updatedViewSort.viewId,
|
||||
}),
|
||||
fields: {
|
||||
viewSorts: (existingViewSorts, { readField, toReference }) =>
|
||||
existingViewSorts
|
||||
.map((viewSort) => {
|
||||
const viewSortId = readField<string>('id', viewSort);
|
||||
if (viewSortId === updatedViewSort.id) {
|
||||
return toReference(updatedViewSort);
|
||||
}
|
||||
return viewSort;
|
||||
})
|
||||
.filter(isDefined),
|
||||
},
|
||||
});
|
||||
const toBeModifiedCoreView = newCoreViews.find(
|
||||
(coreView) => coreView.id === updatedViewSort.viewId,
|
||||
);
|
||||
if (isDefined(toBeModifiedCoreView)) {
|
||||
newCoreViews = [
|
||||
...newCoreViews.filter(
|
||||
(coreView) => coreView.id !== updatedViewSort.viewId,
|
||||
),
|
||||
{
|
||||
...toBeModifiedCoreView,
|
||||
viewSorts: [
|
||||
...toBeModifiedCoreView.viewSorts.filter(
|
||||
(viewSort) => viewSort.id !== updatedViewSort.id,
|
||||
),
|
||||
updatedViewSort,
|
||||
],
|
||||
},
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
deletedViewSorts.forEach((deletedViewSort: Pick<CoreViewSort, 'id'>) => {
|
||||
const viewId = coreViews.find((coreView) =>
|
||||
coreView.viewSorts.some(
|
||||
(viewSort) => viewSort.id === deletedViewSort.id,
|
||||
),
|
||||
)?.id;
|
||||
|
||||
if (!viewId) {
|
||||
return;
|
||||
}
|
||||
|
||||
cache.modify<CoreViewWithRelations>({
|
||||
id: cache.identify({
|
||||
__typename: 'CoreView',
|
||||
id: viewId,
|
||||
}),
|
||||
fields: {
|
||||
viewSorts: (existingViewSorts, { readField }) =>
|
||||
existingViewSorts.filter(
|
||||
(viewSort) => readField('id', viewSort) !== deletedViewSort.id,
|
||||
),
|
||||
},
|
||||
});
|
||||
const toBeModifiedCoreView = newCoreViews.find(
|
||||
(coreView) => coreView.id === viewId,
|
||||
);
|
||||
|
||||
if (isDefined(toBeModifiedCoreView)) {
|
||||
newCoreViews = [
|
||||
...newCoreViews.filter((coreView) => coreView.id !== viewId),
|
||||
{
|
||||
...toBeModifiedCoreView,
|
||||
viewSorts: toBeModifiedCoreView.viewSorts.filter(
|
||||
(viewSort) => viewSort.id !== deletedViewSort.id,
|
||||
),
|
||||
},
|
||||
];
|
||||
}
|
||||
});
|
||||
|
||||
if (!isDeeplyEqual(coreViews, newCoreViews)) {
|
||||
store.set(coreViewsState.atom, newCoreViews);
|
||||
}
|
||||
},
|
||||
[cache, store],
|
||||
);
|
||||
|
||||
return {
|
||||
triggerViewSortOptimisticEffect,
|
||||
};
|
||||
};
|
||||
@@ -1,7 +0,0 @@
|
||||
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
|
||||
import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations';
|
||||
|
||||
export const coreViewsState = createAtomState<CoreViewWithRelations[]>({
|
||||
key: 'coreViewsState',
|
||||
defaultValue: [],
|
||||
});
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { coreViewsSelector } from '@/views/states/selectors/coreViewsSelector';
|
||||
import { ViewKey } from '@/views/types/ViewKey';
|
||||
import { convertCoreViewToView } from '@/views/utils/convertCoreViewToView';
|
||||
import { createAtomFamilySelector } from '@/ui/utilities/state/jotai/utils/createAtomFamilySelector';
|
||||
@@ -12,7 +12,7 @@ export const coreIndexViewIdFromObjectMetadataItemFamilySelector =
|
||||
get:
|
||||
({ objectMetadataItemId }) =>
|
||||
({ get }) => {
|
||||
const coreViews = get(coreViewsState);
|
||||
const coreViews = get(coreViewsSelector);
|
||||
const views = coreViews.map(convertCoreViewToView);
|
||||
return views?.find(
|
||||
(view) =>
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { createAtomFamilySelector } from '@/ui/utilities/state/jotai/utils/createAtomFamilySelector';
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { coreViewsSelector } from '@/views/states/selectors/coreViewsSelector';
|
||||
import { type View } from '@/views/types/View';
|
||||
import { convertCoreViewToView } from '@/views/utils/convertCoreViewToView';
|
||||
|
||||
@@ -11,7 +11,7 @@ export const coreViewFromViewIdFamilySelector = createAtomFamilySelector<
|
||||
get:
|
||||
({ viewId }) =>
|
||||
({ get }) => {
|
||||
const coreViews = get(coreViewsState);
|
||||
const coreViews = get(coreViewsSelector);
|
||||
const views = coreViews.map(convertCoreViewToView);
|
||||
return views?.find((view) => view.id === viewId);
|
||||
},
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { coreViewsSelector } from '@/views/states/selectors/coreViewsSelector';
|
||||
import { convertCoreViewToView } from '@/views/utils/convertCoreViewToView';
|
||||
import { createAtomFamilySelector } from '@/ui/utilities/state/jotai/utils/createAtomFamilySelector';
|
||||
|
||||
@@ -8,7 +8,7 @@ export const coreViewIdsFromObjectMetadataItemFamilySelector =
|
||||
get:
|
||||
({ objectMetadataItemId }) =>
|
||||
({ get }) => {
|
||||
const coreViews = get(coreViewsState);
|
||||
const coreViews = get(coreViewsSelector);
|
||||
const views = coreViews.map(convertCoreViewToView);
|
||||
return views
|
||||
.filter((view) => view.objectMetadataId === objectMetadataItemId)
|
||||
|
||||
+2
-2
@@ -1,10 +1,10 @@
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { coreViewsSelector } from '@/views/states/selectors/coreViewsSelector';
|
||||
import { createAtomSelector } from '@/ui/utilities/state/jotai/utils/createAtomSelector';
|
||||
|
||||
export const coreViewLengthFamilySelector = createAtomSelector<number>({
|
||||
key: 'coreViewLengthFamilySelector',
|
||||
get: ({ get }) => {
|
||||
const coreViews = get(coreViewsState);
|
||||
const coreViews = get(coreViewsSelector);
|
||||
return coreViews?.length ?? 0;
|
||||
},
|
||||
});
|
||||
|
||||
+4
-17
@@ -1,29 +1,16 @@
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations';
|
||||
import { createAtomWritableFamilySelector } from '@/ui/utilities/state/jotai/utils/createAtomWritableFamilySelector';
|
||||
import { coreViewsSelector } from '@/views/states/selectors/coreViewsSelector';
|
||||
import { createAtomFamilySelector } from '@/ui/utilities/state/jotai/utils/createAtomFamilySelector';
|
||||
|
||||
export const coreViewsByObjectMetadataIdFamilySelector =
|
||||
createAtomWritableFamilySelector<CoreViewWithRelations[], string>({
|
||||
createAtomFamilySelector<CoreViewWithRelations[], string>({
|
||||
key: 'coreViewsByObjectMetadataIdFamilySelector',
|
||||
get:
|
||||
(objectMetadataId) =>
|
||||
({ get }) => {
|
||||
const coreViews = get(coreViewsState);
|
||||
const coreViews = get(coreViewsSelector);
|
||||
return coreViews.filter(
|
||||
(view) => view.objectMetadataId === objectMetadataId,
|
||||
);
|
||||
},
|
||||
set:
|
||||
(objectMetadataId) =>
|
||||
({ get, set }, newViewsForObject) => {
|
||||
const currentCoreViews = get(coreViewsState);
|
||||
const viewsFromOtherObjects = currentCoreViews.filter(
|
||||
(view) => view.objectMetadataId !== objectMetadataId,
|
||||
);
|
||||
const newCoreViews = [
|
||||
...viewsFromOtherObjects,
|
||||
...(Array.isArray(newViewsForObject) ? newViewsForObject : []),
|
||||
];
|
||||
set(coreViewsState, newCoreViews);
|
||||
},
|
||||
});
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
import { createAtomFamilySelector } from '@/ui/utilities/state/jotai/utils/createAtomFamilySelector';
|
||||
import { coreViewsState } from '@/views/states/coreViewState';
|
||||
import { coreViewsSelector } from '@/views/states/selectors/coreViewsSelector';
|
||||
import { type View } from '@/views/types/View';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { convertCoreViewToView } from '@/views/utils/convertCoreViewToView';
|
||||
@@ -10,7 +10,7 @@ export const coreViewsFromObjectMetadataItemFamilySelector =
|
||||
get:
|
||||
({ objectMetadataItemId }) =>
|
||||
({ get }) => {
|
||||
const coreViews = get(coreViewsState);
|
||||
const coreViews = get(coreViewsSelector);
|
||||
const views = coreViews.map(convertCoreViewToView);
|
||||
return views
|
||||
.filter(
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
import { metadataStoreState } from '@/metadata-store/states/metadataStoreState';
|
||||
import { type FlatView } from '@/metadata-store/types/FlatView';
|
||||
import { type FlatViewField } from '@/metadata-store/types/FlatViewField';
|
||||
import { type FlatViewFieldGroup } from '@/metadata-store/types/FlatViewFieldGroup';
|
||||
import { type FlatViewFilter } from '@/metadata-store/types/FlatViewFilter';
|
||||
import { type FlatViewFilterGroup } from '@/metadata-store/types/FlatViewFilterGroup';
|
||||
import { type FlatViewGroup } from '@/metadata-store/types/FlatViewGroup';
|
||||
import { type FlatViewSort } from '@/metadata-store/types/FlatViewSort';
|
||||
import { createAtomSelector } from '@/ui/utilities/state/jotai/utils/createAtomSelector';
|
||||
import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations';
|
||||
|
||||
export const coreViewsSelector = createAtomSelector<CoreViewWithRelations[]>({
|
||||
key: 'coreViewsSelector',
|
||||
get: ({ get }) => {
|
||||
const flatViews = get(metadataStoreState, 'views').current as FlatView[];
|
||||
const flatViewFields = get(metadataStoreState, 'viewFields')
|
||||
.current as FlatViewField[];
|
||||
const flatViewFilters = get(metadataStoreState, 'viewFilters')
|
||||
.current as FlatViewFilter[];
|
||||
const flatViewSorts = get(metadataStoreState, 'viewSorts')
|
||||
.current as FlatViewSort[];
|
||||
const flatViewGroups = get(metadataStoreState, 'viewGroups')
|
||||
.current as FlatViewGroup[];
|
||||
const flatViewFilterGroups = get(metadataStoreState, 'viewFilterGroups')
|
||||
.current as FlatViewFilterGroup[];
|
||||
const flatViewFieldGroups = get(metadataStoreState, 'viewFieldGroups')
|
||||
.current as FlatViewFieldGroup[];
|
||||
|
||||
const viewFieldsByViewId = new Map<string, FlatViewField[]>();
|
||||
const viewFiltersByViewId = new Map<string, FlatViewFilter[]>();
|
||||
const viewSortsByViewId = new Map<string, FlatViewSort[]>();
|
||||
const viewGroupsByViewId = new Map<string, FlatViewGroup[]>();
|
||||
const viewFilterGroupsByViewId = new Map<string, FlatViewFilterGroup[]>();
|
||||
const viewFieldGroupsByViewId = new Map<string, FlatViewFieldGroup[]>();
|
||||
|
||||
for (const field of flatViewFields) {
|
||||
const existing = viewFieldsByViewId.get(field.viewId) ?? [];
|
||||
existing.push(field);
|
||||
viewFieldsByViewId.set(field.viewId, existing);
|
||||
}
|
||||
|
||||
for (const filter of flatViewFilters) {
|
||||
const existing = viewFiltersByViewId.get(filter.viewId) ?? [];
|
||||
existing.push(filter);
|
||||
viewFiltersByViewId.set(filter.viewId, existing);
|
||||
}
|
||||
|
||||
for (const sort of flatViewSorts) {
|
||||
const existing = viewSortsByViewId.get(sort.viewId) ?? [];
|
||||
existing.push(sort);
|
||||
viewSortsByViewId.set(sort.viewId, existing);
|
||||
}
|
||||
|
||||
for (const group of flatViewGroups) {
|
||||
const existing = viewGroupsByViewId.get(group.viewId) ?? [];
|
||||
existing.push(group);
|
||||
viewGroupsByViewId.set(group.viewId, existing);
|
||||
}
|
||||
|
||||
for (const filterGroup of flatViewFilterGroups) {
|
||||
if ('viewId' in filterGroup && typeof filterGroup.viewId === 'string') {
|
||||
const existing = viewFilterGroupsByViewId.get(filterGroup.viewId) ?? [];
|
||||
existing.push(filterGroup);
|
||||
viewFilterGroupsByViewId.set(filterGroup.viewId, existing);
|
||||
}
|
||||
}
|
||||
|
||||
for (const fieldGroup of flatViewFieldGroups) {
|
||||
if ('viewId' in fieldGroup && typeof fieldGroup.viewId === 'string') {
|
||||
const existing = viewFieldGroupsByViewId.get(fieldGroup.viewId) ?? [];
|
||||
existing.push(fieldGroup);
|
||||
viewFieldGroupsByViewId.set(fieldGroup.viewId, existing);
|
||||
}
|
||||
}
|
||||
|
||||
return flatViews.map((view) => ({
|
||||
...view,
|
||||
viewFields: viewFieldsByViewId.get(view.id) ?? [],
|
||||
viewFilters: viewFiltersByViewId.get(view.id) ?? [],
|
||||
viewSorts: viewSortsByViewId.get(view.id) ?? [],
|
||||
viewGroups: viewGroupsByViewId.get(view.id) ?? [],
|
||||
viewFilterGroups: viewFilterGroupsByViewId.get(view.id) ?? [],
|
||||
viewFieldGroups: (viewFieldGroupsByViewId.get(view.id) ?? []).map(
|
||||
(fieldGroup) => ({
|
||||
...fieldGroup,
|
||||
viewFields: (viewFieldsByViewId.get(view.id) ?? []).filter(
|
||||
(field) =>
|
||||
'viewFieldGroupId' in field &&
|
||||
field.viewFieldGroupId === fieldGroup.id,
|
||||
),
|
||||
}),
|
||||
),
|
||||
})) as CoreViewWithRelations[];
|
||||
},
|
||||
});
|
||||
@@ -1,11 +0,0 @@
|
||||
import { type CoreView } from '~/generated-metadata/graphql';
|
||||
|
||||
export type CoreViewWithoutRelations = Exclude<
|
||||
CoreView,
|
||||
| 'viewFields'
|
||||
| 'viewFieldGroups'
|
||||
| 'viewGroups'
|
||||
| 'viewFilters'
|
||||
| 'viewFilterGroups'
|
||||
| 'viewSorts'
|
||||
>;
|
||||
-9
@@ -7,7 +7,6 @@ import { useAtomFamilySelectorValue } from '@/ui/utilities/state/jotai/hooks/use
|
||||
import { usePerformViewAPIPersist } from '@/views/hooks/internal/usePerformViewAPIPersist';
|
||||
import { useChangeView } from '@/views/hooks/useChangeView';
|
||||
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
|
||||
import { coreViewsByObjectMetadataIdFamilySelector } from '@/views/states/selectors/coreViewsByObjectMetadataIdFamilySelector';
|
||||
import { coreViewsFromObjectMetadataItemFamilySelector } from '@/views/states/selectors/coreViewsFromObjectMetadataItemFamilySelector';
|
||||
import { useCloseAndResetViewPicker } from '@/views/view-picker/hooks/useCloseAndResetViewPicker';
|
||||
import { viewPickerIsDirtyComponentState } from '@/views/view-picker/states/viewPickerIsDirtyComponentState';
|
||||
@@ -72,18 +71,10 @@ export const useDestroyViewFromCurrentState = (viewBarInstanceId?: string) => {
|
||||
changeView(remainingViews[0].id);
|
||||
}
|
||||
|
||||
store.set(
|
||||
coreViewsByObjectMetadataIdFamilySelector.selectorFamily(
|
||||
objectMetadataItem.id,
|
||||
),
|
||||
(views) => views.filter((view) => view.id !== viewPickerReferenceViewId),
|
||||
);
|
||||
|
||||
await performViewAPIDestroy({ id: viewPickerReferenceViewId });
|
||||
}, [
|
||||
currentView,
|
||||
closeAndResetViewPicker,
|
||||
objectMetadataItem.id,
|
||||
changeView,
|
||||
performViewAPIDestroy,
|
||||
store,
|
||||
|
||||
Reference in New Issue
Block a user