Skip to content

Commit

Permalink
New view picker (#4610)
Browse files Browse the repository at this point in the history
* Implement new view picker

* Complete feature

* Fixes according to review
  • Loading branch information
charlesBochet authored Mar 22, 2024
1 parent d876b40 commit 4a493b6
Show file tree
Hide file tree
Showing 61 changed files with 1,215 additions and 421 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
import { useIcons } from '@/ui/display/icon/hooks/useIcons';
import { NavigationDrawerItem } from '@/ui/navigation/navigation-drawer/components/NavigationDrawerItem';
import { GraphQLView } from '@/views/types/GraphQLView';
import { getObjectMetadataItemViews } from '@/views/utils/getObjectMetadataItemViews';

export const ObjectMetadataNavItems = () => {
const { activeObjectMetadataItems } = useObjectMetadataItemForSettings();
const navigate = useNavigate();
const { getIcon } = useIcons();
const currentPath = useLocation().pathname;

const { records } = usePrefetchedData<GraphQLView>(PrefetchKey.AllViews);
const { records: views } = usePrefetchedData<GraphQLView>(
PrefetchKey.AllViews,
);

return (
<>
Expand Down Expand Up @@ -45,9 +48,11 @@ export const ObjectMetadataNavItems = () => {
: -1;
}),
].map((objectMetadataItem) => {
const viewId = records?.find(
(view: any) => view?.objectMetadataId === objectMetadataItem.id,
)?.id;
const objectMetadataViews = getObjectMetadataItemViews(
objectMetadataItem.id,
views,
);
const viewId = objectMetadataViews[0]?.id;

const navigationPath = `/objects/${objectMetadataItem.namePlural}${
viewId ? `?view=${viewId}` : ''
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { onRecordBoardFetchMoreVisibilityChangeComponentState } from '@/object-r
import { recordBoardColumnIdsComponentState } from '@/object-record/record-board/states/recordBoardColumnIdsComponentState';
import { recordBoardFieldDefinitionsComponentState } from '@/object-record/record-board/states/recordBoardFieldDefinitionsComponentState';
import { recordBoardFiltersComponentState } from '@/object-record/record-board/states/recordBoardFiltersComponentState';
import { recordBoardKanbanFieldMetadataNameComponentState } from '@/object-record/record-board/states/recordBoardKanbanFieldMetadataNameComponentState';
import { recordBoardObjectSingularNameComponentState } from '@/object-record/record-board/states/recordBoardObjectSingularNameComponentState';
import { recordBoardRecordIdsByColumnIdComponentFamilyState } from '@/object-record/record-board/states/recordBoardRecordIdsByColumnIdComponentFamilyState';
import { recordBoardSortsComponentState } from '@/object-record/record-board/states/recordBoardSortsComponentState';
Expand All @@ -32,6 +33,10 @@ export const useRecordBoardStates = (recordBoardId?: string) => {
recordBoardObjectSingularNameComponentState,
scopeId,
),
kanbanFieldMetadataNameState: extractComponentState(
recordBoardKanbanFieldMetadataNameComponentState,
scopeId,
),
isFetchingRecordState: extractComponentState(
isRecordBoardFetchingRecordsComponentState,
scopeId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const useSetRecordBoardRecordIds = (recordBoardId?: string) => {
recordIdsByColumnIdFamilyState,
columnsFamilySelector,
columnIdsState,
kanbanFieldMetadataNameState,
} = useRecordBoardStates(recordBoardId);

const setRecordIds = useRecoilCallback(
Expand All @@ -26,8 +27,18 @@ export const useSetRecordBoardRecordIds = (recordBoardId?: string) => {
.getLoadable(recordIdsByColumnIdFamilyState(columnId))
.getValue();

const kanbanFieldMetadataName = snapshot
.getLoadable(kanbanFieldMetadataNameState)
.getValue();

if (!kanbanFieldMetadataName) {
return;
}

const columnRecordIds = records
.filter((record) => record.stage === column?.value)
.filter(
(record) => record[kanbanFieldMetadataName] === column?.value,
)
.sort(sortRecordsByPosition)
.map((record) => record.id);

Expand All @@ -36,7 +47,12 @@ export const useSetRecordBoardRecordIds = (recordBoardId?: string) => {
}
});
},
[columnsFamilySelector, columnIdsState, recordIdsByColumnIdFamilyState],
[
columnIdsState,
columnsFamilySelector,
recordIdsByColumnIdFamilyState,
kanbanFieldMetadataNameState,
],
);

return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,24 @@ export const useRecordBoard = (recordBoardId?: string) => {
selectedRecordIdsSelector,
isCompactModeActiveState,
onFetchMoreVisibilityChangeState,
kanbanFieldMetadataNameState,
} = useRecordBoardStates(recordBoardId);

const { setColumns } = useSetRecordBoardColumns(recordBoardId);
const { setRecordIds } = useSetRecordBoardRecordIds(recordBoardId);
const setFieldDefinitions = useSetRecoilState(fieldDefinitionsState);
const setObjectSingularName = useSetRecoilState(objectSingularNameState);
const setKanbanFieldMetadataName = useSetRecoilState(
kanbanFieldMetadataNameState,
);

return {
scopeId,
setColumns,
setRecordIds,
setFieldDefinitions,
setObjectSingularName,
setKanbanFieldMetadataName,
selectedRecordIdsSelector,
isCompactModeActiveState,
onFetchMoreVisibilityChangeState,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';

export const recordBoardKanbanFieldMetadataNameComponentState =
createComponentState<string | undefined>({
key: 'recordBoardKanbanFieldMetadataNameComponentState',
defaultValue: undefined,
});
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import { useRecordBoard } from '@/object-record/record-board/hooks/useRecordBoar
import { useRecordBoardSelection } from '@/object-record/record-board/hooks/useRecordBoardSelection';
import { useLoadRecordIndexBoard } from '@/object-record/record-index/hooks/useLoadRecordIndexBoard';
import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState';
import { recordIndexKanbanFieldMetadataIdState } from '@/object-record/record-index/states/recordIndexKanbanFieldMetadataIdState';
import { computeRecordBoardColumnDefinitionsFromObjectMetadata } from '@/object-record/utils/computeRecordBoardColumnDefinitionsFromObjectMetadata';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { isDefined } from '~/utils/isDefined';

type RecordIndexBoardContainerEffectProps = {
objectNameSingular: string;
Expand All @@ -31,6 +34,7 @@ export const RecordIndexBoardContainerEffect = ({
selectedRecordIdsSelector,
setFieldDefinitions,
onFetchMoreVisibilityChangeState,
setKanbanFieldMetadataName,
} = useRecordBoard(recordBoardId);

const { fetchMoreRecords, loading } = useLoadRecordIndexBoard({
Expand All @@ -43,6 +47,10 @@ export const RecordIndexBoardContainerEffect = ({
onFetchMoreVisibilityChangeState,
);

const recordIndexKanbanFieldMetadataId = useRecoilValue(
recordIndexKanbanFieldMetadataIdState,
);

useEffect(() => {
setOnFetchMoreVisibilityChange(() => () => {
if (!loading) {
Expand All @@ -67,13 +75,15 @@ export const RecordIndexBoardContainerEffect = ({
setColumns(
computeRecordBoardColumnDefinitionsFromObjectMetadata(
objectMetadataItem,
recordIndexKanbanFieldMetadataId ?? '',
navigateToSelectSettings,
),
);
}, [
navigateToSelectSettings,
objectMetadataItem,
objectNameSingular,
recordIndexKanbanFieldMetadataId,
setColumns,
]);

Expand All @@ -85,6 +95,24 @@ export const RecordIndexBoardContainerEffect = ({
setFieldDefinitions(recordIndexFieldDefinitions);
}, [objectMetadataItem, setFieldDefinitions, recordIndexFieldDefinitions]);

useEffect(() => {
if (isDefined(recordIndexKanbanFieldMetadataId)) {
const kanbanFieldMetadataName = objectMetadataItem?.fields.find(
(field) =>
field.type === FieldMetadataType.Select &&
field.id === recordIndexKanbanFieldMetadataId,
)?.name;

if (isDefined(kanbanFieldMetadataName)) {
setKanbanFieldMetadataName(kanbanFieldMetadataName);
}
}
}, [
objectMetadataItem,
recordIndexKanbanFieldMetadataId,
setKanbanFieldMetadataName,
]);

const selectedRecordIds = useRecoilValue(selectedRecordIdsSelector());

const { setActionBarEntries, setContextMenuEntries } = useRecordActionBar({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import { RecordIndexTableContainer } from '@/object-record/record-index/componen
import { RecordIndexTableContainerEffect } from '@/object-record/record-index/components/RecordIndexTableContainerEffect';
import { RecordIndexViewBarEffect } from '@/object-record/record-index/components/RecordIndexViewBarEffect';
import { RecordIndexOptionsDropdown } from '@/object-record/record-index/options/components/RecordIndexOptionsDropdown';
import { RECORD_INDEX_OPTIONS_DROPDOWN_ID } from '@/object-record/record-index/options/constants/RecordIndexOptionsDropdownId';
import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState';
import { recordIndexFiltersState } from '@/object-record/record-index/states/recordIndexFiltersState';
import { recordIndexIsCompactModeActiveState } from '@/object-record/record-index/states/recordIndexIsCompactModeActiveState';
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 { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable';
Expand Down Expand Up @@ -65,6 +65,9 @@ export const RecordIndexContainer = ({
const setRecordIndexIsCompactModeActive = useSetRecoilState(
recordIndexIsCompactModeActiveState,
);
const setRecordIndexViewKanbanFieldMetadataIdState = useSetRecoilState(
recordIndexKanbanFieldMetadataIdState,
);

const { setTableFilters, setTableSorts, setTableColumns } = useRecordTable({
recordTableId: recordIndexId,
Expand Down Expand Up @@ -129,9 +132,11 @@ export const RecordIndexContainer = ({
mapViewSortsToSorts(view.viewSorts, sortDefinitions),
);
setRecordIndexViewType(view.type);
setRecordIndexViewKanbanFieldMetadataIdState(
view.kanbanFieldMetadataId,
);
setRecordIndexIsCompactModeActive(view.isCompact);
}}
optionsDropdownScopeId={RECORD_INDEX_OPTIONS_DROPDOWN_ID}
/>
<RecordIndexViewBarEffect
objectNamePlural={objectNamePlural}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { RecordIndexOptionsDropdownContent } from '@/object-record/record-index/
import { RECORD_INDEX_OPTIONS_DROPDOWN_ID } from '@/object-record/record-index/options/constants/RecordIndexOptionsDropdownId';
import { TableOptionsHotkeyScope } from '@/object-record/record-table/types/TableOptionsHotkeyScope';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { useViewBarEditMode } from '@/views/hooks/useViewBarEditMode';
import { ViewType } from '@/views/types/ViewType';

type RecordIndexOptionsDropdownProps = {
Expand All @@ -17,8 +16,6 @@ export const RecordIndexOptionsDropdown = ({
objectNameSingular,
viewType,
}: RecordIndexOptionsDropdownProps) => {
const { setViewEditMode } = useViewBarEditMode(recordIndexId);

return (
<Dropdown
dropdownId={RECORD_INDEX_OPTIONS_DROPDOWN_ID}
Expand All @@ -32,7 +29,6 @@ export const RecordIndexOptionsDropdown = ({
recordIndexId={recordIndexId}
/>
}
onClickOutside={() => setViewEditMode('none')}
/>
);
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { useRef, useState } from 'react';
import { useState } from 'react';
import { Key } from 'ts-key-enum';
import { v4 } from 'uuid';

import { RECORD_INDEX_OPTIONS_DROPDOWN_ID } from '@/object-record/record-index/options/constants/RecordIndexOptionsDropdownId';
import { useRecordIndexOptionsForBoard } from '@/object-record/record-index/options/hooks/useRecordIndexOptionsForBoard';
Expand All @@ -14,7 +13,6 @@ import {
IconTag,
} from '@/ui/display/icon';
import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenuHeader';
import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
Expand All @@ -23,8 +21,6 @@ import { MenuItemToggle } from '@/ui/navigation/menu-item/components/MenuItemTog
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { ViewFieldsVisibilityDropdownSection } from '@/views/components/ViewFieldsVisibilityDropdownSection';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { useHandleViews } from '@/views/hooks/useHandleViews';
import { useViewBarEditMode } from '@/views/hooks/useViewBarEditMode';
import { ViewType } from '@/views/types/ViewType';

type RecordIndexOptionsMenu = 'fields';
Expand All @@ -40,9 +36,6 @@ export const RecordIndexOptionsDropdownContent = ({
recordIndexId,
objectNameSingular,
}: RecordIndexOptionsDropdownContentProps) => {
const { updateCurrentView, createEmptyView, selectView } =
useHandleViews(recordIndexId);
const { viewEditMode, setViewEditMode } = useViewBarEditMode(recordIndexId);
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();

const { closeDropdown } = useDropdown(RECORD_INDEX_OPTIONS_DROPDOWN_ID);
Expand All @@ -53,8 +46,6 @@ export const RecordIndexOptionsDropdownContent = ({

const resetMenu = () => setCurrentMenu(undefined);

const viewEditInputRef = useRef<HTMLInputElement>(null);

const handleSelectMenu = (option: RecordIndexOptionsMenu) => {
setCurrentMenu(option);
};
Expand All @@ -67,25 +58,6 @@ export const RecordIndexOptionsDropdownContent = ({
TableOptionsHotkeyScope.Dropdown,
);

useScopedHotkeys(
Key.Enter,
async () => {
const name = viewEditInputRef.current?.value;
if (viewEditMode === 'create') {
const id = v4();
await createEmptyView(id, name ?? '');
selectView(id);
} else {
updateCurrentView({ name });
}

resetMenu();
setViewEditMode('none');
closeDropdown();
},
TableOptionsHotkeyScope.Dropdown,
);

const {
handleColumnVisibilityChange,
handleReorderColumns,
Expand Down Expand Up @@ -128,37 +100,18 @@ export const RecordIndexOptionsDropdownContent = ({
return (
<>
{!currentMenu && (
<>
<DropdownMenuInput
ref={viewEditInputRef}
autoFocus={viewEditMode !== 'none'}
placeholder={
viewEditMode === 'create'
? 'New view'
: viewEditMode === 'edit'
? 'View name'
: ''
}
defaultValue={
viewEditMode === 'create'
? ''
: currentViewWithCombinedFiltersAndSorts?.name
}
<DropdownMenuItemsContainer>
<MenuItem
onClick={() => handleSelectMenu('fields')}
LeftIcon={IconTag}
text="Fields"
/>
<DropdownMenuSeparator />
<DropdownMenuItemsContainer>
<MenuItem
onClick={() => handleSelectMenu('fields')}
LeftIcon={IconTag}
text="Fields"
/>
<MenuItem
onClick={() => openRecordSpreadsheetImport()}
LeftIcon={IconFileImport}
text="Import"
/>
</DropdownMenuItemsContainer>
</>
<MenuItem
onClick={() => openRecordSpreadsheetImport()}
LeftIcon={IconFileImport}
text="Import"
/>
</DropdownMenuItemsContainer>
)}
{currentMenu === 'fields' && (
<>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { createState } from '@/ui/utilities/state/utils/createState';

export const recordIndexKanbanFieldMetadataIdState = createState<string | null>(
{
key: 'recordIndexKanbanFieldMetadataIdState',
defaultValue: null,
},
);
Loading

0 comments on commit 4a493b6

Please sign in to comment.