diff --git a/packages/twenty-front/src/hooks/useScrollRestoration.ts b/packages/twenty-front/src/hooks/useScrollRestoration.ts index 1b145940a9..2367b21310 100644 --- a/packages/twenty-front/src/hooks/useScrollRestoration.ts +++ b/packages/twenty-front/src/hooks/useScrollRestoration.ts @@ -7,6 +7,7 @@ import { scrollPositionState } from '@/ui/utilities/scroll/states/scrollPosition import { isDefined } from '~/utils/isDefined'; /** + * @deprecated We should now use useScrollToPosition instead * Note that `location.key` is used in the cache key, not `location.pathname`, * so the same path navigated to at different points in the history stack will * not share the same scroll position. diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/useActiveFieldMetadataItems.ts b/packages/twenty-front/src/modules/object-metadata/hooks/useActiveFieldMetadataItems.ts new file mode 100644 index 0000000000..e60ab4e1a1 --- /dev/null +++ b/packages/twenty-front/src/modules/object-metadata/hooks/useActiveFieldMetadataItems.ts @@ -0,0 +1,20 @@ +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; +import { useMemo } from 'react'; + +export const useActiveFieldMetadataItems = ({ + objectMetadataItem, +}: { + objectMetadataItem: ObjectMetadataItem; +}) => { + const activeFieldMetadataItems = useMemo( + () => + objectMetadataItem + ? objectMetadataItem.fields.filter( + ({ isActive, isSystem }) => isActive && !isSystem, + ) + : [], + [objectMetadataItem], + ); + + return { activeFieldMetadataItems }; +}; diff --git a/packages/twenty-front/src/modules/object-record/hooks/useFetchMoreRecordsWithPagination.ts b/packages/twenty-front/src/modules/object-record/hooks/useFetchMoreRecordsWithPagination.ts index 2cc6be1c0b..8eb10ecc4e 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useFetchMoreRecordsWithPagination.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useFetchMoreRecordsWithPagination.ts @@ -209,15 +209,16 @@ export const useFetchMoreRecordsWithPagination = < const totalCount = data?.[objectMetadataItem.namePlural]?.totalCount; + const recordConnection = data?.[objectMetadataItem.namePlural]; + const records = useMemo( () => - data?.[objectMetadataItem.namePlural] + isDefined(recordConnection) ? getRecordsFromRecordConnection({ - recordConnection: data?.[objectMetadataItem.namePlural], + recordConnection, }) - : ([] as T[]), - - [data, objectMetadataItem.namePlural], + : [], + [recordConnection], ); return { diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx b/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx index a551db4cb5..9b096cac1f 100644 --- a/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx +++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx @@ -13,7 +13,7 @@ import { RecordUpdateHookParams, } from '@/object-record/record-field/contexts/FieldContext'; import { getFieldButtonIcon } from '@/object-record/record-field/utils/getFieldButtonIcon'; -import { RecordIndexRecordChip } from '@/object-record/record-index/components/RecordIndexRecordChip'; +import { RecordIdentifierChip } from '@/object-record/record-index/components/RecordIndexRecordChip'; import { RecordInlineCell } from '@/object-record/record-inline-cell/components/RecordInlineCell'; import { InlineCellHotkeyScope } from '@/object-record/record-inline-cell/types/InlineCellHotkeyScope'; import { RecordValueSetterEffect } from '@/object-record/record-store/components/RecordValueSetterEffect'; @@ -222,7 +222,7 @@ export const RecordBoardCard = () => { }} > - { const { fieldDefinition, isLabelIdentifier } = useContext(FieldContext); - const isChipDisplay = isFieldChipDisplay(fieldDefinition, isLabelIdentifier); + const isChipDisplay = isFieldIdentifierDisplay( + fieldDefinition, + isLabelIdentifier, + ); return isChipDisplay ? ( diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/ChipFieldDisplay.tsx b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/ChipFieldDisplay.tsx index 4a8682f385..94360aa0f2 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/ChipFieldDisplay.tsx +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/components/ChipFieldDisplay.tsx @@ -1,6 +1,6 @@ import { RecordChip } from '@/object-record/components/RecordChip'; import { useChipFieldDisplay } from '@/object-record/record-field/meta-types/hooks/useChipFieldDisplay'; -import { RecordIndexRecordChip } from '@/object-record/record-index/components/RecordIndexRecordChip'; +import { RecordIdentifierChip } from '@/object-record/record-index/components/RecordIndexRecordChip'; export const ChipFieldDisplay = () => { const { recordValue, objectNameSingular, isLabelIdentifier } = @@ -11,7 +11,7 @@ export const ChipFieldDisplay = () => { } return isLabelIdentifier ? ( - diff --git a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/utils/isFieldChipDisplay.ts b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/utils/isFieldIdentifierDisplay.ts similarity index 92% rename from packages/twenty-front/src/modules/object-record/record-field/meta-types/display/utils/isFieldChipDisplay.ts rename to packages/twenty-front/src/modules/object-record/record-field/meta-types/display/utils/isFieldIdentifierDisplay.ts index cb45decfe7..8272d9cdde 100644 --- a/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/utils/isFieldChipDisplay.ts +++ b/packages/twenty-front/src/modules/object-record/record-field/meta-types/display/utils/isFieldIdentifierDisplay.ts @@ -3,7 +3,7 @@ import { isFieldFullName } from '@/object-record/record-field/types/guards/isFie import { isFieldNumber } from '@/object-record/record-field/types/guards/isFieldNumber'; import { isFieldText } from '@/object-record/record-field/types/guards/isFieldText'; -export const isFieldChipDisplay = ( +export const isFieldIdentifierDisplay = ( field: Pick, isLabelIdentifier: boolean, ) => diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx index c7098481c0..39320c9111 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainer.tsx @@ -1,17 +1,10 @@ import styled from '@emotion/styled'; -import { - useRecoilCallback, - useRecoilState, - useRecoilValue, - useSetRecoilState, -} from 'recoil'; +import { useRecoilCallback, useRecoilState, useSetRecoilState } from 'recoil'; import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural'; -import { turnSortsIntoOrderBy } from '@/object-record/object-sort-dropdown/utils/turnSortsIntoOrderBy'; import { lastShowPageRecordIdState } from '@/object-record/record-field/states/lastShowPageRecordId'; -import { turnObjectDropdownFilterIntoQueryFilter } from '@/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter'; import { RecordIndexBoardContainer } from '@/object-record/record-index/components/RecordIndexBoardContainer'; import { RecordIndexBoardDataLoader } from '@/object-record/record-index/components/RecordIndexBoardDataLoader'; import { RecordIndexBoardDataLoaderEffect } from '@/object-record/record-index/components/RecordIndexBoardDataLoaderEffect'; @@ -26,22 +19,17 @@ import { recordIndexIsCompactModeActiveState } from '@/object-record/record-inde import { recordIndexKanbanFieldMetadataIdState } from '@/object-record/record-index/states/recordIndexKanbanFieldMetadataIdState'; import { recordIndexSortsState } from '@/object-record/record-index/states/recordIndexSortsState'; import { recordIndexViewTypeState } from '@/object-record/record-index/states/recordIndexViewTypeState'; -import { useFindRecordCursorFromFindManyCacheRootQuery } from '@/object-record/record-show/hooks/useFindRecordCursorFromFindManyCacheRootQuery'; -import { findView } from '@/object-record/record-show/hooks/useRecordShowPagePagination'; + +import { useHandleIndexIdentifierClick } from '@/object-record/record-index/hooks/useHandleIndexIdentifierClick'; import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; -import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; -import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider'; import { ViewBar } from '@/views/components/ViewBar'; -import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState'; -import { View } from '@/views/types/View'; import { ViewField } from '@/views/types/ViewField'; import { ViewType } from '@/views/types/ViewType'; import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions'; import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters'; import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts'; -import { useNavigate } from 'react-router-dom'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; const StyledContainer = styled.div` @@ -124,54 +112,11 @@ export const RecordIndexContainer = ({ [columnDefinitions, setTableColumns], ); - const navigate = useNavigate(); - - const { records: views } = usePrefetchedData(PrefetchKey.AllViews); - - const currentViewId = useRecoilValue( - currentViewIdComponentState({ - scopeId: recordIndexId, - }), - ); - - const view = findView({ - objectMetadataItemId: objectMetadataItem?.id ?? '', - viewId: currentViewId ?? null, - views, - }); - - const filter = turnObjectDropdownFilterIntoQueryFilter( - mapViewFiltersToFilters(view?.viewFilters ?? [], filterDefinitions), - objectMetadataItem?.fields ?? [], - ); - - const orderBy = turnSortsIntoOrderBy( + const { handleIndexIdentifierClick } = useHandleIndexIdentifierClick({ objectMetadataItem, - mapViewSortsToSorts(view?.viewSorts ?? [], sortDefinitions), - ); - - const { findCursorInCache } = useFindRecordCursorFromFindManyCacheRootQuery({ - fieldVariables: { - filter, - orderBy, - }, - objectNamePlural: objectNamePlural, + recordIndexId, }); - const handleIndexIdentifierClick = (recordId: string) => { - const cursor = findCursorInCache(recordId); - - // TODO: use URL builder - navigate( - `/object/${objectNameSingular}/${recordId}?view=${currentViewId}`, - { - state: { - cursor, - }, - }, - ); - }; - const handleIndexRecordsLoaded = useRecoilCallback( ({ set }) => () => { diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexRecordChip.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexRecordChip.tsx index 1a064570ca..7def9788b0 100644 --- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexRecordChip.tsx +++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexRecordChip.tsx @@ -5,17 +5,17 @@ import { RecordIndexEventContext } from '@/object-record/record-index/contexts/R import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { useContext } from 'react'; -export type RecordIndexRecordChipProps = { +export type RecordIdentifierChipProps = { objectNameSingular: string; record: ObjectRecord; variant?: AvatarChipVariant; }; -export const RecordIndexRecordChip = ({ +export const RecordIdentifierChip = ({ objectNameSingular, record, variant, -}: RecordIndexRecordChipProps) => { +}: RecordIdentifierChipProps) => { const { onIndexIdentifierClick } = useContext(RecordIndexEventContext); const { recordChipData } = useRecordChipData({ diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleIndexIdentifierClick.ts b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleIndexIdentifierClick.ts new file mode 100644 index 0000000000..a72fda64b9 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/useHandleIndexIdentifierClick.ts @@ -0,0 +1,33 @@ +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; +import { buildShowPageURL } from '@/object-record/record-show/utils/buildShowPageURL'; +import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState'; +import { useNavigate } from 'react-router-dom'; +import { useRecoilValue } from 'recoil'; + +export const useHandleIndexIdentifierClick = ({ + objectMetadataItem, + recordIndexId, +}: { + recordIndexId: string; + objectMetadataItem: ObjectMetadataItem; +}) => { + const navigate = useNavigate(); + + const currentViewId = useRecoilValue( + currentViewIdComponentState({ + scopeId: recordIndexId, + }), + ); + + const handleIndexIdentifierClick = (recordId: string) => { + const showPageURL = buildShowPageURL( + objectMetadataItem.nameSingular, + recordId, + currentViewId, + ); + + navigate(showPageURL); + }; + + return { handleIndexIdentifierClick }; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-show/graphql/operations/factories/findOneRecordForShowPageOperationSignatureFactory.ts b/packages/twenty-front/src/modules/object-record/record-show/graphql/operations/factories/findOneRecordForShowPageOperationSignatureFactory.ts index 50082029ae..f3ec81af02 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/graphql/operations/factories/findOneRecordForShowPageOperationSignatureFactory.ts +++ b/packages/twenty-front/src/modules/object-record/record-show/graphql/operations/factories/findOneRecordForShowPageOperationSignatureFactory.ts @@ -1,11 +1,10 @@ -import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; import { RecordGqlOperationSignatureFactory } from '@/object-record/graphql/types/RecordGqlOperationSignatureFactory'; import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields'; -export const findOneRecordForShowPageOperationSignatureFactory: RecordGqlOperationSignatureFactory = +export const buildFindOneRecordForShowPageOperationSignature: RecordGqlOperationSignatureFactory = ({ objectMetadataItem }: { objectMetadataItem: ObjectMetadataItem }) => ({ - objectNameSingular: CoreObjectNameSingular.Activity, + objectNameSingular: objectMetadataItem.nameSingular, variables: {}, fields: generateDepthOneRecordGqlFields({ objectMetadataItem }), }); diff --git a/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPage.ts b/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPage.ts index f584c4cabc..0455dd6de2 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPage.ts +++ b/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPage.ts @@ -7,7 +7,7 @@ import { useFavorites } from '@/favorites/hooks/useFavorites'; import { useLabelIdentifierFieldMetadataItem } from '@/object-metadata/hooks/useLabelIdentifierFieldMetadataItem'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord'; -import { findOneRecordForShowPageOperationSignatureFactory } from '@/object-record/record-show/graphql/operations/factories/findOneRecordForShowPageOperationSignatureFactory'; +import { buildFindOneRecordForShowPageOperationSignature } from '@/object-record/record-show/graphql/operations/factories/findOneRecordForShowPageOperationSignatureFactory'; import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; import { FieldMetadataType } from '~/generated-metadata/graphql'; import { isDefined } from '~/utils/isDefined'; @@ -39,7 +39,8 @@ export const useRecordShowPage = ( const { getIcon } = useIcons(); const headerIcon = getIcon(objectMetadataItem?.icon); const FIND_ONE_RECORD_FOR_SHOW_PAGE_OPERATION_SIGNATURE = - findOneRecordForShowPageOperationSignatureFactory({ objectMetadataItem }); + buildFindOneRecordForShowPageOperationSignature({ objectMetadataItem }); + const { record, loading } = useFindOneRecord({ objectRecordId, objectNameSingular, diff --git a/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts b/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts index 2b2d0c25e9..d22878e7d1 100644 --- a/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts +++ b/packages/twenty-front/src/modules/object-record/record-show/hooks/useRecordShowPagePagination.ts @@ -1,52 +1,19 @@ /* eslint-disable @nx/workspace-no-navigate-prefer-link */ -import { useMemo, useState } from 'react'; -import { - useLocation, - useNavigate, - useParams, - useSearchParams, -} from 'react-router-dom'; +import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; import { useSetRecoilState } from 'recoil'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; -import { formatFieldMetadataItemsAsFilterDefinitions } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; -import { formatFieldMetadataItemsAsSortDefinitions } from '@/object-metadata/utils/formatFieldMetadataItemsAsSortDefinitions'; import { generateDepthOneRecordGqlFields } from '@/object-record/graphql/utils/generateDepthOneRecordGqlFields'; import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords'; -import { turnSortsIntoOrderBy } from '@/object-record/object-sort-dropdown/utils/turnSortsIntoOrderBy'; import { lastShowPageRecordIdState } from '@/object-record/record-field/states/lastShowPageRecordId'; -import { turnObjectDropdownFilterIntoQueryFilter } from '@/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter'; import { useRecordIdsFromFindManyCacheRootQuery } from '@/object-record/record-show/hooks/useRecordIdsFromFindManyCacheRootQuery'; -import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; -import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; -import { View } from '@/views/types/View'; -import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters'; -import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts'; +import { buildShowPageURL } from '@/object-record/record-show/utils/buildShowPageURL'; +import { buildIndexTablePageURL } from '@/object-record/record-table/utils/buildIndexTableURL'; +import { useQueryVariablesFromActiveFieldsOfViewOrDefaultView } from '@/views/hooks/useQueryVariablesFromActiveFieldsOfViewOrDefaultView'; import { isNonEmptyString } from '@sniptt/guards'; +import { getRelayCursorFromRecordId } from '~/utils/getRelayCursorFromRecordId'; import { capitalize } from '~/utils/string/capitalize'; -export const findView = ({ - viewId, - objectMetadataItemId, - views, -}: { - viewId: string | null; - objectMetadataItemId: string; - views: View[]; -}) => { - if (!viewId) { - return views.find( - (view: any) => - view.key === 'INDEX' && view?.objectMetadataId === objectMetadataItemId, - ) as View; - } else { - return views.find( - (view: any) => - view?.id === viewId && view?.objectMetadataId === objectMetadataItemId, - ) as View; - } -}; - export const useRecordShowPagePagination = ( propsObjectNameSingular: string, propsObjectRecordId: string, @@ -61,8 +28,6 @@ export const useRecordShowPagePagination = ( const setLastShowPageRecordId = useSetRecoilState(lastShowPageRecordIdState); - const [isLoadedRecords] = useState(false); - const objectNameSingular = propsObjectNameSingular || paramObjectNameSingular; const objectRecordId = propsObjectRecordId || paramObjectRecordId; @@ -71,77 +36,26 @@ export const useRecordShowPagePagination = ( } const { objectMetadataItem } = useObjectMetadataItem({ objectNameSingular }); - const { records: views } = usePrefetchedData(PrefetchKey.AllViews); - - const view = useMemo(() => { - return findView({ - objectMetadataItemId: objectMetadataItem?.id ?? '', - viewId: viewIdQueryParam, - views, - }); - }, [viewIdQueryParam, objectMetadataItem, views]); - - const activeFieldMetadataItems = useMemo( - () => - objectMetadataItem - ? objectMetadataItem.fields.filter( - ({ isActive, isSystem }) => isActive && !isSystem, - ) - : [], - [objectMetadataItem], - ); - - const filterDefinitions = formatFieldMetadataItemsAsFilterDefinitions({ - fields: activeFieldMetadataItems, - }); - - const sortDefinitions = formatFieldMetadataItemsAsSortDefinitions({ - fields: activeFieldMetadataItems, - }); - - const filter = turnObjectDropdownFilterIntoQueryFilter( - mapViewFiltersToFilters(view?.viewFilters ?? [], filterDefinitions), - objectMetadataItem?.fields ?? [], - ); - - const orderBy = turnSortsIntoOrderBy( - objectMetadataItem, - mapViewSortsToSorts(view?.viewSorts ?? [], sortDefinitions), - ); const recordGqlFields = generateDepthOneRecordGqlFields({ objectMetadataItem, }); - const { state } = useLocation(); - - const cursorFromIndexPage = state?.cursor; - - const { loading: loadingCurrentRecord, pageInfo: currentRecordsPageInfo } = - useFindManyRecords({ - filter: { - id: { eq: objectRecordId }, - }, - orderBy, - skip: isLoadedRecords, - limit: 1, - objectNameSingular, - recordGqlFields, + const { filter, orderBy } = + useQueryVariablesFromActiveFieldsOfViewOrDefaultView({ + objectMetadataItem, + viewId: viewIdQueryParam, }); - const currentRecordCursor = currentRecordsPageInfo?.endCursor; - - const cursor = cursorFromIndexPage ?? currentRecordCursor; + const cursor = getRelayCursorFromRecordId(objectRecordId); const { loading: loadingRecordBefore, records: recordsBefore, - pageInfo: pageInfoBefore, totalCount: totalCountBefore, } = useFindManyRecords({ filter, orderBy, - skip: isLoadedRecords, cursorFilter: isNonEmptyString(cursor) ? { cursorDirection: 'before', @@ -156,12 +70,10 @@ export const useRecordShowPagePagination = ( const { loading: loadingRecordAfter, records: recordsAfter, - pageInfo: pageInfoAfter, totalCount: totalCountAfter, } = useFindManyRecords({ filter, orderBy, - skip: isLoadedRecords, cursorFilter: cursor ? { cursorDirection: 'after', @@ -175,8 +87,7 @@ export const useRecordShowPagePagination = ( const totalCount = Math.max(totalCountBefore ?? 0, totalCountAfter ?? 0); - const loading = - loadingRecordAfter || loadingRecordBefore || loadingCurrentRecord; + const loading = loadingRecordAfter || loadingRecordBefore; const isThereARecordBefore = recordsBefore.length > 0; const isThereARecordAfter = recordsAfter.length > 0; @@ -184,43 +95,27 @@ export const useRecordShowPagePagination = ( const recordBefore = recordsBefore[0]; const recordAfter = recordsAfter[0]; - const recordBeforeCursor = pageInfoBefore?.endCursor; - const recordAfterCursor = pageInfoAfter?.endCursor; - const navigateToPreviousRecord = () => { navigate( - `/object/${objectNameSingular}/${recordBefore.id}${ - viewIdQueryParam ? `?view=${viewIdQueryParam}` : '' - }`, - { - state: { - cursor: recordBeforeCursor, - }, - }, + buildShowPageURL(objectNameSingular, recordBefore.id, viewIdQueryParam), ); }; const navigateToNextRecord = () => { navigate( - `/object/${objectNameSingular}/${recordAfter.id}${ - viewIdQueryParam ? `?view=${viewIdQueryParam}` : '' - }`, - { - state: { - cursor: recordAfterCursor, - }, - }, + buildShowPageURL(objectNameSingular, recordAfter.id, viewIdQueryParam), ); }; const navigateToIndexView = () => { - const indexPath = `/objects/${objectMetadataItem.namePlural}${ - viewIdQueryParam ? `?view=${viewIdQueryParam}` : '' - }`; + const indexTableURL = buildIndexTablePageURL( + objectMetadataItem.namePlural, + viewIdQueryParam, + ); setLastShowPageRecordId(objectRecordId); - navigate(indexPath); + navigate(indexTableURL); }; const { recordIdsInCache } = useRecordIdsFromFindManyCacheRootQuery({ diff --git a/packages/twenty-front/src/modules/object-record/record-show/utils/buildShowPageURL.ts b/packages/twenty-front/src/modules/object-record/record-show/utils/buildShowPageURL.ts new file mode 100644 index 0000000000..93d7878c11 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-show/utils/buildShowPageURL.ts @@ -0,0 +1,9 @@ +export const buildShowPageURL = ( + objectNameSingular: string, + recordId: string, + viewId?: string | null | undefined, +) => { + return `/object/${objectNameSingular}/${recordId}${ + viewId ? `?view=${viewId}` : '' + }`; +}; diff --git a/packages/twenty-front/src/modules/object-record/record-table/constants/RowHeight.ts b/packages/twenty-front/src/modules/object-record/record-table/constants/RowHeight.ts new file mode 100644 index 0000000000..fde70b4684 --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/constants/RowHeight.ts @@ -0,0 +1 @@ +export const ROW_HEIGHT = 32; diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSetRecordTableData.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSetRecordTableData.ts index eeaf15147c..c36df9f083 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSetRecordTableData.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useSetRecordTableData.ts @@ -24,17 +24,18 @@ export const useSetRecordTableData = ({ return useRecoilCallback( ({ set, snapshot }) => - (newEntityArray: T[], totalCount?: number) => { - for (const entity of newEntityArray) { + (newRecords: T[], totalCount?: number) => { + for (const record of newRecords) { // TODO: refactor with scoped state later - const currentEntity = snapshot - .getLoadable(recordStoreFamilyState(entity.id)) + const currentRecord = snapshot + .getLoadable(recordStoreFamilyState(record.id)) .getValue(); - if (JSON.stringify(currentEntity) !== JSON.stringify(entity)) { - set(recordStoreFamilyState(entity.id), entity); + if (JSON.stringify(currentRecord) !== JSON.stringify(record)) { + set(recordStoreFamilyState(record.id), record); } } + const currentRowIds = getSnapshotValue(snapshot, tableRowIdsState); const hasUserSelectedAllRows = getSnapshotValue( @@ -42,7 +43,7 @@ export const useSetRecordTableData = ({ hasUserSelectedAllRowsState, ); - const entityIds = newEntityArray.map((entity) => entity.id); + const entityIds = newRecords.map((entity) => entity.id); if (!isDeeplyEqual(currentRowIds, entityIds)) { set(tableRowIdsState, entityIds); diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyEffect.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyEffect.tsx index 33816ad4d3..2c76c61988 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyEffect.tsx +++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyEffect.tsx @@ -4,6 +4,7 @@ import { useDebouncedCallback } from 'use-debounce'; import { lastShowPageRecordIdState } from '@/object-record/record-field/states/lastShowPageRecordId'; import { useLoadRecordIndexTable } from '@/object-record/record-index/hooks/useLoadRecordIndexTable'; +import { ROW_HEIGHT } from '@/object-record/record-table/constants/RowHeight'; import { RecordTableContext } from '@/object-record/record-table/contexts/RecordTableContext'; import { useRecordTableStates } from '@/object-record/record-table/hooks/internal/useRecordTableStates'; import { isRecordTableScrolledLeftComponentState } from '@/object-record/record-table/states/isRecordTableScrolledLeftComponentState'; @@ -13,11 +14,8 @@ import { scrollLeftState } from '@/ui/utilities/scroll/states/scrollLeftState'; import { scrollTopState } from '@/ui/utilities/scroll/states/scrollTopState'; import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState'; import { isNonEmptyString } from '@sniptt/guards'; -import { useScrollRestoration } from '~/hooks/useScrollRestoration'; import { useScrollToPosition } from '~/hooks/useScrollToPosition'; -export const ROW_HEIGHT = 32; - export const RecordTableBodyEffect = () => { const { objectNameSingular } = useContext(RecordTableContext); @@ -30,6 +28,7 @@ export const RecordTableBodyEffect = () => { setRecordTableData, loading, queryStateIdentifier, + cursorsByRecordId, } = useLoadRecordIndexTable(objectNameSingular); const isFetchingMoreObjects = useRecoilValue( @@ -45,6 +44,7 @@ export const RecordTableBodyEffect = () => { isRecordTableScrolledTopComponentState, ); + // TODO: move this outside because it might cause way too many re-renders for other hooks useEffect(() => { setIsRecordTableScrolledTop(scrollTop === 0); if (scrollTop > 0) { @@ -83,9 +83,6 @@ export const RecordTableBodyEffect = () => { } }, [scrollLeft, setIsRecordTableScrolledLeft]); - const rowHeight = ROW_HEIGHT; - const viewportHeight = records.length * rowHeight; - const [lastShowPageRecordId, setLastShowPageRecordId] = useRecoilState( lastShowPageRecordIdState, ); @@ -121,13 +118,11 @@ export const RecordTableBodyEffect = () => { setLastShowPageRecordId, ]); - useScrollRestoration(viewportHeight); - useEffect(() => { if (!loading) { setRecordTableData(records, totalCount); } - }, [records, totalCount, setRecordTableData, loading]); + }, [records, totalCount, setRecordTableData, loading, cursorsByRecordId]); const fetchMoreDebouncedIfRequested = useDebouncedCallback(async () => { // We are debouncing here to give the user some room to scroll if they want to within this throttle window diff --git a/packages/twenty-front/src/modules/object-record/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext.ts b/packages/twenty-front/src/modules/object-record/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext.ts index a4dcca1442..40e3e30c2d 100644 --- a/packages/twenty-front/src/modules/object-record/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext.ts +++ b/packages/twenty-front/src/modules/object-record/record-table/scopes/scope-internal-context/RecordTableScopeInternalContext.ts @@ -4,6 +4,7 @@ import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/Co import { ColumnDefinition } from '../../types/ColumnDefinition'; +// TODO: separate scope contexts from event contexts type RecordTableScopeInternalContextProps = ComponentStateKey & { onColumnsChange: (columns: ColumnDefinition[]) => void; }; diff --git a/packages/twenty-front/src/modules/object-record/record-table/utils/buildIndexTableURL.ts b/packages/twenty-front/src/modules/object-record/record-table/utils/buildIndexTableURL.ts new file mode 100644 index 0000000000..6610eb835d --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/record-table/utils/buildIndexTableURL.ts @@ -0,0 +1,6 @@ +export const buildIndexTablePageURL = ( + objectNamePlural: string, + viewId?: string | null | undefined, +) => { + return `/objects/${objectNamePlural}${viewId ? `?view=${viewId}` : ''}`; +}; diff --git a/packages/twenty-front/src/modules/object-record/utils/getRecordChipGenerators.ts b/packages/twenty-front/src/modules/object-record/utils/getRecordChipGenerators.ts index c80fe1b763..fa56378afd 100644 --- a/packages/twenty-front/src/modules/object-record/utils/getRecordChipGenerators.ts +++ b/packages/twenty-front/src/modules/object-record/utils/getRecordChipGenerators.ts @@ -8,7 +8,7 @@ import { getAvatarUrl } from '@/object-metadata/utils/getAvatarUrl'; import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem'; import { getLabelIdentifierFieldValue } from '@/object-metadata/utils/getLabelIdentifierFieldValue'; import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField'; -import { isFieldChipDisplay } from '@/object-record/record-field/meta-types/display/utils/isFieldChipDisplay'; +import { isFieldIdentifierDisplay } from '@/object-record/record-field/meta-types/display/utils/isFieldIdentifierDisplay'; import { RecordChipData } from '@/object-record/record-field/types/RecordChipData'; import { ObjectRecord } from '@/object-record/types/ObjectRecord'; import { FieldMetadataType } from '~/generated-metadata/graphql'; @@ -34,7 +34,7 @@ export const getRecordChipGenerators = ( (fieldMetadataItem) => labelIdentifierFieldMetadataItem?.id === fieldMetadataItem.id || fieldMetadataItem.type === FieldMetadataType.Relation || - isFieldChipDisplay( + isFieldIdentifierDisplay( fieldMetadataItem, isLabelIdentifierField({ fieldMetadataItem: fieldMetadataItem, diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useExtractedComponentFamilyStateV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useExtractedComponentFamilyStateV2.ts new file mode 100644 index 0000000000..8bf347a2b6 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useExtractedComponentFamilyStateV2.ts @@ -0,0 +1,35 @@ +import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; +import { getScopeIdOrUndefinedFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdOrUndefinedFromComponentId'; +import { ComponentFamilyState } from '@/ui/utilities/state/component-state/types/ComponentFamilyState'; +import { SerializableParam } from 'recoil'; + +export const useExtractedComponentFamilyStateV2 = < + FamilyKey extends SerializableParam, + Value, +>( + componentFamilyState: ComponentFamilyState, + componentId?: string, +) => { + const componentContext = (window as any).componentContextStateMap?.get( + componentFamilyState.key, + ); + + if (!componentContext) { + throw new Error( + `Component context for key "${componentFamilyState.key}" is not defined`, + ); + } + + const internalScopeId = useAvailableScopeIdOrThrow( + componentContext, + getScopeIdOrUndefinedFromComponentId(componentId), + ); + + const extractedComponentFamilyState = (familyKey: FamilyKey) => + componentFamilyState.atomFamily({ + scopeId: internalScopeId, + familyKey, + }); + + return extractedComponentFamilyState; +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValue.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValue.ts new file mode 100644 index 0000000000..58af1dc02e --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValue.ts @@ -0,0 +1,36 @@ +import { SerializableParam, useRecoilValue } from 'recoil'; + +import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId'; +import { getScopeIdOrUndefinedFromComponentId } from '@/ui/utilities/recoil-scope/utils/getScopeIdOrUndefinedFromComponentId'; +import { ComponentFamilyState } from '@/ui/utilities/state/component-state/types/ComponentFamilyState'; + +export const useRecoilComponentFamilyValue = < + StateType, + FamilyKey extends SerializableParam, +>( + componentFamilyState: ComponentFamilyState, + familyKey: FamilyKey, + componentId?: string, +) => { + const componentContext = (window as any).componentContextStateMap?.get( + componentFamilyState.key, + ); + + if (!componentContext) { + throw new Error( + `Component context for key "${componentFamilyState.key}" is not defined`, + ); + } + + const internalComponentId = useAvailableScopeIdOrThrow( + componentContext, + getScopeIdOrUndefinedFromComponentId(componentId), + ); + + return useRecoilValue( + componentFamilyState.atomFamily({ + scopeId: internalComponentId, + familyKey, + }), + ); +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useScopeIdFromStateContext.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useScopeIdFromStateContext.ts new file mode 100644 index 0000000000..e500060c98 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/hooks/useScopeIdFromStateContext.ts @@ -0,0 +1,23 @@ +import { useScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useScopeInternalContext'; +import { ComponentFamilyState } from '@/ui/utilities/state/component-state/types/ComponentFamilyState'; +import { ComponentState } from '@/ui/utilities/state/component-state/types/ComponentState'; + +export const useScopeIdFromStateContext = ( + componentState: ComponentState | ComponentFamilyState, +) => { + const componentContext = (window as any).componentContextStateMap?.get( + componentState.key, + ); + + if (!componentContext) { + throw new Error( + `Component context for key "${componentState.key}" is not defined`, + ); + } + + const scopeInternalContext = useScopeInternalContext(componentContext); + + const scopeIdFromContext = scopeInternalContext?.scopeId; + + return { scopeId: scopeIdFromContext }; +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentFamilyState.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentFamilyState.ts new file mode 100644 index 0000000000..1a4be07864 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/types/ComponentFamilyState.ts @@ -0,0 +1,13 @@ +import { RecoilState, SerializableParam } from 'recoil'; + +import { ComponentFamilyStateKey } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateKey'; + +export type ComponentFamilyState< + StateType, + FamilyKey extends SerializableParam, +> = { + key: string; + atomFamily: ( + componentStateKey: ComponentFamilyStateKey, + ) => RecoilState; +}; diff --git a/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentFamilyStateV2.ts b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentFamilyStateV2.ts new file mode 100644 index 0000000000..b3f7b3b5b4 --- /dev/null +++ b/packages/twenty-front/src/modules/ui/utilities/state/component-state/utils/createComponentFamilyStateV2.ts @@ -0,0 +1,39 @@ +import { AtomEffect, atomFamily, SerializableParam } from 'recoil'; + +import { ScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/types/ScopeInternalContext'; +import { ComponentFamilyStateKey } from '@/ui/utilities/state/component-state/types/ComponentFamilyStateKey'; +import { isDefined } from 'twenty-ui'; + +type CreateComponentFamilyStateV2Type = { + key: string; + defaultValue: ValueType; + componentContext: ScopeInternalContext | null; + effects?: AtomEffect[]; +}; + +export const createComponentFamilyStateV2 = < + ValueType, + FamilyKey extends SerializableParam, +>({ + key, + effects, + defaultValue, + componentContext, +}: CreateComponentFamilyStateV2Type) => { + if (isDefined(componentContext)) { + if (!isDefined((window as any).componentContextStateMap)) { + (window as any).componentContextStateMap = new Map(); + } + + (window as any).componentContextStateMap.set(key, componentContext); + } + + return { + key, + atomFamily: atomFamily>({ + key, + default: defaultValue, + effects, + }), + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useQueryVariablesFromActiveFieldsOfViewOrDefaultView.ts b/packages/twenty-front/src/modules/views/hooks/useQueryVariablesFromActiveFieldsOfViewOrDefaultView.ts new file mode 100644 index 0000000000..f5431bc45a --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useQueryVariablesFromActiveFieldsOfViewOrDefaultView.ts @@ -0,0 +1,32 @@ +import { useActiveFieldMetadataItems } from '@/object-metadata/hooks/useActiveFieldMetadataItems'; +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; +import { useViewOrDefaultViewFromPrefetchedViews } from '@/views/hooks/useViewOrDefaultViewFromPrefetchedViews'; +import { getQueryVariablesFromView } from '@/views/utils/getQueryVariablesFromView'; + +export const useQueryVariablesFromActiveFieldsOfViewOrDefaultView = ({ + objectMetadataItem, + viewId, +}: { + objectMetadataItem: ObjectMetadataItem; + viewId: string | null | undefined; +}) => { + const { view } = useViewOrDefaultViewFromPrefetchedViews({ + objectMetadataItemId: objectMetadataItem.id, + viewId, + }); + + const { activeFieldMetadataItems } = useActiveFieldMetadataItems({ + objectMetadataItem, + }); + + const { filter, orderBy } = getQueryVariablesFromView({ + fieldMetadataItems: activeFieldMetadataItems, + objectMetadataItem, + view, + }); + + return { + filter, + orderBy, + }; +}; diff --git a/packages/twenty-front/src/modules/views/hooks/useViewOrDefaultViewFromPrefetchedViews.ts b/packages/twenty-front/src/modules/views/hooks/useViewOrDefaultViewFromPrefetchedViews.ts new file mode 100644 index 0000000000..40bd3d7a73 --- /dev/null +++ b/packages/twenty-front/src/modules/views/hooks/useViewOrDefaultViewFromPrefetchedViews.ts @@ -0,0 +1,24 @@ +import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData'; +import { PrefetchKey } from '@/prefetch/types/PrefetchKey'; +import { View } from '@/views/types/View'; +import { useMemo } from 'react'; + +export const useViewOrDefaultViewFromPrefetchedViews = ({ + objectMetadataItemId, + viewId, +}: { + objectMetadataItemId: string; + viewId: string | null | undefined; +}) => { + const { records: views } = usePrefetchedData(PrefetchKey.AllViews); + + const view = useMemo(() => { + return views.find( + (view: View) => + (view.key === 'INDEX' || view?.id === viewId) && + view?.objectMetadataId === objectMetadataItemId, + ); + }, [viewId, views, objectMetadataItemId]); + + return { view }; +}; diff --git a/packages/twenty-front/src/modules/views/utils/getQueryVariablesFromView.ts b/packages/twenty-front/src/modules/views/utils/getQueryVariablesFromView.ts new file mode 100644 index 0000000000..f946d83892 --- /dev/null +++ b/packages/twenty-front/src/modules/views/utils/getQueryVariablesFromView.ts @@ -0,0 +1,52 @@ +import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem'; +import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem'; +import { formatFieldMetadataItemsAsFilterDefinitions } from '@/object-metadata/utils/formatFieldMetadataItemsAsFilterDefinitions'; +import { formatFieldMetadataItemsAsSortDefinitions } from '@/object-metadata/utils/formatFieldMetadataItemsAsSortDefinitions'; +import { turnSortsIntoOrderBy } from '@/object-record/object-sort-dropdown/utils/turnSortsIntoOrderBy'; +import { turnObjectDropdownFilterIntoQueryFilter } from '@/object-record/record-filter/utils/turnObjectDropdownFilterIntoQueryFilter'; +import { View } from '@/views/types/View'; +import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters'; +import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts'; +import { isDefined } from '~/utils/isDefined'; + +export const getQueryVariablesFromView = ({ + view, + fieldMetadataItems, + objectMetadataItem, +}: { + view: View | null | undefined; + fieldMetadataItems: FieldMetadataItem[]; + objectMetadataItem: ObjectMetadataItem; +}) => { + if (!isDefined(view)) { + return { + filter: {}, + orderBy: [], + }; + } + + const { viewFilters, viewSorts } = view; + + const filterDefinitions = formatFieldMetadataItemsAsFilterDefinitions({ + fields: fieldMetadataItems, + }); + + const sortDefinitions = formatFieldMetadataItemsAsSortDefinitions({ + fields: fieldMetadataItems, + }); + + const filter = turnObjectDropdownFilterIntoQueryFilter( + mapViewFiltersToFilters(viewFilters, filterDefinitions), + objectMetadataItem?.fields ?? [], + ); + + const orderBy = turnSortsIntoOrderBy( + objectMetadataItem, + mapViewSortsToSorts(viewSorts, sortDefinitions), + ); + + return { + filter, + orderBy, + }; +}; diff --git a/packages/twenty-front/src/pages/object-record/__stories__/RecordShowPage.stories.tsx b/packages/twenty-front/src/pages/object-record/__stories__/RecordShowPage.stories.tsx index 2674fd4bde..dd494a1f29 100644 --- a/packages/twenty-front/src/pages/object-record/__stories__/RecordShowPage.stories.tsx +++ b/packages/twenty-front/src/pages/object-record/__stories__/RecordShowPage.stories.tsx @@ -11,6 +11,7 @@ import { graphqlMocks } from '~/testing/graphqlMocks'; import { getPeopleMock, peopleQueryResult } from '~/testing/mock-data/people'; import { mockedWorkspaceMemberData } from '~/testing/mock-data/users'; +import { viewQueryResultMock } from '~/testing/mock-data/views'; import { RecordShowPage } from '../RecordShowPage'; const peopleMock = getPeopleMock(); @@ -65,15 +66,7 @@ const meta: Meta = { graphql.query('FindManyViews', () => { return HttpResponse.json({ data: { - views: { - edges: [], - pageInfo: { - hasNextPage: false, - startCursor: peopleMock[0].id, - endCursor: peopleMock[0].id, - }, - totalCount: 0, - }, + views: viewQueryResultMock, }, }); }), diff --git a/packages/twenty-front/src/testing/mock-data/views.ts b/packages/twenty-front/src/testing/mock-data/views.ts index 555e0a7c5d..f924a9fccd 100644 --- a/packages/twenty-front/src/testing/mock-data/views.ts +++ b/packages/twenty-front/src/testing/mock-data/views.ts @@ -1,3 +1,808 @@ +import { RecordGqlConnection } from '@/object-record/graphql/types/RecordGqlConnection'; +import { ViewType } from '@/views/types/ViewType'; + +export const viewQueryResultMock: RecordGqlConnection = { + __typename: 'ViewConnection', + totalCount: 6, + pageInfo: { + __typename: 'PageInfo', + hasNextPage: false, + hasPreviousPage: false, + startCursor: 'WyIyY2M5MGJjZC0wNzkzLTRkMzctYWZlOS1kZTVlY2NmYmFlNzEiXQ==', + endCursor: 'WyJmZjhlZGQyMi02NjVhLTQ5NWYtODljYy03MGFiOGZkNWMxYTYiXQ==', + }, + edges: [ + { + __typename: 'ViewEdge', + cursor: 'WyIyY2M5MGJjZC0wNzkzLTRkMzctYWZlOS1kZTVlY2NmYmFlNzEiXQ==', + node: { + __typename: 'View', + position: 1, + updatedAt: '2024-07-11T10:21:33.304Z', + key: null, + id: '2cc90bcd-0793-4d37-afe9-de5eccfbae71', + objectMetadataId: '9c293c05-f461-456a-b5a2-2710b5b30447', + createdAt: '2024-07-11T10:21:33.304Z', + icon: 'IconLayoutKanban', + isCompact: false, + name: 'By Stage', + type: 'kanban' as ViewType, + kanbanFieldMetadataId: 'f74de381-4392-4662-a890-5ed3b5bd847d', + viewSorts: { + __typename: 'ViewSortConnection', + edges: [], + }, + viewFilters: { + __typename: 'ViewFilterConnection', + edges: [], + }, + viewFields: { + __typename: 'ViewFieldConnection', + edges: [ + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 2, + id: '05ffd5e0-69b0-4774-843a-fbae12231e7d', + viewId: '2cc90bcd-0793-4d37-afe9-de5eccfbae71', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: 'c4e1b90f-bf9a-4a04-b67a-0f88263d8706', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 4, + id: '573ae123-1eed-4671-8fff-d9ac9455b1b4', + viewId: '2cc90bcd-0793-4d37-afe9-de5eccfbae71', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: '6e073ac2-034c-43ab-b0c6-206b1dd1174b', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 0, + id: 'ae4f318f-5059-41ba-b365-22daa0b3cb0e', + viewId: '2cc90bcd-0793-4d37-afe9-de5eccfbae71', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: '4ee7183a-f1f6-42a6-94e5-79f741357760', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 1, + id: 'b5ac37dc-9f64-412f-a598-611bdb5d27f8', + viewId: '2cc90bcd-0793-4d37-afe9-de5eccfbae71', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: '37593700-f3ac-43a2-9ce2-1b811fa3fbfc', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 5, + id: 'bda12277-2962-4b35-a549-665cbbe53483', + viewId: '2cc90bcd-0793-4d37-afe9-de5eccfbae71', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: '031bc747-1787-4e46-9320-562a8b75f3ff', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 3, + id: 'f43e660f-bbf8-4a2f-aeb1-54890ac40f4b', + viewId: '2cc90bcd-0793-4d37-afe9-de5eccfbae71', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: '2cc0fa2b-dbea-4fd0-b7f5-11fa54cd0242', + }, + }, + ], + }, + }, + }, + { + __typename: 'ViewEdge', + cursor: 'WyI1N2FkYTUyMy0zZDgzLTQzOTEtYThiOS0wZTkxOGUyNGE1MTkiXQ==', + node: { + __typename: 'View', + position: null, + updatedAt: '2024-07-12T09:52:15.595Z', + key: 'INDEX', + id: '57ada523-3d83-4391-a8b9-0e918e24a519', + objectMetadataId: '3561dbe5-39a2-40fa-a111-4af924e39908', + createdAt: '2024-07-12T09:52:15.595Z', + icon: 'IconListNumbers', + isCompact: false, + name: 'All Tests', + type: 'table', + kanbanFieldMetadataId: '', + viewSorts: { + __typename: 'ViewSortConnection', + edges: [], + }, + viewFilters: { + __typename: 'ViewFilterConnection', + edges: [], + }, + viewFields: { + __typename: 'ViewFieldConnection', + edges: [ + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-16T12:58:56.823Z', + position: 2, + id: '39a026d9-8362-4a4c-9b35-3d23218122a7', + viewId: '57ada523-3d83-4391-a8b9-0e918e24a519', + createdAt: '2024-07-16T12:58:56.823Z', + isVisible: true, + size: 100, + fieldMetadataId: '9918f304-99d9-4d5b-8351-c6b6f7cc38bb', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-12T09:52:15.598Z', + position: 0, + id: '3ab70930-e60a-4bfd-830a-57355121d889', + viewId: '57ada523-3d83-4391-a8b9-0e918e24a519', + createdAt: '2024-07-12T09:52:15.598Z', + isVisible: true, + size: 180, + fieldMetadataId: 'f7f485fc-0c14-4b70-a180-0508699a5c14', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-12T09:52:15.604Z', + position: 1, + id: '43ec0b2c-d94f-4eaf-a4bc-f00d409661b5', + viewId: '57ada523-3d83-4391-a8b9-0e918e24a519', + createdAt: '2024-07-12T09:52:15.604Z', + isVisible: true, + size: 180, + fieldMetadataId: '66645848-4100-4649-bc0e-d50281df2fd6', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-12T09:52:15.604Z', + position: 2, + id: '53f01c19-7042-4551-97d8-d36b6ae28602', + viewId: '57ada523-3d83-4391-a8b9-0e918e24a519', + createdAt: '2024-07-12T09:52:15.604Z', + isVisible: true, + size: 180, + fieldMetadataId: '1b3caa7a-343a-4b4b-8c2e-3371cd1dd237', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-16T12:59:52.966Z', + position: 3, + id: 'ecbc275e-f937-4d00-b035-6225e6f87c90', + viewId: '57ada523-3d83-4391-a8b9-0e918e24a519', + createdAt: '2024-07-16T12:59:46.864Z', + isVisible: true, + size: 209, + fieldMetadataId: '9e3e6ed9-7889-4979-bc15-c7803bf437f1', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-12T09:52:15.605Z', + position: 3, + id: 'ed9f32e7-cd08-4bcf-b78f-838371cd282a', + viewId: '57ada523-3d83-4391-a8b9-0e918e24a519', + createdAt: '2024-07-12T09:52:15.605Z', + isVisible: true, + size: 180, + fieldMetadataId: 'ffa953c4-d8e0-49af-b2ef-f16e238f4687', + }, + }, + ], + }, + }, + }, + { + __typename: 'ViewEdge', + cursor: 'WyI1ODJmMjI0Yy0zYzNmLTQxMjctYjFlZC0yOTcxZDI3ZTU0YTQiXQ==', + node: { + __typename: 'View', + position: 0, + updatedAt: '2024-07-11T10:21:33.304Z', + key: 'INDEX', + id: '582f224c-3c3f-4127-b1ed-2971d27e54a4', + objectMetadataId: '9c293c05-f461-456a-b5a2-2710b5b30447', + createdAt: '2024-07-11T10:21:33.304Z', + icon: 'IconTargetArrow', + isCompact: false, + name: 'All Opportunities', + type: 'table', + kanbanFieldMetadataId: '', + viewSorts: { + __typename: 'ViewSortConnection', + edges: [], + }, + viewFilters: { + __typename: 'ViewFilterConnection', + edges: [], + }, + viewFields: { + __typename: 'ViewFieldConnection', + edges: [ + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 2, + id: '0f0cacad-7f1d-4667-a0e8-466cddad3e65', + viewId: '582f224c-3c3f-4127-b1ed-2971d27e54a4', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: 'c4e1b90f-bf9a-4a04-b67a-0f88263d8706', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 1, + id: '19d0d674-9825-492d-bbd0-c1de494201dc', + viewId: '582f224c-3c3f-4127-b1ed-2971d27e54a4', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: '37593700-f3ac-43a2-9ce2-1b811fa3fbfc', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 5, + id: '77d6a102-7b8e-40c0-9d53-33e9a8d0df0f', + viewId: '582f224c-3c3f-4127-b1ed-2971d27e54a4', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: '031bc747-1787-4e46-9320-562a8b75f3ff', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 4, + id: '8d1da76d-4056-4675-b2e5-907021c1b482', + viewId: '582f224c-3c3f-4127-b1ed-2971d27e54a4', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: '6e073ac2-034c-43ab-b0c6-206b1dd1174b', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 3, + id: 'a5556adc-e4a0-4f71-aee3-2ff2a4e53b31', + viewId: '582f224c-3c3f-4127-b1ed-2971d27e54a4', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: '2cc0fa2b-dbea-4fd0-b7f5-11fa54cd0242', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 0, + id: 'fa8cdb32-24f0-483d-a9f6-bc92f2704452', + viewId: '582f224c-3c3f-4127-b1ed-2971d27e54a4', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: '4ee7183a-f1f6-42a6-94e5-79f741357760', + }, + }, + ], + }, + }, + }, + { + __typename: 'ViewEdge', + cursor: 'WyI2NTM3M2UxZS0xNmU1LTRlNWYtOWJjMS1jMDlkOTAxNTZmMjciXQ==', + node: { + __typename: 'View', + position: null, + updatedAt: '2024-07-11T15:41:08.076Z', + key: null, + id: '65373e1e-16e5-4e5f-9bc1-c09d90156f27', + objectMetadataId: 'b8115dc1-5304-4d22-b300-0b4efda42ebc', + createdAt: '2024-07-11T15:41:08.076Z', + icon: 'IconBuildingSkyscraper', + isCompact: false, + name: 'All Companies L', + type: 'kanban', + kanbanFieldMetadataId: '4ba829d2-c34a-40d0-9ae6-a65d11d2ff5a', + viewSorts: { + __typename: 'ViewSortConnection', + edges: [], + }, + viewFilters: { + __typename: 'ViewFilterConnection', + edges: [], + }, + viewFields: { + __typename: 'ViewFieldConnection', + edges: [ + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T15:41:09.141Z', + position: 5, + id: '00bf00d5-f257-4ed0-9a80-ce6d7fa2eace', + viewId: '65373e1e-16e5-4e5f-9bc1-c09d90156f27', + createdAt: '2024-07-11T15:41:09.141Z', + isVisible: true, + size: 170, + fieldMetadataId: 'f50611a0-d4b2-49a3-8110-1ca1282ad9c2', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T15:41:09.082Z', + position: 4, + id: '08ccb08d-d279-4738-bdc0-32a0f9b01390', + viewId: '65373e1e-16e5-4e5f-9bc1-c09d90156f27', + createdAt: '2024-07-11T15:41:09.082Z', + isVisible: true, + size: 150, + fieldMetadataId: '2334adb8-a0c5-408e-a449-6730f010aff1', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T15:41:09.115Z', + position: 2, + id: '478c93ae-1dcc-4d79-b821-b53431348abe', + viewId: '65373e1e-16e5-4e5f-9bc1-c09d90156f27', + createdAt: '2024-07-11T15:41:09.115Z', + isVisible: true, + size: 150, + fieldMetadataId: 'be572271-de80-4d55-ae25-6141ec48e1a7', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T15:41:09.083Z', + position: 7, + id: '4b28e7c9-f97b-4e86-80bf-ca7a1cc49f64', + viewId: '65373e1e-16e5-4e5f-9bc1-c09d90156f27', + createdAt: '2024-07-11T15:41:09.083Z', + isVisible: true, + size: 180, + fieldMetadataId: '4ba829d2-c34a-40d0-9ae6-a65d11d2ff5a', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T15:41:09.076Z', + position: 3, + id: '6402a5db-dc6f-433c-9de3-af19a6d71a28', + viewId: '65373e1e-16e5-4e5f-9bc1-c09d90156f27', + createdAt: '2024-07-11T15:41:09.076Z', + isVisible: true, + size: 150, + fieldMetadataId: '04f98129-3433-43f6-a5fa-5ede5314fafd', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T15:41:09.141Z', + position: 1, + id: '97938fb7-d3a2-42a1-8c04-7ff59d18e41c', + viewId: '65373e1e-16e5-4e5f-9bc1-c09d90156f27', + createdAt: '2024-07-11T15:41:09.141Z', + isVisible: true, + size: 100, + fieldMetadataId: '7b76bf52-04ff-4624-9dd5-26ef59be0d88', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T15:41:09.129Z', + position: 0, + id: 'c7429772-5214-49ee-9d96-c4c9ea929888', + viewId: '65373e1e-16e5-4e5f-9bc1-c09d90156f27', + createdAt: '2024-07-11T15:41:09.129Z', + isVisible: true, + size: 180, + fieldMetadataId: '716b202a-7f2f-4d7a-a78a-666db003d94f', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T15:41:09.083Z', + position: 6, + id: 'ec211171-6676-40d2-acc2-5fa13f11ed00', + viewId: '65373e1e-16e5-4e5f-9bc1-c09d90156f27', + createdAt: '2024-07-11T15:41:09.083Z', + isVisible: true, + size: 170, + fieldMetadataId: '479e7d9f-cd8a-4064-b009-65cb89a16c36', + }, + }, + ], + }, + }, + }, + { + __typename: 'ViewEdge', + cursor: 'WyJiZWU2NWJjNC05YmNiLTQ5YTgtOGVhNS0xYmQ5MjQxYjA5YzMiXQ==', + node: { + __typename: 'View', + position: 0, + updatedAt: '2024-07-11T10:21:33.304Z', + key: 'INDEX', + id: 'bee65bc4-9bcb-49a8-8ea5-1bd9241b09c3', + objectMetadataId: '48824ee2-367d-481f-b80b-ca1eeb85c4ab', + createdAt: '2024-07-11T10:21:33.304Z', + icon: 'IconUser', + isCompact: false, + name: 'All People', + type: 'table', + kanbanFieldMetadataId: '', + viewSorts: { + __typename: 'ViewSortConnection', + edges: [], + }, + viewFilters: { + __typename: 'ViewFilterConnection', + edges: [], + }, + viewFields: { + __typename: 'ViewFieldConnection', + edges: [ + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 3, + id: '2dc48490-3ee8-4ade-a979-d5326da33d43', + viewId: 'bee65bc4-9bcb-49a8-8ea5-1bd9241b09c3', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: '34ed07ad-067a-4f5f-bdee-21a37616f96b', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 0, + id: '67af4225-56e0-4ef9-bcfc-4a551d676c2b', + viewId: 'bee65bc4-9bcb-49a8-8ea5-1bd9241b09c3', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 210, + fieldMetadataId: 'c485ed46-3f8a-4ee6-af70-628b9f18ad47', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 5, + id: '796bdd63-cc83-4f8c-b538-9f8e9dfb1937', + viewId: 'bee65bc4-9bcb-49a8-8ea5-1bd9241b09c3', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: '4aadffed-1df4-4732-bb99-559f31a464af', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 7, + id: '80cb1229-5e05-45d4-89da-b2ec850ffb2f', + viewId: 'bee65bc4-9bcb-49a8-8ea5-1bd9241b09c3', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: 'a8298361-b7c8-4b6c-be6c-d33885e00237', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 8, + id: '835b104c-b9fc-4c9f-b659-3dc4bb54d9ef', + viewId: 'bee65bc4-9bcb-49a8-8ea5-1bd9241b09c3', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: '125cbc00-7efb-473d-b0a6-581d3cf868dd', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 6, + id: '8f494c43-6b63-4033-b303-0110698cf19c', + viewId: 'bee65bc4-9bcb-49a8-8ea5-1bd9241b09c3', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: '22566388-8ece-43dc-8205-371e662716d4', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 4, + id: 'b2d72e77-a323-4e2e-acef-598b6da04712', + viewId: 'bee65bc4-9bcb-49a8-8ea5-1bd9241b09c3', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: 'b328512c-ff13-431b-9c94-1018ef0bd53c', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 1, + id: 'c7e1a253-9af8-498a-b579-adab742acf2d', + viewId: 'bee65bc4-9bcb-49a8-8ea5-1bd9241b09c3', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: '2eb50615-376c-45e8-b99b-440a92a912d3', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 2, + id: 'cceae812-2687-49b5-a0c8-eb59956865e8', + viewId: 'bee65bc4-9bcb-49a8-8ea5-1bd9241b09c3', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: 'f34c04f8-ce2f-4c92-8dbc-9166c6e0d49f', + }, + }, + ], + }, + }, + }, + { + __typename: 'ViewEdge', + cursor: 'WyJmZjhlZGQyMi02NjVhLTQ5NWYtODljYy03MGFiOGZkNWMxYTYiXQ==', + node: { + __typename: 'View', + position: 0, + updatedAt: '2024-07-11T10:21:33.304Z', + key: 'INDEX', + id: 'ff8edd22-665a-495f-89cc-70ab8fd5c1a6', + objectMetadataId: 'b8115dc1-5304-4d22-b300-0b4efda42ebc', + createdAt: '2024-07-11T10:21:33.304Z', + icon: 'IconBuildingSkyscraper', + isCompact: false, + name: 'All Companies', + type: 'table', + kanbanFieldMetadataId: '', + viewSorts: { + __typename: 'ViewSortConnection', + edges: [], + }, + viewFilters: { + __typename: 'ViewFilterConnection', + edges: [], + }, + viewFields: { + __typename: 'ViewFieldConnection', + edges: [ + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 3, + id: '1cb6aeed-8011-495f-9371-20bace45814a', + viewId: 'ff8edd22-665a-495f-89cc-70ab8fd5c1a6', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: '04f98129-3433-43f6-a5fa-5ede5314fafd', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 6, + id: '3beb2130-bdc5-48d1-8cd0-22c5d0010ad2', + viewId: 'ff8edd22-665a-495f-89cc-70ab8fd5c1a6', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 170, + fieldMetadataId: '479e7d9f-cd8a-4064-b009-65cb89a16c36', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 4, + id: '5f73729b-9592-473a-8742-8e52b693c780', + viewId: 'ff8edd22-665a-495f-89cc-70ab8fd5c1a6', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: '2334adb8-a0c5-408e-a449-6730f010aff1', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T15:41:03.814Z', + position: 7, + id: '788627cb-0d3a-4659-ab4b-69deabf02f27', + viewId: 'ff8edd22-665a-495f-89cc-70ab8fd5c1a6', + createdAt: '2024-07-11T15:41:03.814Z', + isVisible: true, + size: 180, + fieldMetadataId: '4ba829d2-c34a-40d0-9ae6-a65d11d2ff5a', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 2, + id: 'ac5797a1-2d29-42d2-b9fb-d679a945eec5', + viewId: 'ff8edd22-665a-495f-89cc-70ab8fd5c1a6', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 150, + fieldMetadataId: 'be572271-de80-4d55-ae25-6141ec48e1a7', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 0, + id: 'ae98037e-38f7-4fbf-8ae1-c0b6754c6311', + viewId: 'ff8edd22-665a-495f-89cc-70ab8fd5c1a6', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 180, + fieldMetadataId: '716b202a-7f2f-4d7a-a78a-666db003d94f', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 5, + id: 'b4d9f94e-0c4b-4422-839a-f2ceb293fde1', + viewId: 'ff8edd22-665a-495f-89cc-70ab8fd5c1a6', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 170, + fieldMetadataId: 'f50611a0-d4b2-49a3-8110-1ca1282ad9c2', + }, + }, + { + __typename: 'ViewFieldEdge', + node: { + __typename: 'ViewField', + updatedAt: '2024-07-11T10:21:33.304Z', + position: 1, + id: 'd45b1412-ff6b-41e5-86df-0fb778033bb3', + viewId: 'ff8edd22-665a-495f-89cc-70ab8fd5c1a6', + createdAt: '2024-07-11T10:21:33.304Z', + isVisible: true, + size: 100, + fieldMetadataId: '7b76bf52-04ff-4624-9dd5-26ef59be0d88', + }, + }, + ], + }, + }, + }, + ], +}; + export const mockedViewsData = [ { id: '37a8a866-eb17-4e76-9382-03143a2f6a80', diff --git a/packages/twenty-front/src/utils/getRelayCursorFromRecordId.ts b/packages/twenty-front/src/utils/getRelayCursorFromRecordId.ts new file mode 100644 index 0000000000..60fa31c080 --- /dev/null +++ b/packages/twenty-front/src/utils/getRelayCursorFromRecordId.ts @@ -0,0 +1,3 @@ +export const getRelayCursorFromRecordId = (recordId: string) => { + return btoa(`[1, "${recordId}"]`); +};