Translations - FIX - views not being refreshed on locale change (#14207)

as per title
This commit is contained in:
nitin
2025-09-02 17:30:40 +05:30
committed by GitHub
parent ce3fcb295d
commit c4f56156d6
9 changed files with 88 additions and 22 deletions
@@ -9,6 +9,7 @@ import {
import { UPDATE_ONE_OBJECT_METADATA_ITEM } from '../graphql/mutations';
import { useRefreshObjectMetadataItems } from '@/object-metadata/hooks/useRefreshObjectMetadataItems';
import { useRefreshCoreViewsByObjectMetadataId } from '@/views/hooks/useRefreshCoreViewsByObjectMetadataId';
// TODO: Slice the Apollo store synchronously in the update function instead of subscribing, so we can use update after read in the same function call
export const useUpdateOneObjectMetadataItem = () => {
@@ -20,6 +21,9 @@ export const useUpdateOneObjectMetadataItem = () => {
const { refreshObjectMetadataItems } =
useRefreshObjectMetadataItems('network-only');
const { refreshCoreViewsByObjectMetadataId } =
useRefreshCoreViewsByObjectMetadataId();
const updateOneObjectMetadataItem = async ({
idToUpdate,
updatePayload,
@@ -35,6 +39,7 @@ export const useUpdateOneObjectMetadataItem = () => {
});
await refreshObjectMetadataItems();
await refreshCoreViewsByObjectMetadataId(idToUpdate);
return result;
};
@@ -16,7 +16,7 @@ import { useAreViewFiltersDifferentFromRecordFilters } from '@/views/hooks/useAr
import { useAreViewSortsDifferentFromRecordSorts } from '@/views/hooks/useAreViewSortsDifferentFromRecordSorts';
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import { useIsViewAnyFieldFilterDifferentFromCurrentAnyFieldFilter } from '@/views/hooks/useIsViewAnyFieldFilterDifferentFromCurrentAnyFieldFilter';
import { useRefreshCoreViews } from '@/views/hooks/useRefreshCoreViews';
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';
@@ -36,7 +36,8 @@ const StyledContainer = styled.div`
export const UpdateViewButtonGroup = () => {
const { saveCurrentViewFilterAndSorts } = useSaveCurrentViewFiltersAndSorts();
const { refreshCoreViews } = useRefreshCoreViews();
const { refreshCoreViewsByObjectMetadataId } =
useRefreshCoreViewsByObjectMetadataId();
const { objectMetadataItem } = useRecordIndexContextOrThrow();
@@ -78,7 +79,7 @@ export const UpdateViewButtonGroup = () => {
const handleUpdateViewClick = async () => {
await saveCurrentViewFilterAndSorts();
await refreshCoreViews(objectMetadataItem.id);
await refreshCoreViewsByObjectMetadataId(objectMetadataItem.id);
};
const { hasFiltersQueryParams } = useViewFromQueryParams();
@@ -13,7 +13,7 @@ import { usePersistViewFilterGroupRecords } from '@/views/hooks/internal/usePers
import { usePersistViewFilterRecords } from '@/views/hooks/internal/usePersistViewFilterRecords';
import { usePersistViewGroupRecords } from '@/views/hooks/internal/usePersistViewGroupRecords';
import { usePersistViewSortRecords } from '@/views/hooks/internal/usePersistViewSortRecords';
import { useRefreshCoreViews } from '@/views/hooks/useRefreshCoreViews';
import { useRefreshCoreViewsByObjectMetadataId } from '@/views/hooks/useRefreshCoreViewsByObjectMetadataId';
import { isPersistingViewFieldsState } from '@/views/states/isPersistingViewFieldsState';
import { type GraphQLView } from '@/views/types/GraphQLView';
import { type ViewGroup } from '@/views/types/ViewGroup';
@@ -54,7 +54,8 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
const { objectMetadataItem } = useRecordIndexContextOrThrow();
const { refreshCoreViews } = useRefreshCoreViews();
const { refreshCoreViewsByObjectMetadataId } =
useRefreshCoreViewsByObjectMetadataId();
const currentRecordFilterGroups = useRecoilComponentValue(
currentRecordFilterGroupsComponentState,
@@ -212,7 +213,7 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
await createViewSortRecords(viewSortsToCreate, { id: newViewId });
}
await refreshCoreViews(objectMetadataItem.id);
await refreshCoreViewsByObjectMetadataId(objectMetadataItem.id);
set(isPersistingViewFieldsState, false);
return newViewId;
@@ -231,7 +232,7 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
createViewFilterGroupRecords,
createViewFilterRecords,
createViewSortRecords,
refreshCoreViews,
refreshCoreViewsByObjectMetadataId,
],
);
@@ -1,12 +1,13 @@
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { useRefreshCoreViews } from '@/views/hooks/useRefreshCoreViews';
import { useRefreshCoreViewsByObjectMetadataId } from '@/views/hooks/useRefreshCoreViewsByObjectMetadataId';
import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
import { useDeleteCoreViewMutation } from '~/generated/graphql';
export const useDeleteView = () => {
const [deleteCoreViewMutation] = useDeleteCoreViewMutation();
const { refreshCoreViews } = useRefreshCoreViews();
const { refreshCoreViewsByObjectMetadataId } =
useRefreshCoreViewsByObjectMetadataId();
const deleteView = useRecoilCallback(
({ snapshot }) =>
@@ -29,9 +30,9 @@ export const useDeleteView = () => {
},
});
await refreshCoreViews(currentView.objectMetadataId);
await refreshCoreViewsByObjectMetadataId(currentView.objectMetadataId);
},
[deleteCoreViewMutation, refreshCoreViews],
[deleteCoreViewMutation, refreshCoreViewsByObjectMetadataId],
);
return { deleteView };
@@ -0,0 +1,42 @@
import { coreViewsState } from '@/views/states/coreViewState';
import { type FetchPolicy, useApolloClient } from '@apollo/client';
import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
import { type FindManyCoreViewsQuery } from '~/generated/graphql';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { FIND_MANY_CORE_VIEWS } from '../graphql/queries/findManyCoreViews';
export const useRefreshAllCoreViews = (
fetchPolicy: FetchPolicy = 'network-only',
) => {
const client = useApolloClient();
const refreshAllCoreViews = useRecoilCallback(
({ snapshot, set }) =>
async () => {
const result = await client.query<FindManyCoreViewsQuery>({
query: FIND_MANY_CORE_VIEWS,
variables: {},
fetchPolicy,
});
const currentCoreViews = snapshot
.getLoadable(coreViewsState)
.getValue();
if (
isDefined(result.data?.getCoreViews) &&
!isDeeplyEqual(currentCoreViews, result.data.getCoreViews)
) {
set(coreViewsState, result.data.getCoreViews);
}
return result.data?.getCoreViews;
},
[client, fetchPolicy],
);
return {
refreshAllCoreViews,
};
};
@@ -4,10 +4,10 @@ import { isDefined } from 'twenty-shared/utils';
import { useFindManyCoreViewsLazyQuery } from '~/generated/graphql';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
export const useRefreshCoreViews = () => {
export const useRefreshCoreViewsByObjectMetadataId = () => {
const [findManyCoreViewsLazy] = useFindManyCoreViewsLazyQuery();
const refreshCoreViews = useRecoilCallback(
const refreshCoreViewsByObjectMetadataId = useRecoilCallback(
({ snapshot, set }) =>
async (objectMetadataId: string) => {
const result = await findManyCoreViewsLazy({
@@ -37,6 +37,6 @@ export const useRefreshCoreViews = () => {
);
return {
refreshCoreViews,
refreshCoreViewsByObjectMetadataId,
};
};
@@ -3,7 +3,7 @@ import { useRecoilCallback } from 'recoil';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { prefetchViewFromViewIdFamilySelector } from '@/prefetch/states/selector/prefetchViewFromViewIdFamilySelector';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { useRefreshCoreViews } from '@/views/hooks/useRefreshCoreViews';
import { useRefreshCoreViewsByObjectMetadataId } from '@/views/hooks/useRefreshCoreViewsByObjectMetadataId';
import { type GraphQLView } from '@/views/types/GraphQLView';
import { convertUpdateViewInputToCore } from '@/views/utils/convertUpdateViewInputToCore';
import { isDefined } from 'twenty-shared/utils';
@@ -14,7 +14,8 @@ export const useUpdateCurrentView = () => {
contextStoreCurrentViewIdComponentState,
);
const { refreshCoreViews } = useRefreshCoreViews();
const { refreshCoreViewsByObjectMetadataId } =
useRefreshCoreViewsByObjectMetadataId();
const [updateOneCoreView] = useUpdateCoreViewMutation();
@@ -46,10 +47,16 @@ export const useUpdateCurrentView = () => {
input,
},
});
await refreshCoreViews(currentView.objectMetadataId);
await refreshCoreViewsByObjectMetadataId(
currentView.objectMetadataId,
);
}
},
[currentViewIdCallbackState, refreshCoreViews, updateOneCoreView],
[
currentViewIdCallbackState,
refreshCoreViewsByObjectMetadataId,
updateOneCoreView,
],
);
return {
@@ -1,15 +1,16 @@
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import { useRefreshCoreViewsByObjectMetadataId } from '@/views/hooks/useRefreshCoreViewsByObjectMetadataId';
import { type GraphQLView } from '@/views/types/GraphQLView';
import { convertUpdateViewInputToCore } from '@/views/utils/convertUpdateViewInputToCore';
import { useRecoilCallback } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
import { useUpdateCoreViewMutation } from '~/generated/graphql';
import { useRefreshCoreViews } from './useRefreshCoreViews';
export const useUpdateView = () => {
const [updateOneCoreView] = useUpdateCoreViewMutation();
const { refreshCoreViews } = useRefreshCoreViews();
const { refreshCoreViewsByObjectMetadataId } =
useRefreshCoreViewsByObjectMetadataId();
const { objectMetadataItem } = useRecordIndexContextOrThrow();
@@ -26,9 +27,13 @@ export const useUpdateView = () => {
},
});
await refreshCoreViews(objectMetadataItem.id);
await refreshCoreViewsByObjectMetadataId(objectMetadataItem.id);
},
[objectMetadataItem.id, refreshCoreViews, updateOneCoreView],
[
objectMetadataItem.id,
refreshCoreViewsByObjectMetadataId,
updateOneCoreView,
],
);
return {
@@ -8,6 +8,7 @@ import { getDateFnsLocale } from '@/ui/field/display/utils/getDateFnsLocale.util
import { Select } from '@/ui/input/components/Select';
import { useRefreshObjectMetadataItems } from '@/object-metadata/hooks/useRefreshObjectMetadataItems';
import { useRefreshAllCoreViews } from '@/views/hooks/useRefreshAllCoreViews';
import { useLingui } from '@lingui/react/macro';
import { enUS } from 'date-fns/locale';
import { APP_LOCALES } from 'twenty-shared/translations';
@@ -36,6 +37,8 @@ export const LocalePicker = () => {
const { refreshObjectMetadataItems } =
useRefreshObjectMetadataItems('network-only');
const { refreshAllCoreViews } = useRefreshAllCoreViews('network-only');
const updateWorkspaceMember = async (changedFields: any) => {
if (!currentWorkspaceMember?.id) {
throw new Error('User is not logged in');
@@ -74,6 +77,7 @@ export const LocalePicker = () => {
console.log('Failed to save locale to localStorage:', error);
}
await refreshObjectMetadataItems();
await refreshAllCoreViews();
};
const unsortedLocaleOptions: Array<{