New view picker (#4610)

* Implement new view picker

* Complete feature

* Fixes according to review
This commit is contained in:
Charles Bochet
2024-03-22 15:04:17 +01:00
committed by GitHub
parent d876b40056
commit 4a493b6ecf
61 changed files with 1216 additions and 422 deletions

View File

@ -0,0 +1,46 @@
import { useCallback } from 'react';
import { useSetRecoilState } from 'recoil';
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
import { VIEW_PICKER_KANBAN_FIELD_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerKanbanFieldDropdownId';
import { VIEW_PICKER_VIEW_TYPE_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerViewTypeDropdownId';
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
import { useViewPickerStates } from '@/views/view-picker/hooks/useViewPickerStates';
export const useCloseAndResetViewPicker = () => {
const { setViewPickerMode } = useViewPickerMode();
const { viewPickerIsPersistingState } = useViewPickerStates();
const setViewPickerIsPersisting = useSetRecoilState(
viewPickerIsPersistingState,
);
const { closeDropdown: closeViewPickerDropdown } = useDropdown(
VIEW_PICKER_DROPDOWN_ID,
);
const { closeDropdown: closeKanbanFieldDropdown } = useDropdown(
VIEW_PICKER_KANBAN_FIELD_DROPDOWN_ID,
);
const { closeDropdown: closeTypeDropdown } = useDropdown(
VIEW_PICKER_VIEW_TYPE_DROPDOWN_ID,
);
const closeAndResetViewPicker = useCallback(() => {
setViewPickerIsPersisting(false);
setViewPickerMode('list');
closeKanbanFieldDropdown();
closeTypeDropdown();
closeViewPickerDropdown();
}, [
closeKanbanFieldDropdown,
closeTypeDropdown,
closeViewPickerDropdown,
setViewPickerIsPersisting,
setViewPickerMode,
]);
return { closeAndResetViewPicker };
};

View File

@ -0,0 +1,34 @@
import { useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
import { useRecoilValue } from 'recoil';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { useViewStates } from '@/views/hooks/internal/useViewStates';
import { FieldMetadataType } from '~/generated-metadata/graphql';
export const useGetAvailableFieldsForKanban = () => {
const { viewObjectMetadataIdState } = useViewStates();
const viewObjectMetadataId = useRecoilValue(viewObjectMetadataIdState);
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const objectMetadataItem = objectMetadataItems.find(
(objectMetadata) => objectMetadata.id === viewObjectMetadataId,
);
const availableFieldsForKanban =
objectMetadataItem?.fields.filter(
(field) => field.type === FieldMetadataType.Select,
) ?? [];
const navigate = useNavigate();
const navigateToSelectSettings = useCallback(() => {
navigate(`/settings/objects/${objectMetadataItem?.namePlural}`);
}, [navigate, objectMetadataItem?.namePlural]);
return {
availableFieldsForKanban,
navigateToSelectSettings,
};
};

View File

@ -0,0 +1,15 @@
import { useRecoilState } from 'recoil';
import { useViewPickerStates } from '@/views/view-picker/hooks/useViewPickerStates';
export const useViewPickerMode = (viewBarComponentId?: string) => {
const { viewPickerModeState } = useViewPickerStates(viewBarComponentId);
const [viewPickerMode, setViewPickerMode] =
useRecoilState(viewPickerModeState);
return {
viewPickerMode,
setViewPickerMode,
};
};

View File

@ -0,0 +1,125 @@
import { useRecoilCallback } from 'recoil';
import { v4 } from 'uuid';
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
import { useHandleViews } from '@/views/hooks/useHandleViews';
import { useCloseAndResetViewPicker } from '@/views/view-picker/hooks/useCloseAndResetViewPicker';
import { useViewPickerStates } from '@/views/view-picker/hooks/useViewPickerStates';
export const useViewPickerPersistView = () => {
const {
viewPickerInputNameState,
viewPickerSelectedIconState,
viewPickerIsPersistingState,
viewPickerReferenceViewIdState,
viewPickerKanbanFieldMetadataIdState,
viewPickerTypeState,
} = useViewPickerStates();
const { createView, selectView, removeView, updateView } = useHandleViews();
const { viewsOnCurrentObject } = useGetCurrentView();
const { closeAndResetViewPicker } = useCloseAndResetViewPicker();
const handleCreate = useRecoilCallback(
({ snapshot, set }) =>
async () => {
const name = getSnapshotValue(snapshot, viewPickerInputNameState);
const iconKey = getSnapshotValue(snapshot, viewPickerSelectedIconState);
const type = getSnapshotValue(snapshot, viewPickerTypeState);
const kanbanFieldMetadataId = getSnapshotValue(
snapshot,
viewPickerKanbanFieldMetadataIdState,
);
const id = v4();
set(viewPickerIsPersistingState, true);
await createView({
id,
name,
icon: iconKey,
type,
kanbanFieldMetadataId,
});
closeAndResetViewPicker();
selectView(id);
},
[
closeAndResetViewPicker,
createView,
selectView,
viewPickerInputNameState,
viewPickerIsPersistingState,
viewPickerKanbanFieldMetadataIdState,
viewPickerSelectedIconState,
viewPickerTypeState,
],
);
const handleDelete = useRecoilCallback(
({ set, snapshot }) =>
async () => {
set(viewPickerIsPersistingState, true);
const viewPickerReferenceViewId = getSnapshotValue(
snapshot,
viewPickerReferenceViewIdState,
);
selectView(
viewsOnCurrentObject.filter(
(view) => view.id !== viewPickerReferenceViewId,
)[0].id,
);
await removeView(viewPickerReferenceViewId);
closeAndResetViewPicker();
},
[
closeAndResetViewPicker,
removeView,
selectView,
viewPickerIsPersistingState,
viewPickerReferenceViewIdState,
viewsOnCurrentObject,
],
);
const handleUpdate = useRecoilCallback(
({ set, snapshot }) =>
async () => {
set(viewPickerIsPersistingState, true);
const viewPickerReferenceViewId = getSnapshotValue(
snapshot,
viewPickerReferenceViewIdState,
);
const viewPickerInputName = getSnapshotValue(
snapshot,
viewPickerInputNameState,
);
const viewPickerSelectedIcon = getSnapshotValue(
snapshot,
viewPickerSelectedIconState,
);
await updateView({
id: viewPickerReferenceViewId,
name: viewPickerInputName,
icon: viewPickerSelectedIcon,
});
selectView(viewPickerReferenceViewId);
closeAndResetViewPicker();
},
[
viewPickerIsPersistingState,
viewPickerReferenceViewIdState,
viewPickerInputNameState,
viewPickerSelectedIconState,
updateView,
selectView,
closeAndResetViewPicker,
],
);
return { handleCreate, handleDelete, handleUpdate };
};

View File

@ -0,0 +1,50 @@
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
import { viewPickerInputNameComponentState } from '@/views/view-picker/states/viewPickerInputNameComponentState';
import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState';
import { viewPickerKanbanFieldMetadataIdComponentState } from '@/views/view-picker/states/viewPickerKanbanFieldMetadataIdComponentState';
import { viewPickerModeComponentState } from '@/views/view-picker/states/viewPickerModeComponentState';
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
import { viewPickerSelectedIconComponentState } from '@/views/view-picker/states/viewPickerSelectedIconComponentState';
import { viewPickerTypeComponentState } from '@/views/view-picker/states/viewPickerTypeComponentState';
import { ViewScopeInternalContext } from '../../scopes/scope-internal-context/ViewScopeInternalContext';
export const useViewPickerStates = (viewComponentId?: string) => {
const componentId = useAvailableScopeIdOrThrow(
ViewScopeInternalContext,
viewComponentId,
);
return {
componentId,
viewPickerModeState: extractComponentState(
viewPickerModeComponentState,
componentId,
),
viewPickerInputNameState: extractComponentState(
viewPickerInputNameComponentState,
componentId,
),
viewPickerSelectedIconState: extractComponentState(
viewPickerSelectedIconComponentState,
componentId,
),
viewPickerKanbanFieldMetadataIdState: extractComponentState(
viewPickerKanbanFieldMetadataIdComponentState,
componentId,
),
viewPickerReferenceViewIdState: extractComponentState(
viewPickerReferenceViewIdComponentState,
componentId,
),
viewPickerIsPersistingState: extractComponentState(
viewPickerIsPersistingComponentState,
componentId,
),
viewPickerTypeState: extractComponentState(
viewPickerTypeComponentState,
componentId,
),
};
};