refactor: move view recoil states to ui/view-bar folder (#1482)

* refactor: move view recoil states to ui/view-bar folder

Closes #1481

* refactor: rename some view related Recoil states and selectors
This commit is contained in:
Thaïs
2023-09-08 11:26:15 +02:00
committed by GitHub
parent 47151525ce
commit ccb57c91a3
30 changed files with 268 additions and 279 deletions

View File

@ -9,13 +9,13 @@ import {
} from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper'; import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
import { SortType } from '@/ui/view-bar/types/interface'; import { SortType } from '@/ui/view-bar/types/interface';
import type { View } from '@/ui/view-bar/types/View';
import { EntityUpdateMutationContext } from '../contexts/EntityUpdateMutationHookContext'; import { EntityUpdateMutationContext } from '../contexts/EntityUpdateMutationHookContext';
import { useLeaveTableFocus } from '../hooks/useLeaveTableFocus'; import { useLeaveTableFocus } from '../hooks/useLeaveTableFocus';
import { useMapKeyboardToSoftFocus } from '../hooks/useMapKeyboardToSoftFocus'; import { useMapKeyboardToSoftFocus } from '../hooks/useMapKeyboardToSoftFocus';
import { useResetTableRowSelection } from '../hooks/useResetTableRowSelection'; import { useResetTableRowSelection } from '../hooks/useResetTableRowSelection';
import { useSetRowSelectedState } from '../hooks/useSetRowSelectedState'; import { useSetRowSelectedState } from '../hooks/useSetRowSelectedState';
import type { TableView } from '../states/tableViewsState';
import { TableHeader } from '../table-header/components/TableHeader'; import { TableHeader } from '../table-header/components/TableHeader';
import { TableHotkeyScope } from '../types/TableHotkeyScope'; import { TableHotkeyScope } from '../types/TableHotkeyScope';
@ -88,7 +88,7 @@ type OwnProps<SortField> = {
viewName: string; viewName: string;
viewIcon?: React.ReactNode; viewIcon?: React.ReactNode;
availableSorts?: Array<SortType<SortField>>; availableSorts?: Array<SortType<SortField>>;
onViewsChange?: (views: TableView[]) => void; onViewsChange?: (views: View[]) => void;
onViewSubmit?: () => void; onViewSubmit?: () => void;
onImport?: () => void; onImport?: () => void;
updateEntityMutation: any; updateEntityMutation: any;

View File

@ -1,13 +1,12 @@
import { DropdownButton } from '@/ui/dropdown/components/DropdownButton'; import { DropdownButton } from '@/ui/dropdown/components/DropdownButton';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope'; import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import type { View } from '@/ui/view-bar/types/View';
import { type TableView } from '../../states/tableViewsState';
import { TableOptionsDropdownButton } from './TableOptionsDropdownButton'; import { TableOptionsDropdownButton } from './TableOptionsDropdownButton';
import { TableOptionsDropdownContent } from './TableOptionsDropdownContent'; import { TableOptionsDropdownContent } from './TableOptionsDropdownContent';
type TableOptionsDropdownProps = { type TableOptionsDropdownProps = {
onViewsChange?: (views: TableView[]) => void; onViewsChange?: (views: View[]) => void;
onImport?: () => void; onImport?: () => void;
customHotkeyScope: HotkeyScope; customHotkeyScope: HotkeyScope;
}; };

View File

@ -15,28 +15,26 @@ import { tableColumnsScopedState } from '@/ui/table/states/tableColumnsScopedSta
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys'; import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId'; import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { currentViewIdScopedState } from '@/ui/view-bar/states/currentViewIdScopedState';
import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState'; import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState';
import { savedFiltersScopedState } from '@/ui/view-bar/states/savedFiltersScopedState'; import { savedFiltersFamilyState } from '@/ui/view-bar/states/savedFiltersFamilyState';
import { savedSortsScopedState } from '@/ui/view-bar/states/savedSortsScopedState'; import { savedSortsFamilyState } from '@/ui/view-bar/states/savedSortsFamilyState';
import { viewsByIdScopedSelector } from '@/ui/view-bar/states/selectors/viewsByIdScopedSelector';
import { sortsScopedState } from '@/ui/view-bar/states/sortsScopedState'; import { sortsScopedState } from '@/ui/view-bar/states/sortsScopedState';
import { viewEditModeState } from '@/ui/view-bar/states/viewEditModeState';
import { viewsScopedState } from '@/ui/view-bar/states/viewsScopedState';
import type { View } from '@/ui/view-bar/types/View';
import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext'; import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext';
import { savedTableColumnsScopedState } from '../../states/savedTableColumnsScopedState'; import { savedTableColumnsFamilyState } from '../../states/savedTableColumnsFamilyState';
import { hiddenTableColumnsScopedSelector } from '../../states/selectors/hiddenTableColumnsScopedSelector'; import { hiddenTableColumnsScopedSelector } from '../../states/selectors/hiddenTableColumnsScopedSelector';
import { visibleTableColumnsScopedSelector } from '../../states/selectors/visibleTableColumnsScopedSelector'; import { visibleTableColumnsScopedSelector } from '../../states/selectors/visibleTableColumnsScopedSelector';
import {
currentTableViewIdState,
type TableView,
tableViewEditModeState,
tableViewsByIdState,
tableViewsState,
} from '../../states/tableViewsState';
import { TableOptionsHotkeyScope } from '../../types/TableOptionsHotkeyScope'; import { TableOptionsHotkeyScope } from '../../types/TableOptionsHotkeyScope';
import { TableOptionsDropdownColumnVisibility } from './TableOptionsDropdownSection'; import { TableOptionsDropdownColumnVisibility } from './TableOptionsDropdownSection';
type TableOptionsDropdownButtonProps = { type TableOptionsDropdownButtonProps = {
onViewsChange?: (views: TableView[]) => void; onViewsChange?: (views: View[]) => void;
onImport?: () => void; onImport?: () => void;
}; };
@ -58,9 +56,7 @@ export function TableOptionsDropdownContent({
const viewEditInputRef = useRef<HTMLInputElement>(null); const viewEditInputRef = useRef<HTMLInputElement>(null);
const [tableViewEditMode, setTableViewEditMode] = useRecoilState( const [viewEditMode, setViewEditMode] = useRecoilState(viewEditModeState);
tableViewEditModeState,
);
const visibleTableColumns = useRecoilScopedValue( const visibleTableColumns = useRecoilScopedValue(
visibleTableColumnsScopedSelector, visibleTableColumnsScopedSelector,
TableRecoilScopeContext, TableRecoilScopeContext,
@ -69,18 +65,18 @@ export function TableOptionsDropdownContent({
hiddenTableColumnsScopedSelector, hiddenTableColumnsScopedSelector,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const tableViewsById = useRecoilScopedValue( const viewsById = useRecoilScopedValue(
tableViewsByIdState, viewsByIdScopedSelector,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const resetViewEditMode = useCallback(() => { const resetViewEditMode = useCallback(() => {
setTableViewEditMode({ mode: undefined, viewId: undefined }); setViewEditMode({ mode: undefined, viewId: undefined });
if (viewEditInputRef.current) { if (viewEditInputRef.current) {
viewEditInputRef.current.value = ''; viewEditInputRef.current.value = '';
} }
}, [setTableViewEditMode]); }, [setViewEditMode]);
const handleViewNameSubmit = useRecoilCallback( const handleViewNameSubmit = useRecoilCallback(
({ set, snapshot }) => ({ set, snapshot }) =>
@ -89,43 +85,43 @@ export function TableOptionsDropdownContent({
const name = viewEditInputRef.current?.value; const name = viewEditInputRef.current?.value;
if (!tableViewEditMode.mode || !name) { if (!viewEditMode.mode || !name) {
return resetViewEditMode(); return resetViewEditMode();
} }
const views = await snapshot.getPromise(tableViewsState(tableScopeId)); const views = await snapshot.getPromise(viewsScopedState(tableScopeId));
if (tableViewEditMode.mode === 'create') { if (viewEditMode.mode === 'create') {
const viewToCreate = { id: v4(), name }; const viewToCreate = { id: v4(), name };
const nextViews = [...views, viewToCreate]; const nextViews = [...views, viewToCreate];
const currentColumns = await snapshot.getPromise( const currentColumns = await snapshot.getPromise(
tableColumnsScopedState(tableScopeId), tableColumnsScopedState(tableScopeId),
); );
set(savedTableColumnsScopedState(viewToCreate.id), currentColumns); set(savedTableColumnsFamilyState(viewToCreate.id), currentColumns);
const selectedFilters = await snapshot.getPromise( const selectedFilters = await snapshot.getPromise(
filtersScopedState(tableScopeId), filtersScopedState(tableScopeId),
); );
set(savedFiltersScopedState(viewToCreate.id), selectedFilters); set(savedFiltersFamilyState(viewToCreate.id), selectedFilters);
const selectedSorts = await snapshot.getPromise( const selectedSorts = await snapshot.getPromise(
sortsScopedState(tableScopeId), sortsScopedState(tableScopeId),
); );
set(savedSortsScopedState(viewToCreate.id), selectedSorts); set(savedSortsFamilyState(viewToCreate.id), selectedSorts);
set(tableViewsState(tableScopeId), nextViews); set(viewsScopedState(tableScopeId), nextViews);
await Promise.resolve(onViewsChange?.(nextViews)); await Promise.resolve(onViewsChange?.(nextViews));
set(currentTableViewIdState(tableScopeId), viewToCreate.id); set(currentViewIdScopedState(tableScopeId), viewToCreate.id);
} }
if (tableViewEditMode.mode === 'edit') { if (viewEditMode.mode === 'edit') {
const nextViews = views.map((view) => const nextViews = views.map((view) =>
view.id === tableViewEditMode.viewId ? { ...view, name } : view, view.id === viewEditMode.viewId ? { ...view, name } : view,
); );
set(tableViewsState(tableScopeId), nextViews); set(viewsScopedState(tableScopeId), nextViews);
await Promise.resolve(onViewsChange?.(nextViews)); await Promise.resolve(onViewsChange?.(nextViews));
} }
@ -135,8 +131,8 @@ export function TableOptionsDropdownContent({
onViewsChange, onViewsChange,
resetViewEditMode, resetViewEditMode,
tableScopeId, tableScopeId,
tableViewEditMode.mode, viewEditMode.mode,
tableViewEditMode.viewId, viewEditMode.viewId,
], ],
); );
@ -174,16 +170,16 @@ export function TableOptionsDropdownContent({
<StyledDropdownMenu> <StyledDropdownMenu>
{!selectedOption && ( {!selectedOption && (
<> <>
{!!tableViewEditMode.mode ? ( {!!viewEditMode.mode ? (
<DropdownMenuInput <DropdownMenuInput
ref={viewEditInputRef} ref={viewEditInputRef}
autoFocus autoFocus
placeholder={ placeholder={
tableViewEditMode.mode === 'create' ? 'New view' : 'View name' viewEditMode.mode === 'create' ? 'New view' : 'View name'
} }
defaultValue={ defaultValue={
tableViewEditMode.viewId viewEditMode.viewId
? tableViewsById[tableViewEditMode.viewId]?.name ? viewsById[viewEditMode.viewId]?.name
: undefined : undefined
} }
/> />

View File

@ -13,21 +13,19 @@ import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId'; import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { DropdownMenuContainer } from '@/ui/view-bar/components/DropdownMenuContainer'; import { DropdownMenuContainer } from '@/ui/view-bar/components/DropdownMenuContainer';
import { currentViewIdScopedState } from '@/ui/view-bar/states/currentViewIdScopedState';
import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState'; import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState';
import { savedFiltersScopedState } from '@/ui/view-bar/states/savedFiltersScopedState'; import { savedFiltersFamilyState } from '@/ui/view-bar/states/savedFiltersFamilyState';
import { savedSortsScopedState } from '@/ui/view-bar/states/savedSortsScopedState'; import { savedSortsFamilyState } from '@/ui/view-bar/states/savedSortsFamilyState';
import { canPersistFiltersScopedSelector } from '@/ui/view-bar/states/selectors/canPersistFiltersScopedSelector'; import { canPersistFiltersScopedFamilySelector } from '@/ui/view-bar/states/selectors/canPersistFiltersScopedFamilySelector';
import { canPersistSortsScopedSelector } from '@/ui/view-bar/states/selectors/canPersistSortsScopedSelector'; import { canPersistSortsScopedFamilySelector } from '@/ui/view-bar/states/selectors/canPersistSortsScopedFamilySelector';
import { sortsScopedState } from '@/ui/view-bar/states/sortsScopedState'; import { sortsScopedState } from '@/ui/view-bar/states/sortsScopedState';
import { viewEditModeState } from '@/ui/view-bar/states/viewEditModeState';
import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext'; import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext';
import { savedTableColumnsScopedState } from '../../states/savedTableColumnsScopedState'; import { savedTableColumnsFamilyState } from '../../states/savedTableColumnsFamilyState';
import { canPersistTableColumnsScopedSelector } from '../../states/selectors/canPersistTableColumnsScopedSelector'; import { canPersistTableColumnsScopedFamilySelector } from '../../states/selectors/canPersistTableColumnsScopedFamilySelector';
import { tableColumnsScopedState } from '../../states/tableColumnsScopedState'; import { tableColumnsScopedState } from '../../states/tableColumnsScopedState';
import {
currentTableViewIdState,
tableViewEditModeState,
} from '../../states/tableViewsState';
const StyledContainer = styled.div` const StyledContainer = styled.div`
display: inline-flex; display: inline-flex;
@ -48,8 +46,8 @@ export const TableUpdateViewButtonGroup = ({
const tableScopeId = useContextScopeId(TableRecoilScopeContext); const tableScopeId = useContextScopeId(TableRecoilScopeContext);
const currentTableViewId = useRecoilScopedValue( const currentViewId = useRecoilScopedValue(
currentTableViewIdState, currentViewIdScopedState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
@ -58,10 +56,10 @@ export const TableUpdateViewButtonGroup = ({
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const setSavedColumns = useSetRecoilState( const setSavedColumns = useSetRecoilState(
savedTableColumnsScopedState(currentTableViewId), savedTableColumnsFamilyState(currentViewId),
); );
const canPersistColumns = useRecoilValue( const canPersistColumns = useRecoilValue(
canPersistTableColumnsScopedSelector([tableScopeId, currentTableViewId]), canPersistTableColumnsScopedFamilySelector([tableScopeId, currentViewId]),
); );
const filters = useRecoilScopedValue( const filters = useRecoilScopedValue(
@ -69,21 +67,19 @@ export const TableUpdateViewButtonGroup = ({
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const setSavedFilters = useSetRecoilState( const setSavedFilters = useSetRecoilState(
savedFiltersScopedState(currentTableViewId), savedFiltersFamilyState(currentViewId),
); );
const canPersistFilters = useRecoilValue( const canPersistFilters = useRecoilValue(
canPersistFiltersScopedSelector([tableScopeId, currentTableViewId]), canPersistFiltersScopedFamilySelector([tableScopeId, currentViewId]),
); );
const sorts = useRecoilScopedValue(sortsScopedState, TableRecoilScopeContext); const sorts = useRecoilScopedValue(sortsScopedState, TableRecoilScopeContext);
const setSavedSorts = useSetRecoilState( const setSavedSorts = useSetRecoilState(savedSortsFamilyState(currentViewId));
savedSortsScopedState(currentTableViewId),
);
const canPersistSorts = useRecoilValue( const canPersistSorts = useRecoilValue(
canPersistSortsScopedSelector([tableScopeId, currentTableViewId]), canPersistSortsScopedFamilySelector([tableScopeId, currentViewId]),
); );
const setViewEditMode = useSetRecoilState(tableViewEditModeState); const setViewEditMode = useSetRecoilState(viewEditModeState);
const { openDropdownButton: openOptionsDropdownButton } = useDropdownButton({ const { openDropdownButton: openOptionsDropdownButton } = useDropdownButton({
key: 'options', key: 'options',
@ -135,7 +131,7 @@ export const TableUpdateViewButtonGroup = ({
<Button <Button
title="Update view" title="Update view"
disabled={ disabled={
!currentTableViewId || !currentViewId ||
(!canPersistColumns && !canPersistFilters && !canPersistSorts) (!canPersistColumns && !canPersistFilters && !canPersistSorts)
} }
onClick={handleViewSubmit} onClick={handleViewSubmit}

View File

@ -14,29 +14,27 @@ import {
IconTrash, IconTrash,
} from '@/ui/icon'; } from '@/ui/icon';
import { MenuItem } from '@/ui/menu-item/components/MenuItem'; import { MenuItem } from '@/ui/menu-item/components/MenuItem';
import {
currentTableViewIdState,
currentTableViewState,
type TableView,
tableViewEditModeState,
tableViewsState,
} from '@/ui/table/states/tableViewsState';
import { MOBILE_VIEWPORT } from '@/ui/theme/constants/theme'; import { MOBILE_VIEWPORT } from '@/ui/theme/constants/theme';
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId'; import { useContextScopeId } from '@/ui/utilities/recoil-scope/hooks/useContextScopeId';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import DropdownButton from '@/ui/view-bar/components/DropdownButton'; import DropdownButton from '@/ui/view-bar/components/DropdownButton';
import { currentViewIdScopedState } from '@/ui/view-bar/states/currentViewIdScopedState';
import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState'; import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState';
import { savedFiltersScopedState } from '@/ui/view-bar/states/savedFiltersScopedState'; import { savedFiltersFamilyState } from '@/ui/view-bar/states/savedFiltersFamilyState';
import { savedSortsScopedState } from '@/ui/view-bar/states/savedSortsScopedState'; import { savedSortsFamilyState } from '@/ui/view-bar/states/savedSortsFamilyState';
import { currentViewScopedSelector } from '@/ui/view-bar/states/selectors/currentViewScopedSelector';
import { sortsScopedState } from '@/ui/view-bar/states/sortsScopedState'; import { sortsScopedState } from '@/ui/view-bar/states/sortsScopedState';
import { viewEditModeState } from '@/ui/view-bar/states/viewEditModeState';
import { viewsScopedState } from '@/ui/view-bar/states/viewsScopedState';
import type { View } from '@/ui/view-bar/types/View';
import { ViewsHotkeyScope } from '@/ui/view-bar/types/ViewsHotkeyScope';
import { assertNotNull } from '~/utils/assert'; import { assertNotNull } from '~/utils/assert';
import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext'; import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext';
import { savedTableColumnsScopedState } from '../../states/savedTableColumnsScopedState'; import { savedTableColumnsFamilyState } from '../../states/savedTableColumnsFamilyState';
import { tableColumnsScopedState } from '../../states/tableColumnsScopedState'; import { tableColumnsScopedState } from '../../states/tableColumnsScopedState';
import { TableViewsHotkeyScope } from '../../types/TableViewsHotkeyScope';
const StyledBoldDropdownMenuItemsContainer = styled( const StyledBoldDropdownMenuItemsContainer = styled(
StyledDropdownMenuItemsContainer, StyledDropdownMenuItemsContainer,
@ -73,8 +71,8 @@ const StyledViewName = styled.span`
type TableViewsDropdownButtonProps = { type TableViewsDropdownButtonProps = {
defaultViewName: string; defaultViewName: string;
HotkeyScope: TableViewsHotkeyScope; HotkeyScope: ViewsHotkeyScope;
onViewsChange?: (views: TableView[]) => void; onViewsChange?: (views: View[]) => void;
}; };
export const TableViewsDropdownButton = ({ export const TableViewsDropdownButton = ({
@ -91,19 +89,19 @@ export const TableViewsDropdownButton = ({
key: 'options', key: 'options',
}); });
const [, setCurrentTableViewId] = useRecoilScopedState( const [, setCurrentViewId] = useRecoilScopedState(
currentTableViewIdState, currentViewIdScopedState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const currentTableView = useRecoilScopedValue( const currentView = useRecoilScopedValue(
currentTableViewState, currentViewScopedSelector,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const [tableViews, setTableViews] = useRecoilScopedState( const [views, setViews] = useRecoilScopedState(
tableViewsState, viewsScopedState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const setViewEditMode = useSetRecoilState(tableViewEditModeState); const setViewEditMode = useSetRecoilState(viewEditModeState);
const { const {
goBackToPreviousHotkeyScope, goBackToPreviousHotkeyScope,
@ -114,19 +112,19 @@ export const TableViewsDropdownButton = ({
({ set, snapshot }) => ({ set, snapshot }) =>
async (viewId: string) => { async (viewId: string) => {
const savedColumns = await snapshot.getPromise( const savedColumns = await snapshot.getPromise(
savedTableColumnsScopedState(viewId), savedTableColumnsFamilyState(viewId),
); );
const savedFilters = await snapshot.getPromise( const savedFilters = await snapshot.getPromise(
savedFiltersScopedState(viewId), savedFiltersFamilyState(viewId),
); );
const savedSorts = await snapshot.getPromise( const savedSorts = await snapshot.getPromise(
savedSortsScopedState(viewId), savedSortsFamilyState(viewId),
); );
set(tableColumnsScopedState(tableScopeId), savedColumns); set(tableColumnsScopedState(tableScopeId), savedColumns);
set(filtersScopedState(tableScopeId), savedFilters); set(filtersScopedState(tableScopeId), savedFilters);
set(sortsScopedState(tableScopeId), savedSorts); set(sortsScopedState(tableScopeId), savedSorts);
set(currentTableViewIdState(tableScopeId), viewId); set(currentViewIdScopedState(tableScopeId), viewId);
setIsUnfolded(false); setIsUnfolded(false);
}, },
[tableScopeId], [tableScopeId],
@ -152,21 +150,15 @@ export const TableViewsDropdownButton = ({
async (event: MouseEvent<HTMLButtonElement>, viewId: string) => { async (event: MouseEvent<HTMLButtonElement>, viewId: string) => {
event.stopPropagation(); event.stopPropagation();
if (currentTableView?.id === viewId) setCurrentTableViewId(undefined); if (currentView?.id === viewId) setCurrentViewId(undefined);
const nextViews = tableViews.filter((view) => view.id !== viewId); const nextViews = views.filter((view) => view.id !== viewId);
setTableViews(nextViews); setViews(nextViews);
await Promise.resolve(onViewsChange?.(nextViews)); await Promise.resolve(onViewsChange?.(nextViews));
setIsUnfolded(false); setIsUnfolded(false);
}, },
[ [currentView?.id, onViewsChange, setCurrentViewId, setViews, views],
currentTableView?.id,
onViewsChange,
setCurrentTableViewId,
setTableViews,
tableViews,
],
); );
useEffect(() => { useEffect(() => {
@ -186,10 +178,10 @@ export const TableViewsDropdownButton = ({
<> <>
<StyledViewIcon size={theme.icon.size.md} /> <StyledViewIcon size={theme.icon.size.md} />
<StyledViewName> <StyledViewName>
{currentTableView?.name || defaultViewName} {currentView?.name || defaultViewName}
</StyledViewName> </StyledViewName>
<StyledDropdownLabelAdornments> <StyledDropdownLabelAdornments>
· {tableViews.length} <IconChevronDown size={theme.icon.size.sm} /> · {views.length} <IconChevronDown size={theme.icon.size.sm} />
</StyledDropdownLabelAdornments> </StyledDropdownLabelAdornments>
</> </>
} }
@ -201,7 +193,7 @@ export const TableViewsDropdownButton = ({
menuWidth="auto" menuWidth="auto"
> >
<StyledDropdownMenuItemsContainer> <StyledDropdownMenuItemsContainer>
{tableViews.map((view) => ( {views.map((view) => (
<MenuItem <MenuItem
key={view.id} key={view.id}
iconButtons={[ iconButtons={[
@ -210,7 +202,7 @@ export const TableViewsDropdownButton = ({
onClick: (event: MouseEvent<HTMLButtonElement>) => onClick: (event: MouseEvent<HTMLButtonElement>) =>
handleEditViewButtonClick(event, view.id), handleEditViewButtonClick(event, view.id),
}, },
tableViews.length > 1 views.length > 1
? { ? {
Icon: IconTrash, Icon: IconTrash,
onClick: (event: MouseEvent<HTMLButtonElement>) => onClick: (event: MouseEvent<HTMLButtonElement>) =>

View File

@ -4,10 +4,10 @@ import type { ViewFieldMetadata } from '@/ui/editable-field/types/ViewField';
import type { ColumnDefinition } from '../types/ColumnDefinition'; import type { ColumnDefinition } from '../types/ColumnDefinition';
export const savedTableColumnsScopedState = atomFamily< export const savedTableColumnsFamilyState = atomFamily<
ColumnDefinition<ViewFieldMetadata>[], ColumnDefinition<ViewFieldMetadata>[],
string | undefined string | undefined
>({ >({
key: 'savedTableColumnsScopedState', key: 'savedTableColumnsFamilyState',
default: [], default: [],
}); });

View File

@ -2,16 +2,16 @@ import { selectorFamily } from 'recoil';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { savedTableColumnsScopedState } from '../savedTableColumnsScopedState'; import { savedTableColumnsFamilyState } from '../savedTableColumnsFamilyState';
import { tableColumnsScopedState } from '../tableColumnsScopedState'; import { tableColumnsScopedState } from '../tableColumnsScopedState';
export const canPersistTableColumnsScopedSelector = selectorFamily({ export const canPersistTableColumnsScopedFamilySelector = selectorFamily({
key: 'canPersistTableColumnsScopedSelector', key: 'canPersistTableColumnsScopedFamilySelector',
get: get:
([scopeId, viewId]: [string, string | undefined]) => ([scopeId, viewId]: [string, string | undefined]) =>
({ get }) => ({ get }) =>
!isDeeplyEqual( !isDeeplyEqual(
get(savedTableColumnsScopedState(viewId)), get(savedTableColumnsFamilyState(viewId)),
get(tableColumnsScopedState(scopeId)), get(tableColumnsScopedState(scopeId)),
), ),
}); });

View File

@ -3,14 +3,14 @@ import { selectorFamily } from 'recoil';
import type { ViewFieldMetadata } from '@/ui/editable-field/types/ViewField'; import type { ViewFieldMetadata } from '@/ui/editable-field/types/ViewField';
import type { ColumnDefinition } from '../../types/ColumnDefinition'; import type { ColumnDefinition } from '../../types/ColumnDefinition';
import { savedTableColumnsScopedState } from '../savedTableColumnsScopedState'; import { savedTableColumnsFamilyState } from '../savedTableColumnsFamilyState';
export const savedTableColumnsByKeyScopedSelector = selectorFamily({ export const savedTableColumnsByKeyFamilySelector = selectorFamily({
key: 'savedTableColumnsByKeyScopedSelector', key: 'savedTableColumnsByKeyFamilySelector',
get: get:
(viewId: string | undefined) => (viewId: string | undefined) =>
({ get }) => ({ get }) =>
get(savedTableColumnsScopedState(viewId)).reduce< get(savedTableColumnsFamilyState(viewId)).reduce<
Record<string, ColumnDefinition<ViewFieldMetadata>> Record<string, ColumnDefinition<ViewFieldMetadata>>
>((result, column) => ({ ...result, [column.key]: column }), {}), >((result, column) => ({ ...result, [column.key]: column }), {}),
}); });

View File

@ -1,50 +0,0 @@
import { atom, atomFamily, selectorFamily } from 'recoil';
export type TableView = { id: string; name: string };
export const tableViewsState = atomFamily<TableView[], string>({
key: 'tableViewsState',
default: [],
});
export const tableViewsByIdState = selectorFamily<
Record<string, TableView>,
string
>({
key: 'tableViewsByIdState',
get:
(scopeId) =>
({ get }) =>
get(tableViewsState(scopeId)).reduce<Record<string, TableView>>(
(result, view) => ({ ...result, [view.id]: view }),
{},
),
});
export const currentTableViewIdState = atomFamily<string | undefined, string>({
key: 'currentTableViewIdState',
default: undefined,
});
export const currentTableViewState = selectorFamily<
TableView | undefined,
string
>({
key: 'currentTableViewState',
get:
(scopeId) =>
({ get }) => {
const currentViewId = get(currentTableViewIdState(scopeId));
return currentViewId
? get(tableViewsByIdState(scopeId))[currentViewId]
: undefined;
},
});
export const tableViewEditModeState = atom<{
mode: 'create' | 'edit' | undefined;
viewId: string | undefined;
}>({
key: 'tableViewEditModeState',
default: { mode: undefined, viewId: undefined },
});

View File

@ -10,28 +10,26 @@ import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoi
import { FilterDropdownButton } from '@/ui/view-bar/components/FilterDropdownButton'; import { FilterDropdownButton } from '@/ui/view-bar/components/FilterDropdownButton';
import { SortDropdownButton } from '@/ui/view-bar/components/SortDropdownButton'; import { SortDropdownButton } from '@/ui/view-bar/components/SortDropdownButton';
import ViewBarDetails from '@/ui/view-bar/components/ViewBarDetails'; import ViewBarDetails from '@/ui/view-bar/components/ViewBarDetails';
import { canPersistFiltersScopedSelector } from '@/ui/view-bar/states/selectors/canPersistFiltersScopedSelector'; import { currentViewIdScopedState } from '@/ui/view-bar/states/currentViewIdScopedState';
import { canPersistSortsScopedSelector } from '@/ui/view-bar/states/selectors/canPersistSortsScopedSelector'; import { canPersistFiltersScopedFamilySelector } from '@/ui/view-bar/states/selectors/canPersistFiltersScopedFamilySelector';
import { canPersistSortsScopedFamilySelector } from '@/ui/view-bar/states/selectors/canPersistSortsScopedFamilySelector';
import { sortsScopedState } from '@/ui/view-bar/states/sortsScopedState'; import { sortsScopedState } from '@/ui/view-bar/states/sortsScopedState';
import { FiltersHotkeyScope } from '@/ui/view-bar/types/FiltersHotkeyScope'; import { FiltersHotkeyScope } from '@/ui/view-bar/types/FiltersHotkeyScope';
import { SelectedSortType, SortType } from '@/ui/view-bar/types/interface'; import { SelectedSortType, SortType } from '@/ui/view-bar/types/interface';
import type { View } from '@/ui/view-bar/types/View';
import { ViewsHotkeyScope } from '@/ui/view-bar/types/ViewsHotkeyScope';
import { TableOptionsDropdown } from '../../options/components/TableOptionsDropdown'; import { TableOptionsDropdown } from '../../options/components/TableOptionsDropdown';
import { TableUpdateViewButtonGroup } from '../../options/components/TableUpdateViewButtonGroup'; import { TableUpdateViewButtonGroup } from '../../options/components/TableUpdateViewButtonGroup';
import { TableViewsDropdownButton } from '../../options/components/TableViewsDropdownButton'; import { TableViewsDropdownButton } from '../../options/components/TableViewsDropdownButton';
import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext'; import { TableRecoilScopeContext } from '../../states/recoil-scope-contexts/TableRecoilScopeContext';
import { canPersistTableColumnsScopedSelector } from '../../states/selectors/canPersistTableColumnsScopedSelector'; import { canPersistTableColumnsScopedFamilySelector } from '../../states/selectors/canPersistTableColumnsScopedFamilySelector';
import {
currentTableViewIdState,
type TableView,
} from '../../states/tableViewsState';
import { TableOptionsHotkeyScope } from '../../types/TableOptionsHotkeyScope'; import { TableOptionsHotkeyScope } from '../../types/TableOptionsHotkeyScope';
import { TableViewsHotkeyScope } from '../../types/TableViewsHotkeyScope';
type OwnProps<SortField> = { type OwnProps<SortField> = {
viewName: string; viewName: string;
availableSorts?: Array<SortType<SortField>>; availableSorts?: Array<SortType<SortField>>;
onViewsChange?: (views: TableView[]) => void; onViewsChange?: (views: View[]) => void;
onViewSubmit?: () => void; onViewSubmit?: () => void;
onImport?: () => void; onImport?: () => void;
}; };
@ -45,8 +43,8 @@ export function TableHeader<SortField>({
}: OwnProps<SortField>) { }: OwnProps<SortField>) {
const tableScopeId = useContextScopeId(TableRecoilScopeContext); const tableScopeId = useContextScopeId(TableRecoilScopeContext);
const currentTableViewId = useRecoilScopedValue( const currentViewId = useRecoilScopedValue(
currentTableViewIdState, currentViewIdScopedState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const [sorts, setSorts] = useRecoilScopedState<SelectedSortType<SortField>[]>( const [sorts, setSorts] = useRecoilScopedState<SelectedSortType<SortField>[]>(
@ -54,14 +52,14 @@ export function TableHeader<SortField>({
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const canPersistTableColumns = useRecoilValue( const canPersistTableColumns = useRecoilValue(
canPersistTableColumnsScopedSelector([tableScopeId, currentTableViewId]), canPersistTableColumnsScopedFamilySelector([tableScopeId, currentViewId]),
); );
const canPersistFilters = useRecoilValue( const canPersistFilters = useRecoilValue(
canPersistFiltersScopedSelector([tableScopeId, currentTableViewId]), canPersistFiltersScopedFamilySelector([tableScopeId, currentViewId]),
); );
const canPersistSorts = useRecoilValue( const canPersistSorts = useRecoilValue(
canPersistSortsScopedSelector([tableScopeId, currentTableViewId]), canPersistSortsScopedFamilySelector([tableScopeId, currentViewId]),
); );
const sortSelect = useCallback( const sortSelect = useCallback(
@ -87,7 +85,7 @@ export function TableHeader<SortField>({
<TableViewsDropdownButton <TableViewsDropdownButton
defaultViewName={viewName} defaultViewName={viewName}
onViewsChange={onViewsChange} onViewsChange={onViewsChange}
HotkeyScope={TableViewsHotkeyScope.ListDropdown} HotkeyScope={ViewsHotkeyScope.ListDropdown}
/> />
} }
displayBottomBorder={false} displayBottomBorder={false}
@ -126,7 +124,7 @@ export function TableHeader<SortField>({
rightComponent={ rightComponent={
<TableUpdateViewButtonGroup <TableUpdateViewButtonGroup
onViewSubmit={onViewSubmit} onViewSubmit={onViewSubmit}
HotkeyScope={TableViewsHotkeyScope.CreateDropdown} HotkeyScope={ViewsHotkeyScope.CreateDropdown}
/> />
} }
/> />

View File

@ -1,4 +0,0 @@
export enum TableViewsHotkeyScope {
ListDropdown = 'table-views-list-dropdown',
CreateDropdown = 'table-views-create-dropdown',
}

View File

@ -0,0 +1,6 @@
import { atomFamily } from 'recoil';
export const currentViewIdScopedState = atomFamily<string | undefined, string>({
key: 'currentViewIdScopedState',
default: undefined,
});

View File

@ -2,9 +2,9 @@ import { atomFamily } from 'recoil';
import type { Filter } from '../types/Filter'; import type { Filter } from '../types/Filter';
export const savedFiltersScopedState = atomFamily<Filter[], string | undefined>( export const savedFiltersFamilyState = atomFamily<Filter[], string | undefined>(
{ {
key: 'savedFiltersScopedState', key: 'savedFiltersFamilyState',
default: [], default: [],
}, },
); );

View File

@ -2,10 +2,10 @@ import { atomFamily } from 'recoil';
import type { SelectedSortType } from '../types/interface'; import type { SelectedSortType } from '../types/interface';
export const savedSortsScopedState = atomFamily< export const savedSortsFamilyState = atomFamily<
SelectedSortType<any>[], SelectedSortType<any>[],
string | undefined string | undefined
>({ >({
key: 'savedSortsScopedState', key: 'savedSortsFamilyState',
default: [], default: [],
}); });

View File

@ -3,15 +3,15 @@ import { selectorFamily } from 'recoil';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { filtersScopedState } from '../filtersScopedState'; import { filtersScopedState } from '../filtersScopedState';
import { savedFiltersScopedState } from '../savedFiltersScopedState'; import { savedFiltersFamilyState } from '../savedFiltersFamilyState';
export const canPersistFiltersScopedSelector = selectorFamily({ export const canPersistFiltersScopedFamilySelector = selectorFamily({
key: 'canPersistFiltersScopedSelector', key: 'canPersistFiltersScopedFamilySelector',
get: get:
([scopeId, viewId]: [string, string | undefined]) => ([scopeId, viewId]: [string, string | undefined]) =>
({ get }) => ({ get }) =>
!isDeeplyEqual( !isDeeplyEqual(
get(savedFiltersScopedState(viewId)), get(savedFiltersFamilyState(viewId)),
get(filtersScopedState(scopeId)), get(filtersScopedState(scopeId)),
), ),
}); });

View File

@ -2,16 +2,16 @@ import { selectorFamily } from 'recoil';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
import { savedSortsScopedState } from '../savedSortsScopedState'; import { savedSortsFamilyState } from '../savedSortsFamilyState';
import { sortsScopedState } from '../sortsScopedState'; import { sortsScopedState } from '../sortsScopedState';
export const canPersistSortsScopedSelector = selectorFamily({ export const canPersistSortsScopedFamilySelector = selectorFamily({
key: 'canPersistSortsScopedSelector', key: 'canPersistSortsScopedFamilySelector',
get: get:
([scopeId, viewId]: [string, string | undefined]) => ([scopeId, viewId]: [string, string | undefined]) =>
({ get }) => ({ get }) =>
!isDeeplyEqual( !isDeeplyEqual(
get(savedSortsScopedState(viewId)), get(savedSortsFamilyState(viewId)),
get(sortsScopedState(scopeId)), get(sortsScopedState(scopeId)),
), ),
}); });

View File

@ -0,0 +1,21 @@
import { selectorFamily } from 'recoil';
import type { View } from '../../types/View';
import { currentViewIdScopedState } from '../currentViewIdScopedState';
import { viewsByIdScopedSelector } from './viewsByIdScopedSelector';
export const currentViewScopedSelector = selectorFamily<
View | undefined,
string
>({
key: 'currentViewScopedSelector',
get:
(scopeId) =>
({ get }) => {
const currentViewId = get(currentViewIdScopedState(scopeId));
return currentViewId
? get(viewsByIdScopedSelector(scopeId))[currentViewId]
: undefined;
},
});

View File

@ -0,0 +1,15 @@
import { selectorFamily } from 'recoil';
import type { Filter } from '../../types/Filter';
import { savedFiltersFamilyState } from '../savedFiltersFamilyState';
export const savedFiltersByKeyFamilySelector = selectorFamily({
key: 'savedFiltersByKeyFamilySelector',
get:
(viewId: string | undefined) =>
({ get }) =>
get(savedFiltersFamilyState(viewId)).reduce<Record<string, Filter>>(
(result, filter) => ({ ...result, [filter.key]: filter }),
{},
),
});

View File

@ -1,15 +0,0 @@
import { selectorFamily } from 'recoil';
import type { Filter } from '../../types/Filter';
import { savedFiltersScopedState } from '../savedFiltersScopedState';
export const savedFiltersByKeyScopedSelector = selectorFamily({
key: 'savedFiltersByKeyScopedSelector',
get:
(param: string | undefined) =>
({ get }) =>
get(savedFiltersScopedState(param)).reduce<Record<string, Filter>>(
(result, filter) => ({ ...result, [filter.key]: filter }),
{},
),
});

View File

@ -1,14 +1,14 @@
import { selectorFamily } from 'recoil'; import { selectorFamily } from 'recoil';
import type { SelectedSortType } from '../../types/interface'; import type { SelectedSortType } from '../../types/interface';
import { savedSortsScopedState } from '../savedSortsScopedState'; import { savedSortsFamilyState } from '../savedSortsFamilyState';
export const savedSortsByKeyScopedSelector = selectorFamily({ export const savedSortsByKeyFamilySelector = selectorFamily({
key: 'savedSortsByKeyScopedSelector', key: 'savedSortsByKeyFamilySelector',
get: get:
(viewId: string | undefined) => (viewId: string | undefined) =>
({ get }) => ({ get }) =>
get(savedSortsScopedState(viewId)).reduce< get(savedSortsFamilyState(viewId)).reduce<
Record<string, SelectedSortType<any>> Record<string, SelectedSortType<any>>
>((result, sort) => ({ ...result, [sort.key]: sort }), {}), >((result, sort) => ({ ...result, [sort.key]: sort }), {}),
}); });

View File

@ -0,0 +1,18 @@
import { selectorFamily } from 'recoil';
import type { View } from '../../types/View';
import { viewsScopedState } from '../viewsScopedState';
export const viewsByIdScopedSelector = selectorFamily<
Record<string, View>,
string
>({
key: 'viewsByIdScopedSelector',
get:
(scopeId) =>
({ get }) =>
get(viewsScopedState(scopeId)).reduce<Record<string, View>>(
(result, view) => ({ ...result, [view.id]: view }),
{},
),
});

View File

@ -0,0 +1,9 @@
import { atom } from 'recoil';
export const viewEditModeState = atom<{
mode: 'create' | 'edit' | undefined;
viewId: string | undefined;
}>({
key: 'viewEditModeState',
default: { mode: undefined, viewId: undefined },
});

View File

@ -0,0 +1,8 @@
import { atomFamily } from 'recoil';
import type { View } from '../types/View';
export const viewsScopedState = atomFamily<View[], string>({
key: 'viewsScopedState',
default: [],
});

View File

@ -0,0 +1 @@
export type View = { id: string; name: string };

View File

@ -0,0 +1,4 @@
export enum ViewsHotkeyScope {
ListDropdown = 'views-list-dropdown',
CreateDropdown = 'views-create-dropdown',
}

View File

@ -4,13 +4,13 @@ import { useRecoilValue, useSetRecoilState } from 'recoil';
import type { ViewFieldMetadata } from '@/ui/editable-field/types/ViewField'; import type { ViewFieldMetadata } from '@/ui/editable-field/types/ViewField';
import { availableTableColumnsScopedState } from '@/ui/table/states/availableTableColumnsScopedState'; import { availableTableColumnsScopedState } from '@/ui/table/states/availableTableColumnsScopedState';
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext'; import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { savedTableColumnsScopedState } from '@/ui/table/states/savedTableColumnsScopedState'; import { savedTableColumnsFamilyState } from '@/ui/table/states/savedTableColumnsFamilyState';
import { savedTableColumnsByKeyScopedSelector } from '@/ui/table/states/selectors/savedTableColumnsByKeyScopedSelector'; import { savedTableColumnsByKeyFamilySelector } from '@/ui/table/states/selectors/savedTableColumnsByKeyFamilySelector';
import { tableColumnsScopedState } from '@/ui/table/states/tableColumnsScopedState'; import { tableColumnsScopedState } from '@/ui/table/states/tableColumnsScopedState';
import { currentTableViewIdState } from '@/ui/table/states/tableViewsState';
import type { ColumnDefinition } from '@/ui/table/types/ColumnDefinition'; import type { ColumnDefinition } from '@/ui/table/types/ColumnDefinition';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { currentViewIdScopedState } from '@/ui/view-bar/states/currentViewIdScopedState';
import { import {
SortOrder, SortOrder,
useCreateViewFieldsMutation, useCreateViewFieldsMutation,
@ -41,8 +41,8 @@ export const useTableViewFields = ({
columnDefinitions: ColumnDefinition<ViewFieldMetadata>[]; columnDefinitions: ColumnDefinition<ViewFieldMetadata>[];
skipFetch?: boolean; skipFetch?: boolean;
}) => { }) => {
const currentTableViewId = useRecoilScopedValue( const currentViewId = useRecoilScopedValue(
currentTableViewIdState, currentViewIdScopedState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const [availableTableColumns, setAvailableTableColumns] = const [availableTableColumns, setAvailableTableColumns] =
@ -55,10 +55,10 @@ export const useTableViewFields = ({
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const setSavedTableColumns = useSetRecoilState( const setSavedTableColumns = useSetRecoilState(
savedTableColumnsScopedState(currentTableViewId), savedTableColumnsFamilyState(currentViewId),
); );
const savedTableColumnsByKey = useRecoilValue( const savedTableColumnsByKey = useRecoilValue(
savedTableColumnsByKeyScopedSelector(currentTableViewId), savedTableColumnsByKeyFamilySelector(currentViewId),
); );
const [createViewFieldsMutation] = useCreateViewFieldsMutation(); const [createViewFieldsMutation] = useCreateViewFieldsMutation();
@ -67,7 +67,7 @@ export const useTableViewFields = ({
const createViewFields = useCallback( const createViewFields = useCallback(
( (
columns: ColumnDefinition<ViewFieldMetadata>[], columns: ColumnDefinition<ViewFieldMetadata>[],
viewId = currentTableViewId, viewId = currentViewId,
) => { ) => {
if (!viewId || !columns.length) return; if (!viewId || !columns.length) return;
@ -80,12 +80,12 @@ export const useTableViewFields = ({
}, },
}); });
}, },
[createViewFieldsMutation, currentTableViewId, objectId], [createViewFieldsMutation, currentViewId, objectId],
); );
const updateViewFields = useCallback( const updateViewFields = useCallback(
(columns: ColumnDefinition<ViewFieldMetadata>[]) => { (columns: ColumnDefinition<ViewFieldMetadata>[]) => {
if (!currentTableViewId || !columns.length) return; if (!currentViewId || !columns.length) return;
return Promise.all( return Promise.all(
columns.map((column) => columns.map((column) =>
@ -96,22 +96,22 @@ export const useTableViewFields = ({
size: column.size, size: column.size,
}, },
where: { where: {
viewId_key: { key: column.key, viewId: currentTableViewId }, viewId_key: { key: column.key, viewId: currentViewId },
}, },
}, },
}), }),
), ),
); );
}, },
[currentTableViewId, updateViewFieldMutation], [currentViewId, updateViewFieldMutation],
); );
const { refetch } = useGetViewFieldsQuery({ const { refetch } = useGetViewFieldsQuery({
skip: !currentTableViewId || skipFetch, skip: !currentViewId || skipFetch,
variables: { variables: {
orderBy: { index: SortOrder.Asc }, orderBy: { index: SortOrder.Asc },
where: { where: {
viewId: { equals: currentTableViewId }, viewId: { equals: currentViewId },
}, },
}, },
onCompleted: async (data) => { onCompleted: async (data) => {
@ -152,7 +152,7 @@ export const useTableViewFields = ({
}); });
const persistColumns = useCallback(async () => { const persistColumns = useCallback(async () => {
if (!currentTableViewId) return; if (!currentViewId) return;
const viewFieldsToCreate = tableColumns.filter( const viewFieldsToCreate = tableColumns.filter(
(column) => !savedTableColumnsByKey[column.key], (column) => !savedTableColumnsByKey[column.key],
@ -170,7 +170,7 @@ export const useTableViewFields = ({
return refetch(); return refetch();
}, [ }, [
createViewFields, createViewFields,
currentTableViewId, currentViewId,
refetch, refetch,
savedTableColumnsByKey, savedTableColumnsByKey,
tableColumns, tableColumns,

View File

@ -3,7 +3,6 @@ import { useCallback } from 'react';
import type { ViewFieldMetadata } from '@/ui/editable-field/types/ViewField'; import type { ViewFieldMetadata } from '@/ui/editable-field/types/ViewField';
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext'; import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { tableColumnsScopedState } from '@/ui/table/states/tableColumnsScopedState'; import { tableColumnsScopedState } from '@/ui/table/states/tableColumnsScopedState';
import { currentTableViewIdState } from '@/ui/table/states/tableViewsState';
import type { ColumnDefinition } from '@/ui/table/types/ColumnDefinition'; import type { ColumnDefinition } from '@/ui/table/types/ColumnDefinition';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState'; import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState';
@ -28,10 +27,6 @@ export const useTableViews = <Entity, SortField>({
objectId: 'company' | 'person'; objectId: 'company' | 'person';
columnDefinitions: ColumnDefinition<ViewFieldMetadata>[]; columnDefinitions: ColumnDefinition<ViewFieldMetadata>[];
}) => { }) => {
const currentTableViewId = useRecoilScopedValue(
currentTableViewIdState,
TableRecoilScopeContext,
);
const tableColumns = useRecoilScopedValue( const tableColumns = useRecoilScopedValue(
tableColumnsScopedState, tableColumnsScopedState,
TableRecoilScopeContext, TableRecoilScopeContext,
@ -54,13 +49,11 @@ export const useTableViews = <Entity, SortField>({
}); });
const { createViewFilters, persistFilters } = useViewFilters({ const { createViewFilters, persistFilters } = useViewFilters({
availableFilters, availableFilters,
currentViewId: currentTableViewId,
scopeContext: TableRecoilScopeContext, scopeContext: TableRecoilScopeContext,
skipFetch: isFetchingViews, skipFetch: isFetchingViews,
}); });
const { createViewSorts, persistSorts } = useViewSorts({ const { createViewSorts, persistSorts } = useViewSorts({
availableSorts, availableSorts,
currentViewId: currentTableViewId,
scopeContext: TableRecoilScopeContext, scopeContext: TableRecoilScopeContext,
skipFetch: isFetchingViews, skipFetch: isFetchingViews,
}); });

View File

@ -2,9 +2,11 @@ import { Context, useCallback } from 'react';
import { useRecoilState, useRecoilValue } from 'recoil'; import { useRecoilState, useRecoilValue } from 'recoil';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { currentViewIdScopedState } from '@/ui/view-bar/states/currentViewIdScopedState';
import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState'; import { filtersScopedState } from '@/ui/view-bar/states/filtersScopedState';
import { savedFiltersScopedState } from '@/ui/view-bar/states/savedFiltersScopedState'; import { savedFiltersFamilyState } from '@/ui/view-bar/states/savedFiltersFamilyState';
import { savedFiltersByKeyScopedSelector } from '@/ui/view-bar/states/selectors/savedFiltersByKeyScopedSelector'; import { savedFiltersByKeyFamilySelector } from '@/ui/view-bar/states/selectors/savedFiltersByKeyFamilySelector';
import type { Filter } from '@/ui/view-bar/types/Filter'; import type { Filter } from '@/ui/view-bar/types/Filter';
import type { FilterDefinitionByEntity } from '@/ui/view-bar/types/FilterDefinitionByEntity'; import type { FilterDefinitionByEntity } from '@/ui/view-bar/types/FilterDefinitionByEntity';
import { import {
@ -17,24 +19,26 @@ import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
export const useViewFilters = <Entity>({ export const useViewFilters = <Entity>({
availableFilters, availableFilters,
currentViewId,
scopeContext, scopeContext,
skipFetch, skipFetch,
}: { }: {
availableFilters: FilterDefinitionByEntity<Entity>[]; availableFilters: FilterDefinitionByEntity<Entity>[];
currentViewId: string | undefined;
scopeContext: Context<string | null>; scopeContext: Context<string | null>;
skipFetch?: boolean; skipFetch?: boolean;
}) => { }) => {
const currentViewId = useRecoilScopedValue(
currentViewIdScopedState,
scopeContext,
);
const [filters, setFilters] = useRecoilScopedState( const [filters, setFilters] = useRecoilScopedState(
filtersScopedState, filtersScopedState,
scopeContext, scopeContext,
); );
const [, setSavedFilters] = useRecoilState( const [, setSavedFilters] = useRecoilState(
savedFiltersScopedState(currentViewId), savedFiltersFamilyState(currentViewId),
); );
const savedFiltersByKey = useRecoilValue( const savedFiltersByKey = useRecoilValue(
savedFiltersByKeyScopedSelector(currentViewId), savedFiltersByKeyFamilySelector(currentViewId),
); );
const { refetch } = useGetViewFiltersQuery({ const { refetch } = useGetViewFiltersQuery({

View File

@ -2,8 +2,10 @@ import { Context, useCallback } from 'react';
import { useRecoilState, useRecoilValue } from 'recoil'; import { useRecoilState, useRecoilValue } from 'recoil';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { savedSortsScopedState } from '@/ui/view-bar/states/savedSortsScopedState'; import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { savedSortsByKeyScopedSelector } from '@/ui/view-bar/states/selectors/savedSortsByKeyScopedSelector'; import { currentViewIdScopedState } from '@/ui/view-bar/states/currentViewIdScopedState';
import { savedSortsFamilyState } from '@/ui/view-bar/states/savedSortsFamilyState';
import { savedSortsByKeyFamilySelector } from '@/ui/view-bar/states/selectors/savedSortsByKeyFamilySelector';
import { sortsScopedState } from '@/ui/view-bar/states/sortsScopedState'; import { sortsScopedState } from '@/ui/view-bar/states/sortsScopedState';
import type { SelectedSortType, SortType } from '@/ui/view-bar/types/interface'; import type { SelectedSortType, SortType } from '@/ui/view-bar/types/interface';
import { import {
@ -17,24 +19,26 @@ import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
export const useViewSorts = <SortField>({ export const useViewSorts = <SortField>({
availableSorts, availableSorts,
currentViewId,
scopeContext, scopeContext,
skipFetch, skipFetch,
}: { }: {
availableSorts: SortType<SortField>[]; availableSorts: SortType<SortField>[];
currentViewId: string | undefined;
scopeContext: Context<string | null>; scopeContext: Context<string | null>;
skipFetch?: boolean; skipFetch?: boolean;
}) => { }) => {
const currentViewId = useRecoilScopedValue(
currentViewIdScopedState,
scopeContext,
);
const [sorts, setSorts] = useRecoilScopedState( const [sorts, setSorts] = useRecoilScopedState(
sortsScopedState, sortsScopedState,
scopeContext, scopeContext,
); );
const [, setSavedSorts] = useRecoilState( const [, setSavedSorts] = useRecoilState(
savedSortsScopedState(currentViewId), savedSortsFamilyState(currentViewId),
); );
const savedSortsByKey = useRecoilValue( const savedSortsByKey = useRecoilValue(
savedSortsByKeyScopedSelector(currentViewId), savedSortsByKeyFamilySelector(currentViewId),
); );
const { refetch } = useGetViewSortsQuery({ const { refetch } = useGetViewSortsQuery({

View File

@ -1,17 +1,15 @@
import { useRecoilCallback } from 'recoil'; import { useRecoilCallback } from 'recoil';
import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext'; import { TableRecoilScopeContext } from '@/ui/table/states/recoil-scope-contexts/TableRecoilScopeContext';
import { savedTableColumnsScopedState } from '@/ui/table/states/savedTableColumnsScopedState'; import { savedTableColumnsFamilyState } from '@/ui/table/states/savedTableColumnsFamilyState';
import {
currentTableViewIdState,
type TableView,
tableViewsByIdState,
tableViewsState,
} from '@/ui/table/states/tableViewsState';
import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState'; import { useRecoilScopedState } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedState';
import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue'; import { useRecoilScopedValue } from '@/ui/utilities/recoil-scope/hooks/useRecoilScopedValue';
import { savedFiltersScopedState } from '@/ui/view-bar/states/savedFiltersScopedState'; import { currentViewIdScopedState } from '@/ui/view-bar/states/currentViewIdScopedState';
import { savedSortsScopedState } from '@/ui/view-bar/states/savedSortsScopedState'; import { savedFiltersFamilyState } from '@/ui/view-bar/states/savedFiltersFamilyState';
import { savedSortsFamilyState } from '@/ui/view-bar/states/savedSortsFamilyState';
import { viewsByIdScopedSelector } from '@/ui/view-bar/states/selectors/viewsByIdScopedSelector';
import { viewsScopedState } from '@/ui/view-bar/states/viewsScopedState';
import { View } from '@/ui/view-bar/types/View';
import { import {
useCreateViewMutation, useCreateViewMutation,
useDeleteViewMutation, useDeleteViewMutation,
@ -30,16 +28,16 @@ export const useViews = ({
onViewCreate: (viewId: string) => Promise<void>; onViewCreate: (viewId: string) => Promise<void>;
type: ViewType; type: ViewType;
}) => { }) => {
const [currentTableViewId, setCurrentTableViewId] = useRecoilScopedState( const [currentViewId, setCurrentViewId] = useRecoilScopedState(
currentTableViewIdState, currentViewIdScopedState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const [tableViews, setTableViews] = useRecoilScopedState( const [views, setViews] = useRecoilScopedState(
tableViewsState, viewsScopedState,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
const tableViewsById = useRecoilScopedValue( const viewsById = useRecoilScopedValue(
tableViewsByIdState, viewsByIdScopedSelector,
TableRecoilScopeContext, TableRecoilScopeContext,
); );
@ -47,7 +45,7 @@ export const useViews = ({
const [updateViewMutation] = useUpdateViewMutation(); const [updateViewMutation] = useUpdateViewMutation();
const [deleteViewMutation] = useDeleteViewMutation(); const [deleteViewMutation] = useDeleteViewMutation();
const createView = async (view: TableView) => { const createView = async (view: View) => {
const { data } = await createViewMutation({ const { data } = await createViewMutation({
variables: { variables: {
data: { data: {
@ -61,7 +59,7 @@ export const useViews = ({
if (data?.view) await onViewCreate(data.view.id); if (data?.view) await onViewCreate(data.view.id);
}; };
const updateView = (view: TableView) => const updateView = (view: View) =>
updateViewMutation({ updateViewMutation({
variables: { variables: {
data: { name: view.name }, data: { name: view.name },
@ -75,13 +73,13 @@ export const useViews = ({
const handleResetSavedViews = useRecoilCallback( const handleResetSavedViews = useRecoilCallback(
({ reset }) => ({ reset }) =>
() => { () => {
tableViews.forEach((view) => { views.forEach((view) => {
reset(savedTableColumnsScopedState(view.id)); reset(savedTableColumnsFamilyState(view.id));
reset(savedFiltersScopedState(view.id)); reset(savedFiltersFamilyState(view.id));
reset(savedSortsScopedState(view.id)); reset(savedSortsFamilyState(view.id));
}); });
}, },
[tableViews], [views],
); );
const { loading, refetch } = useGetViewsQuery({ const { loading, refetch } = useGetViewsQuery({
@ -97,25 +95,22 @@ export const useViews = ({
name: view.name, name: view.name,
})); }));
if (!isDeeplyEqual(tableViews, nextViews)) setTableViews(nextViews); if (!isDeeplyEqual(views, nextViews)) setViews(nextViews);
// If there is no current view selected, // If there is no current view selected,
// or if the current view cannot be found in the views list (user switched workspaces) // or if the current view cannot be found in the views list (user switched workspaces)
if ( if (
nextViews.length && nextViews.length &&
(!currentTableViewId || (!currentViewId || !nextViews.some((view) => view.id === currentViewId))
!nextViews.some((view) => view.id === currentTableViewId))
) { ) {
setCurrentTableViewId(nextViews[0].id); setCurrentViewId(nextViews[0].id);
handleResetSavedViews(); handleResetSavedViews();
} }
}, },
}); });
const handleViewsChange = async (nextViews: TableView[]) => { const handleViewsChange = async (nextViews: View[]) => {
const viewToCreate = nextViews.find( const viewToCreate = nextViews.find((nextView) => !viewsById[nextView.id]);
(nextView) => !tableViewsById[nextView.id],
);
if (viewToCreate) { if (viewToCreate) {
await createView(viewToCreate); await createView(viewToCreate);
return refetch(); return refetch();
@ -123,8 +118,7 @@ export const useViews = ({
const viewToUpdate = nextViews.find( const viewToUpdate = nextViews.find(
(nextView) => (nextView) =>
tableViewsById[nextView.id] && viewsById[nextView.id] && viewsById[nextView.id].name !== nextView.name,
tableViewsById[nextView.id].name !== nextView.name,
); );
if (viewToUpdate) { if (viewToUpdate) {
await updateView(viewToUpdate); await updateView(viewToUpdate);
@ -132,7 +126,7 @@ export const useViews = ({
} }
const nextViewIds = nextViews.map((nextView) => nextView.id); const nextViewIds = nextViews.map((nextView) => nextView.id);
const viewIdToDelete = Object.keys(tableViewsById).find( const viewIdToDelete = Object.keys(viewsById).find(
(previousViewId) => !nextViewIds.includes(previousViewId), (previousViewId) => !nextViewIds.includes(previousViewId),
); );
if (viewIdToDelete) await deleteView(viewIdToDelete); if (viewIdToDelete) await deleteView(viewIdToDelete);