Replace sign-in mocked metadata with hardcoded BackgroundMock (#20308)
## Summary When the user is logged out, we render the auth modal on top of a sample table to make the empty page feel alive. So far this was achieved by **loading a full set of mocked object / field / view / navigation-menu metadata into the runtime metadata store** and then mounting the real `RecordTable` and `AppNavigationDrawer` behind the modal. This had a few downsides: - Significant bundle weight pulled in for unauthenticated users (mocked GraphQL fixtures + the real `RecordTable` virtualization stack). - Plenty of code paths that had to know about the "showAuthModal" case (`useRecordIndexTableQuery`, `useTriggerInitialRecordTableDataLoad`, `MainContextStoreProvider`, `IsMinimalMetadataReadyEffect`...). - Any change to metadata-store internals or to the record-table runtime risked breaking the logged-out background. This PR replaces the entire flow with a small, self-contained `BackgroundMock` component tree that **does not consume any metadata** and **does not load any mocked metadata at runtime**. ### What changed - New module under `sign-in-background-mock`: - `BackgroundMockPage` + `BackgroundMockViewBar` + `BackgroundMockTable` + `BackgroundMockTableRow` render a hardcoded "Companies" table that visually mirrors the real one. - `BackgroundMockNavigationDrawer` renders a hardcoded sidebar with People / Companies / Opportunities / Tasks / Notes (with their standard colors). - Hardcoded constants in `BackgroundMockCompanies.ts`, `BackgroundMockColumns.ts`, `BackgroundMockNavigationItems.ts`. - `MinimalMetadataLoadEffect` no longer calls `loadMockedMetadataAtomic` for unauthenticated users — it just doesn't load anything. - `IsMinimalMetadataReadyEffect` now reports ready immediately when there is no access token pair, so the skeleton loader doesn't hang waiting for metadata that will never come. - `MainContextStoreProvider`, `useRecordIndexTableQuery`, and `useTriggerInitialRecordTableDataLoad` drop their `showAuthModal` branches — the real `RecordTable` is no longer mounted behind the modal. - `DefaultLayout` and `NotFound` now lazily load `BackgroundMockPage` / `BackgroundMockNavigationDrawer` instead of the deleted `SignInBackgroundMockPage` / `SignInAppNavigationDrawerMock`. - Removed: `SignInBackgroundMockPage`, `SignInBackgroundMockContainer`, `SignInBackgroundMockContainerEffect`, `SignInAppNavigationDrawerMock`, `SignInBackgroundMockColumnDefinitions`, `SignInBackgroundMockCompanies`, `SignInBackgroundMockViewFields`. `useLoadMockedMetadata` and `preloadMockedMetadata` are kept on purpose: Storybook decorators (`ObjectMetadataItemsDecorator`, `WorkflowStepDecorator`) still rely on the mocked metadata fixtures, but **production** unauthenticated runtime no longer touches them. ### Visual parity Side-by-side at 1440×900 on `/sign-in`: **Before** (loads mocked metadata + real RecordTable):  **After** (purely hardcoded BackgroundMock):  ## Test plan - [ ] `npx nx typecheck twenty-front` ✅ (passes locally) - [ ] `npx nx lint:diff-with-main twenty-front` ✅ (oxlint + prettier clean) - [ ] `npx jest useRecordIndexTableQuery` ✅ - [ ] Manually verify `/sign-in` renders the table + nav drawer behind the modal - [ ] Manually verify `/not-found` still renders the background - [ ] Verify CI: storybook, unit tests, e2e tests
This commit is contained in:
+2
-11
@@ -3,7 +3,6 @@ import { metadataStoreState } from '@/metadata-store/states/metadataStoreState';
|
|||||||
import { useIsSettingsPage } from '@/navigation/hooks/useIsSettingsPage';
|
import { useIsSettingsPage } from '@/navigation/hooks/useIsSettingsPage';
|
||||||
import { useLastVisitedView } from '@/navigation/hooks/useLastVisitedView';
|
import { useLastVisitedView } from '@/navigation/hooks/useLastVisitedView';
|
||||||
import { objectMetadataItemsSelector } from '@/object-metadata/states/objectMetadataItemsSelector';
|
import { objectMetadataItemsSelector } from '@/object-metadata/states/objectMetadataItemsSelector';
|
||||||
import { useShowAuthModal } from '@/ui/layout/hooks/useShowAuthModal';
|
|
||||||
import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue';
|
import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue';
|
||||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||||
import { viewsSelector } from '@/views/states/selectors/viewsSelector';
|
import { viewsSelector } from '@/views/states/selectors/viewsSelector';
|
||||||
@@ -38,8 +37,6 @@ const getViewId = (
|
|||||||
return undefined;
|
return undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
const SIGN_IN_BACKGROUND_OBJECT_NAME_PLURAL = 'companies';
|
|
||||||
|
|
||||||
export const MainContextStoreProvider = () => {
|
export const MainContextStoreProvider = () => {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const isRecordIndexPage = isMatchingLocation(
|
const isRecordIndexPage = isMatchingLocation(
|
||||||
@@ -49,15 +46,10 @@ export const MainContextStoreProvider = () => {
|
|||||||
const isRecordShowPage = isMatchingLocation(location, AppPath.RecordShowPage);
|
const isRecordShowPage = isMatchingLocation(location, AppPath.RecordShowPage);
|
||||||
const isStandalonePage = isMatchingLocation(location, AppPath.PageLayoutPage);
|
const isStandalonePage = isMatchingLocation(location, AppPath.PageLayoutPage);
|
||||||
const isSettingsPage = useIsSettingsPage();
|
const isSettingsPage = useIsSettingsPage();
|
||||||
const showAuthModal = useShowAuthModal();
|
|
||||||
|
|
||||||
const objectNamePluralFromParams = useParams().objectNamePlural ?? '';
|
const objectNamePlural = useParams().objectNamePlural ?? '';
|
||||||
const objectNameSingular = useParams().objectNameSingular ?? '';
|
const objectNameSingular = useParams().objectNameSingular ?? '';
|
||||||
|
|
||||||
const objectNamePlural = showAuthModal
|
|
||||||
? SIGN_IN_BACKGROUND_OBJECT_NAME_PLURAL
|
|
||||||
: objectNamePluralFromParams;
|
|
||||||
|
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const viewIdQueryParamRaw = searchParams.get('viewId');
|
const viewIdQueryParamRaw = searchParams.get('viewId');
|
||||||
|
|
||||||
@@ -120,8 +112,7 @@ export const MainContextStoreProvider = () => {
|
|||||||
(isRecordIndexPage ||
|
(isRecordIndexPage ||
|
||||||
isRecordShowPage ||
|
isRecordShowPage ||
|
||||||
isStandalonePage ||
|
isStandalonePage ||
|
||||||
isSettingsPage ||
|
isSettingsPage) &&
|
||||||
showAuthModal) &&
|
|
||||||
metadataStore.status === 'up-to-date';
|
metadataStore.status === 'up-to-date';
|
||||||
|
|
||||||
if (!shouldComputeContextStore) {
|
if (!shouldComputeContextStore) {
|
||||||
|
|||||||
+8
-5
@@ -28,21 +28,24 @@ export const IsMinimalMetadataReadyEffect = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!hasAccessTokenPair) {
|
||||||
|
setIsMinimalMetadataReady(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const hasActiveWorkspace = isWorkspaceActiveOrSuspended(currentWorkspace);
|
const hasActiveWorkspace = isWorkspaceActiveOrSuspended(currentWorkspace);
|
||||||
|
|
||||||
const areObjectsLoaded = metadataStore.status === 'up-to-date';
|
const areObjectsLoaded = metadataStore.status === 'up-to-date';
|
||||||
const areViewsLoaded = metadataStoreViews.status === 'up-to-date';
|
const areViewsLoaded = metadataStoreViews.status === 'up-to-date';
|
||||||
|
|
||||||
const isReady = !areObjectsLoaded
|
|
||||||
? false
|
|
||||||
: !hasAccessTokenPair ||
|
|
||||||
(isDefined(currentUser) && (!hasActiveWorkspace || areViewsLoaded));
|
|
||||||
|
|
||||||
if (!areObjectsLoaded) {
|
if (!areObjectsLoaded) {
|
||||||
setIsMinimalMetadataReady(false);
|
setIsMinimalMetadataReady(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const isReady =
|
||||||
|
isDefined(currentUser) && (!hasActiveWorkspace || areViewsLoaded);
|
||||||
|
|
||||||
if (isReady) {
|
if (isReady) {
|
||||||
setIsMinimalMetadataReady(true);
|
setIsMinimalMetadataReady(true);
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-42
@@ -2,70 +2,41 @@ import { useHasAccessTokenPair } from '@/auth/hooks/useHasAccessTokenPair';
|
|||||||
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
|
||||||
import { isCurrentUserLoadedState } from '@/auth/states/isCurrentUserLoadedState';
|
import { isCurrentUserLoadedState } from '@/auth/states/isCurrentUserLoadedState';
|
||||||
import { useLoadMinimalMetadata } from '@/metadata-store/hooks/useLoadMinimalMetadata';
|
import { useLoadMinimalMetadata } from '@/metadata-store/hooks/useLoadMinimalMetadata';
|
||||||
import { useLoadMockedMetadata } from '@/metadata-store/hooks/useLoadMockedMetadata';
|
|
||||||
import { useLoadStaleMetadataEntities } from '@/metadata-store/hooks/useLoadStaleMetadataEntities';
|
import { useLoadStaleMetadataEntities } from '@/metadata-store/hooks/useLoadStaleMetadataEntities';
|
||||||
import { metadataLoadedVersionState } from '@/metadata-store/states/metadataLoadedVersionState';
|
import { metadataLoadedVersionState } from '@/metadata-store/states/metadataLoadedVersionState';
|
||||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { isWorkspaceActiveOrSuspended } from 'twenty-shared/workspace';
|
import { isWorkspaceActiveOrSuspended } from 'twenty-shared/workspace';
|
||||||
|
|
||||||
type LoadedState = 'none' | 'mocked' | 'real';
|
|
||||||
|
|
||||||
const computeDesiredLoadState = (
|
|
||||||
hasAccessTokenPair: boolean,
|
|
||||||
isActiveWorkspace: boolean,
|
|
||||||
): LoadedState => {
|
|
||||||
if (hasAccessTokenPair && isActiveWorkspace) {
|
|
||||||
return 'real';
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'mocked';
|
|
||||||
};
|
|
||||||
|
|
||||||
export const MinimalMetadataLoadEffect = () => {
|
export const MinimalMetadataLoadEffect = () => {
|
||||||
const hasAccessTokenPair = useHasAccessTokenPair();
|
const hasAccessTokenPair = useHasAccessTokenPair();
|
||||||
const isCurrentUserLoaded = useAtomStateValue(isCurrentUserLoadedState);
|
const isCurrentUserLoaded = useAtomStateValue(isCurrentUserLoadedState);
|
||||||
const currentWorkspace = useAtomStateValue(currentWorkspaceState);
|
const currentWorkspace = useAtomStateValue(currentWorkspaceState);
|
||||||
const metadataLoadedVersion = useAtomStateValue(metadataLoadedVersionState);
|
const metadataLoadedVersion = useAtomStateValue(metadataLoadedVersionState);
|
||||||
const [lastMetadataLoadData, setLastMetadataLoadData] = useState<{
|
const [lastLoadedVersion, setLastLoadedVersion] = useState<number>(-1);
|
||||||
state: LoadedState;
|
|
||||||
version: number;
|
|
||||||
}>({ state: 'none', version: -1 });
|
|
||||||
|
|
||||||
const { loadMinimalMetadata } = useLoadMinimalMetadata();
|
const { loadMinimalMetadata } = useLoadMinimalMetadata();
|
||||||
const { loadMockedMetadataAtomic } = useLoadMockedMetadata();
|
|
||||||
const { loadStaleMetadataEntities } = useLoadStaleMetadataEntities();
|
const { loadStaleMetadataEntities } = useLoadStaleMetadataEntities();
|
||||||
|
|
||||||
const isActiveWorkspace = isWorkspaceActiveOrSuspended(currentWorkspace);
|
const isActiveWorkspace = isWorkspaceActiveOrSuspended(currentWorkspace);
|
||||||
|
const shouldLoadRealMetadata = hasAccessTokenPair && isActiveWorkspace;
|
||||||
const desiredLoadState = computeDesiredLoadState(
|
|
||||||
hasAccessTokenPair,
|
|
||||||
isActiveWorkspace,
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isCurrentUserLoaded) {
|
if (!isCurrentUserLoaded) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const versionChanged =
|
if (!shouldLoadRealMetadata) {
|
||||||
metadataLoadedVersion !== lastMetadataLoadData.version;
|
|
||||||
|
|
||||||
if (!versionChanged && lastMetadataLoadData.state === desiredLoadState) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
setLastMetadataLoadData({
|
if (metadataLoadedVersion === lastLoadedVersion) {
|
||||||
state: desiredLoadState,
|
return;
|
||||||
version: metadataLoadedVersion,
|
}
|
||||||
});
|
|
||||||
|
setLastLoadedVersion(metadataLoadedVersion);
|
||||||
|
|
||||||
const performLoad = async () => {
|
const performLoad = async () => {
|
||||||
if (desiredLoadState === 'mocked') {
|
|
||||||
await loadMockedMetadataAtomic();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const result = await loadMinimalMetadata();
|
const result = await loadMinimalMetadata();
|
||||||
|
|
||||||
if (result?.staleEntityKeys && result.staleEntityKeys.length > 0) {
|
if (result?.staleEntityKeys && result.staleEntityKeys.length > 0) {
|
||||||
@@ -76,13 +47,10 @@ export const MinimalMetadataLoadEffect = () => {
|
|||||||
performLoad();
|
performLoad();
|
||||||
}, [
|
}, [
|
||||||
isCurrentUserLoaded,
|
isCurrentUserLoaded,
|
||||||
hasAccessTokenPair,
|
shouldLoadRealMetadata,
|
||||||
isActiveWorkspace,
|
lastLoadedVersion,
|
||||||
desiredLoadState,
|
|
||||||
lastMetadataLoadData,
|
|
||||||
metadataLoadedVersion,
|
metadataLoadedVersion,
|
||||||
loadMinimalMetadata,
|
loadMinimalMetadata,
|
||||||
loadMockedMetadataAtomic,
|
|
||||||
loadStaleMetadataEntities,
|
loadStaleMetadataEntities,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
+2
-7
@@ -2,12 +2,8 @@ import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadata
|
|||||||
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
||||||
import { useRelevantRecordsGqlFields } from '@/object-record/record-field/hooks/useRelevantRecordsGqlFields';
|
import { useRelevantRecordsGqlFields } from '@/object-record/record-field/hooks/useRelevantRecordsGqlFields';
|
||||||
import { useFindManyRecordIndexTableParams } from '@/object-record/record-index/hooks/useFindManyRecordIndexTableParams';
|
import { useFindManyRecordIndexTableParams } from '@/object-record/record-index/hooks/useFindManyRecordIndexTableParams';
|
||||||
import { SIGN_IN_BACKGROUND_MOCK_COMPANIES } from '@/sign-in-background-mock/constants/SignInBackgroundMockCompanies';
|
|
||||||
import { useShowAuthModal } from '@/ui/layout/hooks/useShowAuthModal';
|
|
||||||
|
|
||||||
export const useRecordIndexTableQuery = (objectNameSingular: string) => {
|
export const useRecordIndexTableQuery = (objectNameSingular: string) => {
|
||||||
const showAuthModal = useShowAuthModal();
|
|
||||||
|
|
||||||
const params = useFindManyRecordIndexTableParams(objectNameSingular);
|
const params = useFindManyRecordIndexTableParams(objectNameSingular);
|
||||||
|
|
||||||
const { objectMetadataItem } = useObjectMetadataItem({
|
const { objectMetadataItem } = useObjectMetadataItem({
|
||||||
@@ -28,12 +24,11 @@ export const useRecordIndexTableQuery = (objectNameSingular: string) => {
|
|||||||
} = useFindManyRecords({
|
} = useFindManyRecords({
|
||||||
...params,
|
...params,
|
||||||
recordGqlFields,
|
recordGqlFields,
|
||||||
skip: showAuthModal,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
records: showAuthModal ? SIGN_IN_BACKGROUND_MOCK_COMPANIES : records,
|
records,
|
||||||
loading: showAuthModal ? false : loading,
|
loading,
|
||||||
hasNextPage,
|
hasNextPage,
|
||||||
queryIdentifier,
|
queryIdentifier,
|
||||||
totalCount,
|
totalCount,
|
||||||
|
|||||||
+26
-36
@@ -30,8 +30,6 @@ import { recordIdByRealIndexComponentState } from '@/object-record/record-table/
|
|||||||
import { scrollAtRealIndexComponentState } from '@/object-record/record-table/virtualization/states/scrollAtRealIndexComponentState';
|
import { scrollAtRealIndexComponentState } from '@/object-record/record-table/virtualization/states/scrollAtRealIndexComponentState';
|
||||||
import { totalNumberOfRecordsToVirtualizeComponentState } from '@/object-record/record-table/virtualization/states/totalNumberOfRecordsToVirtualizeComponentState';
|
import { totalNumberOfRecordsToVirtualizeComponentState } from '@/object-record/record-table/virtualization/states/totalNumberOfRecordsToVirtualizeComponentState';
|
||||||
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
|
||||||
import { SIGN_IN_BACKGROUND_MOCK_COMPANIES } from '@/sign-in-background-mock/constants/SignInBackgroundMockCompanies';
|
|
||||||
import { useShowAuthModal } from '@/ui/layout/hooks/useShowAuthModal';
|
|
||||||
import { useAtomComponentFamilyStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateCallbackState';
|
import { useAtomComponentFamilyStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateCallbackState';
|
||||||
import { useAtomComponentSelectorCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentSelectorCallbackState';
|
import { useAtomComponentSelectorCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentSelectorCallbackState';
|
||||||
import { useAtomComponentStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateCallbackState';
|
import { useAtomComponentStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateCallbackState';
|
||||||
@@ -41,8 +39,6 @@ import { isDefined } from 'twenty-shared/utils';
|
|||||||
export const useTriggerInitialRecordTableDataLoad = () => {
|
export const useTriggerInitialRecordTableDataLoad = () => {
|
||||||
const { recordTableId, objectNameSingular } = useRecordTableContextOrThrow();
|
const { recordTableId, objectNameSingular } = useRecordTableContextOrThrow();
|
||||||
|
|
||||||
const showAuthModal = useShowAuthModal();
|
|
||||||
|
|
||||||
const { findManyRecordsLazy } =
|
const { findManyRecordsLazy } =
|
||||||
useRecordIndexTableLazyQuery(objectNameSingular);
|
useRecordIndexTableLazyQuery(objectNameSingular);
|
||||||
|
|
||||||
@@ -155,40 +151,35 @@ export const useTriggerInitialRecordTableDataLoad = () => {
|
|||||||
let records: ObjectRecord[] | null = null;
|
let records: ObjectRecord[] | null = null;
|
||||||
let totalCount = 0;
|
let totalCount = 0;
|
||||||
|
|
||||||
if (showAuthModal) {
|
const newRecordIdByRealIndex = new Map(
|
||||||
records = SIGN_IN_BACKGROUND_MOCK_COMPANIES;
|
store.get(recordIdByRealIndexCallbackState),
|
||||||
totalCount = SIGN_IN_BACKGROUND_MOCK_COMPANIES.length;
|
);
|
||||||
} else {
|
const newDataLoadingStatusByRealIndex = new Map(
|
||||||
const newRecordIdByRealIndex = new Map(
|
store.get(dataLoadingStatusByRealIndexCallbackState),
|
||||||
store.get(recordIdByRealIndexCallbackState),
|
);
|
||||||
);
|
|
||||||
const newDataLoadingStatusByRealIndex = new Map(
|
|
||||||
store.get(dataLoadingStatusByRealIndexCallbackState),
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const [realIndex] of currentRecordIds.entries()) {
|
for (const [realIndex] of currentRecordIds.entries()) {
|
||||||
newDataLoadingStatusByRealIndex.set(realIndex, 'not-loaded');
|
newDataLoadingStatusByRealIndex.set(realIndex, 'not-loaded');
|
||||||
newRecordIdByRealIndex.delete(realIndex);
|
newRecordIdByRealIndex.delete(realIndex);
|
||||||
}
|
|
||||||
|
|
||||||
store.set(recordIdByRealIndexCallbackState, newRecordIdByRealIndex);
|
|
||||||
store.set(
|
|
||||||
dataLoadingStatusByRealIndexCallbackState,
|
|
||||||
newDataLoadingStatusByRealIndex,
|
|
||||||
);
|
|
||||||
|
|
||||||
store.set(
|
|
||||||
recordIndexRecordIdsByGroupFamilyState(NO_RECORD_GROUP_FAMILY_KEY),
|
|
||||||
[],
|
|
||||||
);
|
|
||||||
|
|
||||||
const { records: findManyRecords, totalCount: findManyTotalCount } =
|
|
||||||
await findManyRecordsLazy();
|
|
||||||
|
|
||||||
records = findManyRecords;
|
|
||||||
totalCount = findManyTotalCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
store.set(recordIdByRealIndexCallbackState, newRecordIdByRealIndex);
|
||||||
|
store.set(
|
||||||
|
dataLoadingStatusByRealIndexCallbackState,
|
||||||
|
newDataLoadingStatusByRealIndex,
|
||||||
|
);
|
||||||
|
|
||||||
|
store.set(
|
||||||
|
recordIndexRecordIdsByGroupFamilyState(NO_RECORD_GROUP_FAMILY_KEY),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
const { records: findManyRecords, totalCount: findManyTotalCount } =
|
||||||
|
await findManyRecordsLazy();
|
||||||
|
|
||||||
|
records = findManyRecords;
|
||||||
|
totalCount = findManyTotalCount;
|
||||||
|
|
||||||
store.set(totalNumberOfRecordsToVirtualizeCallbackState, totalCount);
|
store.set(totalNumberOfRecordsToVirtualizeCallbackState, totalCount);
|
||||||
|
|
||||||
if (isDefined(records)) {
|
if (isDefined(records)) {
|
||||||
@@ -230,7 +221,6 @@ export const useTriggerInitialRecordTableDataLoad = () => {
|
|||||||
recordIndexAllRecordIds,
|
recordIndexAllRecordIds,
|
||||||
recordIndexRecordIdsByGroupFamilyState,
|
recordIndexRecordIdsByGroupFamilyState,
|
||||||
store,
|
store,
|
||||||
showAuthModal,
|
|
||||||
dataPagesLoadedCallbackState,
|
dataPagesLoadedCallbackState,
|
||||||
isRecordTableInitialLoading,
|
isRecordTableInitialLoading,
|
||||||
lastScrollPositionCallbackState,
|
lastScrollPositionCallbackState,
|
||||||
|
|||||||
+35
-26
@@ -1,11 +1,3 @@
|
|||||||
import { NavigationDrawer } from '@/ui/navigation/navigation-drawer/components/NavigationDrawer';
|
|
||||||
|
|
||||||
import { NavigationDrawerSectionForObjectMetadataItems } from '@/object-metadata/components/NavigationDrawerSectionForObjectMetadataItems';
|
|
||||||
import { objectMetadataItemsSelector } from '@/object-metadata/states/objectMetadataItemsSelector';
|
|
||||||
import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem';
|
|
||||||
import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection';
|
|
||||||
import { DEFAULT_WORKSPACE_NAME } from '@/ui/navigation/navigation-drawer/constants/DefaultWorkspaceName';
|
|
||||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
|
||||||
import { styled } from '@linaria/react';
|
import { styled } from '@linaria/react';
|
||||||
import { useLingui } from '@lingui/react/macro';
|
import { useLingui } from '@lingui/react/macro';
|
||||||
import { SettingsPath } from 'twenty-shared/types';
|
import { SettingsPath } from 'twenty-shared/types';
|
||||||
@@ -13,28 +5,27 @@ import { getSettingsPath } from 'twenty-shared/utils';
|
|||||||
import { IconSearch, IconSettings } from 'twenty-ui/display';
|
import { IconSearch, IconSettings } from 'twenty-ui/display';
|
||||||
import { getOsControlSymbol, useIsMobile } from 'twenty-ui/utilities';
|
import { getOsControlSymbol, useIsMobile } from 'twenty-ui/utilities';
|
||||||
|
|
||||||
|
import { BACKGROUND_MOCK_OTHER_ITEMS } from '@/sign-in-background-mock/constants/BackgroundMockOtherItems';
|
||||||
|
import { BACKGROUND_MOCK_WORKSPACE_ITEMS } from '@/sign-in-background-mock/constants/BackgroundMockNavigationItems';
|
||||||
|
import { NavigationDrawer } from '@/ui/navigation/navigation-drawer/components/NavigationDrawer';
|
||||||
|
import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem';
|
||||||
|
import { NavigationDrawerSection } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSection';
|
||||||
|
import { NavigationDrawerSectionTitle } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerSectionTitle';
|
||||||
|
import { DEFAULT_WORKSPACE_NAME } from '@/ui/navigation/navigation-drawer/constants/DefaultWorkspaceName';
|
||||||
|
|
||||||
const StyledMainSectionWrapper = styled.div`
|
const StyledMainSectionWrapper = styled.div`
|
||||||
min-height: fit-content;
|
min-height: fit-content;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const WORKSPACE_FAVORITES = [
|
export type BackgroundMockNavigationDrawerProps = {
|
||||||
'person',
|
|
||||||
'company',
|
|
||||||
'opportunity',
|
|
||||||
'task',
|
|
||||||
'note',
|
|
||||||
];
|
|
||||||
|
|
||||||
export type SignInAppNavigationDrawerMockProps = {
|
|
||||||
className?: string;
|
className?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SignInAppNavigationDrawerMock = ({
|
export const BackgroundMockNavigationDrawer = ({
|
||||||
className,
|
className,
|
||||||
}: SignInAppNavigationDrawerMockProps) => {
|
}: BackgroundMockNavigationDrawerProps) => {
|
||||||
const isMobile = useIsMobile();
|
const isMobile = useIsMobile();
|
||||||
const { t } = useLingui();
|
const { t } = useLingui();
|
||||||
const objectMetadataItems = useAtomStateValue(objectMetadataItemsSelector);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NavigationDrawer className={className} title={DEFAULT_WORKSPACE_NAME}>
|
<NavigationDrawer className={className} title={DEFAULT_WORKSPACE_NAME}>
|
||||||
@@ -56,12 +47,30 @@ export const SignInAppNavigationDrawerMock = ({
|
|||||||
</NavigationDrawerSection>
|
</NavigationDrawerSection>
|
||||||
</StyledMainSectionWrapper>
|
</StyledMainSectionWrapper>
|
||||||
)}
|
)}
|
||||||
<NavigationDrawerSectionForObjectMetadataItems
|
<NavigationDrawerSection>
|
||||||
sectionTitle={t`Workspace`}
|
<NavigationDrawerSectionTitle label={t`Workspace`} />
|
||||||
objectMetadataItems={objectMetadataItems.filter((item) =>
|
{BACKGROUND_MOCK_WORKSPACE_ITEMS.map((item, index) => (
|
||||||
WORKSPACE_FAVORITES.includes(item.nameSingular),
|
<NavigationDrawerItem
|
||||||
)}
|
key={item.label}
|
||||||
/>
|
label={item.label}
|
||||||
|
Icon={item.Icon}
|
||||||
|
iconColor={item.color}
|
||||||
|
active={index === 0}
|
||||||
|
onClick={() => {}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</NavigationDrawerSection>
|
||||||
|
<NavigationDrawerSection>
|
||||||
|
<NavigationDrawerSectionTitle label={t`Other`} />
|
||||||
|
{BACKGROUND_MOCK_OTHER_ITEMS.map((item) => (
|
||||||
|
<NavigationDrawerItem
|
||||||
|
key={item.label}
|
||||||
|
label={item.label}
|
||||||
|
Icon={item.Icon}
|
||||||
|
onClick={() => {}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</NavigationDrawerSection>
|
||||||
</NavigationDrawer>
|
</NavigationDrawer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
+63
@@ -0,0 +1,63 @@
|
|||||||
|
import { styled } from '@linaria/react';
|
||||||
|
import { t } from '@lingui/core/macro';
|
||||||
|
import {
|
||||||
|
IconBuildingSkyscraper,
|
||||||
|
IconDotsVertical,
|
||||||
|
IconLayoutSidebarRight,
|
||||||
|
IconPlus,
|
||||||
|
TintedIconTile,
|
||||||
|
} from 'twenty-ui/display';
|
||||||
|
import { Button, LightIconButton } from 'twenty-ui/input';
|
||||||
|
|
||||||
|
import { BackgroundMockTable } from '@/sign-in-background-mock/components/BackgroundMockTable';
|
||||||
|
import { BackgroundMockViewBar } from '@/sign-in-background-mock/components/BackgroundMockViewBar';
|
||||||
|
import { PageBody } from '@/ui/layout/page/components/PageBody';
|
||||||
|
import { PageContainer } from '@/ui/layout/page/components/PageContainer';
|
||||||
|
import { PageHeader } from '@/ui/layout/page/components/PageHeader';
|
||||||
|
|
||||||
|
const StyledTableContainer = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const BackgroundMockPage = () => {
|
||||||
|
return (
|
||||||
|
<PageContainer>
|
||||||
|
<PageHeader
|
||||||
|
title={t`Companies`}
|
||||||
|
Icon={() => (
|
||||||
|
<TintedIconTile Icon={IconBuildingSkyscraper} color="blue" />
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
Icon={IconPlus}
|
||||||
|
title={t`New Company`}
|
||||||
|
variant="primary"
|
||||||
|
accent="default"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
<LightIconButton
|
||||||
|
Icon={IconDotsVertical}
|
||||||
|
accent="tertiary"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
Icon={IconLayoutSidebarRight}
|
||||||
|
variant="secondary"
|
||||||
|
accent="default"
|
||||||
|
size="small"
|
||||||
|
/>
|
||||||
|
</PageHeader>
|
||||||
|
<PageBody>
|
||||||
|
<StyledTableContainer>
|
||||||
|
<BackgroundMockViewBar />
|
||||||
|
<BackgroundMockTable />
|
||||||
|
</StyledTableContainer>
|
||||||
|
</PageBody>
|
||||||
|
</PageContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
+232
@@ -0,0 +1,232 @@
|
|||||||
|
import { styled } from '@linaria/react';
|
||||||
|
import { useContext } from 'react';
|
||||||
|
|
||||||
|
import { BackgroundMockTableRow } from '@/sign-in-background-mock/components/BackgroundMockTableRow';
|
||||||
|
import { BACKGROUND_MOCK_COLUMNS } from '@/sign-in-background-mock/constants/BackgroundMockColumns';
|
||||||
|
import { BACKGROUND_MOCK_COMPANIES } from '@/sign-in-background-mock/constants/BackgroundMockCompanies';
|
||||||
|
import { BACKGROUND_MOCK_TABLE_DIMENSIONS } from '@/sign-in-background-mock/constants/BackgroundMockTableDimensions';
|
||||||
|
import {
|
||||||
|
IconChevronDown,
|
||||||
|
IconPlus,
|
||||||
|
OverflowingTextWithTooltip,
|
||||||
|
useIcons,
|
||||||
|
} from 'twenty-ui/display';
|
||||||
|
import { Checkbox } from 'twenty-ui/input';
|
||||||
|
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
|
||||||
|
|
||||||
|
const StyledTableWrapper = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledTable = styled.div`
|
||||||
|
background: ${themeCssVariables.background.primary};
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
flex-direction: column;
|
||||||
|
font-size: ${themeCssVariables.font.size.md};
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledHeaderRow = styled.div`
|
||||||
|
background: ${themeCssVariables.background.primary};
|
||||||
|
display: flex;
|
||||||
|
height: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.rowHeight}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledDragHandleColumn = styled.div`
|
||||||
|
background: ${themeCssVariables.background.primary};
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.rowHeight}px;
|
||||||
|
width: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.dragHandleColumnWidth}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledCheckboxHeaderColumn = styled.div`
|
||||||
|
align-items: center;
|
||||||
|
background: ${themeCssVariables.background.primary};
|
||||||
|
border-bottom: 1px solid ${themeCssVariables.border.color.light};
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.rowHeight}px;
|
||||||
|
justify-content: center;
|
||||||
|
padding-right: ${themeCssVariables.spacing[1]};
|
||||||
|
width: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.checkboxColumnWidth}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledHeaderCell = styled.div<{ width: number }>`
|
||||||
|
align-items: center;
|
||||||
|
background: ${themeCssVariables.background.primary};
|
||||||
|
border-bottom: 1px solid ${themeCssVariables.border.color.light};
|
||||||
|
border-right: 1px solid ${themeCssVariables.border.color.light};
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: ${themeCssVariables.font.color.tertiary};
|
||||||
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-weight: ${themeCssVariables.font.weight.medium};
|
||||||
|
gap: ${themeCssVariables.spacing[1]};
|
||||||
|
height: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.rowHeight}px;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0 ${themeCssVariables.spacing[2]};
|
||||||
|
width: ${({ width }) => width}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledHeaderLabel = styled.span`
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledAddColumnHeaderCell = styled.div`
|
||||||
|
align-items: center;
|
||||||
|
background: ${themeCssVariables.background.primary};
|
||||||
|
border-bottom: 1px solid ${themeCssVariables.border.color.light};
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: ${themeCssVariables.font.color.tertiary};
|
||||||
|
display: flex;
|
||||||
|
flex: 1;
|
||||||
|
height: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.rowHeight}px;
|
||||||
|
min-width: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.addColumnButtonWidth}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledAddColumnIconWrapper = styled.div`
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.rowHeight}px;
|
||||||
|
justify-content: center;
|
||||||
|
width: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.addColumnButtonWidth}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledTableBody = styled.div`
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
flex-shrink: 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledFooterRow = styled.div`
|
||||||
|
display: flex;
|
||||||
|
height: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.rowHeight}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledFooterCheckboxColumn = styled.div`
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.rowHeight}px;
|
||||||
|
width: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.checkboxColumnWidth}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledFooterCell = styled.div<{ width: number }>`
|
||||||
|
align-items: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: ${themeCssVariables.font.color.tertiary};
|
||||||
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
font-weight: ${themeCssVariables.font.weight.medium};
|
||||||
|
gap: ${themeCssVariables.spacing[1]};
|
||||||
|
height: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.rowHeight}px;
|
||||||
|
justify-content: space-between;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 0 ${themeCssVariables.spacing[2]};
|
||||||
|
white-space: nowrap;
|
||||||
|
width: ${({ width }) => width}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledFooterLabel = styled.div`
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledFooterValue = styled.span`
|
||||||
|
color: ${themeCssVariables.font.color.primary};
|
||||||
|
flex-shrink: 0;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledLastEmptyCell = styled.div`
|
||||||
|
flex: 1;
|
||||||
|
height: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.rowHeight}px;
|
||||||
|
min-width: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.addColumnButtonWidth}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const BackgroundMockTable = () => {
|
||||||
|
const { theme } = useContext(ThemeContext);
|
||||||
|
const { getIcon } = useIcons();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledTableWrapper>
|
||||||
|
<StyledTable>
|
||||||
|
<StyledHeaderRow>
|
||||||
|
<StyledDragHandleColumn />
|
||||||
|
<StyledCheckboxHeaderColumn>
|
||||||
|
<Checkbox hoverable checked={false} />
|
||||||
|
</StyledCheckboxHeaderColumn>
|
||||||
|
{BACKGROUND_MOCK_COLUMNS.map((column) => {
|
||||||
|
const Icon = getIcon(column.iconName);
|
||||||
|
return (
|
||||||
|
<StyledHeaderCell key={column.label} width={column.width}>
|
||||||
|
{Icon !== undefined && (
|
||||||
|
<Icon
|
||||||
|
size={theme.icon.size.md}
|
||||||
|
stroke={theme.icon.stroke.sm}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
<StyledHeaderLabel>{column.label}</StyledHeaderLabel>
|
||||||
|
</StyledHeaderCell>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
<StyledAddColumnHeaderCell>
|
||||||
|
<StyledAddColumnIconWrapper>
|
||||||
|
<IconPlus
|
||||||
|
size={theme.icon.size.sm}
|
||||||
|
stroke={theme.icon.stroke.sm}
|
||||||
|
/>
|
||||||
|
</StyledAddColumnIconWrapper>
|
||||||
|
</StyledAddColumnHeaderCell>
|
||||||
|
</StyledHeaderRow>
|
||||||
|
<StyledTableBody>
|
||||||
|
{BACKGROUND_MOCK_COMPANIES.map((company) => (
|
||||||
|
<BackgroundMockTableRow key={company.id} company={company} />
|
||||||
|
))}
|
||||||
|
</StyledTableBody>
|
||||||
|
<StyledFooterRow>
|
||||||
|
<StyledDragHandleColumn />
|
||||||
|
<StyledFooterCheckboxColumn />
|
||||||
|
<StyledFooterCell width={BACKGROUND_MOCK_COLUMNS[0].width}>
|
||||||
|
<StyledFooterLabel>
|
||||||
|
<OverflowingTextWithTooltip text="Calculate" />
|
||||||
|
</StyledFooterLabel>
|
||||||
|
<IconChevronDown
|
||||||
|
size={theme.icon.size.sm}
|
||||||
|
stroke={theme.icon.stroke.sm}
|
||||||
|
/>
|
||||||
|
</StyledFooterCell>
|
||||||
|
<StyledFooterCell width={BACKGROUND_MOCK_COLUMNS[1].width}>
|
||||||
|
<StyledFooterLabel>
|
||||||
|
<OverflowingTextWithTooltip text="Count all" />
|
||||||
|
</StyledFooterLabel>
|
||||||
|
<StyledFooterValue>599</StyledFooterValue>
|
||||||
|
</StyledFooterCell>
|
||||||
|
<StyledFooterCell width={BACKGROUND_MOCK_COLUMNS[2].width} />
|
||||||
|
<StyledFooterCell width={BACKGROUND_MOCK_COLUMNS[3].width} />
|
||||||
|
<StyledFooterCell width={BACKGROUND_MOCK_COLUMNS[4].width} />
|
||||||
|
<StyledFooterCell width={BACKGROUND_MOCK_COLUMNS[5].width}>
|
||||||
|
<StyledFooterLabel>
|
||||||
|
<OverflowingTextWithTooltip text="Max of Employees" />
|
||||||
|
</StyledFooterLabel>
|
||||||
|
<StyledFooterValue>284,571</StyledFooterValue>
|
||||||
|
</StyledFooterCell>
|
||||||
|
<StyledFooterCell width={BACKGROUND_MOCK_COLUMNS[6].width}>
|
||||||
|
<StyledFooterLabel>
|
||||||
|
<OverflowingTextWithTooltip text="Not empty of Address" />
|
||||||
|
</StyledFooterLabel>
|
||||||
|
<StyledFooterValue>599</StyledFooterValue>
|
||||||
|
</StyledFooterCell>
|
||||||
|
<StyledLastEmptyCell />
|
||||||
|
</StyledFooterRow>
|
||||||
|
</StyledTable>
|
||||||
|
</StyledTableWrapper>
|
||||||
|
);
|
||||||
|
};
|
||||||
+164
@@ -0,0 +1,164 @@
|
|||||||
|
import { styled } from '@linaria/react';
|
||||||
|
import { useContext } from 'react';
|
||||||
|
|
||||||
|
import { type BackgroundMockCompany } from '@/sign-in-background-mock/constants/BackgroundMockCompanies';
|
||||||
|
import { BACKGROUND_MOCK_COLUMN_WIDTHS } from '@/sign-in-background-mock/constants/BackgroundMockColumnWidths';
|
||||||
|
import { BACKGROUND_MOCK_TABLE_DIMENSIONS } from '@/sign-in-background-mock/constants/BackgroundMockTableDimensions';
|
||||||
|
import { Avatar, IconLink } from 'twenty-ui/display';
|
||||||
|
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
|
||||||
|
import { Chip, ChipAccent, ChipSize, ChipVariant } from 'twenty-ui/components';
|
||||||
|
import { Checkbox } from 'twenty-ui/input';
|
||||||
|
import { getLogoUrlFromDomainName } from 'twenty-shared/utils';
|
||||||
|
|
||||||
|
const StyledRow = styled.div`
|
||||||
|
display: flex;
|
||||||
|
height: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.rowHeight}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledDragHandleColumn = styled.div`
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.rowHeight}px;
|
||||||
|
width: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.dragHandleColumnWidth}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledCheckboxColumn = styled.div`
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid ${themeCssVariables.border.color.light};
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.rowHeight}px;
|
||||||
|
justify-content: center;
|
||||||
|
padding-right: ${themeCssVariables.spacing[1]};
|
||||||
|
width: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.checkboxColumnWidth}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledCell = styled.div<{ width: number }>`
|
||||||
|
align-items: center;
|
||||||
|
border-bottom: 1px solid ${themeCssVariables.border.color.light};
|
||||||
|
border-right: 1px solid ${themeCssVariables.border.color.light};
|
||||||
|
box-sizing: border-box;
|
||||||
|
color: ${themeCssVariables.font.color.primary};
|
||||||
|
display: flex;
|
||||||
|
flex-shrink: 0;
|
||||||
|
height: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.rowHeight}px;
|
||||||
|
overflow: hidden;
|
||||||
|
padding-left: ${themeCssVariables.spacing[2]};
|
||||||
|
white-space: nowrap;
|
||||||
|
width: ${({ width }) => width}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledTruncated = styled.span`
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledMutedText = styled.span`
|
||||||
|
color: ${themeCssVariables.font.color.tertiary};
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledLastEmptyCell = styled.div`
|
||||||
|
border-bottom: 1px solid ${themeCssVariables.border.color.light};
|
||||||
|
flex: 1;
|
||||||
|
height: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.rowHeight}px;
|
||||||
|
min-width: ${BACKGROUND_MOCK_TABLE_DIMENSIONS.addColumnButtonWidth}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
type BackgroundMockTableRowProps = {
|
||||||
|
company: BackgroundMockCompany;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatNumber = (value: number) => value.toLocaleString('en-US');
|
||||||
|
|
||||||
|
const PersonChip = ({ fullName }: { fullName: string | null }) => {
|
||||||
|
if (fullName === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Chip
|
||||||
|
label={fullName}
|
||||||
|
size={ChipSize.Small}
|
||||||
|
variant={ChipVariant.Transparent}
|
||||||
|
accent={ChipAccent.TextPrimary}
|
||||||
|
clickable={false}
|
||||||
|
leftComponent={
|
||||||
|
<Avatar
|
||||||
|
type="rounded"
|
||||||
|
placeholder={fullName}
|
||||||
|
placeholderColorSeed={fullName}
|
||||||
|
size="md"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const BackgroundMockTableRow = ({
|
||||||
|
company,
|
||||||
|
}: BackgroundMockTableRowProps) => {
|
||||||
|
const { theme } = useContext(ThemeContext);
|
||||||
|
|
||||||
|
const logoUrl = getLogoUrlFromDomainName(company.domainName);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyledRow>
|
||||||
|
<StyledDragHandleColumn />
|
||||||
|
<StyledCheckboxColumn>
|
||||||
|
<Checkbox hoverable checked={false} />
|
||||||
|
</StyledCheckboxColumn>
|
||||||
|
<StyledCell width={BACKGROUND_MOCK_COLUMN_WIDTHS.Name}>
|
||||||
|
<Chip
|
||||||
|
label={company.name}
|
||||||
|
size={ChipSize.Small}
|
||||||
|
variant={ChipVariant.Transparent}
|
||||||
|
accent={ChipAccent.TextPrimary}
|
||||||
|
clickable={false}
|
||||||
|
leftComponent={
|
||||||
|
<Avatar
|
||||||
|
type="squared"
|
||||||
|
avatarUrl={logoUrl}
|
||||||
|
placeholder={company.name}
|
||||||
|
placeholderColorSeed={company.id}
|
||||||
|
size="md"
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</StyledCell>
|
||||||
|
<StyledCell width={BACKGROUND_MOCK_COLUMN_WIDTHS.Domain}>
|
||||||
|
<Chip
|
||||||
|
label={company.domainName}
|
||||||
|
size={ChipSize.Small}
|
||||||
|
variant={ChipVariant.Transparent}
|
||||||
|
accent={ChipAccent.TextSecondary}
|
||||||
|
clickable={false}
|
||||||
|
leftComponent={
|
||||||
|
<IconLink
|
||||||
|
size={theme.icon.size.sm}
|
||||||
|
stroke={theme.icon.stroke.sm}
|
||||||
|
color={theme.font.color.tertiary}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</StyledCell>
|
||||||
|
<StyledCell width={BACKGROUND_MOCK_COLUMN_WIDTHS['Created by']}>
|
||||||
|
<PersonChip fullName={company.createdBy} />
|
||||||
|
</StyledCell>
|
||||||
|
<StyledCell width={BACKGROUND_MOCK_COLUMN_WIDTHS['Account Owner']}>
|
||||||
|
<PersonChip fullName={company.accountOwner} />
|
||||||
|
</StyledCell>
|
||||||
|
<StyledCell width={BACKGROUND_MOCK_COLUMN_WIDTHS['Creation date']}>
|
||||||
|
<StyledMutedText>{company.creationDate}</StyledMutedText>
|
||||||
|
</StyledCell>
|
||||||
|
<StyledCell width={BACKGROUND_MOCK_COLUMN_WIDTHS.Employees}>
|
||||||
|
<StyledTruncated>{formatNumber(company.employees)}</StyledTruncated>
|
||||||
|
</StyledCell>
|
||||||
|
<StyledCell width={BACKGROUND_MOCK_COLUMN_WIDTHS.Address}>
|
||||||
|
<StyledTruncated>{company.address}</StyledTruncated>
|
||||||
|
</StyledCell>
|
||||||
|
<StyledLastEmptyCell />
|
||||||
|
</StyledRow>
|
||||||
|
);
|
||||||
|
};
|
||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
import { styled } from '@linaria/react';
|
||||||
|
import { useContext } from 'react';
|
||||||
|
|
||||||
|
import { TopBar } from '@/ui/layout/top-bar/components/TopBar';
|
||||||
|
import {
|
||||||
|
IconBuildingSkyscraper,
|
||||||
|
IconChevronDown,
|
||||||
|
TintedIconTile,
|
||||||
|
} from 'twenty-ui/display';
|
||||||
|
import { ThemeContext, themeCssVariables } from 'twenty-ui/theme-constants';
|
||||||
|
|
||||||
|
const StyledViewPicker = styled.div`
|
||||||
|
align-items: center;
|
||||||
|
color: ${themeCssVariables.font.color.secondary};
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
font-weight: ${themeCssVariables.font.weight.medium};
|
||||||
|
gap: ${themeCssVariables.spacing[1]};
|
||||||
|
height: 100%;
|
||||||
|
padding: 0 ${themeCssVariables.spacing[2]};
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledViewPickerCount = styled.span`
|
||||||
|
color: ${themeCssVariables.font.color.tertiary};
|
||||||
|
`;
|
||||||
|
|
||||||
|
const StyledRightAction = styled.div`
|
||||||
|
align-items: center;
|
||||||
|
color: ${themeCssVariables.font.color.tertiary};
|
||||||
|
display: flex;
|
||||||
|
font-weight: ${themeCssVariables.font.weight.regular};
|
||||||
|
height: 100%;
|
||||||
|
padding: 0 ${themeCssVariables.spacing[2]};
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const BackgroundMockViewBar = () => {
|
||||||
|
const { theme } = useContext(ThemeContext);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TopBar
|
||||||
|
leftComponent={
|
||||||
|
<StyledViewPicker>
|
||||||
|
<TintedIconTile Icon={IconBuildingSkyscraper} color="blue" />
|
||||||
|
<span>All Companies</span>
|
||||||
|
<StyledViewPickerCount>· 599</StyledViewPickerCount>
|
||||||
|
<IconChevronDown
|
||||||
|
size={theme.icon.size.sm}
|
||||||
|
stroke={theme.icon.stroke.sm}
|
||||||
|
/>
|
||||||
|
</StyledViewPicker>
|
||||||
|
}
|
||||||
|
rightComponent={
|
||||||
|
<>
|
||||||
|
<StyledRightAction>Filter</StyledRightAction>
|
||||||
|
<StyledRightAction>Sort</StyledRightAction>
|
||||||
|
<StyledRightAction>Options</StyledRightAction>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
-113
@@ -1,113 +0,0 @@
|
|||||||
import { styled } from '@linaria/react';
|
|
||||||
|
|
||||||
import { CommandMenuComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuComponentInstanceContext';
|
|
||||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
|
||||||
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
|
|
||||||
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
|
|
||||||
import { objectMetadataItemsSelector } from '@/object-metadata/states/objectMetadataItemsSelector';
|
|
||||||
import { RecordComponentInstanceContextsWrapper } from '@/object-record/components/RecordComponentInstanceContextsWrapper';
|
|
||||||
import { RecordIndexContextProvider } from '@/object-record/record-index/contexts/RecordIndexContext';
|
|
||||||
import { useRecordIndexFieldMetadataDerivedStates } from '@/object-record/record-index/hooks/useRecordIndexFieldMetadataDerivedStates';
|
|
||||||
import { RecordTableWithWrappers } from '@/object-record/record-table/components/RecordTableWithWrappers';
|
|
||||||
import { SignInBackgroundMockContainerEffect } from '@/sign-in-background-mock/components/SignInBackgroundMockContainerEffect';
|
|
||||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
|
||||||
import { ViewBar } from '@/views/components/ViewBar';
|
|
||||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
|
||||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
|
||||||
import { isDefined } from 'twenty-shared/utils';
|
|
||||||
|
|
||||||
const StyledContainer = styled.div`
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: 100%;
|
|
||||||
overflow: auto;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const SignInBackgroundMockContainer = () => {
|
|
||||||
const objectNamePlural = 'companies';
|
|
||||||
const objectNameSingular = 'company';
|
|
||||||
const recordIndexId = 'sign-up-mock-record-table-id';
|
|
||||||
const viewBarId = 'companies-mock';
|
|
||||||
|
|
||||||
const objectMetadataItems = useAtomStateValue(objectMetadataItemsSelector);
|
|
||||||
|
|
||||||
const contextStoreCurrentObjectMetadataItemId = useAtomComponentStateValue(
|
|
||||||
contextStoreCurrentObjectMetadataItemIdComponentState,
|
|
||||||
MAIN_CONTEXT_STORE_INSTANCE_ID,
|
|
||||||
);
|
|
||||||
|
|
||||||
const objectMetadataItem = objectMetadataItems.find(
|
|
||||||
(objectMetadataItem) =>
|
|
||||||
objectMetadataItem.id === contextStoreCurrentObjectMetadataItemId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const {
|
|
||||||
fieldDefinitionByFieldMetadataItemId,
|
|
||||||
fieldMetadataItemByFieldMetadataItemId,
|
|
||||||
labelIdentifierFieldMetadataItem,
|
|
||||||
recordFieldByFieldMetadataItemId,
|
|
||||||
} = useRecordIndexFieldMetadataDerivedStates(
|
|
||||||
objectMetadataItem,
|
|
||||||
recordIndexId,
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<StyledContainer>
|
|
||||||
<RecordIndexContextProvider
|
|
||||||
value={{
|
|
||||||
objectPermissionsByObjectMetadataId: {},
|
|
||||||
recordIndexId,
|
|
||||||
viewBarInstanceId: recordIndexId,
|
|
||||||
objectNamePlural,
|
|
||||||
objectNameSingular,
|
|
||||||
objectMetadataItem: objectMetadataItem ?? objectMetadataItems[0],
|
|
||||||
onIndexRecordsLoaded: () => {},
|
|
||||||
indexIdentifierUrl: () => '',
|
|
||||||
fieldDefinitionByFieldMetadataItemId,
|
|
||||||
fieldMetadataItemByFieldMetadataItemId,
|
|
||||||
labelIdentifierFieldMetadataItem,
|
|
||||||
recordFieldByFieldMetadataItemId,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ViewComponentInstanceContext.Provider
|
|
||||||
value={{ instanceId: recordIndexId }}
|
|
||||||
>
|
|
||||||
<RecordComponentInstanceContextsWrapper
|
|
||||||
componentInstanceId={recordIndexId}
|
|
||||||
>
|
|
||||||
<ContextStoreComponentInstanceContext.Provider
|
|
||||||
value={{
|
|
||||||
instanceId: MAIN_CONTEXT_STORE_INSTANCE_ID,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<SignInBackgroundMockContainerEffect
|
|
||||||
objectNamePlural={objectNamePlural}
|
|
||||||
recordTableId={recordIndexId}
|
|
||||||
viewId={viewBarId}
|
|
||||||
/>
|
|
||||||
<CommandMenuComponentInstanceContext.Provider
|
|
||||||
value={{ instanceId: recordIndexId }}
|
|
||||||
>
|
|
||||||
{isDefined(objectMetadataItem) && (
|
|
||||||
<>
|
|
||||||
<ViewBar
|
|
||||||
viewBarId={viewBarId}
|
|
||||||
optionsDropdownButton={<></>}
|
|
||||||
isReadOnly
|
|
||||||
/>
|
|
||||||
|
|
||||||
<RecordTableWithWrappers
|
|
||||||
objectNameSingular={objectNameSingular}
|
|
||||||
recordTableId={recordIndexId}
|
|
||||||
viewBarId={viewBarId}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</CommandMenuComponentInstanceContext.Provider>
|
|
||||||
</ContextStoreComponentInstanceContext.Provider>
|
|
||||||
</RecordComponentInstanceContextsWrapper>
|
|
||||||
</ViewComponentInstanceContext.Provider>
|
|
||||||
</RecordIndexContextProvider>
|
|
||||||
</StyledContainer>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
-86
@@ -1,86 +0,0 @@
|
|||||||
import { useEffect } from 'react';
|
|
||||||
|
|
||||||
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
|
|
||||||
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
|
|
||||||
import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector';
|
|
||||||
|
|
||||||
import { currentRecordFieldsComponentState } from '@/object-record/record-field/states/currentRecordFieldsComponentState';
|
|
||||||
import { type RecordField } from '@/object-record/record-field/types/RecordField';
|
|
||||||
import { SIGN_IN_BACKGROUND_MOCK_COLUMN_DEFINITIONS } from '@/sign-in-background-mock/constants/SignInBackgroundMockColumnDefinitions';
|
|
||||||
import { useAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentState';
|
|
||||||
import { useAtomFamilySelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilySelectorValue';
|
|
||||||
import { useSetAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useSetAtomComponentState';
|
|
||||||
import { isDefined } from 'twenty-shared/utils';
|
|
||||||
import { useInitViewBar } from '@/views/hooks/useInitViewBar';
|
|
||||||
|
|
||||||
type SignInBackgroundMockContainerEffectProps = {
|
|
||||||
objectNamePlural: string;
|
|
||||||
recordTableId: string;
|
|
||||||
viewId: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SignInBackgroundMockContainerEffect = ({
|
|
||||||
objectNamePlural,
|
|
||||||
recordTableId,
|
|
||||||
viewId,
|
|
||||||
}: SignInBackgroundMockContainerEffectProps) => {
|
|
||||||
const [
|
|
||||||
contextStoreCurrentObjectMetadataItemId,
|
|
||||||
setContextStoreCurrentObjectMetadataItemId,
|
|
||||||
] = useAtomComponentState(
|
|
||||||
contextStoreCurrentObjectMetadataItemIdComponentState,
|
|
||||||
MAIN_CONTEXT_STORE_INSTANCE_ID,
|
|
||||||
);
|
|
||||||
|
|
||||||
const setCurrentRecordFields = useSetAtomComponentState(
|
|
||||||
currentRecordFieldsComponentState,
|
|
||||||
recordTableId,
|
|
||||||
);
|
|
||||||
|
|
||||||
const objectMetadataItem = useAtomFamilySelectorValue(
|
|
||||||
objectMetadataItemFamilySelector,
|
|
||||||
{ objectName: objectNamePlural, objectNameType: 'plural' },
|
|
||||||
);
|
|
||||||
|
|
||||||
const { setAvailableFieldDefinitions, setViewObjectMetadataId } =
|
|
||||||
useInitViewBar(viewId);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!isDefined(objectMetadataItem)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setViewObjectMetadataId?.(objectMetadataItem.id);
|
|
||||||
|
|
||||||
setAvailableFieldDefinitions?.(SIGN_IN_BACKGROUND_MOCK_COLUMN_DEFINITIONS);
|
|
||||||
|
|
||||||
const recordFields = SIGN_IN_BACKGROUND_MOCK_COLUMN_DEFINITIONS.filter(
|
|
||||||
(fieldDefinition) => fieldDefinition.fieldMetadataId !== '',
|
|
||||||
).map(
|
|
||||||
(columnDefinitionMock) =>
|
|
||||||
({
|
|
||||||
fieldMetadataItemId: columnDefinitionMock.fieldMetadataId,
|
|
||||||
id: columnDefinitionMock.fieldMetadataId,
|
|
||||||
isVisible: columnDefinitionMock.isVisible,
|
|
||||||
position: columnDefinitionMock.position,
|
|
||||||
size: columnDefinitionMock.size,
|
|
||||||
}) satisfies RecordField as RecordField,
|
|
||||||
);
|
|
||||||
|
|
||||||
setCurrentRecordFields(recordFields);
|
|
||||||
|
|
||||||
if (contextStoreCurrentObjectMetadataItemId !== objectMetadataItem.id) {
|
|
||||||
setContextStoreCurrentObjectMetadataItemId(objectMetadataItem.id);
|
|
||||||
}
|
|
||||||
}, [
|
|
||||||
setViewObjectMetadataId,
|
|
||||||
setAvailableFieldDefinitions,
|
|
||||||
objectMetadataItem,
|
|
||||||
recordTableId,
|
|
||||||
setContextStoreCurrentObjectMetadataItemId,
|
|
||||||
contextStoreCurrentObjectMetadataItemId,
|
|
||||||
setCurrentRecordFields,
|
|
||||||
]);
|
|
||||||
|
|
||||||
return <></>;
|
|
||||||
};
|
|
||||||
-27
@@ -1,27 +0,0 @@
|
|||||||
import { t } from '@lingui/core/macro';
|
|
||||||
import { styled } from '@linaria/react';
|
|
||||||
|
|
||||||
import { SignInBackgroundMockContainer } from '@/sign-in-background-mock/components/SignInBackgroundMockContainer';
|
|
||||||
import { PageBody } from '@/ui/layout/page/components/PageBody';
|
|
||||||
import { PageContainer } from '@/ui/layout/page/components/PageContainer';
|
|
||||||
import { PageHeader } from '@/ui/layout/page/components/PageHeader';
|
|
||||||
import { IconBuildingSkyscraper } from 'twenty-ui/display';
|
|
||||||
|
|
||||||
const StyledTableContainer = styled.div`
|
|
||||||
display: flex;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
`;
|
|
||||||
|
|
||||||
export const SignInBackgroundMockPage = () => {
|
|
||||||
return (
|
|
||||||
<PageContainer>
|
|
||||||
<PageHeader title={t`Companies`} Icon={IconBuildingSkyscraper} />
|
|
||||||
<PageBody>
|
|
||||||
<StyledTableContainer>
|
|
||||||
<SignInBackgroundMockContainer />
|
|
||||||
</StyledTableContainer>
|
|
||||||
</PageBody>
|
|
||||||
</PageContainer>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
export const BACKGROUND_MOCK_COLUMN_WIDTHS = {
|
||||||
|
Name: 180,
|
||||||
|
Domain: 130,
|
||||||
|
'Created by': 130,
|
||||||
|
'Account Owner': 130,
|
||||||
|
'Creation date': 130,
|
||||||
|
Employees: 110,
|
||||||
|
Address: 200,
|
||||||
|
} as const;
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
import { BACKGROUND_MOCK_COLUMN_WIDTHS } from '@/sign-in-background-mock/constants/BackgroundMockColumnWidths';
|
||||||
|
|
||||||
|
export type BackgroundMockColumn = {
|
||||||
|
label: keyof typeof BACKGROUND_MOCK_COLUMN_WIDTHS;
|
||||||
|
iconName: string;
|
||||||
|
width: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const BACKGROUND_MOCK_COLUMNS = [
|
||||||
|
{
|
||||||
|
label: 'Name',
|
||||||
|
iconName: 'IconBuildingSkyscraper',
|
||||||
|
width: BACKGROUND_MOCK_COLUMN_WIDTHS.Name,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Domain',
|
||||||
|
iconName: 'IconLink',
|
||||||
|
width: BACKGROUND_MOCK_COLUMN_WIDTHS.Domain,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Created by',
|
||||||
|
iconName: 'IconUserCircle',
|
||||||
|
width: BACKGROUND_MOCK_COLUMN_WIDTHS['Created by'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Account Owner',
|
||||||
|
iconName: 'IconUserCircle',
|
||||||
|
width: BACKGROUND_MOCK_COLUMN_WIDTHS['Account Owner'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Creation date',
|
||||||
|
iconName: 'IconCalendar',
|
||||||
|
width: BACKGROUND_MOCK_COLUMN_WIDTHS['Creation date'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Employees',
|
||||||
|
iconName: 'IconUsers',
|
||||||
|
width: BACKGROUND_MOCK_COLUMN_WIDTHS.Employees,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Address',
|
||||||
|
iconName: 'IconMap',
|
||||||
|
width: BACKGROUND_MOCK_COLUMN_WIDTHS.Address,
|
||||||
|
},
|
||||||
|
] satisfies BackgroundMockColumn[];
|
||||||
+223
@@ -0,0 +1,223 @@
|
|||||||
|
export type BackgroundMockCompany = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
domainName: string;
|
||||||
|
createdBy: string | null;
|
||||||
|
accountOwner: string | null;
|
||||||
|
creationDate: string;
|
||||||
|
employees: number;
|
||||||
|
address: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const BACKGROUND_MOCK_COMPANIES = [
|
||||||
|
{
|
||||||
|
id: 'google',
|
||||||
|
name: 'Google',
|
||||||
|
domainName: 'goo.gle',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Phil Schiller',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 284571,
|
||||||
|
address: 'Mountain View',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'microsoft',
|
||||||
|
name: 'Microsoft',
|
||||||
|
domainName: 'microsoft.com',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Jony Ive',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 226067,
|
||||||
|
address: 'Redmond',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'meta',
|
||||||
|
name: 'Meta',
|
||||||
|
domainName: 'metacareers.com',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Phil Schiller',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 119511,
|
||||||
|
address: 'Menlo Park',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'slb',
|
||||||
|
name: 'SLB',
|
||||||
|
domainName: 'slb.com',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Phil Schiller',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 113151,
|
||||||
|
address: 'Houston',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'cisco',
|
||||||
|
name: 'Cisco',
|
||||||
|
domainName: 'cisco.com',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Phil Schiller',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 99625,
|
||||||
|
address: 'San Jose',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'uber',
|
||||||
|
name: 'Uber',
|
||||||
|
domainName: 'uber.com',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Tim Apple',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 90545,
|
||||||
|
address: 'San Francisco',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'salesforce',
|
||||||
|
name: 'Salesforce',
|
||||||
|
domainName: 'salesforce.com',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Phil Schiller',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 71322,
|
||||||
|
address: 'San Francisco',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'amdocs',
|
||||||
|
name: 'Amdocs',
|
||||||
|
domainName: 'amdocs.com',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Jony Ive',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 35731,
|
||||||
|
address: 'Chesterfield',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'vmware',
|
||||||
|
name: 'VMware',
|
||||||
|
domainName: 'vmware.com',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Phil Schiller',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 34759,
|
||||||
|
address: 'Palo Alto',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'globallogic',
|
||||||
|
name: 'GlobalLogic',
|
||||||
|
domainName: 'globallogic.com',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Jony Ive',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 24461,
|
||||||
|
address: 'Santa Clara',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'servicenow',
|
||||||
|
name: 'ServiceNow',
|
||||||
|
domainName: 'servicenow.com',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Tim Apple',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 24104,
|
||||||
|
address: 'Santa Clara',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'ssctech',
|
||||||
|
name: 'SS&C Technologies',
|
||||||
|
domainName: 'ssctech.com',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Phil Schiller',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 20311,
|
||||||
|
address: 'Windsor',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'workday',
|
||||||
|
name: 'Workday',
|
||||||
|
domainName: 'workday.com',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Jony Ive',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 20036,
|
||||||
|
address: 'Pleasanton',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'redhat',
|
||||||
|
name: 'Red Hat',
|
||||||
|
domainName: 'redhat.com',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Phil Schiller',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 19945,
|
||||||
|
address: 'Raleigh',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'netsuite',
|
||||||
|
name: 'NetSuite',
|
||||||
|
domainName: 'netsuite.com',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Jony Ive',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 19269,
|
||||||
|
address: 'Austin',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'synopsys',
|
||||||
|
name: 'Synopsys Inc',
|
||||||
|
domainName: 'synopsys.com',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Jony Ive',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 18061,
|
||||||
|
address: 'Sunnyvale',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'siemens',
|
||||||
|
name: 'Siemens Digital Industries',
|
||||||
|
domainName: 'sw.siemens.com',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Tim Apple',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 17262,
|
||||||
|
address: 'Plano',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'sas',
|
||||||
|
name: 'SAS',
|
||||||
|
domainName: 'sas.com',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Phil Schiller',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 16287,
|
||||||
|
address: 'Cary',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'intuit',
|
||||||
|
name: 'Intuit',
|
||||||
|
domainName: 'intuit.com',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Jony Ive',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 15851,
|
||||||
|
address: 'Mountain View',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'broadcom',
|
||||||
|
name: 'Broadcom Software',
|
||||||
|
domainName: 'broadcom.com',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Phil Schiller',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 15127,
|
||||||
|
address: 'San Jose',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'autodesk',
|
||||||
|
name: 'Autodesk',
|
||||||
|
domainName: 'autodesk.com',
|
||||||
|
createdBy: 'Tim Apple',
|
||||||
|
accountOwner: 'Jony Ive',
|
||||||
|
creationDate: 'about 13 hours ago',
|
||||||
|
employees: 14593,
|
||||||
|
address: 'San Francisco',
|
||||||
|
},
|
||||||
|
] satisfies BackgroundMockCompany[];
|
||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
import {
|
||||||
|
IconBuildingSkyscraper,
|
||||||
|
IconCalendarEvent,
|
||||||
|
IconCheckbox,
|
||||||
|
type IconComponent,
|
||||||
|
IconFileText,
|
||||||
|
IconHeart,
|
||||||
|
IconLayoutDashboard,
|
||||||
|
IconNotes,
|
||||||
|
IconRocket,
|
||||||
|
IconStar,
|
||||||
|
IconTargetArrow,
|
||||||
|
IconUser,
|
||||||
|
IconUserCircle,
|
||||||
|
} from 'twenty-ui/display';
|
||||||
|
import { type ThemeColor } from 'twenty-ui/theme';
|
||||||
|
|
||||||
|
export type BackgroundMockNavigationItem = {
|
||||||
|
label: string;
|
||||||
|
Icon: IconComponent;
|
||||||
|
color: ThemeColor;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const BACKGROUND_MOCK_WORKSPACE_ITEMS = [
|
||||||
|
{ label: 'Companies', Icon: IconBuildingSkyscraper, color: 'blue' },
|
||||||
|
{ label: 'People', Icon: IconUser, color: 'blue' },
|
||||||
|
{ label: 'Opportunities', Icon: IconTargetArrow, color: 'red' },
|
||||||
|
{ label: 'Tasks', Icon: IconCheckbox, color: 'turquoise' },
|
||||||
|
{ label: 'Notes', Icon: IconNotes, color: 'turquoise' },
|
||||||
|
{ label: 'Dashboards', Icon: IconLayoutDashboard, color: 'orange' },
|
||||||
|
{ label: 'Workflows', Icon: IconRocket, color: 'pink' },
|
||||||
|
{ label: 'Rockets', Icon: IconRocket, color: 'sky' },
|
||||||
|
{ label: 'Pets', Icon: IconHeart, color: 'orange' },
|
||||||
|
{ label: 'Survey results', Icon: IconStar, color: 'yellow' },
|
||||||
|
{ label: 'Employment Histories', Icon: IconUserCircle, color: 'green' },
|
||||||
|
{ label: 'Pet Care Agreements', Icon: IconFileText, color: 'purple' },
|
||||||
|
{ label: 'Star History', Icon: IconCalendarEvent, color: 'red' },
|
||||||
|
] satisfies BackgroundMockNavigationItem[];
|
||||||
+8
@@ -0,0 +1,8 @@
|
|||||||
|
import { IconFileText, IconSettings } from 'twenty-ui/display';
|
||||||
|
|
||||||
|
import { type BackgroundMockNavigationItem } from '@/sign-in-background-mock/constants/BackgroundMockNavigationItems';
|
||||||
|
|
||||||
|
export const BACKGROUND_MOCK_OTHER_ITEMS = [
|
||||||
|
{ label: 'Settings', Icon: IconSettings, color: 'gray' },
|
||||||
|
{ label: 'Documentation', Icon: IconFileText, color: 'gray' },
|
||||||
|
] satisfies BackgroundMockNavigationItem[];
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
export const BACKGROUND_MOCK_TABLE_DIMENSIONS = {
|
||||||
|
rowHeight: 32,
|
||||||
|
dragHandleColumnWidth: 12,
|
||||||
|
checkboxColumnWidth: 28,
|
||||||
|
addColumnButtonWidth: 32,
|
||||||
|
} as const;
|
||||||
-302
@@ -1,302 +0,0 @@
|
|||||||
/* oxlint-disable twenty/max-consts-per-file */
|
|
||||||
import { type FieldMetadata } from '@/object-record/record-field/ui/types/FieldMetadata';
|
|
||||||
import { type ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
|
||||||
import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns';
|
|
||||||
import { findByProperty } from 'twenty-shared/utils';
|
|
||||||
import { FieldMetadataType, RelationType } from '~/generated-metadata/graphql';
|
|
||||||
import { getMockObjectMetadataItemOrThrow } from '~/testing/utils/getMockObjectMetadataItemOrThrow';
|
|
||||||
|
|
||||||
const COMPANY_MOCK_OBJECT = getMockObjectMetadataItemOrThrow('company');
|
|
||||||
|
|
||||||
export const SIGN_IN_BACKGROUND_MOCK_COLUMN_DEFINITIONS = (
|
|
||||||
[
|
|
||||||
{
|
|
||||||
position: 0,
|
|
||||||
fieldMetadataId:
|
|
||||||
COMPANY_MOCK_OBJECT.fields.find(findByProperty('name', 'name'))?.id ??
|
|
||||||
'',
|
|
||||||
label: 'Name',
|
|
||||||
size: 100,
|
|
||||||
type: FieldMetadataType.TEXT,
|
|
||||||
metadata: {
|
|
||||||
fieldName: 'name',
|
|
||||||
placeHolder: 'Name',
|
|
||||||
relationObjectMetadataNameSingular: '',
|
|
||||||
relationObjectMetadataNamePlural: '',
|
|
||||||
objectMetadataNameSingular: 'company',
|
|
||||||
},
|
|
||||||
iconName: 'IconBuildingSkyscraper',
|
|
||||||
isVisible: true,
|
|
||||||
defaultValue: '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
position: 1,
|
|
||||||
fieldMetadataId:
|
|
||||||
COMPANY_MOCK_OBJECT.fields.find(findByProperty('name', 'domainName'))
|
|
||||||
?.id ?? '',
|
|
||||||
label: 'Domain Name',
|
|
||||||
size: 100,
|
|
||||||
type: FieldMetadataType.LINKS,
|
|
||||||
metadata: {
|
|
||||||
fieldName: 'domainName',
|
|
||||||
placeHolder: 'Domain Name',
|
|
||||||
relationObjectMetadataNameSingular: '',
|
|
||||||
relationObjectMetadataNamePlural: '',
|
|
||||||
objectMetadataNameSingular: 'company',
|
|
||||||
},
|
|
||||||
iconName: 'IconLink',
|
|
||||||
isVisible: true,
|
|
||||||
defaultValue: '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
position: 2,
|
|
||||||
fieldMetadataId:
|
|
||||||
COMPANY_MOCK_OBJECT.fields.find(findByProperty('name', 'employees'))
|
|
||||||
?.id ?? '',
|
|
||||||
label: 'Employees',
|
|
||||||
size: 100,
|
|
||||||
type: FieldMetadataType.NUMBER,
|
|
||||||
metadata: {
|
|
||||||
fieldName: 'employees',
|
|
||||||
placeHolder: 'Employees',
|
|
||||||
relationObjectMetadataNameSingular: '',
|
|
||||||
relationObjectMetadataNamePlural: '',
|
|
||||||
objectMetadataNameSingular: 'company',
|
|
||||||
},
|
|
||||||
iconName: 'IconUsers',
|
|
||||||
isVisible: true,
|
|
||||||
defaultValue: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
position: 3,
|
|
||||||
fieldMetadataId:
|
|
||||||
COMPANY_MOCK_OBJECT.fields.find(findByProperty('name', 'people'))?.id ??
|
|
||||||
'',
|
|
||||||
label: 'People',
|
|
||||||
size: 100,
|
|
||||||
type: FieldMetadataType.RELATION,
|
|
||||||
metadata: {
|
|
||||||
fieldName: 'people',
|
|
||||||
relationType: RelationType.ONE_TO_MANY,
|
|
||||||
relationObjectMetadataNameSingular: '',
|
|
||||||
relationObjectMetadataNamePlural: '',
|
|
||||||
objectMetadataNameSingular: 'company',
|
|
||||||
},
|
|
||||||
iconName: 'IconUsers',
|
|
||||||
isVisible: true,
|
|
||||||
defaultValue: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
position: 4,
|
|
||||||
fieldMetadataId:
|
|
||||||
COMPANY_MOCK_OBJECT.fields.find(findByProperty('name', 'address'))
|
|
||||||
?.id ?? '',
|
|
||||||
label: 'Address',
|
|
||||||
size: 100,
|
|
||||||
type: FieldMetadataType.ADDRESS,
|
|
||||||
metadata: {
|
|
||||||
fieldName: 'address',
|
|
||||||
placeHolder: 'Address',
|
|
||||||
relationObjectMetadataNameSingular: '',
|
|
||||||
relationObjectMetadataNamePlural: '',
|
|
||||||
objectMetadataNameSingular: 'company',
|
|
||||||
},
|
|
||||||
iconName: 'IconMap',
|
|
||||||
isVisible: true,
|
|
||||||
defaultValue: '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
position: 5,
|
|
||||||
fieldMetadataId:
|
|
||||||
COMPANY_MOCK_OBJECT.fields.find(findByProperty('name', 'accountOwner'))
|
|
||||||
?.id ?? '',
|
|
||||||
label: 'Account Owner',
|
|
||||||
size: 100,
|
|
||||||
type: FieldMetadataType.RELATION,
|
|
||||||
metadata: {
|
|
||||||
fieldName: 'accountOwner',
|
|
||||||
relationType: RelationType.MANY_TO_ONE,
|
|
||||||
relationObjectMetadataNameSingular: 'workspaceMember',
|
|
||||||
relationObjectMetadataNamePlural: 'workspaceMembers',
|
|
||||||
objectMetadataNameSingular: 'company',
|
|
||||||
},
|
|
||||||
iconName: 'IconUserCircle',
|
|
||||||
isVisible: true,
|
|
||||||
defaultValue: null,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
position: 6,
|
|
||||||
fieldMetadataId:
|
|
||||||
COMPANY_MOCK_OBJECT.fields.find(findByProperty('name', 'attachments'))
|
|
||||||
?.id ?? '',
|
|
||||||
label: 'Attachments',
|
|
||||||
size: 100,
|
|
||||||
type: FieldMetadataType.RELATION,
|
|
||||||
metadata: {
|
|
||||||
fieldName: 'attachments',
|
|
||||||
relationType: RelationType.ONE_TO_MANY,
|
|
||||||
relationObjectMetadataNameSingular: '',
|
|
||||||
relationObjectMetadataNamePlural: '',
|
|
||||||
objectMetadataNameSingular: 'company',
|
|
||||||
},
|
|
||||||
iconName: 'IconFileImport',
|
|
||||||
isVisible: true,
|
|
||||||
defaultValue: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
position: 7,
|
|
||||||
fieldMetadataId:
|
|
||||||
COMPANY_MOCK_OBJECT.fields.find(findByProperty('name', 'createdAt'))
|
|
||||||
?.id ?? '',
|
|
||||||
label: 'Creation date',
|
|
||||||
size: 100,
|
|
||||||
type: FieldMetadataType.DATE_TIME,
|
|
||||||
metadata: {
|
|
||||||
fieldName: 'createdAt',
|
|
||||||
placeHolder: 'Creation date',
|
|
||||||
relationObjectMetadataNameSingular: '',
|
|
||||||
relationObjectMetadataNamePlural: '',
|
|
||||||
objectMetadataNameSingular: 'company',
|
|
||||||
},
|
|
||||||
iconName: 'IconCalendar',
|
|
||||||
isVisible: true,
|
|
||||||
defaultValue: '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
position: 8,
|
|
||||||
fieldMetadataId:
|
|
||||||
COMPANY_MOCK_OBJECT.fields.find(
|
|
||||||
findByProperty('name', 'idealCustomerProfile'),
|
|
||||||
)?.id ?? '',
|
|
||||||
label: 'ICP',
|
|
||||||
size: 100,
|
|
||||||
type: FieldMetadataType.BOOLEAN,
|
|
||||||
metadata: {
|
|
||||||
fieldName: 'idealCustomerProfile',
|
|
||||||
placeHolder: 'ICP',
|
|
||||||
relationObjectMetadataNameSingular: '',
|
|
||||||
relationObjectMetadataNamePlural: '',
|
|
||||||
objectMetadataNameSingular: 'company',
|
|
||||||
},
|
|
||||||
iconName: 'IconTarget',
|
|
||||||
isVisible: true,
|
|
||||||
defaultValue: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
position: 9,
|
|
||||||
fieldMetadataId:
|
|
||||||
COMPANY_MOCK_OBJECT.fields.find(findByProperty('name', 'linkedinLink'))
|
|
||||||
?.id ?? '',
|
|
||||||
label: 'Linkedin',
|
|
||||||
size: 100,
|
|
||||||
type: FieldMetadataType.LINKS,
|
|
||||||
metadata: {
|
|
||||||
fieldName: 'linkedinLink',
|
|
||||||
placeHolder: 'Linkedin',
|
|
||||||
relationObjectMetadataNameSingular: '',
|
|
||||||
relationObjectMetadataNamePlural: '',
|
|
||||||
objectMetadataNameSingular: 'company',
|
|
||||||
},
|
|
||||||
iconName: 'IconBrandLinkedin',
|
|
||||||
isVisible: true,
|
|
||||||
defaultValue: '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
position: 10,
|
|
||||||
fieldMetadataId:
|
|
||||||
COMPANY_MOCK_OBJECT.fields.find(findByProperty('name', 'opportunities'))
|
|
||||||
?.id ?? '',
|
|
||||||
label: 'Opportunities',
|
|
||||||
size: 100,
|
|
||||||
type: FieldMetadataType.RELATION,
|
|
||||||
metadata: {
|
|
||||||
fieldName: 'opportunities',
|
|
||||||
relationType: RelationType.ONE_TO_MANY,
|
|
||||||
relationObjectMetadataNameSingular: '',
|
|
||||||
relationObjectMetadataNamePlural: '',
|
|
||||||
objectMetadataNameSingular: 'company',
|
|
||||||
},
|
|
||||||
iconName: 'IconTargetArrow',
|
|
||||||
isVisible: true,
|
|
||||||
defaultValue: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
position: 11,
|
|
||||||
fieldMetadataId:
|
|
||||||
COMPANY_MOCK_OBJECT.fields.find(findByProperty('name', 'xLink'))?.id ??
|
|
||||||
'',
|
|
||||||
label: 'X',
|
|
||||||
size: 100,
|
|
||||||
type: FieldMetadataType.LINKS,
|
|
||||||
metadata: {
|
|
||||||
fieldName: 'xLink',
|
|
||||||
placeHolder: 'X',
|
|
||||||
relationObjectMetadataNameSingular: '',
|
|
||||||
relationObjectMetadataNamePlural: '',
|
|
||||||
objectMetadataNameSingular: 'company',
|
|
||||||
},
|
|
||||||
iconName: 'IconBrandX',
|
|
||||||
isVisible: true,
|
|
||||||
defaultValue: '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
position: 12,
|
|
||||||
fieldMetadataId:
|
|
||||||
COMPANY_MOCK_OBJECT.fields.find(
|
|
||||||
findByProperty('name', 'activityTargets'),
|
|
||||||
)?.id ?? '',
|
|
||||||
label: 'Activities',
|
|
||||||
size: 100,
|
|
||||||
type: FieldMetadataType.RELATION,
|
|
||||||
metadata: {
|
|
||||||
fieldName: 'activityTargets',
|
|
||||||
relationType: RelationType.ONE_TO_MANY,
|
|
||||||
relationObjectMetadataNameSingular: '',
|
|
||||||
relationObjectMetadataNamePlural: '',
|
|
||||||
objectMetadataNameSingular: 'company',
|
|
||||||
},
|
|
||||||
iconName: 'IconCheckbox',
|
|
||||||
isVisible: true,
|
|
||||||
defaultValue: [],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
position: 13,
|
|
||||||
fieldMetadataId:
|
|
||||||
COMPANY_MOCK_OBJECT.fields.find(
|
|
||||||
findByProperty('name', 'annualRecurringRevenue'),
|
|
||||||
)?.id ?? '',
|
|
||||||
label: 'ARR',
|
|
||||||
size: 100,
|
|
||||||
type: FieldMetadataType.CURRENCY,
|
|
||||||
metadata: {
|
|
||||||
fieldName: 'annualRecurringRevenue',
|
|
||||||
placeHolder: 'ARR',
|
|
||||||
relationObjectMetadataNameSingular: '',
|
|
||||||
relationObjectMetadataNamePlural: '',
|
|
||||||
objectMetadataNameSingular: 'company',
|
|
||||||
},
|
|
||||||
iconName: 'IconMoneybag',
|
|
||||||
isVisible: true,
|
|
||||||
defaultValue: 0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
position: 14,
|
|
||||||
fieldMetadataId:
|
|
||||||
COMPANY_MOCK_OBJECT.fields.find(findByProperty('name', 'favorites'))
|
|
||||||
?.id ?? '',
|
|
||||||
label: 'Favorites',
|
|
||||||
size: 100,
|
|
||||||
type: FieldMetadataType.RELATION,
|
|
||||||
metadata: {
|
|
||||||
fieldName: 'favorites',
|
|
||||||
relationType: RelationType.ONE_TO_MANY,
|
|
||||||
relationObjectMetadataNameSingular: '',
|
|
||||||
relationObjectMetadataNamePlural: '',
|
|
||||||
objectMetadataNameSingular: 'company',
|
|
||||||
},
|
|
||||||
iconName: 'IconHeart',
|
|
||||||
isVisible: true,
|
|
||||||
defaultValue: [],
|
|
||||||
},
|
|
||||||
] satisfies ColumnDefinition<FieldMetadata>[]
|
|
||||||
).filter(filterAvailableTableColumns);
|
|
||||||
-1385
File diff suppressed because it is too large
Load Diff
-78
@@ -1,78 +0,0 @@
|
|||||||
import { type ViewField } from '@/views/types/ViewField';
|
|
||||||
|
|
||||||
export const SIGN_IN_BACKGROUND_MOCK_VIEW_FIELDS = [
|
|
||||||
{
|
|
||||||
id: '5168be09-f200-40f5-9e04-29d607de06e5',
|
|
||||||
fieldMetadataId: '20202020-7fbd-41ad-b64d-25a15ff62f04',
|
|
||||||
size: 150,
|
|
||||||
createdAt: '2023-11-23T15:38:03.706Z',
|
|
||||||
viewId: '20202020-2441-4424-8163-4002c523d415',
|
|
||||||
position: 4,
|
|
||||||
isVisible: true,
|
|
||||||
updatedAt: '2023-11-23T15:38:03.706Z',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '5ece850b-76fd-4135-9b99-06d49cad14ae',
|
|
||||||
fieldMetadataId: '20202020-a61d-4b78-b998-3fd88b4f73a1',
|
|
||||||
size: 170,
|
|
||||||
createdAt: '2023-11-23T15:38:03.706Z',
|
|
||||||
viewId: '20202020-2441-4424-8163-4002c523d415',
|
|
||||||
position: 5,
|
|
||||||
isVisible: true,
|
|
||||||
updatedAt: '2023-11-23T15:38:03.706Z',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '604dbdbb-df01-4e47-921b-f9963109f912',
|
|
||||||
fieldMetadataId: '20202020-0739-495d-8e70-c0807f6b2268',
|
|
||||||
size: 150,
|
|
||||||
createdAt: '2023-11-23T15:38:03.706Z',
|
|
||||||
viewId: '20202020-2441-4424-8163-4002c523d415',
|
|
||||||
position: 2,
|
|
||||||
isVisible: true,
|
|
||||||
updatedAt: '2023-11-23T15:38:03.706Z',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '7cbc36c8-37c6-4561-8c46-ddb316ddd121',
|
|
||||||
fieldMetadataId: '20202020-4dc2-47c9-bb15-6e6f19ba9e46',
|
|
||||||
size: 150,
|
|
||||||
createdAt: '2023-11-23T15:38:03.706Z',
|
|
||||||
viewId: '20202020-2441-4424-8163-4002c523d415',
|
|
||||||
position: 3,
|
|
||||||
isVisible: true,
|
|
||||||
updatedAt: '2023-11-23T15:38:03.706Z',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'a7d19be3-1ce9-479b-9453-2930a381e07c',
|
|
||||||
fieldMetadataId: '20202020-5e4e-4007-a630-8a2617914889',
|
|
||||||
size: 100,
|
|
||||||
createdAt: '2023-11-23T15:38:03.706Z',
|
|
||||||
viewId: '20202020-2441-4424-8163-4002c523d415',
|
|
||||||
position: 1,
|
|
||||||
isVisible: true,
|
|
||||||
updatedAt: '2023-11-23T15:38:03.706Z',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'cafacdc8-cbfc-4545-8242-94787f144ace',
|
|
||||||
fieldMetadataId: 'REPLACE_ME',
|
|
||||||
size: 180,
|
|
||||||
createdAt: '2023-11-23T15:38:03.706Z',
|
|
||||||
viewId: '20202020-2441-4424-8163-4002c523d415',
|
|
||||||
position: 0,
|
|
||||||
isVisible: true,
|
|
||||||
updatedAt: '2023-11-23T15:38:03.706Z',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'f0cc50c9-b9b6-405b-a1c0-23f7698ea731',
|
|
||||||
fieldMetadataId: '20202020-ad10-4117-a039-3f04b7a5f939',
|
|
||||||
size: 170,
|
|
||||||
createdAt: '2023-11-23T15:38:03.706Z',
|
|
||||||
viewId: '20202020-2441-4424-8163-4002c523d415',
|
|
||||||
position: 6,
|
|
||||||
isVisible: true,
|
|
||||||
updatedAt: '2023-11-23T15:38:03.706Z',
|
|
||||||
},
|
|
||||||
] as (ViewField & {
|
|
||||||
createdAt: string;
|
|
||||||
viewId: string;
|
|
||||||
updatedAt: string;
|
|
||||||
})[];
|
|
||||||
@@ -11,12 +11,12 @@ import { MobileNavigationBar } from '@/navigation/components/MobileNavigationBar
|
|||||||
import { PageDragDropProvider } from '@/navigation-menu-item/display/dnd/providers/PageDragDropProvider';
|
import { PageDragDropProvider } from '@/navigation-menu-item/display/dnd/providers/PageDragDropProvider';
|
||||||
import { useIsSettingsPage } from '@/navigation/hooks/useIsSettingsPage';
|
import { useIsSettingsPage } from '@/navigation/hooks/useIsSettingsPage';
|
||||||
import { OBJECT_SETTINGS_WIDTH } from '@/settings/data-model/constants/ObjectSettings';
|
import { OBJECT_SETTINGS_WIDTH } from '@/settings/data-model/constants/ObjectSettings';
|
||||||
import { SignInAppNavigationDrawerMock } from '@/sign-in-background-mock/components/SignInAppNavigationDrawerMock';
|
import { BackgroundMockNavigationDrawer } from '@/sign-in-background-mock/components/BackgroundMockNavigationDrawer';
|
||||||
import { Suspense, lazy, useContext } from 'react';
|
import { Suspense, lazy, useContext } from 'react';
|
||||||
|
|
||||||
const SignInBackgroundMockPage = lazy(() =>
|
const BackgroundMockPage = lazy(() =>
|
||||||
import('@/sign-in-background-mock/components/SignInBackgroundMockPage').then(
|
import('@/sign-in-background-mock/components/BackgroundMockPage').then(
|
||||||
(module) => ({ default: module.SignInBackgroundMockPage }),
|
(module) => ({ default: module.BackgroundMockPage }),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
import { useShowFullscreen } from '@/ui/layout/fullscreen/hooks/useShowFullscreen';
|
import { useShowFullscreen } from '@/ui/layout/fullscreen/hooks/useShowFullscreen';
|
||||||
@@ -95,7 +95,7 @@ export const DefaultLayout = () => {
|
|||||||
{!showAuthModal && <KeyboardShortcutMenu />}
|
{!showAuthModal && <KeyboardShortcutMenu />}
|
||||||
{showAuthModal ? (
|
{showAuthModal ? (
|
||||||
<StyledNavigationDrawerWrapper>
|
<StyledNavigationDrawerWrapper>
|
||||||
<SignInAppNavigationDrawerMock />
|
<BackgroundMockNavigationDrawer />
|
||||||
</StyledNavigationDrawerWrapper>
|
</StyledNavigationDrawerWrapper>
|
||||||
) : useShowFullScreen ? null : (
|
) : useShowFullScreen ? null : (
|
||||||
<StyledNavigationDrawerWrapper>
|
<StyledNavigationDrawerWrapper>
|
||||||
@@ -106,7 +106,7 @@ export const DefaultLayout = () => {
|
|||||||
<>
|
<>
|
||||||
<StyledMainContainer>
|
<StyledMainContainer>
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
<SignInBackgroundMockPage />
|
<BackgroundMockPage />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</StyledMainContainer>
|
</StyledMainContainer>
|
||||||
<AnimatePresence mode="wait">
|
<AnimatePresence mode="wait">
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { Trans, useLingui } from '@lingui/react/macro';
|
import { Trans, useLingui } from '@lingui/react/macro';
|
||||||
import { lazy, Suspense } from 'react';
|
import { lazy, Suspense } from 'react';
|
||||||
|
|
||||||
const SignInBackgroundMockPage = lazy(() =>
|
const BackgroundMockPage = lazy(() =>
|
||||||
import('@/sign-in-background-mock/components/SignInBackgroundMockPage').then(
|
import('@/sign-in-background-mock/components/BackgroundMockPage').then(
|
||||||
(module) => ({ default: module.SignInBackgroundMockPage }),
|
(module) => ({ default: module.BackgroundMockPage }),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
import { AppPath } from 'twenty-shared/types';
|
import { AppPath } from 'twenty-shared/types';
|
||||||
@@ -69,7 +69,7 @@ export const NotFound = () => {
|
|||||||
</AnimatedPlaceholderErrorContainer>
|
</AnimatedPlaceholderErrorContainer>
|
||||||
</StyledBackDrop>
|
</StyledBackDrop>
|
||||||
<Suspense fallback={null}>
|
<Suspense fallback={null}>
|
||||||
<SignInBackgroundMockPage />
|
<BackgroundMockPage />
|
||||||
</Suspense>
|
</Suspense>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
import { useLoadMockedMetadata } from '@/metadata-store/hooks/useLoadMockedMetadata';
|
||||||
|
import { isMinimalMetadataReadyState } from '@/metadata-store/states/isMinimalMetadataReadyState';
|
||||||
|
import { metadataStoreState } from '@/metadata-store/states/metadataStoreState';
|
||||||
|
import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue';
|
||||||
|
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
|
export const MockedMetadataLoadEffect = () => {
|
||||||
|
const { loadMockedMetadataAtomic } = useLoadMockedMetadata();
|
||||||
|
const metadataStore = useAtomFamilyStateValue(
|
||||||
|
metadataStoreState,
|
||||||
|
'objectMetadataItems',
|
||||||
|
);
|
||||||
|
const setIsMinimalMetadataReady = useSetAtomState(
|
||||||
|
isMinimalMetadataReadyState,
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
void loadMockedMetadataAtomic();
|
||||||
|
}, [loadMockedMetadataAtomic]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (metadataStore.status === 'up-to-date') {
|
||||||
|
setIsMinimalMetadataReady(true);
|
||||||
|
} else {
|
||||||
|
setIsMinimalMetadataReady(false);
|
||||||
|
}
|
||||||
|
}, [metadataStore.status, setIsMinimalMetadataReady]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
@@ -16,8 +16,7 @@ import { ApolloCoreClientMockedProvider } from '@/object-metadata/hooks/__mocks_
|
|||||||
import { DefaultLayout } from '@/ui/layout/page/components/DefaultLayout';
|
import { DefaultLayout } from '@/ui/layout/page/components/DefaultLayout';
|
||||||
import { MinimalMetadataGater } from '@/metadata-store/components/MinimalMetadataGater';
|
import { MinimalMetadataGater } from '@/metadata-store/components/MinimalMetadataGater';
|
||||||
import { UserMetadataProviderInitialEffect } from '@/metadata-store/effect-components/UserMetadataProviderInitialEffect';
|
import { UserMetadataProviderInitialEffect } from '@/metadata-store/effect-components/UserMetadataProviderInitialEffect';
|
||||||
import { IsMinimalMetadataReadyEffect } from '@/metadata-store/effect-components/IsMinimalMetadataReadyEffect';
|
import { MockedMetadataLoadEffect } from '~/testing/decorators/MockedMetadataLoadEffect';
|
||||||
import { MinimalMetadataLoadEffect } from '@/metadata-store/effect-components/MinimalMetadataLoadEffect';
|
|
||||||
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
|
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { ClientConfigProvider } from '~/modules/client-config/components/ClientConfigProvider';
|
import { ClientConfigProvider } from '~/modules/client-config/components/ClientConfigProvider';
|
||||||
@@ -87,8 +86,7 @@ const Providers = () => {
|
|||||||
<ClientConfigProviderEffect />
|
<ClientConfigProviderEffect />
|
||||||
<ClientConfigProvider>
|
<ClientConfigProvider>
|
||||||
<UserMetadataProviderInitialEffect />
|
<UserMetadataProviderInitialEffect />
|
||||||
<MinimalMetadataLoadEffect />
|
<MockedMetadataLoadEffect />
|
||||||
<IsMinimalMetadataReadyEffect />
|
|
||||||
<WorkspaceProviderEffect />
|
<WorkspaceProviderEffect />
|
||||||
<MinimalMetadataGater>
|
<MinimalMetadataGater>
|
||||||
<ApolloCoreClientMockedProvider>
|
<ApolloCoreClientMockedProvider>
|
||||||
|
|||||||
Reference in New Issue
Block a user