Load empty board if view type is kanban (#3605)

* Load empty board if view type is kanban

* Fix tests

* Revert
This commit is contained in:
Charles Bochet
2024-01-24 16:17:47 +01:00
committed by GitHub
parent c811206c47
commit ccbf773fd4
21 changed files with 210 additions and 124 deletions

View File

@ -13,7 +13,6 @@ import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailab
import { useSetRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useSetRecoilScopedStateV2'; import { useSetRecoilScopedStateV2 } from '@/ui/utilities/recoil-scope/hooks/useSetRecoilScopedStateV2';
import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates'; import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates';
import { useViewBar } from '@/views/hooks/useViewBar'; import { useViewBar } from '@/views/hooks/useViewBar';
import { ViewType } from '@/views/types/ViewType';
import { mapViewFieldsToBoardFieldDefinitions } from '@/views/utils/mapViewFieldsToBoardFieldDefinitions'; import { mapViewFieldsToBoardFieldDefinitions } from '@/views/utils/mapViewFieldsToBoardFieldDefinitions';
type HooksCompanyBoardEffectProps = { type HooksCompanyBoardEffectProps = {
@ -30,7 +29,6 @@ export const HooksCompanyBoardEffect = ({
setAvailableSortDefinitions, setAvailableSortDefinitions,
setAvailableFieldDefinitions, setAvailableFieldDefinitions,
setViewObjectMetadataId, setViewObjectMetadataId,
setViewType,
} = useViewBar({ viewBarId }); } = useViewBar({ viewBarId });
const { objectMetadataItem } = useObjectMetadataItem({ const { objectMetadataItem } = useObjectMetadataItem({
@ -75,8 +73,7 @@ export const HooksCompanyBoardEffect = ({
return; return;
} }
setViewObjectMetadataId?.(objectMetadataItem.id); setViewObjectMetadataId?.(objectMetadataItem.id);
setViewType?.(ViewType.Kanban); }, [objectMetadataItem, setViewObjectMetadataId]);
}, [objectMetadataItem, setViewObjectMetadataId, setViewType]);
const { const {
currentViewFieldsState, currentViewFieldsState,

View File

@ -1,19 +1,19 @@
import { useState } from 'react';
import styled from '@emotion/styled'; import styled from '@emotion/styled';
import { useSpreadsheetCompanyImport } from '@/companies/hooks/useSpreadsheetCompanyImport'; import { useSpreadsheetCompanyImport } from '@/companies/hooks/useSpreadsheetCompanyImport';
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata'; import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural'; import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
import { RecordUpdateHookParams } from '@/object-record/field/contexts/FieldContext'; import { RecordIndexTableContainer } from '@/object-record/record-index/components/RecordIndexTableContainer';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { RecordIndexViewInitEffect } from '@/object-record/record-index/components/RecordIndexViewInitEffect';
import { RecordTableEffect } from '@/object-record/record-index/components/RecordTableEffect';
import { RecordTableWithWrappers } from '@/object-record/record-table/components/RecordTableWithWrappers';
import { TableOptionsDropdownId } from '@/object-record/record-table/constants/TableOptionsDropdownId'; import { TableOptionsDropdownId } from '@/object-record/record-table/constants/TableOptionsDropdownId';
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
import { TableOptionsDropdown } from '@/object-record/record-table/options/components/TableOptionsDropdown'; import { TableOptionsDropdown } from '@/object-record/record-table/options/components/TableOptionsDropdown';
import { useSpreadsheetPersonImport } from '@/people/hooks/useSpreadsheetPersonImport'; import { useSpreadsheetPersonImport } from '@/people/hooks/useSpreadsheetPersonImport';
import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider'; import { SpreadsheetImportProvider } from '@/spreadsheet-import/provider/components/SpreadsheetImportProvider';
import { ViewBar } from '@/views/components/ViewBar'; import { ViewBar } from '@/views/components/ViewBar';
import { ViewType } from '@/views/types/ViewType';
import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions'; import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions';
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters'; import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts'; import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts';
@ -26,15 +26,21 @@ const StyledContainer = styled.div`
padding-left: ${({ theme }) => theme.table.horizontalCellPadding}; padding-left: ${({ theme }) => theme.table.horizontalCellPadding};
`; `;
export const RecordIndexContainer = ({ type RecordIndexContainerProps = {
recordTableId, recordIndexId: string;
objectNamePlural,
createRecord,
}: {
recordTableId: string;
objectNamePlural: string; objectNamePlural: string;
createRecord: () => void; createRecord: () => Promise<void>;
}) => { };
export const RecordIndexContainer = ({
createRecord,
recordIndexId,
objectNamePlural,
}: RecordIndexContainerProps) => {
const [recordIndexViewType, setRecordIndexViewType] = useState<
ViewType | undefined
>(undefined);
const { objectNameSingular } = useObjectNameSingularFromPlural({ const { objectNameSingular } = useObjectNameSingularFromPlural({
objectNamePlural, objectNamePlural,
}); });
@ -46,26 +52,13 @@ export const RecordIndexContainer = ({
const { columnDefinitions } = const { columnDefinitions } =
useColumnDefinitionsFromFieldMetadata(objectMetadataItem); useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
const { updateOneRecord } = useUpdateOneRecord({
objectNameSingular,
});
const { openPersonSpreadsheetImport } = useSpreadsheetPersonImport(); const { openPersonSpreadsheetImport } = useSpreadsheetPersonImport();
const { openCompanySpreadsheetImport } = useSpreadsheetCompanyImport(); const { openCompanySpreadsheetImport } = useSpreadsheetCompanyImport();
const viewBarId = objectNamePlural ?? '';
const { setTableFilters, setTableSorts, setTableColumns } = useRecordTable({ const { setTableFilters, setTableSorts, setTableColumns } = useRecordTable({
recordTableId, recordTableId: recordIndexId,
}); });
const updateEntity = ({ variables }: RecordUpdateHookParams) => {
updateOneRecord?.({
idToUpdate: variables.where.id as string,
updateOneRecordInput: variables.updateOneRecordInput,
});
};
const handleImport = () => { const handleImport = () => {
const openImport = const openImport =
objectNamePlural === 'companies' objectNamePlural === 'companies'
@ -78,12 +71,12 @@ export const RecordIndexContainer = ({
<StyledContainer> <StyledContainer>
<SpreadsheetImportProvider> <SpreadsheetImportProvider>
<ViewBar <ViewBar
viewBarId={viewBarId} viewBarId={recordIndexId}
optionsDropdownButton={ optionsDropdownButton={
<TableOptionsDropdown <TableOptionsDropdown
recordTableId={recordTableId} recordTableId={recordIndexId}
onImport={ onImport={
['companies', 'people'].includes(recordTableId) ['companies', 'people'].includes(recordIndexId)
? handleImport ? handleImport
: undefined : undefined
} }
@ -101,19 +94,22 @@ export const RecordIndexContainer = ({
onViewSortsChange={(viewSorts) => { onViewSortsChange={(viewSorts) => {
setTableSorts(mapViewSortsToSorts(viewSorts)); setTableSorts(mapViewSortsToSorts(viewSorts));
}} }}
onViewTypeChange={(viewType: ViewType) => {
setRecordIndexViewType(viewType);
}}
/> />
</SpreadsheetImportProvider> </SpreadsheetImportProvider>
<RecordTableEffect {recordIndexViewType === ViewType.Table && (
<RecordIndexTableContainer
recordTableId={recordIndexId}
viewBarId={recordIndexId}
objectNamePlural={objectNamePlural}
createRecord={createRecord}
/>
)}
<RecordIndexViewInitEffect
objectNamePlural={objectNamePlural} objectNamePlural={objectNamePlural}
recordTableId={recordTableId} viewBarId={recordIndexId}
viewBarId={viewBarId}
/>
<RecordTableWithWrappers
recordTableId={recordTableId}
objectNamePlural={objectNamePlural}
viewBarId={viewBarId}
updateRecordMutation={updateEntity}
createRecord={createRecord}
/> />
</StyledContainer> </StyledContainer>
); );

View File

@ -0,0 +1,55 @@
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
import { RecordUpdateHookParams } from '@/object-record/field/contexts/FieldContext';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { RecordTableEffect } from '@/object-record/record-index/components/RecordTableEffect';
import { RecordTableActionBar } from '@/object-record/record-table/action-bar/components/RecordTableActionBar';
import { RecordTableWithWrappers } from '@/object-record/record-table/components/RecordTableWithWrappers';
import { RecordTableContextMenu } from '@/object-record/record-table/context-menu/components/RecordTableContextMenu';
type RecordIndexTableContainerProps = {
recordTableId: string;
viewBarId: string;
objectNamePlural: string;
createRecord: () => Promise<void>;
};
export const RecordIndexTableContainer = ({
recordTableId,
viewBarId,
objectNamePlural,
createRecord,
}: RecordIndexTableContainerProps) => {
const { objectNameSingular } = useObjectNameSingularFromPlural({
objectNamePlural,
});
const { updateOneRecord } = useUpdateOneRecord({
objectNameSingular,
});
const updateEntity = ({ variables }: RecordUpdateHookParams) => {
updateOneRecord?.({
idToUpdate: variables.where.id as string,
updateOneRecordInput: variables.updateOneRecordInput,
});
};
return (
<>
<RecordTableEffect
objectNamePlural={objectNamePlural}
recordTableId={recordTableId}
viewBarId={viewBarId}
/>
<RecordTableWithWrappers
recordTableId={recordTableId}
objectNamePlural={objectNamePlural}
viewBarId={viewBarId}
updateRecordMutation={updateEntity}
createRecord={createRecord}
/>
<RecordTableActionBar recordTableId={recordTableId} />
<RecordTableContextMenu recordTableId={recordTableId} />
</>
);
};

View File

@ -0,0 +1,53 @@
import { useEffect } from 'react';
import { useColumnDefinitionsFromFieldMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromFieldMetadata';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
import { useViewBar } from '@/views/hooks/useViewBar';
export const RecordIndexViewInitEffect = ({
objectNamePlural,
viewBarId,
}: {
objectNamePlural: string;
viewBarId: string;
}) => {
const { objectNameSingular } = useObjectNameSingularFromPlural({
objectNamePlural,
});
const { objectMetadataItem } = useObjectMetadataItem({
objectNameSingular,
});
const { columnDefinitions, filterDefinitions, sortDefinitions } =
useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
const {
setViewObjectMetadataId,
setAvailableSortDefinitions,
setAvailableFilterDefinitions,
setAvailableFieldDefinitions,
} = useViewBar({ viewBarId });
useEffect(() => {
if (!objectMetadataItem) {
return;
}
setViewObjectMetadataId?.(objectMetadataItem.id);
setAvailableSortDefinitions?.(sortDefinitions);
setAvailableFilterDefinitions?.(filterDefinitions);
setAvailableFieldDefinitions?.(columnDefinitions);
}, [
setViewObjectMetadataId,
objectMetadataItem,
setAvailableSortDefinitions,
sortDefinitions,
setAvailableFilterDefinitions,
filterDefinitions,
setAvailableFieldDefinitions,
columnDefinitions,
]);
return <></>;
};

View File

@ -7,7 +7,6 @@ import { useRecordTableContextMenuEntries } from '@/object-record/hooks/useRecor
import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns'; import { filterAvailableTableColumns } from '@/object-record/utils/filterAvailableTableColumns';
import { useViewBar } from '@/views/hooks/useViewBar'; import { useViewBar } from '@/views/hooks/useViewBar';
import { ViewType } from '@/views/types/ViewType';
export const RecordTableEffect = ({ export const RecordTableEffect = ({
objectNamePlural, objectNamePlural,
@ -39,14 +38,9 @@ export const RecordTableEffect = ({
const { columnDefinitions, filterDefinitions, sortDefinitions } = const { columnDefinitions, filterDefinitions, sortDefinitions } =
useColumnDefinitionsFromFieldMetadata(objectMetadataItem); useColumnDefinitionsFromFieldMetadata(objectMetadataItem);
const { const { setEntityCountInCurrentView } = useViewBar({
setAvailableSortDefinitions, viewBarId,
setAvailableFilterDefinitions, });
setAvailableFieldDefinitions,
setViewType,
setViewObjectMetadataId,
setEntityCountInCurrentView,
} = useViewBar({ viewBarId });
useEffect(() => { useEffect(() => {
if (basePathToShowPage && labelIdentifierFieldMetadata) { if (basePathToShowPage && labelIdentifierFieldMetadata) {
@ -63,28 +57,13 @@ export const RecordTableEffect = ({
]); ]);
useEffect(() => { useEffect(() => {
if (!objectMetadataItem) {
return;
}
setViewObjectMetadataId?.(objectMetadataItem.id);
setViewType?.(ViewType.Table);
setAvailableSortDefinitions?.(sortDefinitions);
setAvailableFilterDefinitions?.(filterDefinitions);
setAvailableFieldDefinitions?.(columnDefinitions);
const availableTableColumns = columnDefinitions.filter( const availableTableColumns = columnDefinitions.filter(
filterAvailableTableColumns, filterAvailableTableColumns,
); );
setAvailableTableColumns(availableTableColumns); setAvailableTableColumns(availableTableColumns);
}, [ }, [
setViewObjectMetadataId,
setViewType,
columnDefinitions, columnDefinitions,
setAvailableSortDefinitions,
setAvailableFilterDefinitions,
setAvailableFieldDefinitions,
objectMetadataItem, objectMetadataItem,
sortDefinitions, sortDefinitions,
filterDefinitions, filterDefinitions,

View File

@ -70,7 +70,7 @@ type RecordTableWithWrappersProps = {
recordTableId: string; recordTableId: string;
viewBarId: string; viewBarId: string;
updateRecordMutation: (params: any) => void; updateRecordMutation: (params: any) => void;
createRecord: () => void; createRecord: () => Promise<void>;
}; };
export const RecordTableWithWrappers = ({ export const RecordTableWithWrappers = ({

View File

@ -36,7 +36,7 @@ export const SignInBackgroundMockContainer = () => {
objectNamePlural={objectNamePlural} objectNamePlural={objectNamePlural}
recordTableId={recordTableId} recordTableId={recordTableId}
viewBarId={viewBarId} viewBarId={viewBarId}
createRecord={() => {}} createRecord={async () => {}}
updateRecordMutation={() => {}} updateRecordMutation={() => {}}
/> />
</StyledContainer> </StyledContainer>

View File

@ -12,7 +12,6 @@ import {
} from '@/sign-in-background-mock/constants/signInBackgroundMockDefinitions'; } from '@/sign-in-background-mock/constants/signInBackgroundMockDefinitions';
import { signInBackgroundMockViewFields } from '@/sign-in-background-mock/constants/signInBackgroundMockViewFields'; import { signInBackgroundMockViewFields } from '@/sign-in-background-mock/constants/signInBackgroundMockViewFields';
import { useViewBar } from '@/views/hooks/useViewBar'; import { useViewBar } from '@/views/hooks/useViewBar';
import { ViewType } from '@/views/types/ViewType';
import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions'; import { mapViewFieldsToColumnDefinitions } from '@/views/utils/mapViewFieldsToColumnDefinitions';
type SignInBackgroundMockContainerEffectProps = { type SignInBackgroundMockContainerEffectProps = {
@ -48,14 +47,12 @@ export const SignInBackgroundMockContainerEffect = ({
setAvailableSortDefinitions, setAvailableSortDefinitions,
setAvailableFilterDefinitions, setAvailableFilterDefinitions,
setAvailableFieldDefinitions, setAvailableFieldDefinitions,
setViewType,
setViewObjectMetadataId, setViewObjectMetadataId,
setEntityCountInCurrentView, setEntityCountInCurrentView,
} = useViewBar({ viewBarId: viewId }); } = useViewBar({ viewBarId: viewId });
useEffect(() => { useEffect(() => {
setViewObjectMetadataId?.(objectMetadataItem.id); setViewObjectMetadataId?.(objectMetadataItem.id);
setViewType?.(ViewType.Table);
setAvailableSortDefinitions?.(signInBackgroundMockSortDefinitions); setAvailableSortDefinitions?.(signInBackgroundMockSortDefinitions);
setAvailableFilterDefinitions?.(signInBackgroundMockFilterDefinitions); setAvailableFilterDefinitions?.(signInBackgroundMockFilterDefinitions);
@ -75,7 +72,6 @@ export const SignInBackgroundMockContainerEffect = ({
); );
}, [ }, [
setViewObjectMetadataId, setViewObjectMetadataId,
setViewType,
setAvailableSortDefinitions, setAvailableSortDefinitions,
setAvailableFilterDefinitions, setAvailableFilterDefinitions,
setAvailableFieldDefinitions, setAvailableFieldDefinitions,

View File

@ -15,6 +15,7 @@ import { ViewScope } from '@/views/scopes/ViewScope';
import { ViewField } from '@/views/types/ViewField'; import { ViewField } from '@/views/types/ViewField';
import { ViewFilter } from '@/views/types/ViewFilter'; import { ViewFilter } from '@/views/types/ViewFilter';
import { ViewSort } from '@/views/types/ViewSort'; import { ViewSort } from '@/views/types/ViewSort';
import { ViewType } from '@/views/types/ViewType';
import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope'; import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope';
@ -30,6 +31,7 @@ export type ViewBarProps = {
onViewSortsChange?: (sorts: ViewSort[]) => void | Promise<void>; onViewSortsChange?: (sorts: ViewSort[]) => void | Promise<void>;
onViewFiltersChange?: (filters: ViewFilter[]) => void | Promise<void>; onViewFiltersChange?: (filters: ViewFilter[]) => void | Promise<void>;
onViewFieldsChange?: (fields: ViewField[]) => void | Promise<void>; onViewFieldsChange?: (fields: ViewField[]) => void | Promise<void>;
onViewTypeChange?: (viewType: ViewType) => void | Promise<void>;
}; };
export const ViewBar = ({ export const ViewBar = ({
@ -40,12 +42,13 @@ export const ViewBar = ({
onViewFieldsChange, onViewFieldsChange,
onViewFiltersChange, onViewFiltersChange,
onViewSortsChange, onViewSortsChange,
onViewTypeChange,
}: ViewBarProps) => { }: ViewBarProps) => {
const { openDropdown: openOptionsDropdownButton } = useDropdown( const { openDropdown: openOptionsDropdownButton } = useDropdown(
optionsDropdownScopeId, optionsDropdownScopeId,
); );
const { upsertViewSort, upsertViewFilter } = useViewBar({ const { upsertViewSort, upsertViewFilter } = useViewBar({
viewBarId: viewBarId, viewBarId,
}); });
const { objectNamePlural } = useParams(); const { objectNamePlural } = useParams();
@ -58,6 +61,7 @@ export const ViewBar = ({
onViewFieldsChange={onViewFieldsChange} onViewFieldsChange={onViewFieldsChange}
onViewFiltersChange={onViewFiltersChange} onViewFiltersChange={onViewFiltersChange}
onViewSortsChange={onViewSortsChange} onViewSortsChange={onViewSortsChange}
onViewTypeChange={onViewTypeChange}
> >
<ViewBarEffect /> <ViewBarEffect />
<ViewBarFilterEffect <ViewBarFilterEffect

View File

@ -22,15 +22,10 @@ export const ViewBarEffect = () => {
const [searchParams] = useSearchParams(); const [searchParams] = useSearchParams();
const currentViewIdFromUrl = searchParams.get('view'); const currentViewIdFromUrl = searchParams.get('view');
const { const { viewObjectMetadataIdState, viewsState, currentViewIdState } =
viewTypeState, useViewScopedStates();
viewObjectMetadataIdState,
viewsState,
currentViewIdState,
} = useViewScopedStates();
const [views, setViews] = useRecoilState(viewsState); const [views, setViews] = useRecoilState(viewsState);
const viewType = useRecoilValue(viewTypeState);
const viewObjectMetadataId = useRecoilValue(viewObjectMetadataIdState); const viewObjectMetadataId = useRecoilValue(viewObjectMetadataIdState);
const setCurrentViewId = useSetRecoilState(currentViewIdState); const setCurrentViewId = useSetRecoilState(currentViewIdState);
@ -38,7 +33,6 @@ export const ViewBarEffect = () => {
skip: !viewObjectMetadataId, skip: !viewObjectMetadataId,
objectNameSingular: CoreObjectNameSingular.View, objectNameSingular: CoreObjectNameSingular.View,
filter: { filter: {
type: { eq: viewType },
objectMetadataId: { eq: viewObjectMetadataId }, objectMetadataId: { eq: viewObjectMetadataId },
}, },
useRecordsWithoutConnection: true, useRecordsWithoutConnection: true,
@ -80,10 +74,10 @@ export const ViewBarEffect = () => {
]); ]);
useEffect(() => { useEffect(() => {
if (!currentViewIdFromUrl) return; if (!currentViewIdFromUrl || !newViews.length) return;
loadView(currentViewIdFromUrl); loadView(currentViewIdFromUrl);
}, [currentViewIdFromUrl, loadView]); }, [currentViewIdFromUrl, loadView, newViews]);
return <></>; return <></>;
}; };

View File

@ -22,8 +22,6 @@ import { ViewScope } from '@/views/scopes/ViewScope';
import { entityCountInCurrentViewScopedState } from '@/views/states/entityCountInCurrentViewScopedState'; import { entityCountInCurrentViewScopedState } from '@/views/states/entityCountInCurrentViewScopedState';
import { viewEditModeScopedState } from '@/views/states/viewEditModeScopedState'; import { viewEditModeScopedState } from '@/views/states/viewEditModeScopedState';
import { viewObjectMetadataIdScopeState } from '@/views/states/viewObjectMetadataIdScopeState'; import { viewObjectMetadataIdScopeState } from '@/views/states/viewObjectMetadataIdScopeState';
import { viewTypeScopedState } from '@/views/states/viewTypeScopedState';
import { ViewType } from '@/views/types/ViewType';
jest.mock('@/object-metadata/hooks/useMapFieldMetadataToGraphQLQuery', () => { jest.mock('@/object-metadata/hooks/useMapFieldMetadataToGraphQLQuery', () => {
return { return {
@ -225,25 +223,6 @@ describe('useViewBar', () => {
expect(result.current.metadataId).toBe('newId'); expect(result.current.metadataId).toBe('newId');
}); });
it('should update view type', async () => {
const { result } = renderHook(
() => ({
viewBar: useViewBar({ viewBarId }),
ViewType: useRecoilState(
getScopedStateDeprecated(viewTypeScopedState, viewBarId),
)[0],
}),
renderHookConfig,
);
expect(result.current.ViewType).toBe('table');
await act(async () => {
result.current.viewBar.setViewType(ViewType.Kanban);
});
expect(result.current.ViewType).toBe('kanban');
});
it('should update count in current view', async () => { it('should update count in current view', async () => {
const { result } = renderHook( const { result } = renderHook(
() => ({ () => ({

View File

@ -40,6 +40,7 @@ export const useViewScopedStates = (args?: { viewScopeId?: string }) => {
onViewFieldsChangeState, onViewFieldsChangeState,
onViewFiltersChangeState, onViewFiltersChangeState,
onViewSortsChangeState, onViewSortsChangeState,
onViewTypeChangeState,
savedViewFieldsByKeySelector, savedViewFieldsByKeySelector,
savedViewFieldsState, savedViewFieldsState,
savedViewFiltersByKeySelector, savedViewFiltersByKeySelector,
@ -72,6 +73,7 @@ export const useViewScopedStates = (args?: { viewScopeId?: string }) => {
onViewFieldsChangeState, onViewFieldsChangeState,
onViewFiltersChangeState, onViewFiltersChangeState,
onViewSortsChangeState, onViewSortsChangeState,
onViewTypeChangeState,
savedViewFieldsByKeySelector, savedViewFieldsByKeySelector,
savedViewFieldsState, savedViewFieldsState,
savedViewFiltersByKeySelector, savedViewFiltersByKeySelector,

View File

@ -43,7 +43,6 @@ export const useViewBar = (props?: UseViewProps) => {
availableSortDefinitionsState, availableSortDefinitionsState,
entityCountInCurrentViewState, entityCountInCurrentViewState,
viewObjectMetadataIdState, viewObjectMetadataIdState,
viewTypeState,
} = useViewScopedStates({ } = useViewScopedStates({
viewScopeId: scopeId, viewScopeId: scopeId,
}); });
@ -79,7 +78,6 @@ export const useViewBar = (props?: UseViewProps) => {
const setViewEditMode = useSetRecoilState(viewEditModeState); const setViewEditMode = useSetRecoilState(viewEditModeState);
const setViewObjectMetadataId = useSetRecoilState(viewObjectMetadataIdState); const setViewObjectMetadataId = useSetRecoilState(viewObjectMetadataIdState);
const setViewType = useSetRecoilState(viewTypeState);
const [_, setSearchParams] = useSearchParams(); const [_, setSearchParams] = useSearchParams();
@ -237,16 +235,18 @@ export const useViewBar = (props?: UseViewProps) => {
(viewId: string) => { (viewId: string) => {
setCurrentViewId?.(viewId); setCurrentViewId?.(viewId);
const { currentView } = getViewScopedStateValuesFromSnapshot({ const { currentView, onViewTypeChange } =
snapshot, getViewScopedStateValuesFromSnapshot({
viewScopeId: scopeId, snapshot,
viewId, viewScopeId: scopeId,
}); viewId,
});
if (!currentView) { if (!currentView) {
return; return;
} }
onViewTypeChange?.(currentView.type);
loadViewFields(currentView.viewFields, viewId); loadViewFields(currentView.viewFields, viewId);
loadViewFilters(currentView.viewFilters, viewId); loadViewFilters(currentView.viewFilters, viewId);
loadViewSorts(currentView.viewSorts, viewId); loadViewSorts(currentView.viewSorts, viewId);
@ -418,7 +418,6 @@ export const useViewBar = (props?: UseViewProps) => {
setViewEditMode, setViewEditMode,
setViewObjectMetadataId, setViewObjectMetadataId,
setViewType,
setEntityCountInCurrentView, setEntityCountInCurrentView,
setAvailableFieldDefinitions, setAvailableFieldDefinitions,

View File

@ -2,6 +2,7 @@ import { ReactNode } from 'react';
import { ViewFilter } from '@/views/types/ViewFilter'; import { ViewFilter } from '@/views/types/ViewFilter';
import { ViewSort } from '@/views/types/ViewSort'; import { ViewSort } from '@/views/types/ViewSort';
import { ViewType } from '@/views/types/ViewType';
import { ViewField } from '../types/ViewField'; import { ViewField } from '../types/ViewField';
@ -14,6 +15,7 @@ type ViewScopeProps = {
onViewSortsChange?: (sorts: ViewSort[]) => void | Promise<void>; onViewSortsChange?: (sorts: ViewSort[]) => void | Promise<void>;
onViewFiltersChange?: (filters: ViewFilter[]) => void | Promise<void>; onViewFiltersChange?: (filters: ViewFilter[]) => void | Promise<void>;
onViewFieldsChange?: (fields: ViewField[]) => void | Promise<void>; onViewFieldsChange?: (fields: ViewField[]) => void | Promise<void>;
onViewTypeChange?: (viewType: ViewType) => void | Promise<void>;
}; };
export const ViewScope = ({ export const ViewScope = ({
@ -22,6 +24,7 @@ export const ViewScope = ({
onViewSortsChange, onViewSortsChange,
onViewFiltersChange, onViewFiltersChange,
onViewFieldsChange, onViewFieldsChange,
onViewTypeChange,
}: ViewScopeProps) => { }: ViewScopeProps) => {
return ( return (
<ViewScopeInternalContext.Provider <ViewScopeInternalContext.Provider
@ -34,6 +37,7 @@ export const ViewScope = ({
onViewSortsChange={onViewSortsChange} onViewSortsChange={onViewSortsChange}
onViewFiltersChange={onViewFiltersChange} onViewFiltersChange={onViewFiltersChange}
onViewFieldsChange={onViewFieldsChange} onViewFieldsChange={onViewFieldsChange}
onViewTypeChange={onViewTypeChange}
/> />
{children} {children}
</ViewScopeInternalContext.Provider> </ViewScopeInternalContext.Provider>

View File

@ -5,40 +5,48 @@ import { useViewScopedStates } from '@/views/hooks/internal/useViewScopedStates'
import { ViewField } from '@/views/types/ViewField'; import { ViewField } from '@/views/types/ViewField';
import { ViewFilter } from '@/views/types/ViewFilter'; import { ViewFilter } from '@/views/types/ViewFilter';
import { ViewSort } from '@/views/types/ViewSort'; import { ViewSort } from '@/views/types/ViewSort';
import { ViewType } from '@/views/types/ViewType';
type ViewScopeInitEffectProps = { type ViewScopeInitEffectProps = {
viewScopeId: string; viewScopeId: string;
onViewSortsChange?: (sorts: ViewSort[]) => void | Promise<void>; onViewSortsChange?: (sorts: ViewSort[]) => void | Promise<void>;
onViewFiltersChange?: (filters: ViewFilter[]) => void | Promise<void>; onViewFiltersChange?: (filters: ViewFilter[]) => void | Promise<void>;
onViewFieldsChange?: (fields: ViewField[]) => void | Promise<void>; onViewFieldsChange?: (fields: ViewField[]) => void | Promise<void>;
onViewTypeChange?: (viewType: ViewType) => void | Promise<void>;
}; };
export const ViewScopeInitEffect = ({ export const ViewScopeInitEffect = ({
onViewSortsChange, onViewSortsChange,
onViewFiltersChange, onViewFiltersChange,
onViewFieldsChange, onViewFieldsChange,
onViewTypeChange,
}: ViewScopeInitEffectProps) => { }: ViewScopeInitEffectProps) => {
const { const {
onViewFieldsChangeState, onViewFieldsChangeState,
onViewFiltersChangeState, onViewFiltersChangeState,
onViewSortsChangeState, onViewSortsChangeState,
onViewTypeChangeState,
} = useViewScopedStates(); } = useViewScopedStates();
const setOnViewSortsChange = useSetRecoilState(onViewSortsChangeState); const setOnViewSortsChange = useSetRecoilState(onViewSortsChangeState);
const setOnViewFiltersChange = useSetRecoilState(onViewFiltersChangeState); const setOnViewFiltersChange = useSetRecoilState(onViewFiltersChangeState);
const setOnViewFieldsChange = useSetRecoilState(onViewFieldsChangeState); const setOnViewFieldsChange = useSetRecoilState(onViewFieldsChangeState);
const setOnViewTypeChange = useSetRecoilState(onViewTypeChangeState);
useEffect(() => { useEffect(() => {
setOnViewSortsChange(() => onViewSortsChange); setOnViewSortsChange(() => onViewSortsChange);
setOnViewFiltersChange(() => onViewFiltersChange); setOnViewFiltersChange(() => onViewFiltersChange);
setOnViewFieldsChange(() => onViewFieldsChange); setOnViewFieldsChange(() => onViewFieldsChange);
setOnViewTypeChange(() => onViewTypeChange);
}, [ }, [
onViewFieldsChange, onViewFieldsChange,
onViewFiltersChange, onViewFiltersChange,
onViewSortsChange, onViewSortsChange,
onViewTypeChange,
setOnViewFieldsChange, setOnViewFieldsChange,
setOnViewFiltersChange, setOnViewFiltersChange,
setOnViewSortsChange, setOnViewSortsChange,
setOnViewTypeChange,
]); ]);
return <></>; return <></>;

View File

@ -0,0 +1,9 @@
import { createStateScopeMap } from '@/ui/utilities/recoil-scope/utils/createStateScopeMap';
import { ViewType } from '@/views/types/ViewType';
export const onViewTypeChangeScopedState = createStateScopeMap<
((viewType: ViewType) => void | Promise<void>) | undefined
>({
key: 'onViewTypeChangeScopedState',
defaultValue: undefined,
});

View File

@ -1,10 +1,12 @@
import { ViewField } from '@/views/types/ViewField'; import { ViewField } from '@/views/types/ViewField';
import { ViewFilter } from '@/views/types/ViewFilter'; import { ViewFilter } from '@/views/types/ViewFilter';
import { ViewSort } from '@/views/types/ViewSort'; import { ViewSort } from '@/views/types/ViewSort';
import { ViewType } from '@/views/types/ViewType';
export type GraphQLView = { export type GraphQLView = {
id: string; id: string;
name: string; name: string;
type: ViewType;
objectMetadataId: string; objectMetadataId: string;
viewFields: ViewField[]; viewFields: ViewField[];
viewFilters: ViewFilter[]; viewFilters: ViewFilter[];

View File

@ -1,5 +1,8 @@
import { ViewType } from '@/views/types/ViewType';
export type View = { export type View = {
id: string; id: string;
name: string; name: string;
objectMetadataId: string; objectMetadataId: string;
type: ViewType;
}; };

View File

@ -41,6 +41,7 @@ export const getViewScopedStateValuesFromSnapshot = ({
onViewFieldsChangeState, onViewFieldsChangeState,
onViewFiltersChangeState, onViewFiltersChangeState,
onViewSortsChangeState, onViewSortsChangeState,
onViewTypeChangeState,
savedViewFieldsByKeySelector, savedViewFieldsByKeySelector,
savedViewFieldsState, savedViewFieldsState,
savedViewFiltersByKeySelector, savedViewFiltersByKeySelector,
@ -85,6 +86,7 @@ export const getViewScopedStateValuesFromSnapshot = ({
onViewFieldsChange: getSnapshotValue(snapshot, onViewFieldsChangeState), onViewFieldsChange: getSnapshotValue(snapshot, onViewFieldsChangeState),
onViewFiltersChange: getSnapshotValue(snapshot, onViewFiltersChangeState), onViewFiltersChange: getSnapshotValue(snapshot, onViewFiltersChangeState),
onViewSortsChange: getSnapshotValue(snapshot, onViewSortsChangeState), onViewSortsChange: getSnapshotValue(snapshot, onViewSortsChangeState),
onViewTypeChange: getSnapshotValue(snapshot, onViewTypeChangeState),
savedViewFieldsByKey: getSnapshotValue( savedViewFieldsByKey: getSnapshotValue(
snapshot, snapshot,
savedViewFieldsByKeySelector, savedViewFieldsByKeySelector,

View File

@ -3,6 +3,7 @@ import { getScopedSelectorDeprecated } from '@/ui/utilities/recoil-scope/utils/g
import { getScopedStateDeprecated } from '@/ui/utilities/recoil-scope/utils/getScopedStateDeprecated'; import { getScopedStateDeprecated } from '@/ui/utilities/recoil-scope/utils/getScopedStateDeprecated';
import { currentViewIdScopedState } from '@/views/states/currentViewIdScopedState'; import { currentViewIdScopedState } from '@/views/states/currentViewIdScopedState';
import { isPersistingViewScopedState } from '@/views/states/isPersistingViewScopedState'; import { isPersistingViewScopedState } from '@/views/states/isPersistingViewScopedState';
import { onViewTypeChangeScopedState } from '@/views/states/onViewTypeChangeScopedState';
import { currentViewScopedSelector } from '@/views/states/selectors/currentViewScopedSelector'; import { currentViewScopedSelector } from '@/views/states/selectors/currentViewScopedSelector';
import { availableFieldDefinitionsScopedState } from '../../states/availableFieldDefinitionsScopedState'; import { availableFieldDefinitionsScopedState } from '../../states/availableFieldDefinitionsScopedState';
@ -164,6 +165,11 @@ export const getViewScopedStates = ({
viewScopeId, viewScopeId,
); );
const onViewTypeChangeState = getScopedStateDeprecated(
onViewTypeChangeScopedState,
viewScopeId,
);
const currentViewIdState = getScopedStateDeprecated( const currentViewIdState = getScopedStateDeprecated(
currentViewIdScopedState, currentViewIdScopedState,
viewScopeId, viewScopeId,
@ -207,5 +213,6 @@ export const getViewScopedStates = ({
onViewSortsChangeState, onViewSortsChangeState,
onViewFiltersChangeState, onViewFiltersChangeState,
onViewFieldsChangeState, onViewFieldsChangeState,
onViewTypeChangeState,
}; };
}; };

View File

@ -9,8 +9,6 @@ import { useObjectMetadataItemForSettings } from '@/object-metadata/hooks/useObj
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural'; import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord'; import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { RecordIndexContainer } from '@/object-record/record-index/components/RecordIndexContainer'; import { RecordIndexContainer } from '@/object-record/record-index/components/RecordIndexContainer';
import { RecordTableActionBar } from '@/object-record/record-table/action-bar/components/RecordTableActionBar';
import { RecordTableContextMenu } from '@/object-record/record-table/context-menu/components/RecordTableContextMenu';
import { useSelectedTableCellEditMode } from '@/object-record/record-table/record-table-cell/hooks/useSelectedTableCellEditMode'; import { useSelectedTableCellEditMode } from '@/object-record/record-table/record-table-cell/hooks/useSelectedTableCellEditMode';
import { DEFAULT_CELL_SCOPE } from '@/object-record/record-table/record-table-cell/hooks/useTableCell'; import { DEFAULT_CELL_SCOPE } from '@/object-record/record-table/record-table-cell/hooks/useTableCell';
import { useIcons } from '@/ui/display/icon/hooks/useIcons'; import { useIcons } from '@/ui/display/icon/hooks/useIcons';
@ -21,7 +19,7 @@ import { PageHeader } from '@/ui/layout/page/PageHeader';
import { PageHotkeysEffect } from '@/ui/layout/page/PageHotkeysEffect'; import { PageHotkeysEffect } from '@/ui/layout/page/PageHotkeysEffect';
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
const StyledTableContainer = styled.div` const StyledIndexContainer = styled.div`
display: flex; display: flex;
height: 100%; height: 100%;
width: 100%; width: 100%;
@ -59,12 +57,13 @@ export const RecordIndexPage = () => {
objectNameSingular, objectNameSingular,
}); });
const recordTableId = objectNamePlural ?? ''; const recordIndexId = objectNamePlural ?? '';
const setHotkeyScope = useSetHotkeyScope();
const { setSelectedTableCellEditMode } = useSelectedTableCellEditMode({ const { setSelectedTableCellEditMode } = useSelectedTableCellEditMode({
scopeId: recordTableId, scopeId: recordIndexId,
}); });
const setHotkeyScope = useSetHotkeyScope();
const handleAddButtonClick = async () => { const handleAddButtonClick = async () => {
await createOneObject?.({}); await createOneObject?.({});
@ -85,15 +84,13 @@ export const RecordIndexPage = () => {
<PageAddButton onClick={handleAddButtonClick} /> <PageAddButton onClick={handleAddButtonClick} />
</PageHeader> </PageHeader>
<PageBody> <PageBody>
<StyledTableContainer> <StyledIndexContainer>
<RecordIndexContainer <RecordIndexContainer
recordTableId={recordTableId} recordIndexId={recordIndexId}
objectNamePlural={objectNamePlural} objectNamePlural={objectNamePlural}
createRecord={handleAddButtonClick} createRecord={handleAddButtonClick}
/> />
</StyledTableContainer> </StyledIndexContainer>
<RecordTableActionBar recordTableId={recordTableId} />
<RecordTableContextMenu recordTableId={recordTableId} />
</PageBody> </PageBody>
</PageContainer> </PageContainer>
); );