Seed core views in dev + fixes (#14071)

Seed core views in dev

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Raphaël Bosi
2025-08-26 13:05:20 +02:00
committed by GitHub
parent ab4fd6a182
commit 048455bbb6
13 changed files with 151 additions and 38 deletions
@@ -8,16 +8,25 @@ import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
import { getObjectPermissionsFromMapByObjectMetadataId } from '@/settings/roles/role-permissions/objects-permissions/utils/getObjectPermissionsFromMapByObjectMetadataId';
import { AppPath } from '@/types/AppPath';
import { SettingsPath } from '@/types/SettingsPath';
import { coreViewsState } from '@/views/states/coreViewState';
import { convertCoreViewToView } from '@/views/utils/convertCoreViewToView';
import { useFeatureFlagsMap } from '@/workspace/hooks/useFeatureFlagsMap';
import isEmpty from 'lodash.isempty';
import { useCallback, useMemo } from 'react';
import { useRecoilCallback, useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
import { FeatureFlagKey } from '~/generated/graphql';
import { getAppPath } from '~/utils/navigation/getAppPath';
export const useDefaultHomePagePath = () => {
const currentUser = useRecoilValue(currentUserState);
const { objectPermissionsByObjectMetadataId } = useObjectPermissions();
const featureFlagsMap = useFeatureFlagsMap();
const isCoreViewEnabled =
featureFlagsMap[FeatureFlagKey.IS_CORE_VIEW_ENABLED];
const {
activeNonSystemObjectMetadataItems,
alphaSortedActiveNonSystemObjectMetadataItems,
@@ -54,14 +63,19 @@ export const useDefaultHomePagePath = () => {
return undefined;
}
const views = snapshot.getLoadable(prefetchViewsState).getValue();
const views = isCoreViewEnabled
? snapshot
.getLoadable(coreViewsState)
.getValue()
.map(convertCoreViewToView)
: snapshot.getLoadable(prefetchViewsState).getValue();
return views.find(
(view) => view.objectMetadataId === objectMetadataItemId,
);
};
},
[arePrefetchViewsLoaded],
[arePrefetchViewsLoaded, isCoreViewEnabled],
);
const firstObjectPathInfo = useMemo<ObjectPathInfo | null>(() => {
@@ -1,7 +1,11 @@
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
import { coreViewsState } from '@/views/states/coreViewState';
import { ViewKey } from '@/views/types/ViewKey';
import { convertCoreViewToView } from '@/views/utils/convertCoreViewToView';
import { extractFeatureFlagMapFromWorkspace } from '@/workspace/utils/extractFeatureFlagMapFromWorkspace';
import { selectorFamily } from 'recoil';
import { FeatureFlagKey } from '~/generated/graphql';
export const prefetchIndexViewIdFromObjectMetadataItemFamilySelector =
selectorFamily<string | undefined, { objectMetadataItemId: string }>({
@@ -9,9 +13,20 @@ export const prefetchIndexViewIdFromObjectMetadataItemFamilySelector =
get:
({ objectMetadataItemId }) =>
({ get }) => {
const prefetchedViews = get(prefetchViewsState);
const coreViews = get(coreViewsState);
const views = coreViews.map(convertCoreViewToView);
const currentWorkspace = get(currentWorkspaceState);
const featureFlags =
extractFeatureFlagMapFromWorkspace(currentWorkspace);
const isCoreViewEnabled =
featureFlags[FeatureFlagKey.IS_CORE_VIEW_ENABLED];
const views = isCoreViewEnabled
? coreViews.map(convertCoreViewToView)
: prefetchedViews;
return views?.find(
(view) =>
view.objectMetadataId === objectMetadataItemId &&
@@ -1,7 +1,11 @@
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
import { coreViewsState } from '@/views/states/coreViewState';
import { type View } from '@/views/types/View';
import { convertCoreViewToView } from '@/views/utils/convertCoreViewToView';
import { extractFeatureFlagMapFromWorkspace } from '@/workspace/utils/extractFeatureFlagMapFromWorkspace';
import { selectorFamily } from 'recoil';
import { FeatureFlagKey } from '~/generated/graphql';
export const prefetchViewFromViewIdFamilySelector = selectorFamily<
View | undefined,
@@ -11,9 +15,19 @@ export const prefetchViewFromViewIdFamilySelector = selectorFamily<
get:
({ viewId }) =>
({ get }) => {
const prefetchedViews = get(prefetchViewsState);
const coreViews = get(coreViewsState);
const views = coreViews.map(convertCoreViewToView);
const currentWorkspace = get(currentWorkspaceState);
const featureFlags = extractFeatureFlagMapFromWorkspace(currentWorkspace);
const isCoreViewEnabled =
featureFlags[FeatureFlagKey.IS_CORE_VIEW_ENABLED];
const views = isCoreViewEnabled
? coreViews.map(convertCoreViewToView)
: prefetchedViews;
return views?.find((view) => view.id === viewId);
},
});
@@ -1,6 +1,10 @@
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
import { coreViewsState } from '@/views/states/coreViewState';
import { convertCoreViewToView } from '@/views/utils/convertCoreViewToView';
import { extractFeatureFlagMapFromWorkspace } from '@/workspace/utils/extractFeatureFlagMapFromWorkspace';
import { selectorFamily } from 'recoil';
import { FeatureFlagKey } from '~/generated/graphql';
export const prefetchViewIdsFromObjectMetadataItemFamilySelector =
selectorFamily<string[], { objectMetadataItemId: string }>({
@@ -8,9 +12,20 @@ export const prefetchViewIdsFromObjectMetadataItemFamilySelector =
get:
({ objectMetadataItemId }) =>
({ get }) => {
const prefetchedViews = get(prefetchViewsState);
const coreViews = get(coreViewsState);
const views = coreViews.map(convertCoreViewToView);
const currentWorkspace = get(currentWorkspaceState);
const featureFlags =
extractFeatureFlagMapFromWorkspace(currentWorkspace);
const isCoreViewEnabled =
featureFlags[FeatureFlagKey.IS_CORE_VIEW_ENABLED];
const views = isCoreViewEnabled
? coreViews.map(convertCoreViewToView)
: prefetchedViews;
return views
.filter((view) => view.objectMetadataId === objectMetadataItemId)
.map((view) => view.id);
@@ -1,13 +1,26 @@
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
import { coreViewsState } from '@/views/states/coreViewState';
import { convertCoreViewToView } from '@/views/utils/convertCoreViewToView';
import { extractFeatureFlagMapFromWorkspace } from '@/workspace/utils/extractFeatureFlagMapFromWorkspace';
import { selector } from 'recoil';
import { FeatureFlagKey } from '~/generated/graphql';
export const prefetchViewLengthSelector = selector<number>({
key: 'prefetchViewLengthSelector',
get: ({ get }) => {
const prefetchedViews = get(prefetchViewsState);
const coreViews = get(coreViewsState);
const views = coreViews.map(convertCoreViewToView);
const currentWorkspace = get(currentWorkspaceState);
const featureFlags = extractFeatureFlagMapFromWorkspace(currentWorkspace);
const isCoreViewEnabled = featureFlags[FeatureFlagKey.IS_CORE_VIEW_ENABLED];
const views = isCoreViewEnabled
? coreViews.map(convertCoreViewToView)
: prefetchedViews;
return views?.length ?? 0;
},
});
@@ -1,7 +1,11 @@
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { prefetchViewsState } from '@/prefetch/states/prefetchViewsState';
import { coreViewsState } from '@/views/states/coreViewState';
import { type View } from '@/views/types/View';
import { convertCoreViewToView } from '@/views/utils/convertCoreViewToView';
import { extractFeatureFlagMapFromWorkspace } from '@/workspace/utils/extractFeatureFlagMapFromWorkspace';
import { selectorFamily } from 'recoil';
import { FeatureFlagKey } from '~/generated/graphql';
export const prefetchViewsFromObjectMetadataItemFamilySelector = selectorFamily<
View[],
@@ -11,9 +15,18 @@ export const prefetchViewsFromObjectMetadataItemFamilySelector = selectorFamily<
get:
({ objectMetadataItemId }) =>
({ get }) => {
const prefetchedViews = get(prefetchViewsState);
const coreViews = get(coreViewsState);
const views = coreViews.map(convertCoreViewToView);
const currentWorkspace = get(currentWorkspaceState);
const featureFlags = extractFeatureFlagMapFromWorkspace(currentWorkspace);
const isCoreViewEnabled =
featureFlags[FeatureFlagKey.IS_CORE_VIEW_ENABLED];
const views = isCoreViewEnabled
? coreViews.map(convertCoreViewToView)
: prefetchedViews;
const filteredViews = views.filter(
(view) => view.objectMetadataId === objectMetadataItemId,
@@ -14,6 +14,7 @@ import { detectTimeFormat } from '@/localization/utils/detectTimeFormat';
import { detectTimeZone } from '@/localization/utils/detectTimeZone';
import { getDateFormatFromWorkspaceDateFormat } from '@/localization/utils/getDateFormatFromWorkspaceDateFormat';
import { getTimeFormatFromWorkspaceTimeFormat } from '@/localization/utils/getTimeFormatFromWorkspaceTimeFormat';
import { coreViewsState } from '@/views/states/coreViewState';
import { useCallback } from 'react';
import { useSetRecoilState } from 'recoil';
import { SOURCE_LOCALE, type APP_LOCALES } from 'twenty-shared/translations';
@@ -38,6 +39,7 @@ export const useLoadCurrentUser = () => {
);
const setCurrentWorkspace = useSetRecoilState(currentWorkspaceState);
const setDateTimeFormat = useSetRecoilState(dateTimeFormatState);
const setCoreViews = useSetRecoilState(coreViewsState);
const { isOnAWorkspace } = useIsCurrentLocationOnAWorkspace();
@@ -128,6 +130,10 @@ export const useLoadCurrentUser = () => {
});
}
if (isDefined(workspace) && isDefined(workspace.views)) {
setCoreViews(workspace.views);
}
return {
user,
workspaceMember,
@@ -137,6 +143,7 @@ export const useLoadCurrentUser = () => {
getCurrentUser,
isOnAWorkspace,
setAvailableWorkspaces,
setCoreViews,
setCurrentUser,
setCurrentUserWorkspace,
setCurrentWorkspace,
@@ -52,6 +52,7 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
displayValue: 'test',
viewFilterGroupId: 'group-1',
positionInViewFilterGroup: 0,
subFieldName: null,
};
const mockCoreViewFilter: Omit<CoreViewFilter, 'workspaceId'> = {
@@ -65,6 +66,7 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
viewId: allCompaniesCoreView.id,
positionInViewFilterGroup: 0,
viewFilterGroupId: 'group-1',
subFieldName: null,
};
const mockView = {
@@ -1,24 +1,10 @@
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { extractFeatureFlagMapFromWorkspace } from '@/workspace/utils/extractFeatureFlagMapFromWorkspace';
import { useRecoilValue } from 'recoil';
import { FeatureFlagKey } from '~/generated/graphql';
import { buildRecordFromKeysWithSameValue } from '~/utils/array/buildRecordFromKeysWithSameValue';
import { type FeatureFlagKey } from '~/generated/graphql';
export const useFeatureFlagsMap = (): Record<FeatureFlagKey, boolean> => {
const currentWorkspace = useRecoilValue(currentWorkspaceState);
const currentWorkspaceFeatureFlags = currentWorkspace?.featureFlags;
const initialFeatureFlags = buildRecordFromKeysWithSameValue(
Object.values(FeatureFlagKey),
false,
);
if (!currentWorkspaceFeatureFlags) {
return initialFeatureFlags;
}
return currentWorkspaceFeatureFlags.reduce((acc, featureFlag) => {
acc[featureFlag.key] = featureFlag.value;
return acc;
}, initialFeatureFlags);
return extractFeatureFlagMapFromWorkspace(currentWorkspace);
};
@@ -0,0 +1,23 @@
import { type CurrentWorkspace } from '@/auth/states/currentWorkspaceState';
import { FeatureFlagKey } from '~/generated/graphql';
import { buildRecordFromKeysWithSameValue } from '~/utils/array/buildRecordFromKeysWithSameValue';
export const extractFeatureFlagMapFromWorkspace = (
currentWorkspace: CurrentWorkspace | null,
): Record<FeatureFlagKey, boolean> => {
const currentWorkspaceFeatureFlags = currentWorkspace?.featureFlags;
const initialFeatureFlags = buildRecordFromKeysWithSameValue(
Object.values(FeatureFlagKey),
false,
);
if (!currentWorkspaceFeatureFlags) {
return initialFeatureFlags;
}
return currentWorkspaceFeatureFlags.reduce((acc, featureFlag) => {
acc[featureFlag.key] = featureFlag.value;
return acc;
}, initialFeatureFlags);
};