View module refactor with atomic recoil component instance states (#6810)
This PR refactors the view module to implement utils that avoid having to create hooks to inject the scope id in the states, like `useViewStates`, each componentState will know its unique related InstanceContext (which holds the instanceId), and thus will be able to retrieve it itself. We keep the naming componentState as it reflects the fact that those states are tied to instances of a component (or its children). We introduce the instance word where it is needed, in place of scopeId for example, to precise the fact that we handle instances of component state, one for each instance of a component. For example, the currentViewId is a state that is tied to an instance of the ViewBar, but as we can switch between views, we want currentViewId to be a componentState tied to an instance of the ViewBar component. This PR also refactors view filter and sort states to fix this issue : https://github.com/twentyhq/twenty/issues/6837 and other problems involving resetting those states between page navigation. Fixes https://github.com/twentyhq/twenty/issues/6837 --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -1,5 +1,4 @@
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { MultipleFiltersDropdownContent } from '@/object-record/object-filter-dropdown/components/MultipleFiltersDropdownContent';
|
||||
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
|
||||
@ -8,8 +7,11 @@ import { FilterOperand } from '@/object-record/object-filter-dropdown/types/Filt
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { EditableFilterChip } from '@/views/components/EditableFilterChip';
|
||||
import { useCombinedViewFilters } from '@/views/hooks/useCombinedViewFilters';
|
||||
|
||||
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
|
||||
import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
type EditableFilterDropdownButtonProps = {
|
||||
@ -24,7 +26,6 @@ export const EditableFilterDropdownButton = ({
|
||||
hotkeyScope,
|
||||
}: EditableFilterDropdownButtonProps) => {
|
||||
const {
|
||||
availableFilterDefinitionsState,
|
||||
setFilterDefinitionUsedInDropdown,
|
||||
setSelectedOperandInDropdown,
|
||||
setSelectedFilter,
|
||||
@ -32,13 +33,15 @@ export const EditableFilterDropdownButton = ({
|
||||
filterDropdownId: viewFilterDropdownId,
|
||||
});
|
||||
|
||||
const availableFilterDefinitions = useRecoilValue(
|
||||
availableFilterDefinitionsState,
|
||||
// TODO: verify this instance id works
|
||||
const availableFilterDefinitions = useRecoilComponentValueV2(
|
||||
availableFilterDefinitionsComponentState,
|
||||
viewFilterDropdownId,
|
||||
);
|
||||
|
||||
const { closeDropdown } = useDropdown(viewFilterDropdownId);
|
||||
|
||||
const { removeCombinedViewFilter } = useCombinedViewFilters();
|
||||
const { deleteCombinedViewFilter } = useDeleteCombinedViewFilters();
|
||||
|
||||
useEffect(() => {
|
||||
const filterDefinition = availableFilterDefinitions.find(
|
||||
@ -63,7 +66,7 @@ export const EditableFilterDropdownButton = ({
|
||||
const handleRemove = () => {
|
||||
closeDropdown();
|
||||
|
||||
removeCombinedViewFilter(viewFilter.id);
|
||||
deleteCombinedViewFilter(viewFilter.id);
|
||||
};
|
||||
|
||||
const handleDropdownClickOutside = useCallback(() => {
|
||||
@ -72,9 +75,9 @@ export const EditableFilterDropdownButton = ({
|
||||
!value &&
|
||||
![FilterOperand.IsEmpty, FilterOperand.IsNotEmpty].includes(operand)
|
||||
) {
|
||||
removeCombinedViewFilter(fieldId);
|
||||
deleteCombinedViewFilter(fieldId);
|
||||
}
|
||||
}, [viewFilter, removeCombinedViewFilter]);
|
||||
}, [viewFilter, deleteCombinedViewFilter]);
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
|
||||
@ -2,18 +2,20 @@ import { IconArrowDown, IconArrowUp } from 'twenty-ui';
|
||||
|
||||
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
|
||||
import { SortOrFilterChip } from '@/views/components/SortOrFilterChip';
|
||||
import { useCombinedViewSorts } from '@/views/hooks/useCombinedViewSorts';
|
||||
import { useDeleteCombinedViewSorts } from '@/views/hooks/useDeleteCombinedViewSorts';
|
||||
import { useUpsertCombinedViewSorts } from '@/views/hooks/useUpsertCombinedViewSorts';
|
||||
|
||||
type EditableSortChipProps = {
|
||||
viewSort: Sort;
|
||||
};
|
||||
|
||||
export const EditableSortChip = ({ viewSort }: EditableSortChipProps) => {
|
||||
const { removeCombinedViewSort, upsertCombinedViewSort } =
|
||||
useCombinedViewSorts();
|
||||
const { deleteCombinedViewSort } = useDeleteCombinedViewSorts();
|
||||
|
||||
const { upsertCombinedViewSort } = useUpsertCombinedViewSorts();
|
||||
|
||||
const handleRemoveClick = () => {
|
||||
removeCombinedViewSort(viewSort.fieldMetadataId);
|
||||
deleteCombinedViewSort(viewSort.fieldMetadataId);
|
||||
};
|
||||
|
||||
const handleClick = () => {
|
||||
|
||||
@ -1,18 +1,23 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
import { useSetRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentFamilyStateV2';
|
||||
import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams';
|
||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||
import { useResetCurrentView } from '@/views/hooks/useResetCurrentView';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates';
|
||||
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
|
||||
import { isDefined } from 'twenty-ui';
|
||||
|
||||
export const QueryParamsFiltersEffect = () => {
|
||||
const { hasFiltersQueryParams, getFiltersFromQueryParams } =
|
||||
const { hasFiltersQueryParams, getFiltersFromQueryParams, viewIdQueryParam } =
|
||||
useViewFromQueryParams();
|
||||
const { unsavedToUpsertViewFiltersState } = useViewStates();
|
||||
const setUnsavedViewFilter = useSetRecoilState(
|
||||
unsavedToUpsertViewFiltersState,
|
||||
|
||||
const setUnsavedViewFilter = useSetRecoilComponentFamilyStateV2(
|
||||
unsavedToUpsertViewFiltersComponentFamilyState,
|
||||
{ viewId: viewIdQueryParam },
|
||||
);
|
||||
const { resetCurrentView } = useResetCurrentView();
|
||||
|
||||
const { resetUnsavedViewStates } = useResetUnsavedViewStates();
|
||||
const { currentViewId } = useGetCurrentView();
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasFiltersQueryParams) {
|
||||
@ -26,13 +31,16 @@ export const QueryParamsFiltersEffect = () => {
|
||||
});
|
||||
|
||||
return () => {
|
||||
resetCurrentView();
|
||||
if (isDefined(currentViewId)) {
|
||||
resetUnsavedViewStates(currentViewId);
|
||||
}
|
||||
};
|
||||
}, [
|
||||
getFiltersFromQueryParams,
|
||||
hasFiltersQueryParams,
|
||||
resetCurrentView,
|
||||
resetUnsavedViewStates,
|
||||
setUnsavedViewFilter,
|
||||
currentViewId,
|
||||
]);
|
||||
|
||||
return <></>;
|
||||
|
||||
@ -1,22 +1,26 @@
|
||||
import { useLastVisitedObjectMetadataItem } from '@/navigation/hooks/useLastVisitedObjectMetadataItem';
|
||||
import { useLastVisitedView } from '@/navigation/hooks/useLastVisitedView';
|
||||
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
|
||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||
import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams';
|
||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { useResetCurrentView } from '@/views/hooks/useResetCurrentView';
|
||||
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
||||
import { isUndefined } from '@sniptt/guards';
|
||||
import { useEffect } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const QueryParamsViewIdEffect = () => {
|
||||
const { getFiltersFromQueryParams, viewIdQueryParam } =
|
||||
useViewFromQueryParams();
|
||||
const { currentViewIdState, componentId: objectNamePlural } = useViewStates();
|
||||
|
||||
const [currentViewId, setCurrentViewId] = useRecoilState(currentViewIdState);
|
||||
// TODO: fix this implicit hack
|
||||
const { instanceId: objectNamePlural } = useGetCurrentView();
|
||||
|
||||
const [currentViewId, setCurrentViewId] = useRecoilComponentStateV2(
|
||||
currentViewIdComponentState,
|
||||
);
|
||||
|
||||
const { viewsOnCurrentObject } = useGetCurrentView();
|
||||
const { findObjectMetadataItemByNamePlural } =
|
||||
useFilteredObjectMetadataItems();
|
||||
@ -34,13 +38,14 @@ export const QueryParamsViewIdEffect = () => {
|
||||
lastVisitedObjectMetadataItemId,
|
||||
);
|
||||
|
||||
const { resetCurrentView } = useResetCurrentView();
|
||||
// // TODO: scope view bar per view id if possible
|
||||
// const { resetCurrentView } = useResetCurrentView();
|
||||
|
||||
useEffect(() => {
|
||||
if (isDefined(currentViewId)) {
|
||||
resetCurrentView();
|
||||
}
|
||||
}, [resetCurrentView, currentViewId]);
|
||||
// useEffect(() => {
|
||||
// if (isDefined(currentViewId)) {
|
||||
// resetCurrentView();
|
||||
// }
|
||||
// }, [resetCurrentView, currentViewId]);
|
||||
|
||||
useEffect(() => {
|
||||
const indexView = viewsOnCurrentObject.find((view) => view.key === 'INDEX');
|
||||
|
||||
@ -1,6 +1,4 @@
|
||||
import { useCallback } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import { IconChevronDown, IconPlus } from 'twenty-ui';
|
||||
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
@ -10,14 +8,18 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
|
||||
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { UPDATE_VIEW_BUTTON_DROPDOWN_ID } from '@/views/constants/UpdateViewButtonDropdownId';
|
||||
import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams';
|
||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { useSaveCurrentViewFiltersAndSorts } from '@/views/hooks/useSaveCurrentViewFiltersAndSorts';
|
||||
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
||||
import { canPersistViewComponentFamilySelector } from '@/views/states/selectors/canPersistViewComponentFamilySelector';
|
||||
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
|
||||
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
|
||||
import { useViewPickerStates } from '@/views/view-picker/hooks/useViewPickerStates';
|
||||
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
border-radius: ${({ theme }) => theme.border.radius.md};
|
||||
@ -33,12 +35,16 @@ export type UpdateViewButtonGroupProps = {
|
||||
export const UpdateViewButtonGroup = ({
|
||||
hotkeyScope,
|
||||
}: UpdateViewButtonGroupProps) => {
|
||||
const { canPersistViewSelector, currentViewIdState } = useViewStates();
|
||||
const { saveCurrentViewFilterAndSorts } = useSaveCurrentViewFiltersAndSorts();
|
||||
|
||||
const { setViewPickerMode } = useViewPickerMode();
|
||||
const { viewPickerReferenceViewIdState } = useViewPickerStates();
|
||||
const canPersistView = useRecoilValue(canPersistViewSelector());
|
||||
|
||||
const currentViewId = useRecoilComponentValueV2(currentViewIdComponentState);
|
||||
|
||||
const canPersistView = useRecoilComponentFamilyValueV2(
|
||||
canPersistViewComponentFamilySelector,
|
||||
{ viewId: currentViewId },
|
||||
);
|
||||
|
||||
const { closeDropdown: closeUpdateViewButtonDropdown } = useDropdown(
|
||||
UPDATE_VIEW_BUTTON_DROPDOWN_ID,
|
||||
@ -48,30 +54,31 @@ export const UpdateViewButtonGroup = ({
|
||||
);
|
||||
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
|
||||
|
||||
const currentViewId = useRecoilValue(currentViewIdState);
|
||||
|
||||
const setViewPickerReferenceViewId = useSetRecoilState(
|
||||
viewPickerReferenceViewIdState,
|
||||
const setViewPickerReferenceViewId = useSetRecoilComponentStateV2(
|
||||
viewPickerReferenceViewIdComponentState,
|
||||
);
|
||||
|
||||
const handleViewCreate = useCallback(() => {
|
||||
const openViewPickerInCreateMode = () => {
|
||||
if (!currentViewId) {
|
||||
return;
|
||||
}
|
||||
|
||||
openViewPickerDropdown();
|
||||
setViewPickerReferenceViewId(currentViewId);
|
||||
setViewPickerMode('create');
|
||||
setViewPickerMode('create-from-current');
|
||||
|
||||
closeUpdateViewButtonDropdown();
|
||||
}, [
|
||||
closeUpdateViewButtonDropdown,
|
||||
currentViewId,
|
||||
openViewPickerDropdown,
|
||||
setViewPickerMode,
|
||||
setViewPickerReferenceViewId,
|
||||
]);
|
||||
};
|
||||
|
||||
const handleViewUpdate = async () => {
|
||||
const handleCreateViewClick = () => {
|
||||
openViewPickerInCreateMode();
|
||||
};
|
||||
|
||||
const handleSaveAsNewViewClick = () => {
|
||||
openViewPickerInCreateMode();
|
||||
};
|
||||
|
||||
const handleUpdateViewClick = async () => {
|
||||
await saveCurrentViewFilterAndSorts();
|
||||
};
|
||||
|
||||
@ -87,7 +94,7 @@ export const UpdateViewButtonGroup = ({
|
||||
<StyledContainer>
|
||||
{currentViewWithCombinedFiltersAndSorts?.key !== 'INDEX' ? (
|
||||
<ButtonGroup size="small" accent="blue">
|
||||
<Button title="Update view" onClick={handleViewUpdate} />
|
||||
<Button title="Update view" onClick={handleUpdateViewClick} />
|
||||
<Dropdown
|
||||
dropdownId={UPDATE_VIEW_BUTTON_DROPDOWN_ID}
|
||||
dropdownHotkeyScope={hotkeyScope}
|
||||
@ -103,7 +110,7 @@ export const UpdateViewButtonGroup = ({
|
||||
<>
|
||||
<DropdownMenuItemsContainer>
|
||||
<MenuItem
|
||||
onClick={handleViewCreate}
|
||||
onClick={handleCreateViewClick}
|
||||
LeftIcon={IconPlus}
|
||||
text="Create view"
|
||||
/>
|
||||
@ -115,7 +122,7 @@ export const UpdateViewButtonGroup = ({
|
||||
) : (
|
||||
<Button
|
||||
title="Save as new view"
|
||||
onClick={handleViewCreate}
|
||||
onClick={handleSaveAsNewViewClick}
|
||||
accent="blue"
|
||||
size="small"
|
||||
variant="secondary"
|
||||
|
||||
@ -4,7 +4,7 @@ import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObje
|
||||
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
||||
import { useHandleToggleTrashColumnFilter } from '@/object-record/record-index/hooks/useHandleToggleTrashColumnFilter';
|
||||
import { SortOrFilterChip } from '@/views/components/SortOrFilterChip';
|
||||
import { useCombinedViewFilters } from '@/views/hooks/useCombinedViewFilters';
|
||||
import { useDeleteCombinedViewFilters } from '@/views/hooks/useDeleteCombinedViewFilters';
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
type VariantFilterChipProps = {
|
||||
@ -16,7 +16,7 @@ export const VariantFilterChip = ({
|
||||
viewFilter,
|
||||
viewBarId,
|
||||
}: VariantFilterChipProps) => {
|
||||
const { removeCombinedViewFilter } = useCombinedViewFilters();
|
||||
const { deleteCombinedViewFilter } = useDeleteCombinedViewFilters();
|
||||
|
||||
const { objectNamePlural } = useParams();
|
||||
|
||||
@ -32,7 +32,7 @@ export const VariantFilterChip = ({
|
||||
const { getIcon } = useIcons();
|
||||
|
||||
const handleRemoveClick = () => {
|
||||
removeCombinedViewFilter(viewFilter.id);
|
||||
deleteCombinedViewFilter(viewFilter.id);
|
||||
if (
|
||||
viewFilter.definition.label === 'Deleted' &&
|
||||
viewFilter.operand === 'isNotEmpty'
|
||||
|
||||
@ -13,12 +13,12 @@ import { ViewBarFilterEffect } from '@/views/components/ViewBarFilterEffect';
|
||||
import { ViewBarPageTitle } from '@/views/components/ViewBarPageTitle';
|
||||
import { ViewBarSkeletonLoader } from '@/views/components/ViewBarSkeletonLoader';
|
||||
import { ViewBarSortEffect } from '@/views/components/ViewBarSortEffect';
|
||||
import { ViewScope } from '@/views/scopes/ViewScope';
|
||||
import { GraphQLView } from '@/views/types/GraphQLView';
|
||||
import { ViewPickerDropdown } from '@/views/view-picker/components/ViewPickerDropdown';
|
||||
|
||||
import { ViewsHotkeyScope } from '../types/ViewsHotkeyScope';
|
||||
|
||||
import { ViewEventContext } from '@/views/events/contexts/ViewEventContext';
|
||||
import { UpdateViewButtonGroup } from './UpdateViewButtonGroup';
|
||||
import { ViewBarDetails } from './ViewBarDetails';
|
||||
|
||||
@ -41,15 +41,13 @@ export const ViewBar = ({
|
||||
const sortDropdownId = 'view-sort';
|
||||
|
||||
const loading = useIsPrefetchLoading();
|
||||
|
||||
if (!objectNamePlural) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<ViewScope
|
||||
viewScopeId={viewBarId}
|
||||
onCurrentViewChange={onCurrentViewChange}
|
||||
>
|
||||
<ViewEventContext.Provider value={{ onCurrentViewChange }}>
|
||||
<ViewBarEffect viewBarId={viewBarId} />
|
||||
<ViewBarFilterEffect filterDropdownId={filterDropdownId} />
|
||||
<ViewBarSortEffect sortDropdownId={sortDropdownId} />
|
||||
@ -95,6 +93,6 @@ export const ViewBar = ({
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</ViewScope>
|
||||
</ViewEventContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,20 +1,25 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { ReactNode, useMemo } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { AddObjectFilterFromDetailsButton } from '@/object-record/object-filter-dropdown/components/AddObjectFilterFromDetailsButton';
|
||||
import { ObjectFilterDropdownScope } from '@/object-record/object-filter-dropdown/scopes/ObjectFilterDropdownScope';
|
||||
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
||||
import { DropdownScope } from '@/ui/layout/dropdown/scopes/DropdownScope';
|
||||
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { EditableFilterDropdownButton } from '@/views/components/EditableFilterDropdownButton';
|
||||
import { EditableSortChip } from '@/views/components/EditableSortChip';
|
||||
import { ViewBarFilterEffect } from '@/views/components/ViewBarFilterEffect';
|
||||
import { useViewFromQueryParams } from '@/views/hooks/internal/useViewFromQueryParams';
|
||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { useResetCurrentView } from '@/views/hooks/useResetCurrentView';
|
||||
import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates';
|
||||
import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState';
|
||||
import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState';
|
||||
import { isViewBarExpandedComponentState } from '@/views/states/isViewBarExpandedComponentState';
|
||||
import { canPersistViewComponentFamilySelector } from '@/views/states/selectors/canPersistViewComponentFamilySelector';
|
||||
import { mapViewFiltersToFilters } from '@/views/utils/mapViewFiltersToFilters';
|
||||
import { mapViewSortsToSorts } from '@/views/utils/mapViewSortsToSorts';
|
||||
import { isDefined } from 'twenty-ui';
|
||||
import { VariantFilterChip } from './VariantFilterChip';
|
||||
|
||||
export type ViewBarDetailsProps = {
|
||||
@ -99,26 +104,30 @@ export const ViewBarDetails = ({
|
||||
filterDropdownId,
|
||||
viewBarId,
|
||||
}: ViewBarDetailsProps) => {
|
||||
const {
|
||||
canPersistViewSelector,
|
||||
isViewBarExpandedState,
|
||||
availableFilterDefinitionsState,
|
||||
availableSortDefinitionsState,
|
||||
} = useViewStates();
|
||||
|
||||
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
|
||||
|
||||
const isViewBarExpanded = useRecoilValue(isViewBarExpandedState);
|
||||
const { hasFiltersQueryParams } = useViewFromQueryParams();
|
||||
const canPersistView = useRecoilValue(canPersistViewSelector());
|
||||
const availableFilterDefinitions = useRecoilValue(
|
||||
availableFilterDefinitionsState,
|
||||
);
|
||||
const availableSortDefinitions = useRecoilValue(
|
||||
availableSortDefinitionsState,
|
||||
const viewId = currentViewWithCombinedFiltersAndSorts?.id;
|
||||
|
||||
const isViewBarExpanded = useRecoilComponentValueV2(
|
||||
isViewBarExpandedComponentState,
|
||||
);
|
||||
|
||||
const { resetCurrentView } = useResetCurrentView();
|
||||
const { hasFiltersQueryParams } = useViewFromQueryParams();
|
||||
|
||||
const canPersistView = useRecoilComponentFamilyValueV2(
|
||||
canPersistViewComponentFamilySelector,
|
||||
{ viewId },
|
||||
);
|
||||
|
||||
const availableFilterDefinitions = useRecoilComponentValueV2(
|
||||
availableFilterDefinitionsComponentState,
|
||||
);
|
||||
|
||||
const availableSortDefinitions = useRecoilComponentValueV2(
|
||||
availableSortDefinitionsComponentState,
|
||||
);
|
||||
|
||||
const { resetUnsavedViewStates } = useResetUnsavedViewStates();
|
||||
const canResetView = canPersistView && !hasFiltersQueryParams;
|
||||
|
||||
const { otherViewFilters, defaultViewFilters } = useMemo(() => {
|
||||
@ -145,7 +154,9 @@ export const ViewBarDetails = ({
|
||||
}, [currentViewWithCombinedFiltersAndSorts]);
|
||||
|
||||
const handleCancelClick = () => {
|
||||
resetCurrentView();
|
||||
if (isDefined(viewId)) {
|
||||
resetUnsavedViewStates(viewId);
|
||||
}
|
||||
};
|
||||
|
||||
const shouldExpandViewBar =
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import { isUndefined } from '@sniptt/guards';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useContext, useEffect, useState } from 'react';
|
||||
|
||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { ViewEventContext } from '@/views/events/contexts/ViewEventContext';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState';
|
||||
import { isPersistingViewFieldsComponentState } from '@/views/states/isPersistingViewFieldsComponentState';
|
||||
import { View } from '@/views/types/View';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
|
||||
@ -14,21 +16,22 @@ type ViewBarEffectProps = {
|
||||
export const ViewBarEffect = ({ viewBarId }: ViewBarEffectProps) => {
|
||||
const { currentViewWithCombinedFiltersAndSorts } =
|
||||
useGetCurrentView(viewBarId);
|
||||
const {
|
||||
onCurrentViewChangeState,
|
||||
availableFilterDefinitionsState,
|
||||
isPersistingViewFieldsState,
|
||||
} = useViewStates(viewBarId);
|
||||
|
||||
const { onCurrentViewChange } = useContext(ViewEventContext);
|
||||
|
||||
const [currentViewSnapshot, setCurrentViewSnapshot] = useState<
|
||||
View | undefined
|
||||
>(undefined);
|
||||
|
||||
const onCurrentViewChange = useRecoilValue(onCurrentViewChangeState);
|
||||
const availableFilterDefinitions = useRecoilValue(
|
||||
availableFilterDefinitionsState,
|
||||
const availableFilterDefinitions = useRecoilComponentValueV2(
|
||||
availableFilterDefinitionsComponentState,
|
||||
viewBarId,
|
||||
);
|
||||
|
||||
const isPersistingViewFields = useRecoilComponentValueV2(
|
||||
isPersistingViewFieldsComponentState,
|
||||
viewBarId,
|
||||
);
|
||||
const isPersistingViewFields = useRecoilValue(isPersistingViewFieldsState);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
|
||||
@ -1,12 +1,15 @@
|
||||
import { useEffect } from 'react';
|
||||
import { isNonEmptyString } from '@sniptt/guards';
|
||||
import { useEffect } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
|
||||
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||
import { useCombinedViewFilters } from '@/views/hooks/useCombinedViewFilters';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { useUpsertCombinedViewFilters } from '@/views/hooks/useUpsertCombinedViewFilters';
|
||||
import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
type ViewBarFilterEffectProps = {
|
||||
@ -16,17 +19,15 @@ type ViewBarFilterEffectProps = {
|
||||
export const ViewBarFilterEffect = ({
|
||||
filterDropdownId,
|
||||
}: ViewBarFilterEffectProps) => {
|
||||
const { availableFilterDefinitionsState } = useViewStates();
|
||||
|
||||
const { upsertCombinedViewFilter } = useCombinedViewFilters();
|
||||
const { upsertCombinedViewFilter } = useUpsertCombinedViewFilters();
|
||||
|
||||
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
|
||||
|
||||
const availableFilterDefinitions = useRecoilValue(
|
||||
availableFilterDefinitionsState,
|
||||
const availableFilterDefinitions = useRecoilComponentValueV2(
|
||||
availableFilterDefinitionsComponentState,
|
||||
);
|
||||
|
||||
const {
|
||||
setAvailableFilterDefinitions,
|
||||
setOnFilterSelect,
|
||||
filterDefinitionUsedInDropdownState,
|
||||
setObjectFilterDropdownSelectedRecordIds,
|
||||
@ -37,6 +38,12 @@ export const ViewBarFilterEffect = ({
|
||||
filterDefinitionUsedInDropdownState,
|
||||
);
|
||||
|
||||
// TODO: verify this instance id works
|
||||
const setAvailableFilterDefinitions = useSetRecoilComponentStateV2(
|
||||
availableFilterDefinitionsComponentState,
|
||||
filterDropdownId,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDefined(availableFilterDefinitions)) {
|
||||
setAvailableFilterDefinitions(availableFilterDefinitions);
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
import { useSortDropdown } from '@/object-record/object-sort-dropdown/hooks/useSortDropdown';
|
||||
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
|
||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||
import { useCombinedViewSorts } from '@/views/hooks/useCombinedViewSorts';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { useUpsertCombinedViewSorts } from '@/views/hooks/useUpsertCombinedViewSorts';
|
||||
import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
type ViewBarSortEffectProps = {
|
||||
@ -14,23 +16,23 @@ type ViewBarSortEffectProps = {
|
||||
export const ViewBarSortEffect = ({
|
||||
sortDropdownId,
|
||||
}: ViewBarSortEffectProps) => {
|
||||
const { availableSortDefinitionsState } = useViewStates();
|
||||
const { upsertCombinedViewSort } = useCombinedViewSorts();
|
||||
const { upsertCombinedViewSort } = useUpsertCombinedViewSorts();
|
||||
|
||||
const availableSortDefinitions = useRecoilValue(
|
||||
availableSortDefinitionsState,
|
||||
// TDOO: verify this instance id works
|
||||
const availableSortDefinitions = useRecoilComponentValueV2(
|
||||
availableSortDefinitionsComponentState,
|
||||
);
|
||||
|
||||
const {
|
||||
availableSortDefinitionsState: availableSortDefinitionsInSortDropdownState,
|
||||
onSortSelectState,
|
||||
} = useSortDropdown({
|
||||
const { onSortSelectState } = useSortDropdown({
|
||||
sortDropdownId,
|
||||
});
|
||||
|
||||
const setAvailableSortDefinitionsInSortDropdown = useSetRecoilState(
|
||||
availableSortDefinitionsInSortDropdownState,
|
||||
);
|
||||
// TDOO: verify this instance id works
|
||||
const setAvailableSortDefinitionsInSortDropdown =
|
||||
useSetRecoilComponentStateV2(
|
||||
availableSortDefinitionsComponentState,
|
||||
sortDropdownId,
|
||||
);
|
||||
const setOnSortSelect = useSetRecoilState(onSortSelectState);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
import { View } from '@/views/types/View';
|
||||
import { createEventContext } from '~/utils/createEventContext';
|
||||
|
||||
type ViewEventContextType = {
|
||||
onCurrentViewChange: (view: View | undefined) => void | Promise<void>;
|
||||
};
|
||||
|
||||
export const ViewEventContext = createEventContext<ViewEventContextType>();
|
||||
@ -1,91 +0,0 @@
|
||||
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||
import { extractComponentReadOnlySelector } from '@/ui/utilities/state/component-state/utils/extractComponentReadOnlySelector';
|
||||
import { extractComponentState } from '@/ui/utilities/state/component-state/utils/extractComponentState';
|
||||
import { availableFieldDefinitionsComponentState } from '@/views/states/availableFieldDefinitionsComponentState';
|
||||
import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState';
|
||||
import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState';
|
||||
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
||||
import { entityCountInCurrentViewComponentState } from '@/views/states/entityCountInCurrentViewComponentState';
|
||||
import { isCurrentViewKeyIndexComponentState } from '@/views/states/isCurrentViewIndexComponentState';
|
||||
import { isPersistingViewFieldsComponentState } from '@/views/states/isPersistingViewFieldsComponentState';
|
||||
import { isViewBarExpandedComponentState } from '@/views/states/isViewBarExpandedComponentState';
|
||||
import { onCurrentViewChangeComponentState } from '@/views/states/onCurrentViewChangeComponentState';
|
||||
import { canPersistViewComponentSelector } from '@/views/states/selectors/canPersistViewComponentSelector';
|
||||
import { unsavedToDeleteViewFilterIdsComponentState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentState';
|
||||
import { unsavedToDeleteViewSortIdsComponentState } from '@/views/states/unsavedToDeleteViewSortIdsComponentState';
|
||||
import { unsavedToUpsertViewFiltersComponentState } from '@/views/states/unsavedToUpsertViewFiltersComponentState';
|
||||
import { unsavedToUpsertViewSortsComponentState } from '@/views/states/unsavedToUpsertViewSortsComponentState';
|
||||
import { viewObjectMetadataIdComponentState } from '@/views/states/viewObjectMetadataIdComponentState';
|
||||
|
||||
import { ViewScopeInternalContext } from '../../scopes/scope-internal-context/ViewScopeInternalContext';
|
||||
|
||||
export const useViewStates = (viewComponentId?: string) => {
|
||||
const componentId = useAvailableScopeIdOrThrow(
|
||||
ViewScopeInternalContext,
|
||||
viewComponentId,
|
||||
);
|
||||
|
||||
return {
|
||||
componentId,
|
||||
currentViewIdState: extractComponentState(
|
||||
currentViewIdComponentState,
|
||||
componentId,
|
||||
),
|
||||
availableFieldDefinitionsState: extractComponentState(
|
||||
availableFieldDefinitionsComponentState,
|
||||
componentId,
|
||||
),
|
||||
availableFilterDefinitionsState: extractComponentState(
|
||||
availableFilterDefinitionsComponentState,
|
||||
componentId,
|
||||
),
|
||||
availableSortDefinitionsState: extractComponentState(
|
||||
availableSortDefinitionsComponentState,
|
||||
componentId,
|
||||
),
|
||||
canPersistViewSelector: extractComponentReadOnlySelector(
|
||||
canPersistViewComponentSelector,
|
||||
componentId,
|
||||
),
|
||||
isViewBarExpandedState: extractComponentState(
|
||||
isViewBarExpandedComponentState,
|
||||
componentId,
|
||||
),
|
||||
onCurrentViewChangeState: extractComponentState(
|
||||
onCurrentViewChangeComponentState,
|
||||
componentId,
|
||||
),
|
||||
entityCountInCurrentViewState: extractComponentState(
|
||||
entityCountInCurrentViewComponentState,
|
||||
componentId,
|
||||
),
|
||||
viewObjectMetadataIdState: extractComponentState(
|
||||
viewObjectMetadataIdComponentState,
|
||||
componentId,
|
||||
),
|
||||
unsavedToUpsertViewFiltersState: extractComponentState(
|
||||
unsavedToUpsertViewFiltersComponentState,
|
||||
componentId,
|
||||
),
|
||||
unsavedToUpsertViewSortsState: extractComponentState(
|
||||
unsavedToUpsertViewSortsComponentState,
|
||||
componentId,
|
||||
),
|
||||
unsavedToDeleteViewFilterIdsState: extractComponentState(
|
||||
unsavedToDeleteViewFilterIdsComponentState,
|
||||
componentId,
|
||||
),
|
||||
unsavedToDeleteViewSortIdsState: extractComponentState(
|
||||
unsavedToDeleteViewSortIdsComponentState,
|
||||
componentId,
|
||||
),
|
||||
isPersistingViewFieldsState: extractComponentState(
|
||||
isPersistingViewFieldsComponentState,
|
||||
componentId,
|
||||
),
|
||||
isCurrentViewKeyIndexState: extractComponentState(
|
||||
isCurrentViewKeyIndexComponentState,
|
||||
componentId,
|
||||
),
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,24 @@
|
||||
import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
|
||||
export const useChangeView = (viewBarComponentId?: string) => {
|
||||
const { resetUnsavedViewStates } =
|
||||
useResetUnsavedViewStates(viewBarComponentId);
|
||||
|
||||
const [, setSearchParams] = useSearchParams();
|
||||
|
||||
const setViewInUrl = (viewId: string) => {
|
||||
setSearchParams(() => {
|
||||
const searchParams = new URLSearchParams();
|
||||
searchParams.set('view', viewId);
|
||||
return searchParams;
|
||||
});
|
||||
};
|
||||
|
||||
const changeView = async (viewId: string) => {
|
||||
setViewInUrl(viewId);
|
||||
resetUnsavedViewStates(viewId);
|
||||
};
|
||||
|
||||
return { changeView };
|
||||
};
|
||||
@ -1,162 +0,0 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||
import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
|
||||
import { ViewFilter } from '@/views/types/ViewFilter';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const useCombinedViewFilters = (viewBarComponentId?: string) => {
|
||||
const {
|
||||
unsavedToUpsertViewFiltersState,
|
||||
unsavedToDeleteViewFilterIdsState,
|
||||
currentViewIdState,
|
||||
} = useViewStates(viewBarComponentId);
|
||||
|
||||
const { getViewFromCache } = useGetViewFromCache();
|
||||
|
||||
const upsertCombinedViewFilter = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
async (upsertedFilter: Filter) => {
|
||||
const unsavedToUpsertViewFilters = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToUpsertViewFiltersState,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewFilterIds = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToDeleteViewFilterIdsState,
|
||||
);
|
||||
|
||||
const currentViewId = getSnapshotValue(snapshot, currentViewIdState);
|
||||
|
||||
if (!currentViewId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentView = await getViewFromCache(currentViewId);
|
||||
|
||||
if (!currentView) {
|
||||
return;
|
||||
}
|
||||
|
||||
const matchingFilterInCurrentView = currentView.viewFilters.find(
|
||||
(viewFilter) =>
|
||||
viewFilter.fieldMetadataId === upsertedFilter.fieldMetadataId,
|
||||
);
|
||||
|
||||
const matchingFilterInUnsavedFilters = unsavedToUpsertViewFilters.find(
|
||||
(viewFilter) =>
|
||||
viewFilter.fieldMetadataId === upsertedFilter.fieldMetadataId,
|
||||
);
|
||||
|
||||
if (isDefined(matchingFilterInUnsavedFilters)) {
|
||||
const updatedFilters = unsavedToUpsertViewFilters.map((viewFilter) =>
|
||||
viewFilter.fieldMetadataId ===
|
||||
matchingFilterInUnsavedFilters.fieldMetadataId
|
||||
? { ...viewFilter, ...upsertedFilter, id: viewFilter.id }
|
||||
: viewFilter,
|
||||
);
|
||||
|
||||
set(unsavedToUpsertViewFiltersState, updatedFilters);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDefined(matchingFilterInCurrentView)) {
|
||||
set(unsavedToUpsertViewFiltersState, [
|
||||
...unsavedToUpsertViewFilters,
|
||||
{
|
||||
...matchingFilterInCurrentView,
|
||||
...upsertedFilter,
|
||||
id: matchingFilterInCurrentView.id,
|
||||
},
|
||||
]);
|
||||
set(
|
||||
unsavedToDeleteViewFilterIdsState,
|
||||
unsavedToDeleteViewFilterIds.filter(
|
||||
(id) => id !== matchingFilterInCurrentView.id,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
set(unsavedToUpsertViewFiltersState, [
|
||||
...unsavedToUpsertViewFilters,
|
||||
{
|
||||
...upsertedFilter,
|
||||
__typename: 'ViewFilter',
|
||||
} satisfies ViewFilter,
|
||||
]);
|
||||
},
|
||||
[
|
||||
currentViewIdState,
|
||||
getViewFromCache,
|
||||
unsavedToDeleteViewFilterIdsState,
|
||||
unsavedToUpsertViewFiltersState,
|
||||
],
|
||||
);
|
||||
const removeCombinedViewFilter = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
async (fieldId: string) => {
|
||||
const unsavedToUpsertViewFilters = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToUpsertViewFiltersState,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewFilterIds = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToDeleteViewFilterIdsState,
|
||||
);
|
||||
|
||||
const currentViewId = getSnapshotValue(snapshot, currentViewIdState);
|
||||
|
||||
if (!currentViewId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentView = await getViewFromCache(currentViewId);
|
||||
|
||||
if (!currentView) {
|
||||
return;
|
||||
}
|
||||
|
||||
const matchingFilterInCurrentView = currentView.viewFilters.find(
|
||||
(viewFilter) => viewFilter.id === fieldId,
|
||||
);
|
||||
|
||||
const matchingFilterInUnsavedFilters = unsavedToUpsertViewFilters.find(
|
||||
(viewFilter) => viewFilter.id === fieldId,
|
||||
);
|
||||
|
||||
if (isDefined(matchingFilterInUnsavedFilters)) {
|
||||
set(
|
||||
unsavedToUpsertViewFiltersState,
|
||||
unsavedToUpsertViewFilters.filter(
|
||||
(viewFilter) => viewFilter.id !== fieldId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (isDefined(matchingFilterInCurrentView)) {
|
||||
set(unsavedToDeleteViewFilterIdsState, [
|
||||
...new Set([
|
||||
...unsavedToDeleteViewFilterIds,
|
||||
matchingFilterInCurrentView.id,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
},
|
||||
[
|
||||
currentViewIdState,
|
||||
getViewFromCache,
|
||||
unsavedToDeleteViewFilterIdsState,
|
||||
unsavedToUpsertViewFiltersState,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
upsertCombinedViewFilter,
|
||||
removeCombinedViewFilter,
|
||||
};
|
||||
};
|
||||
@ -1,159 +0,0 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||
import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
|
||||
import { ViewSort } from '@/views/types/ViewSort';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const useCombinedViewSorts = (viewBarComponentId?: string) => {
|
||||
const {
|
||||
unsavedToUpsertViewSortsState,
|
||||
unsavedToDeleteViewSortIdsState,
|
||||
currentViewIdState,
|
||||
} = useViewStates(viewBarComponentId);
|
||||
|
||||
const { getViewFromCache } = useGetViewFromCache();
|
||||
|
||||
const upsertCombinedViewSort = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
async (upsertedSort: Sort) => {
|
||||
const unsavedToUpsertViewSorts = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToUpsertViewSortsState,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewSortIds = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToDeleteViewSortIdsState,
|
||||
);
|
||||
|
||||
const currentViewId = getSnapshotValue(snapshot, currentViewIdState);
|
||||
|
||||
if (!currentViewId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentView = await getViewFromCache(currentViewId);
|
||||
|
||||
if (!currentView) {
|
||||
return;
|
||||
}
|
||||
|
||||
const matchingSortInCurrentView = currentView.viewSorts.find(
|
||||
(viewSort) =>
|
||||
viewSort.fieldMetadataId === upsertedSort.fieldMetadataId,
|
||||
);
|
||||
|
||||
const matchingSortInUnsavedSorts = unsavedToUpsertViewSorts.find(
|
||||
(viewSort) =>
|
||||
viewSort.fieldMetadataId === upsertedSort.fieldMetadataId,
|
||||
);
|
||||
|
||||
if (isDefined(matchingSortInUnsavedSorts)) {
|
||||
const updatedSorts = unsavedToUpsertViewSorts.map((viewSort) =>
|
||||
viewSort.id === matchingSortInUnsavedSorts.id
|
||||
? { ...viewSort, ...upsertedSort }
|
||||
: viewSort,
|
||||
);
|
||||
|
||||
set(unsavedToUpsertViewSortsState, updatedSorts);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDefined(matchingSortInCurrentView)) {
|
||||
set(unsavedToUpsertViewSortsState, [
|
||||
...unsavedToUpsertViewSorts,
|
||||
{ ...matchingSortInCurrentView, ...upsertedSort },
|
||||
]);
|
||||
set(
|
||||
unsavedToDeleteViewSortIdsState,
|
||||
unsavedToDeleteViewSortIds.filter(
|
||||
(id) => id !== matchingSortInCurrentView.id,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
set(unsavedToUpsertViewSortsState, [
|
||||
...unsavedToUpsertViewSorts,
|
||||
{
|
||||
...upsertedSort,
|
||||
id: v4(),
|
||||
__typename: 'ViewSort',
|
||||
} satisfies ViewSort,
|
||||
]);
|
||||
},
|
||||
[
|
||||
currentViewIdState,
|
||||
getViewFromCache,
|
||||
unsavedToDeleteViewSortIdsState,
|
||||
unsavedToUpsertViewSortsState,
|
||||
],
|
||||
);
|
||||
const removeCombinedViewSort = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
async (fieldMetadataId: string) => {
|
||||
const unsavedToUpsertViewSorts = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToUpsertViewSortsState,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewSortIds = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToDeleteViewSortIdsState,
|
||||
);
|
||||
|
||||
const currentViewId = getSnapshotValue(snapshot, currentViewIdState);
|
||||
|
||||
if (!currentViewId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentView = await getViewFromCache(currentViewId);
|
||||
|
||||
if (!currentView) {
|
||||
return;
|
||||
}
|
||||
|
||||
const matchingSortInCurrentView = currentView.viewSorts.find(
|
||||
(viewSort) => viewSort.fieldMetadataId === fieldMetadataId,
|
||||
);
|
||||
|
||||
const matchingSortInUnsavedSorts = unsavedToUpsertViewSorts.find(
|
||||
(viewSort) => viewSort.fieldMetadataId === fieldMetadataId,
|
||||
);
|
||||
|
||||
if (isDefined(matchingSortInUnsavedSorts)) {
|
||||
set(
|
||||
unsavedToUpsertViewSortsState,
|
||||
unsavedToUpsertViewSorts.filter(
|
||||
(viewSort) => viewSort.fieldMetadataId !== fieldMetadataId,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDefined(matchingSortInCurrentView)) {
|
||||
set(unsavedToDeleteViewSortIdsState, [
|
||||
...new Set([
|
||||
...unsavedToDeleteViewSortIds,
|
||||
matchingSortInCurrentView.id,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
},
|
||||
[
|
||||
currentViewIdState,
|
||||
getViewFromCache,
|
||||
unsavedToDeleteViewSortIdsState,
|
||||
unsavedToUpsertViewSortsState,
|
||||
],
|
||||
);
|
||||
return {
|
||||
upsertCombinedViewSort,
|
||||
removeCombinedViewSort,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,34 @@
|
||||
import { usePersistViewFilterRecords } from '@/views/hooks/internal/usePersistViewFilterRecords';
|
||||
import { usePersistViewSortRecords } from '@/views/hooks/internal/usePersistViewSortRecords';
|
||||
|
||||
import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
|
||||
import { ViewFilter } from '@/views/types/ViewFilter';
|
||||
import { ViewSort } from '@/views/types/ViewSort';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const useCreateViewFiltersAndSorts = () => {
|
||||
const { getViewFromCache } = useGetViewFromCache();
|
||||
|
||||
const { createViewSortRecords } = usePersistViewSortRecords();
|
||||
|
||||
const { createViewFilterRecords } = usePersistViewFilterRecords();
|
||||
|
||||
const createViewFiltersAndSorts = async (
|
||||
viewIdToCreateOn: string,
|
||||
filtersToCreate: ViewFilter[],
|
||||
sortsToCreate: ViewSort[],
|
||||
) => {
|
||||
const view = await getViewFromCache(viewIdToCreateOn);
|
||||
|
||||
if (!isDefined(view)) {
|
||||
return;
|
||||
}
|
||||
|
||||
await createViewSortRecords(sortsToCreate, view);
|
||||
await createViewFilterRecords(filtersToCreate, view);
|
||||
};
|
||||
|
||||
return {
|
||||
createViewFiltersAndSorts,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,122 @@
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { usePersistViewFieldRecords } from '@/views/hooks/internal/usePersistViewFieldRecords';
|
||||
import { useCreateViewFiltersAndSorts } from '@/views/hooks/useCreateViewFiltersAndSorts';
|
||||
import { useGetViewFiltersCombined } from '@/views/hooks/useGetCombinedViewFilters';
|
||||
import { useGetViewSortsCombined } from '@/views/hooks/useGetCombinedViewSorts';
|
||||
import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
|
||||
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
||||
import { isPersistingViewFieldsComponentState } from '@/views/states/isPersistingViewFieldsComponentState';
|
||||
import { GraphQLView } from '@/views/types/GraphQLView';
|
||||
import { View } from '@/views/types/View';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-ui';
|
||||
import { v4 } from 'uuid';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
|
||||
export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => {
|
||||
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
|
||||
currentViewIdComponentState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const isPersistingViewFieldsCallbackState = useRecoilComponentCallbackStateV2(
|
||||
isPersistingViewFieldsComponentState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const { getViewFromCache } = useGetViewFromCache();
|
||||
|
||||
const { createOneRecord } = useCreateOneRecord<View>({
|
||||
objectNameSingular: CoreObjectNameSingular.View,
|
||||
});
|
||||
|
||||
const { createViewFieldRecords } = usePersistViewFieldRecords();
|
||||
|
||||
const { createViewFiltersAndSorts } = useCreateViewFiltersAndSorts();
|
||||
|
||||
const { getViewSortsCombined } = useGetViewSortsCombined(viewBarComponentId);
|
||||
const { getViewFiltersCombined } =
|
||||
useGetViewFiltersCombined(viewBarComponentId);
|
||||
|
||||
const createViewFromCurrentView = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
async (
|
||||
{
|
||||
id,
|
||||
name,
|
||||
icon,
|
||||
kanbanFieldMetadataId,
|
||||
type,
|
||||
}: Partial<
|
||||
Pick<
|
||||
GraphQLView,
|
||||
'id' | 'name' | 'icon' | 'kanbanFieldMetadataId' | 'type'
|
||||
>
|
||||
>,
|
||||
shouldCopyFiltersAndSorts?: boolean,
|
||||
) => {
|
||||
const currentViewId = getSnapshotValue(
|
||||
snapshot,
|
||||
currentViewIdCallbackState,
|
||||
);
|
||||
|
||||
if (!isDefined(currentViewId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Here we might instead want to get view from unsaved filters ?
|
||||
const view = await getViewFromCache(currentViewId);
|
||||
|
||||
if (!isDefined(view)) {
|
||||
return;
|
||||
}
|
||||
|
||||
set(isPersistingViewFieldsCallbackState, true);
|
||||
|
||||
const newView = await createOneRecord({
|
||||
id: id ?? v4(),
|
||||
name: name ?? view.name,
|
||||
icon: icon ?? view.icon,
|
||||
key: null,
|
||||
kanbanFieldMetadataId:
|
||||
kanbanFieldMetadataId ?? view.kanbanFieldMetadataId,
|
||||
type: type ?? view.type,
|
||||
objectMetadataId: view.objectMetadataId,
|
||||
});
|
||||
|
||||
if (isUndefinedOrNull(newView)) {
|
||||
throw new Error('Failed to create view');
|
||||
}
|
||||
|
||||
await createViewFieldRecords(view.viewFields, newView);
|
||||
|
||||
if (shouldCopyFiltersAndSorts === true) {
|
||||
const sourceViewCombinedFilters = getViewFiltersCombined(view.id);
|
||||
const sourceViewCombinedSorts = getViewSortsCombined(view.id);
|
||||
|
||||
await createViewFiltersAndSorts(
|
||||
newView.id,
|
||||
sourceViewCombinedFilters,
|
||||
sourceViewCombinedSorts,
|
||||
);
|
||||
}
|
||||
|
||||
set(isPersistingViewFieldsCallbackState, false);
|
||||
},
|
||||
[
|
||||
createOneRecord,
|
||||
createViewFieldRecords,
|
||||
getViewSortsCombined,
|
||||
getViewFiltersCombined,
|
||||
currentViewIdCallbackState,
|
||||
getViewFromCache,
|
||||
isPersistingViewFieldsCallbackState,
|
||||
createViewFiltersAndSorts,
|
||||
],
|
||||
);
|
||||
|
||||
return { createViewFromCurrentView };
|
||||
};
|
||||
@ -0,0 +1,101 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
|
||||
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
||||
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
|
||||
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const useDeleteCombinedViewFilters = (viewBarComponentId?: string) => {
|
||||
const unsavedToUpsertViewFiltersCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewFiltersComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewFilterIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewFilterIdsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
|
||||
currentViewIdComponentState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const { getViewFromCache } = useGetViewFromCache();
|
||||
|
||||
const deleteCombinedViewFilter = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
async (fieldId: string) => {
|
||||
const currentViewId = getSnapshotValue(
|
||||
snapshot,
|
||||
currentViewIdCallbackState,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewFilters = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }),
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewFilterIds = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToDeleteViewFilterIdsCallbackState({ viewId: currentViewId }),
|
||||
);
|
||||
|
||||
if (!currentViewId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentView = await getViewFromCache(currentViewId);
|
||||
|
||||
if (!currentView) {
|
||||
return;
|
||||
}
|
||||
|
||||
const matchingFilterInCurrentView = currentView.viewFilters.find(
|
||||
(viewFilter) => viewFilter.id === fieldId,
|
||||
);
|
||||
|
||||
const matchingFilterInUnsavedFilters = unsavedToUpsertViewFilters.find(
|
||||
(viewFilter) => viewFilter.id === fieldId,
|
||||
);
|
||||
|
||||
if (isDefined(matchingFilterInUnsavedFilters)) {
|
||||
set(
|
||||
unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }),
|
||||
unsavedToUpsertViewFilters.filter(
|
||||
(viewFilter) => viewFilter.id !== fieldId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (isDefined(matchingFilterInCurrentView)) {
|
||||
set(
|
||||
unsavedToDeleteViewFilterIdsCallbackState({
|
||||
viewId: currentViewId,
|
||||
}),
|
||||
[
|
||||
...new Set([
|
||||
...unsavedToDeleteViewFilterIds,
|
||||
matchingFilterInCurrentView.id,
|
||||
]),
|
||||
],
|
||||
);
|
||||
}
|
||||
},
|
||||
[
|
||||
currentViewIdCallbackState,
|
||||
getViewFromCache,
|
||||
unsavedToDeleteViewFilterIdsCallbackState,
|
||||
unsavedToUpsertViewFiltersCallbackState,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
deleteCombinedViewFilter,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,100 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
|
||||
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
||||
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
|
||||
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const useDeleteCombinedViewSorts = (viewBarComponentId?: string) => {
|
||||
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
|
||||
currentViewIdComponentState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewSortsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewSortsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewSortIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewSortIdsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const { getViewFromCache } = useGetViewFromCache();
|
||||
|
||||
const deleteCombinedViewSort = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
async (fieldMetadataId: string) => {
|
||||
const currentViewId = getSnapshotValue(
|
||||
snapshot,
|
||||
currentViewIdCallbackState,
|
||||
);
|
||||
|
||||
if (!currentViewId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const unsavedToUpsertViewSorts = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }),
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewSortIds = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToDeleteViewSortIdsCallbackState({ viewId: currentViewId }),
|
||||
);
|
||||
|
||||
const currentView = await getViewFromCache(currentViewId);
|
||||
|
||||
if (!currentView) {
|
||||
return;
|
||||
}
|
||||
|
||||
const matchingSortInCurrentView = currentView.viewSorts.find(
|
||||
(viewSort) => viewSort.fieldMetadataId === fieldMetadataId,
|
||||
);
|
||||
|
||||
const matchingSortInUnsavedSorts = unsavedToUpsertViewSorts.find(
|
||||
(viewSort) => viewSort.fieldMetadataId === fieldMetadataId,
|
||||
);
|
||||
|
||||
if (isDefined(matchingSortInUnsavedSorts)) {
|
||||
set(
|
||||
unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }),
|
||||
unsavedToUpsertViewSorts.filter(
|
||||
(viewSort) => viewSort.fieldMetadataId !== fieldMetadataId,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDefined(matchingSortInCurrentView)) {
|
||||
set(
|
||||
unsavedToDeleteViewSortIdsCallbackState({ viewId: currentViewId }),
|
||||
[
|
||||
...new Set([
|
||||
...unsavedToDeleteViewSortIds,
|
||||
matchingSortInCurrentView.id,
|
||||
]),
|
||||
],
|
||||
);
|
||||
}
|
||||
},
|
||||
[
|
||||
currentViewIdCallbackState,
|
||||
getViewFromCache,
|
||||
unsavedToDeleteViewSortIdsCallbackState,
|
||||
unsavedToUpsertViewSortsCallbackState,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
deleteCombinedViewSort,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,18 @@
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
export const useDeleteView = () => {
|
||||
const { deleteOneRecord } = useDeleteOneRecord({
|
||||
objectNameSingular: CoreObjectNameSingular.View,
|
||||
});
|
||||
|
||||
const deleteView = useRecoilCallback(
|
||||
() => async (viewId: string) => {
|
||||
await deleteOneRecord(viewId);
|
||||
},
|
||||
[deleteOneRecord],
|
||||
);
|
||||
|
||||
return { deleteView };
|
||||
};
|
||||
@ -0,0 +1,67 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
|
||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
|
||||
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
|
||||
import { View } from '@/views/types/View';
|
||||
import { getCombinedViewFilters } from '@/views/utils/getCombinedViewFilters';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const useGetViewFiltersCombined = (viewBarComponentId?: string) => {
|
||||
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
|
||||
|
||||
const unsavedToUpsertViewFiltersCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewFiltersComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewFilterIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewFilterIdsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const getViewFiltersCombined = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
(viewId: string) => {
|
||||
const view = views.find((view) => view.id === viewId);
|
||||
|
||||
if (!isDefined(view)) {
|
||||
throw new Error(
|
||||
`Cannot get view with id ${viewId}, because it cannot be found in client cache data.`,
|
||||
);
|
||||
}
|
||||
|
||||
const unsavedToUpsertViewFilters = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToUpsertViewFiltersCallbackState({ viewId: view.id }),
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewFilterIds = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToDeleteViewFilterIdsCallbackState({ viewId: view.id }),
|
||||
);
|
||||
|
||||
const combinedViewFilters = getCombinedViewFilters(
|
||||
view.viewFilters,
|
||||
unsavedToUpsertViewFilters,
|
||||
unsavedToDeleteViewFilterIds,
|
||||
);
|
||||
|
||||
return combinedViewFilters;
|
||||
},
|
||||
[
|
||||
views,
|
||||
unsavedToDeleteViewFilterIdsCallbackState,
|
||||
unsavedToUpsertViewFiltersCallbackState,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
getViewFiltersCombined,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,68 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
|
||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
|
||||
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
|
||||
import { View } from '@/views/types/View';
|
||||
import { getCombinedViewSorts } from '@/views/utils/getCombinedViewSorts';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
// TODO: fix naming
|
||||
export const useGetViewSortsCombined = (viewBarComponentId?: string) => {
|
||||
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
|
||||
|
||||
const unsavedToUpsertViewSortsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewSortsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewSortIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewSortIdsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const getViewSortsCombined = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
(viewId: string) => {
|
||||
const view = views.find((view) => view.id === viewId);
|
||||
|
||||
if (!isDefined(view)) {
|
||||
throw new Error(
|
||||
`Cannot get view with id ${viewId}, because it cannot be found in client cache data.`,
|
||||
);
|
||||
}
|
||||
|
||||
const unsavedToUpsertViewSorts = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToUpsertViewSortsCallbackState({ viewId: view.id }),
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewSortIds = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToDeleteViewSortIdsCallbackState({ viewId: view.id }),
|
||||
);
|
||||
|
||||
const combinedViewSorts = getCombinedViewSorts(
|
||||
view.viewSorts,
|
||||
unsavedToUpsertViewSorts,
|
||||
unsavedToDeleteViewSortIds,
|
||||
);
|
||||
|
||||
return combinedViewSorts;
|
||||
},
|
||||
[
|
||||
views,
|
||||
unsavedToDeleteViewSortIdsCallbackState,
|
||||
unsavedToUpsertViewSortsCallbackState,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
getViewSortsCombined,
|
||||
};
|
||||
};
|
||||
@ -1,39 +1,46 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
|
||||
import { usePrefetchedData } from '@/prefetch/hooks/usePrefetchedData';
|
||||
import { PrefetchKey } from '@/prefetch/types/PrefetchKey';
|
||||
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
|
||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||
import { ViewScopeInternalContext } from '@/views/scopes/scope-internal-context/ViewScopeInternalContext';
|
||||
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
|
||||
import { useRecoilComponentFamilyValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValueV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
||||
import { isCurrentViewKeyIndexComponentState } from '@/views/states/isCurrentViewIndexComponentState';
|
||||
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
|
||||
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
|
||||
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
|
||||
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
|
||||
import { viewObjectMetadataIdComponentState } from '@/views/states/viewObjectMetadataIdComponentState';
|
||||
import { View } from '@/views/types/View';
|
||||
import { combinedViewFilters } from '@/views/utils/combinedViewFilters';
|
||||
import { combinedViewSorts } from '@/views/utils/combinedViewSorts';
|
||||
import { getCombinedViewFilters } from '@/views/utils/getCombinedViewFilters';
|
||||
import { getCombinedViewSorts } from '@/views/utils/getCombinedViewSorts';
|
||||
import { getObjectMetadataItemViews } from '@/views/utils/getObjectMetadataItemViews';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const useGetCurrentView = (viewBarComponentId?: string) => {
|
||||
const componentId = useAvailableScopeIdOrThrow(
|
||||
ViewScopeInternalContext,
|
||||
viewBarComponentId,
|
||||
export const useGetCurrentView = (viewBarInstanceId?: string) => {
|
||||
const instanceId = useAvailableComponentInstanceIdOrThrow(
|
||||
ViewComponentInstanceContext,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const { records: views } = usePrefetchedData<View>(PrefetchKey.AllViews);
|
||||
|
||||
const {
|
||||
currentViewIdState,
|
||||
viewObjectMetadataIdState,
|
||||
unsavedToUpsertViewFiltersState,
|
||||
unsavedToDeleteViewFilterIdsState,
|
||||
unsavedToDeleteViewSortIdsState,
|
||||
unsavedToUpsertViewSortsState,
|
||||
isCurrentViewKeyIndexState,
|
||||
} = useViewStates(componentId);
|
||||
const currentViewId = useRecoilComponentValueV2(
|
||||
currentViewIdComponentState,
|
||||
instanceId,
|
||||
);
|
||||
|
||||
const currentViewId = useRecoilValue(currentViewIdState);
|
||||
const viewObjectMetadataId = useRecoilValue(viewObjectMetadataIdState);
|
||||
const setIsCurrentViewKeyIndex = useSetRecoilState(
|
||||
isCurrentViewKeyIndexState,
|
||||
const viewObjectMetadataId = useRecoilComponentValueV2(
|
||||
viewObjectMetadataIdComponentState,
|
||||
instanceId,
|
||||
);
|
||||
|
||||
const setIsCurrentViewKeyIndex = useSetRecoilComponentStateV2(
|
||||
isCurrentViewKeyIndexComponentState,
|
||||
instanceId,
|
||||
);
|
||||
|
||||
const currentViewFromCurrentViewId = views.find(
|
||||
@ -46,6 +53,8 @@ export const useGetCurrentView = (viewBarComponentId?: string) => {
|
||||
|
||||
const currentView = currentViewId ? currentViewFromCurrentViewId : indexView;
|
||||
|
||||
const viewId = currentViewId ?? indexView?.id;
|
||||
|
||||
useEffect(() => {
|
||||
setIsCurrentViewKeyIndex(currentView?.key === 'INDEX');
|
||||
}, [currentView, setIsCurrentViewKeyIndex]);
|
||||
@ -55,22 +64,33 @@ export const useGetCurrentView = (viewBarComponentId?: string) => {
|
||||
views,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewFilters = useRecoilValue(
|
||||
unsavedToUpsertViewFiltersState,
|
||||
const unsavedToUpsertViewFilters = useRecoilComponentFamilyValueV2(
|
||||
unsavedToUpsertViewFiltersComponentFamilyState,
|
||||
{ viewId },
|
||||
instanceId,
|
||||
);
|
||||
const unsavedToUpsertViewSorts = useRecoilValue(
|
||||
unsavedToUpsertViewSortsState,
|
||||
|
||||
const unsavedToUpsertViewSorts = useRecoilComponentFamilyValueV2(
|
||||
unsavedToUpsertViewSortsComponentFamilyState,
|
||||
{ viewId },
|
||||
instanceId,
|
||||
);
|
||||
const unsavedToDeleteViewFilterIds = useRecoilValue(
|
||||
unsavedToDeleteViewFilterIdsState,
|
||||
|
||||
const unsavedToDeleteViewFilterIds = useRecoilComponentFamilyValueV2(
|
||||
unsavedToDeleteViewFilterIdsComponentFamilyState,
|
||||
{ viewId },
|
||||
instanceId,
|
||||
);
|
||||
const unsavedToDeleteViewSortIds = useRecoilValue(
|
||||
unsavedToDeleteViewSortIdsState,
|
||||
|
||||
const unsavedToDeleteViewSortIds = useRecoilComponentFamilyValueV2(
|
||||
unsavedToDeleteViewSortIdsComponentFamilyState,
|
||||
{ viewId },
|
||||
instanceId,
|
||||
);
|
||||
|
||||
if (!isDefined(currentView)) {
|
||||
return {
|
||||
componentId,
|
||||
instanceId,
|
||||
currentViewWithSavedFiltersAndSorts: undefined,
|
||||
currentViewWithCombinedFiltersAndSorts: undefined,
|
||||
viewsOnCurrentObject: viewsOnCurrentObject ?? [],
|
||||
@ -79,12 +99,12 @@ export const useGetCurrentView = (viewBarComponentId?: string) => {
|
||||
|
||||
const currentViewWithCombinedFiltersAndSorts = {
|
||||
...currentView,
|
||||
viewFilters: combinedViewFilters(
|
||||
viewFilters: getCombinedViewFilters(
|
||||
currentView.viewFilters,
|
||||
unsavedToUpsertViewFilters,
|
||||
unsavedToDeleteViewFilterIds,
|
||||
),
|
||||
viewSorts: combinedViewSorts(
|
||||
viewSorts: getCombinedViewSorts(
|
||||
currentView.viewSorts,
|
||||
unsavedToUpsertViewSorts,
|
||||
unsavedToDeleteViewSortIds,
|
||||
@ -92,9 +112,10 @@ export const useGetCurrentView = (viewBarComponentId?: string) => {
|
||||
};
|
||||
|
||||
return {
|
||||
componentId,
|
||||
instanceId,
|
||||
currentViewWithSavedFiltersAndSorts: currentView,
|
||||
currentViewWithCombinedFiltersAndSorts,
|
||||
viewsOnCurrentObject: viewsOnCurrentObject ?? [],
|
||||
currentViewId,
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,165 +0,0 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
|
||||
import { useDeleteOneRecord } from '@/object-record/hooks/useDeleteOneRecord';
|
||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { usePersistViewFieldRecords } from '@/views/hooks/internal/usePersistViewFieldRecords';
|
||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||
import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
|
||||
import { useResetCurrentView } from '@/views/hooks/useResetCurrentView';
|
||||
import { useSaveCurrentViewFiltersAndSorts } from '@/views/hooks/useSaveCurrentViewFiltersAndSorts';
|
||||
import { GraphQLView } from '@/views/types/GraphQLView';
|
||||
import { View } from '@/views/types/View';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
|
||||
export const useHandleViews = (viewBarComponentId?: string) => {
|
||||
const { resetCurrentView } = useResetCurrentView(viewBarComponentId);
|
||||
|
||||
const { currentViewIdState, isPersistingViewFieldsState } =
|
||||
useViewStates(viewBarComponentId);
|
||||
|
||||
const { getViewFromCache } = useGetViewFromCache();
|
||||
|
||||
const { deleteOneRecord } = useDeleteOneRecord({
|
||||
objectNameSingular: CoreObjectNameSingular.View,
|
||||
});
|
||||
|
||||
const { createOneRecord } = useCreateOneRecord<View>({
|
||||
objectNameSingular: CoreObjectNameSingular.View,
|
||||
});
|
||||
|
||||
const { updateOneRecord } = useUpdateOneRecord({
|
||||
objectNameSingular: CoreObjectNameSingular.View,
|
||||
});
|
||||
|
||||
const { createViewFieldRecords } = usePersistViewFieldRecords();
|
||||
const { saveCurrentViewFilterAndSorts } =
|
||||
useSaveCurrentViewFiltersAndSorts(viewBarComponentId);
|
||||
|
||||
const [, setSearchParams] = useSearchParams();
|
||||
|
||||
const removeView = useRecoilCallback(
|
||||
() => async (viewId: string) => {
|
||||
await deleteOneRecord(viewId);
|
||||
},
|
||||
[deleteOneRecord],
|
||||
);
|
||||
|
||||
const createView = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
async ({
|
||||
id,
|
||||
name,
|
||||
icon,
|
||||
kanbanFieldMetadataId,
|
||||
type,
|
||||
}: Partial<
|
||||
Pick<
|
||||
GraphQLView,
|
||||
'id' | 'name' | 'icon' | 'kanbanFieldMetadataId' | 'type'
|
||||
>
|
||||
>) => {
|
||||
const currentViewId = getSnapshotValue(snapshot, currentViewIdState);
|
||||
|
||||
if (!isDefined(currentViewId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const view = await getViewFromCache(currentViewId);
|
||||
|
||||
if (!isDefined(view)) {
|
||||
return;
|
||||
}
|
||||
|
||||
set(isPersistingViewFieldsState, true);
|
||||
|
||||
const newView = await createOneRecord({
|
||||
id: id ?? v4(),
|
||||
name: name ?? view.name,
|
||||
icon: icon ?? view.icon,
|
||||
key: null,
|
||||
kanbanFieldMetadataId:
|
||||
kanbanFieldMetadataId ?? view.kanbanFieldMetadataId,
|
||||
type: type ?? view.type,
|
||||
objectMetadataId: view.objectMetadataId,
|
||||
});
|
||||
|
||||
if (isUndefinedOrNull(newView)) {
|
||||
throw new Error('Failed to create view');
|
||||
}
|
||||
|
||||
await createViewFieldRecords(view.viewFields, newView);
|
||||
await saveCurrentViewFilterAndSorts(newView.id);
|
||||
set(isPersistingViewFieldsState, false);
|
||||
},
|
||||
[
|
||||
createOneRecord,
|
||||
createViewFieldRecords,
|
||||
currentViewIdState,
|
||||
getViewFromCache,
|
||||
isPersistingViewFieldsState,
|
||||
saveCurrentViewFilterAndSorts,
|
||||
],
|
||||
);
|
||||
|
||||
const changeViewInUrl = useCallback(
|
||||
(viewId: string) => {
|
||||
setSearchParams(() => {
|
||||
const searchParams = new URLSearchParams();
|
||||
searchParams.set('view', viewId);
|
||||
return searchParams;
|
||||
});
|
||||
},
|
||||
[setSearchParams],
|
||||
);
|
||||
|
||||
const selectView = useRecoilCallback(
|
||||
() => async (viewId: string) => {
|
||||
changeViewInUrl(viewId);
|
||||
resetCurrentView();
|
||||
},
|
||||
[changeViewInUrl, resetCurrentView],
|
||||
);
|
||||
|
||||
const updateCurrentView = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
async (view: Partial<GraphQLView>) => {
|
||||
const currentViewId = snapshot
|
||||
.getLoadable(currentViewIdState)
|
||||
.getValue();
|
||||
if (isDefined(currentViewId)) {
|
||||
await updateOneRecord({
|
||||
idToUpdate: currentViewId,
|
||||
updateOneRecordInput: view,
|
||||
});
|
||||
}
|
||||
},
|
||||
[currentViewIdState, updateOneRecord],
|
||||
);
|
||||
|
||||
const updateView = useRecoilCallback(
|
||||
() => async (view: Partial<GraphQLView>) => {
|
||||
if (isDefined(view.id)) {
|
||||
await updateOneRecord({
|
||||
idToUpdate: view.id,
|
||||
updateOneRecordInput: view,
|
||||
});
|
||||
}
|
||||
},
|
||||
[updateOneRecord],
|
||||
);
|
||||
|
||||
return {
|
||||
selectView,
|
||||
updateCurrentView,
|
||||
updateView,
|
||||
removeView,
|
||||
createView,
|
||||
};
|
||||
};
|
||||
@ -1,26 +1,29 @@
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { availableFieldDefinitionsComponentState } from '@/views/states/availableFieldDefinitionsComponentState';
|
||||
import { availableFilterDefinitionsComponentState } from '@/views/states/availableFilterDefinitionsComponentState';
|
||||
import { availableSortDefinitionsComponentState } from '@/views/states/availableSortDefinitionsComponentState';
|
||||
import { viewObjectMetadataIdComponentState } from '@/views/states/viewObjectMetadataIdComponentState';
|
||||
|
||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||
|
||||
export const useInitViewBar = (viewBarComponentId?: string) => {
|
||||
const {
|
||||
availableFieldDefinitionsState,
|
||||
availableSortDefinitionsState,
|
||||
availableFilterDefinitionsState,
|
||||
viewObjectMetadataIdState,
|
||||
} = useViewStates(viewBarComponentId);
|
||||
|
||||
const setAvailableFieldDefinitions = useSetRecoilState(
|
||||
availableFieldDefinitionsState,
|
||||
);
|
||||
const setAvailableSortDefinitions = useSetRecoilState(
|
||||
availableSortDefinitionsState,
|
||||
);
|
||||
const setAvailableFilterDefinitions = useSetRecoilState(
|
||||
availableFilterDefinitionsState,
|
||||
export const useInitViewBar = (viewBarInstanceId?: string) => {
|
||||
const setAvailableFieldDefinitions = useSetRecoilComponentStateV2(
|
||||
availableFieldDefinitionsComponentState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const setViewObjectMetadataId = useSetRecoilState(viewObjectMetadataIdState);
|
||||
const setAvailableSortDefinitions = useSetRecoilComponentStateV2(
|
||||
availableSortDefinitionsComponentState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const setAvailableFilterDefinitions = useSetRecoilComponentStateV2(
|
||||
availableFilterDefinitionsComponentState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const setViewObjectMetadataId = useSetRecoilComponentStateV2(
|
||||
viewObjectMetadataIdComponentState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
return {
|
||||
setAvailableFieldDefinitions,
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||
|
||||
export const useResetCurrentView = (viewBarComponentId?: string) => {
|
||||
const {
|
||||
unsavedToDeleteViewSortIdsState,
|
||||
unsavedToUpsertViewSortsState,
|
||||
unsavedToDeleteViewFilterIdsState,
|
||||
unsavedToUpsertViewFiltersState,
|
||||
} = useViewStates(viewBarComponentId);
|
||||
|
||||
const resetCurrentView = useRecoilCallback(
|
||||
({ set }) =>
|
||||
async () => {
|
||||
set(unsavedToDeleteViewFilterIdsState, []);
|
||||
set(unsavedToDeleteViewSortIdsState, []);
|
||||
set(unsavedToUpsertViewFiltersState, []);
|
||||
set(unsavedToUpsertViewSortsState, []);
|
||||
},
|
||||
[
|
||||
unsavedToDeleteViewFilterIdsState,
|
||||
unsavedToDeleteViewSortIdsState,
|
||||
unsavedToUpsertViewFiltersState,
|
||||
unsavedToUpsertViewSortsState,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
resetCurrentView,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,52 @@
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
|
||||
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
|
||||
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
|
||||
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
export const useResetUnsavedViewStates = (viewBarInstanceId?: string) => {
|
||||
const setUnsavedToDeleteViewFilterIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewFilterIdsComponentFamilyState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const setUnsavedToDeleteViewSortIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewSortIdsComponentFamilyState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const setUnsavedToUpsertViewFiltersCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewFiltersComponentFamilyState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewSortsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewSortsComponentFamilyState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const resetUnsavedViewStates = useRecoilCallback(
|
||||
({ set }) =>
|
||||
(viewId: string) => {
|
||||
set(setUnsavedToDeleteViewFilterIdsCallbackState({ viewId }), []);
|
||||
set(setUnsavedToDeleteViewSortIdsCallbackState({ viewId }), []);
|
||||
set(setUnsavedToUpsertViewFiltersCallbackState({ viewId }), []);
|
||||
set(unsavedToUpsertViewSortsCallbackState({ viewId }), []);
|
||||
},
|
||||
[
|
||||
unsavedToUpsertViewSortsCallbackState,
|
||||
setUnsavedToUpsertViewFiltersCallbackState,
|
||||
setUnsavedToDeleteViewSortIdsCallbackState,
|
||||
setUnsavedToDeleteViewFilterIdsCallbackState,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
resetUnsavedViewStates,
|
||||
};
|
||||
};
|
||||
@ -1,8 +1,10 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { usePersistViewFieldRecords } from '@/views/hooks/internal/usePersistViewFieldRecords';
|
||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||
import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
|
||||
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
||||
import { isPersistingViewFieldsComponentState } from '@/views/states/isPersistingViewFieldsComponentState';
|
||||
import { ViewField } from '@/views/types/ViewField';
|
||||
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
@ -14,21 +16,28 @@ export const useSaveCurrentViewFields = (viewBarComponentId?: string) => {
|
||||
|
||||
const { getViewFromCache } = useGetViewFromCache();
|
||||
|
||||
const { isPersistingViewFieldsState, currentViewIdState } =
|
||||
useViewStates(viewBarComponentId);
|
||||
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
|
||||
currentViewIdComponentState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const isPersistingViewFieldsCallbackState = useRecoilComponentCallbackStateV2(
|
||||
isPersistingViewFieldsComponentState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const saveViewFields = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
async (viewFieldsToSave: ViewField[]) => {
|
||||
const currentViewId = snapshot
|
||||
.getLoadable(currentViewIdState)
|
||||
.getLoadable(currentViewIdCallbackState)
|
||||
.getValue();
|
||||
|
||||
if (!currentViewId) {
|
||||
return;
|
||||
}
|
||||
|
||||
set(isPersistingViewFieldsState, true);
|
||||
set(isPersistingViewFieldsCallbackState, true);
|
||||
|
||||
const view = await getViewFromCache(currentViewId);
|
||||
|
||||
@ -85,13 +94,13 @@ export const useSaveCurrentViewFields = (viewBarComponentId?: string) => {
|
||||
updateViewFieldRecords(viewFieldsToUpdate),
|
||||
]);
|
||||
|
||||
set(isPersistingViewFieldsState, false);
|
||||
set(isPersistingViewFieldsCallbackState, false);
|
||||
},
|
||||
[
|
||||
createViewFieldRecords,
|
||||
currentViewIdState,
|
||||
currentViewIdCallbackState,
|
||||
getViewFromCache,
|
||||
isPersistingViewFieldsState,
|
||||
isPersistingViewFieldsCallbackState,
|
||||
updateViewFieldRecords,
|
||||
],
|
||||
);
|
||||
|
||||
@ -1,11 +1,16 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { usePersistViewFilterRecords } from '@/views/hooks/internal/usePersistViewFilterRecords';
|
||||
import { usePersistViewSortRecords } from '@/views/hooks/internal/usePersistViewSortRecords';
|
||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||
import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
|
||||
import { useResetCurrentView } from '@/views/hooks/useResetCurrentView';
|
||||
import { useResetUnsavedViewStates } from '@/views/hooks/useResetUnsavedViewStates';
|
||||
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
||||
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
|
||||
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
|
||||
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
|
||||
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
|
||||
|
||||
@ -14,13 +19,34 @@ export const useSaveCurrentViewFiltersAndSorts = (
|
||||
) => {
|
||||
const { getViewFromCache } = useGetViewFromCache();
|
||||
|
||||
const {
|
||||
unsavedToDeleteViewSortIdsState,
|
||||
unsavedToUpsertViewSortsState,
|
||||
unsavedToDeleteViewFilterIdsState,
|
||||
unsavedToUpsertViewFiltersState,
|
||||
currentViewIdState,
|
||||
} = useViewStates(viewBarComponentId);
|
||||
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
|
||||
currentViewIdComponentState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewSortIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewSortIdsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewSortsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewSortsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewFilterIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewFilterIdsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewFiltersCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewFiltersComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const {
|
||||
createViewSortRecords,
|
||||
@ -34,19 +60,20 @@ export const useSaveCurrentViewFiltersAndSorts = (
|
||||
deleteViewFilterRecords,
|
||||
} = usePersistViewFilterRecords();
|
||||
|
||||
const { resetCurrentView } = useResetCurrentView(viewBarComponentId);
|
||||
const { resetUnsavedViewStates } =
|
||||
useResetUnsavedViewStates(viewBarComponentId);
|
||||
|
||||
const saveViewSorts = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
async (viewId: string) => {
|
||||
const unsavedToDeleteViewSortIds = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToDeleteViewSortIdsState,
|
||||
unsavedToDeleteViewSortIdsCallbackState({ viewId }),
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewSorts = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToUpsertViewSortsState,
|
||||
unsavedToUpsertViewSortsCallbackState({ viewId }),
|
||||
);
|
||||
|
||||
const view = await getViewFromCache(viewId);
|
||||
@ -76,8 +103,8 @@ export const useSaveCurrentViewFiltersAndSorts = (
|
||||
createViewSortRecords,
|
||||
deleteViewSortRecords,
|
||||
getViewFromCache,
|
||||
unsavedToDeleteViewSortIdsState,
|
||||
unsavedToUpsertViewSortsState,
|
||||
unsavedToDeleteViewSortIdsCallbackState,
|
||||
unsavedToUpsertViewSortsCallbackState,
|
||||
updateViewSortRecords,
|
||||
],
|
||||
);
|
||||
@ -87,12 +114,12 @@ export const useSaveCurrentViewFiltersAndSorts = (
|
||||
async (viewId: string) => {
|
||||
const unsavedToDeleteViewFilterIds = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToDeleteViewFilterIdsState,
|
||||
unsavedToDeleteViewFilterIdsCallbackState({ viewId }),
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewFilters = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToUpsertViewFiltersState,
|
||||
unsavedToUpsertViewFiltersCallbackState({ viewId }),
|
||||
);
|
||||
|
||||
const view = await getViewFromCache(viewId);
|
||||
@ -123,28 +150,36 @@ export const useSaveCurrentViewFiltersAndSorts = (
|
||||
createViewFilterRecords,
|
||||
deleteViewFilterRecords,
|
||||
getViewFromCache,
|
||||
unsavedToDeleteViewFilterIdsState,
|
||||
unsavedToUpsertViewFiltersState,
|
||||
unsavedToDeleteViewFilterIdsCallbackState,
|
||||
unsavedToUpsertViewFiltersCallbackState,
|
||||
updateViewFilterRecords,
|
||||
],
|
||||
);
|
||||
|
||||
const saveCurrentViewFilterAndSorts = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
async (viewId?: string) => {
|
||||
async (viewIdFromProps?: string) => {
|
||||
const currentViewId = snapshot
|
||||
.getLoadable(currentViewIdState)
|
||||
.getLoadable(currentViewIdCallbackState)
|
||||
.getValue();
|
||||
|
||||
if (!isDefined(currentViewId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
await saveViewFilters(viewId ?? currentViewId);
|
||||
await saveViewSorts(viewId ?? currentViewId);
|
||||
resetCurrentView();
|
||||
const viewId = viewIdFromProps ?? currentViewId;
|
||||
|
||||
await saveViewFilters(viewId);
|
||||
await saveViewSorts(viewId);
|
||||
|
||||
resetUnsavedViewStates(viewId);
|
||||
},
|
||||
[currentViewIdState, resetCurrentView, saveViewFilters, saveViewSorts],
|
||||
[
|
||||
currentViewIdCallbackState,
|
||||
resetUnsavedViewStates,
|
||||
saveViewFilters,
|
||||
saveViewSorts,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@ -1,12 +1,10 @@
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { entityCountInCurrentViewComponentState } from '@/views/states/entityCountInCurrentViewComponentState';
|
||||
|
||||
export const useSetRecordCountInCurrentView = (viewBarComponentId?: string) => {
|
||||
const { entityCountInCurrentViewState } = useViewStates(viewBarComponentId);
|
||||
|
||||
const setEntityCountInCurrentView = useSetRecoilState(
|
||||
entityCountInCurrentViewState,
|
||||
const setEntityCountInCurrentView = useSetRecoilComponentStateV2(
|
||||
entityCountInCurrentViewComponentState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
||||
import { GraphQLView } from '@/views/types/GraphQLView';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const useUpdateCurrentView = (viewBarComponentId?: string) => {
|
||||
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
|
||||
currentViewIdComponentState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const { updateOneRecord } = useUpdateOneRecord({
|
||||
objectNameSingular: CoreObjectNameSingular.View,
|
||||
});
|
||||
|
||||
const updateCurrentView = useRecoilCallback(
|
||||
({ snapshot }) =>
|
||||
async (view: Partial<GraphQLView>) => {
|
||||
const currentViewId = snapshot
|
||||
.getLoadable(currentViewIdCallbackState)
|
||||
.getValue();
|
||||
|
||||
if (isDefined(currentViewId)) {
|
||||
await updateOneRecord({
|
||||
idToUpdate: currentViewId,
|
||||
updateOneRecordInput: view,
|
||||
});
|
||||
}
|
||||
},
|
||||
[currentViewIdCallbackState, updateOneRecord],
|
||||
);
|
||||
|
||||
return {
|
||||
updateCurrentView,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,27 @@
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||
import { GraphQLView } from '@/views/types/GraphQLView';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { isDefined } from 'twenty-ui';
|
||||
|
||||
export const useUpdateView = () => {
|
||||
const { updateOneRecord } = useUpdateOneRecord({
|
||||
objectNameSingular: CoreObjectNameSingular.View,
|
||||
});
|
||||
|
||||
const updateView = useRecoilCallback(
|
||||
() => async (view: Partial<GraphQLView>) => {
|
||||
if (isDefined(view.id)) {
|
||||
await updateOneRecord({
|
||||
idToUpdate: view.id,
|
||||
updateOneRecordInput: view,
|
||||
});
|
||||
}
|
||||
},
|
||||
[updateOneRecord],
|
||||
);
|
||||
|
||||
return {
|
||||
updateView,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,131 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { Filter } from '@/object-record/object-filter-dropdown/types/Filter';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
|
||||
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
||||
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
|
||||
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
|
||||
import { ViewFilter } from '@/views/types/ViewFilter';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const useUpsertCombinedViewFilters = (viewBarComponentId?: string) => {
|
||||
const unsavedToUpsertViewFiltersCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewFiltersComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewFilterIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewFilterIdsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
|
||||
currentViewIdComponentState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const { getViewFromCache } = useGetViewFromCache();
|
||||
|
||||
const upsertCombinedViewFilter = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
async (upsertedFilter: Filter) => {
|
||||
const currentViewId = getSnapshotValue(
|
||||
snapshot,
|
||||
currentViewIdCallbackState,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewFilters = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }),
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewFilterIds = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToDeleteViewFilterIdsCallbackState({ viewId: currentViewId }),
|
||||
);
|
||||
|
||||
if (!currentViewId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentView = await getViewFromCache(currentViewId);
|
||||
|
||||
if (!currentView) {
|
||||
return;
|
||||
}
|
||||
|
||||
const matchingFilterInCurrentView = currentView.viewFilters.find(
|
||||
(viewFilter) =>
|
||||
viewFilter.fieldMetadataId === upsertedFilter.fieldMetadataId,
|
||||
);
|
||||
|
||||
const matchingFilterInUnsavedFilters = unsavedToUpsertViewFilters.find(
|
||||
(viewFilter) =>
|
||||
viewFilter.fieldMetadataId === upsertedFilter.fieldMetadataId,
|
||||
);
|
||||
|
||||
if (isDefined(matchingFilterInUnsavedFilters)) {
|
||||
const updatedFilters = unsavedToUpsertViewFilters.map((viewFilter) =>
|
||||
viewFilter.fieldMetadataId ===
|
||||
matchingFilterInUnsavedFilters.fieldMetadataId
|
||||
? { ...viewFilter, ...upsertedFilter, id: viewFilter.id }
|
||||
: viewFilter,
|
||||
);
|
||||
|
||||
set(
|
||||
unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }),
|
||||
updatedFilters,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDefined(matchingFilterInCurrentView)) {
|
||||
set(
|
||||
unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }),
|
||||
[
|
||||
...unsavedToUpsertViewFilters,
|
||||
{
|
||||
...matchingFilterInCurrentView,
|
||||
...upsertedFilter,
|
||||
id: matchingFilterInCurrentView.id,
|
||||
},
|
||||
],
|
||||
);
|
||||
set(
|
||||
unsavedToDeleteViewFilterIdsCallbackState({
|
||||
viewId: currentViewId,
|
||||
}),
|
||||
unsavedToDeleteViewFilterIds.filter(
|
||||
(id) => id !== matchingFilterInCurrentView.id,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
set(
|
||||
unsavedToUpsertViewFiltersCallbackState({ viewId: currentViewId }),
|
||||
[
|
||||
...unsavedToUpsertViewFilters,
|
||||
{
|
||||
...upsertedFilter,
|
||||
__typename: 'ViewFilter',
|
||||
} satisfies ViewFilter,
|
||||
],
|
||||
);
|
||||
},
|
||||
[
|
||||
currentViewIdCallbackState,
|
||||
getViewFromCache,
|
||||
unsavedToDeleteViewFilterIdsCallbackState,
|
||||
unsavedToUpsertViewFiltersCallbackState,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
upsertCombinedViewFilter,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,123 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { Sort } from '@/object-record/object-sort-dropdown/types/Sort';
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useGetViewFromCache } from '@/views/hooks/useGetViewFromCache';
|
||||
import { currentViewIdComponentState } from '@/views/states/currentViewIdComponentState';
|
||||
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
|
||||
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
|
||||
import { ViewSort } from '@/views/types/ViewSort';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const useUpsertCombinedViewSorts = (viewBarComponentId?: string) => {
|
||||
const currentViewIdCallbackState = useRecoilComponentCallbackStateV2(
|
||||
currentViewIdComponentState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewSortsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToUpsertViewSortsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewSortIdsCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
unsavedToDeleteViewSortIdsComponentFamilyState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
const { getViewFromCache } = useGetViewFromCache();
|
||||
|
||||
const upsertCombinedViewSort = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
async (upsertedSort: Sort) => {
|
||||
const currentViewId = getSnapshotValue(
|
||||
snapshot,
|
||||
currentViewIdCallbackState,
|
||||
);
|
||||
|
||||
const unsavedToUpsertViewSorts = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }),
|
||||
);
|
||||
|
||||
const unsavedToDeleteViewSortIds = getSnapshotValue(
|
||||
snapshot,
|
||||
unsavedToDeleteViewSortIdsCallbackState({ viewId: currentViewId }),
|
||||
);
|
||||
|
||||
if (!currentViewId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentView = await getViewFromCache(currentViewId);
|
||||
|
||||
if (!currentView) {
|
||||
return;
|
||||
}
|
||||
|
||||
const matchingSortInCurrentView = currentView.viewSorts.find(
|
||||
(viewSort) =>
|
||||
viewSort.fieldMetadataId === upsertedSort.fieldMetadataId,
|
||||
);
|
||||
|
||||
const matchingSortInUnsavedSorts = unsavedToUpsertViewSorts.find(
|
||||
(viewSort) =>
|
||||
viewSort.fieldMetadataId === upsertedSort.fieldMetadataId,
|
||||
);
|
||||
|
||||
if (isDefined(matchingSortInUnsavedSorts)) {
|
||||
const updatedSorts = unsavedToUpsertViewSorts.map((viewSort) =>
|
||||
viewSort.id === matchingSortInUnsavedSorts.id
|
||||
? { ...viewSort, ...upsertedSort }
|
||||
: viewSort,
|
||||
);
|
||||
|
||||
set(
|
||||
unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }),
|
||||
updatedSorts,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDefined(matchingSortInCurrentView)) {
|
||||
set(
|
||||
unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }),
|
||||
[
|
||||
...unsavedToUpsertViewSorts,
|
||||
{ ...matchingSortInCurrentView, ...upsertedSort },
|
||||
],
|
||||
);
|
||||
set(
|
||||
unsavedToDeleteViewSortIdsCallbackState({ viewId: currentViewId }),
|
||||
unsavedToDeleteViewSortIds.filter(
|
||||
(id) => id !== matchingSortInCurrentView.id,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
set(unsavedToUpsertViewSortsCallbackState({ viewId: currentViewId }), [
|
||||
...unsavedToUpsertViewSorts,
|
||||
{
|
||||
...upsertedSort,
|
||||
id: v4(),
|
||||
__typename: 'ViewSort',
|
||||
} satisfies ViewSort,
|
||||
]);
|
||||
},
|
||||
[
|
||||
currentViewIdCallbackState,
|
||||
getViewFromCache,
|
||||
unsavedToDeleteViewSortIdsCallbackState,
|
||||
unsavedToUpsertViewSortsCallbackState,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
upsertCombinedViewSort,
|
||||
};
|
||||
};
|
||||
@ -1,32 +0,0 @@
|
||||
import { ReactNode } from 'react';
|
||||
|
||||
import { GraphQLView } from '@/views/types/GraphQLView';
|
||||
|
||||
import { ViewScopeInitEffect } from './init-effect/ViewScopeInitEffect';
|
||||
import { ViewScopeInternalContext } from './scope-internal-context/ViewScopeInternalContext';
|
||||
|
||||
type ViewScopeProps = {
|
||||
children: ReactNode;
|
||||
viewScopeId: string;
|
||||
onCurrentViewChange: (view: GraphQLView | undefined) => void | Promise<void>;
|
||||
};
|
||||
|
||||
export const ViewScope = ({
|
||||
children,
|
||||
viewScopeId,
|
||||
onCurrentViewChange,
|
||||
}: ViewScopeProps) => {
|
||||
return (
|
||||
<ViewScopeInternalContext.Provider
|
||||
value={{
|
||||
scopeId: viewScopeId,
|
||||
}}
|
||||
>
|
||||
<ViewScopeInitEffect
|
||||
viewScopeId={viewScopeId}
|
||||
onCurrentViewChange={onCurrentViewChange}
|
||||
/>
|
||||
{children}
|
||||
</ViewScopeInternalContext.Provider>
|
||||
);
|
||||
};
|
||||
@ -1,24 +0,0 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||
import { GraphQLView } from '@/views/types/GraphQLView';
|
||||
|
||||
type ViewScopeInitEffectProps = {
|
||||
viewScopeId: string;
|
||||
onCurrentViewChange: (view: GraphQLView | undefined) => void | Promise<void>;
|
||||
};
|
||||
|
||||
export const ViewScopeInitEffect = ({
|
||||
onCurrentViewChange,
|
||||
}: ViewScopeInitEffectProps) => {
|
||||
const { onCurrentViewChangeState } = useViewStates();
|
||||
|
||||
const setOnCurrentViewChange = useSetRecoilState(onCurrentViewChangeState);
|
||||
|
||||
useEffect(() => {
|
||||
setOnCurrentViewChange(() => onCurrentViewChange);
|
||||
}, [onCurrentViewChange, setOnCurrentViewChange]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
@ -1,7 +0,0 @@
|
||||
import { createScopeInternalContext } from '@/ui/utilities/recoil-scope/scopes-internal/utils/createScopeInternalContext';
|
||||
import { ComponentStateKey } from '@/ui/utilities/state/component-state/types/ComponentStateKey';
|
||||
|
||||
type ViewScopeInternalContextProps = ComponentStateKey;
|
||||
|
||||
export const ViewScopeInternalContext =
|
||||
createScopeInternalContext<ViewScopeInternalContextProps>();
|
||||
@ -1,10 +1,12 @@
|
||||
import { FieldMetadata } from '@/object-record/record-field/types/FieldMetadata';
|
||||
import { ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const availableFieldDefinitionsComponentState = createComponentState<
|
||||
export const availableFieldDefinitionsComponentState = createComponentStateV2<
|
||||
ColumnDefinition<FieldMetadata>[]
|
||||
>({
|
||||
key: 'availableFieldDefinitionsComponentState',
|
||||
defaultValue: [],
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import { FilterDefinition } from '@/object-record/object-filter-dropdown/types/FilterDefinition';
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const availableFilterDefinitionsComponentState = createComponentState<
|
||||
export const availableFilterDefinitionsComponentState = createComponentStateV2<
|
||||
FilterDefinition[]
|
||||
>({
|
||||
key: 'availableFilterDefinitionsComponentState',
|
||||
defaultValue: [],
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -1,9 +1,11 @@
|
||||
import { SortDefinition } from '@/object-record/object-sort-dropdown/types/SortDefinition';
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const availableSortDefinitionsComponentState = createComponentState<
|
||||
export const availableSortDefinitionsComponentState = createComponentStateV2<
|
||||
SortDefinition[]
|
||||
>({
|
||||
key: 'availableSortDefinitionsComponentState',
|
||||
defaultValue: [],
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
import { createComponentInstanceContext } from '@/ui/utilities/state/component-state/utils/createComponentInstanceContext';
|
||||
|
||||
export const ViewComponentInstanceContext = createComponentInstanceContext();
|
||||
@ -1,8 +1,10 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const currentViewIdComponentState = createComponentState<
|
||||
export const currentViewIdComponentState = createComponentStateV2<
|
||||
string | undefined
|
||||
>({
|
||||
key: 'currentViewIdComponentState',
|
||||
defaultValue: undefined,
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const entityCountInCurrentViewComponentState = createComponentState<
|
||||
export const entityCountInCurrentViewComponentState = createComponentStateV2<
|
||||
number | undefined
|
||||
>({
|
||||
key: 'entityCountInCurrentViewComponentState',
|
||||
defaultValue: undefined,
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const isCurrentViewKeyIndexComponentState =
|
||||
createComponentState<boolean>({
|
||||
createComponentStateV2<boolean>({
|
||||
key: 'isCurrentViewKeyIndexComponentState',
|
||||
defaultValue: true,
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const isPersistingViewFieldsComponentState =
|
||||
createComponentState<boolean>({
|
||||
createComponentStateV2<boolean>({
|
||||
key: 'isPersistingViewFieldsComponentState',
|
||||
defaultValue: false,
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const isViewBarExpandedComponentState = createComponentState<boolean>({
|
||||
export const isViewBarExpandedComponentState = createComponentStateV2<boolean>({
|
||||
key: 'isViewBarExpandedComponentState',
|
||||
defaultValue: true,
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -1,9 +0,0 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { View } from '@/views/types/View';
|
||||
|
||||
export const onCurrentViewChangeComponentState = createComponentState<
|
||||
((view: View | undefined) => void | Promise<void>) | undefined
|
||||
>({
|
||||
key: 'onCurrentViewChangeComponentState',
|
||||
defaultValue: undefined,
|
||||
});
|
||||
@ -0,0 +1,42 @@
|
||||
import { createComponentFamilySelectorV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilySelectorV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
import { unsavedToDeleteViewFilterIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentFamilyState';
|
||||
import { unsavedToDeleteViewSortIdsComponentFamilyState } from '@/views/states/unsavedToDeleteViewSortIdsComponentFamilyState';
|
||||
import { unsavedToUpsertViewFiltersComponentFamilyState } from '@/views/states/unsavedToUpsertViewFiltersComponentFamilyState';
|
||||
import { unsavedToUpsertViewSortsComponentFamilyState } from '@/views/states/unsavedToUpsertViewSortsComponentFamilyState';
|
||||
|
||||
export const canPersistViewComponentFamilySelector =
|
||||
createComponentFamilySelectorV2<boolean, { viewId?: string }>({
|
||||
key: 'canPersistViewComponentFamilySelector',
|
||||
get:
|
||||
({ familyKey, instanceId }) =>
|
||||
({ get }) => {
|
||||
return (
|
||||
get(
|
||||
unsavedToUpsertViewFiltersComponentFamilyState.atomFamily({
|
||||
familyKey,
|
||||
instanceId,
|
||||
}),
|
||||
).length > 0 ||
|
||||
get(
|
||||
unsavedToUpsertViewSortsComponentFamilyState.atomFamily({
|
||||
familyKey,
|
||||
instanceId,
|
||||
}),
|
||||
).length > 0 ||
|
||||
get(
|
||||
unsavedToDeleteViewFilterIdsComponentFamilyState.atomFamily({
|
||||
familyKey,
|
||||
instanceId,
|
||||
}),
|
||||
).length > 0 ||
|
||||
get(
|
||||
unsavedToDeleteViewSortIdsComponentFamilyState.atomFamily({
|
||||
familyKey,
|
||||
instanceId,
|
||||
}),
|
||||
).length > 0
|
||||
);
|
||||
},
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
@ -1,21 +0,0 @@
|
||||
import { selectorFamily } from 'recoil';
|
||||
|
||||
import { unsavedToDeleteViewFilterIdsComponentState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentState';
|
||||
import { unsavedToDeleteViewSortIdsComponentState } from '@/views/states/unsavedToDeleteViewSortIdsComponentState';
|
||||
import { unsavedToUpsertViewFiltersComponentState } from '@/views/states/unsavedToUpsertViewFiltersComponentState';
|
||||
import { unsavedToUpsertViewSortsComponentState } from '@/views/states/unsavedToUpsertViewSortsComponentState';
|
||||
|
||||
export const canPersistViewComponentSelector = selectorFamily({
|
||||
key: 'canPersistViewComponentSelector',
|
||||
get:
|
||||
({ scopeId }: { scopeId: string }) =>
|
||||
({ get }) => {
|
||||
return (
|
||||
get(unsavedToUpsertViewFiltersComponentState({ scopeId })).length > 0 ||
|
||||
get(unsavedToUpsertViewSortsComponentState({ scopeId })).length > 0 ||
|
||||
get(unsavedToDeleteViewFilterIdsComponentState({ scopeId })).length >
|
||||
0 ||
|
||||
get(unsavedToDeleteViewSortIdsComponentState({ scopeId })).length > 0
|
||||
);
|
||||
},
|
||||
});
|
||||
@ -1,22 +0,0 @@
|
||||
import { selectorFamily } from 'recoil';
|
||||
|
||||
import { unsavedToDeleteViewFilterIdsComponentState } from '@/views/states/unsavedToDeleteViewFilterIdsComponentState';
|
||||
import { unsavedToDeleteViewSortIdsComponentState } from '@/views/states/unsavedToDeleteViewSortIdsComponentState';
|
||||
import { unsavedToUpsertViewFiltersComponentState } from '@/views/states/unsavedToUpsertViewFiltersComponentState';
|
||||
import { unsavedToUpsertViewSortsComponentState } from '@/views/states/unsavedToUpsertViewSortsComponentState';
|
||||
|
||||
export const canResetViewComponentSelector = selectorFamily({
|
||||
key: 'canResetViewComponentSelector',
|
||||
get:
|
||||
({ scopeId }: { scopeId: string }) =>
|
||||
({ get }) => {
|
||||
return (
|
||||
get(unsavedToUpsertViewFiltersComponentState({ scopeId })).length ===
|
||||
0 &&
|
||||
get(unsavedToUpsertViewSortsComponentState({ scopeId })).length === 0 &&
|
||||
get(unsavedToDeleteViewFilterIdsComponentState({ scopeId })).length ===
|
||||
0 &&
|
||||
get(unsavedToDeleteViewSortIdsComponentState({ scopeId })).length === 0
|
||||
);
|
||||
},
|
||||
});
|
||||
@ -0,0 +1,9 @@
|
||||
import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const unsavedToDeleteViewFilterIdsComponentFamilyState =
|
||||
createComponentFamilyStateV2<string[], { viewId?: string }>({
|
||||
key: 'unsavedToDeleteViewFilterIdsComponentFamilyState',
|
||||
defaultValue: [],
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
@ -1,8 +0,0 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
|
||||
export const unsavedToDeleteViewFilterIdsComponentState = createComponentState<
|
||||
string[]
|
||||
>({
|
||||
key: 'unsavedToDeleteViewFilterIdsComponentState',
|
||||
defaultValue: [],
|
||||
});
|
||||
@ -0,0 +1,9 @@
|
||||
import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const unsavedToDeleteViewSortIdsComponentFamilyState =
|
||||
createComponentFamilyStateV2<string[], { viewId?: string }>({
|
||||
key: 'unsavedToDeleteViewSortIdsComponentFamilyState',
|
||||
defaultValue: [],
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
@ -1,8 +0,0 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
|
||||
export const unsavedToDeleteViewSortIdsComponentState = createComponentState<
|
||||
string[]
|
||||
>({
|
||||
key: 'unsavedToDeleteViewSortIdsComponentState',
|
||||
defaultValue: [],
|
||||
});
|
||||
@ -0,0 +1,10 @@
|
||||
import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
import { ViewFilter } from '../types/ViewFilter';
|
||||
|
||||
export const unsavedToUpsertViewFiltersComponentFamilyState =
|
||||
createComponentFamilyStateV2<ViewFilter[], { viewId?: string }>({
|
||||
key: 'unsavedToUpsertViewFiltersComponentFamilyState',
|
||||
defaultValue: [],
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
@ -1,10 +0,0 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
|
||||
import { ViewFilter } from '../types/ViewFilter';
|
||||
|
||||
export const unsavedToUpsertViewFiltersComponentState = createComponentState<
|
||||
ViewFilter[]
|
||||
>({
|
||||
key: 'unsavedToUpsertViewFiltersComponentState',
|
||||
defaultValue: [],
|
||||
});
|
||||
@ -0,0 +1,10 @@
|
||||
import { createComponentFamilyStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentFamilyStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
import { ViewSort } from '../types/ViewSort';
|
||||
|
||||
export const unsavedToUpsertViewSortsComponentFamilyState =
|
||||
createComponentFamilyStateV2<ViewSort[], { viewId?: string }>({
|
||||
key: 'unsavedToUpsertViewSortsComponentFamilyState',
|
||||
defaultValue: [],
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
@ -1,10 +0,0 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
|
||||
import { ViewSort } from '../types/ViewSort';
|
||||
|
||||
export const unsavedToUpsertViewSortsComponentState = createComponentState<
|
||||
ViewSort[]
|
||||
>({
|
||||
key: 'unsavedToUpsertViewSortsComponentState',
|
||||
defaultValue: [],
|
||||
});
|
||||
@ -1,8 +1,10 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const viewObjectMetadataIdComponentState = createComponentState<
|
||||
export const viewObjectMetadataIdComponentState = createComponentStateV2<
|
||||
string | undefined
|
||||
>({
|
||||
key: 'viewObjectMetadataIdComponentState',
|
||||
defaultValue: undefined,
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { ViewFilter } from '@/views/types/ViewFilter';
|
||||
|
||||
export const combinedViewFilters = (
|
||||
export const getCombinedViewFilters = (
|
||||
viewFilters: ViewFilter[],
|
||||
toUpsertViewFilters: ViewFilter[],
|
||||
toDeleteViewFilterIds: string[],
|
||||
@ -1,6 +1,6 @@
|
||||
import { ViewSort } from '@/views/types/ViewSort';
|
||||
|
||||
export const combinedViewSorts = (
|
||||
export const getCombinedViewSorts = (
|
||||
viewSort: ViewSort[],
|
||||
toUpsertViewSorts: ViewSort[],
|
||||
toDeleteViewSortIds: string[],
|
||||
@ -1,7 +1,6 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import { Key } from 'ts-key-enum';
|
||||
import { IconChevronLeft, IconLayoutKanban, IconTable, IconX } from 'twenty-ui';
|
||||
import { IconLayoutKanban, IconTable, IconX } from 'twenty-ui';
|
||||
|
||||
import { IconPicker } from '@/ui/input/components/IconPicker';
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
@ -11,30 +10,26 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
|
||||
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
|
||||
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { ViewsHotkeyScope } from '@/views/types/ViewsHotkeyScope';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { ViewPickerCreateOrEditButton } from '@/views/view-picker/components/ViewPickerCreateOrEditButton';
|
||||
import { ViewPickerCreateButton } from '@/views/view-picker/components/ViewPickerCreateButton';
|
||||
import { ViewPickerIconAndNameContainer } from '@/views/view-picker/components/ViewPickerIconAndNameContainer';
|
||||
import { ViewPickerSaveButtonContainer } from '@/views/view-picker/components/ViewPickerSaveButtonContainer';
|
||||
import { ViewPickerSelectContainer } from '@/views/view-picker/components/ViewPickerSelectContainer';
|
||||
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 { useCreateViewFromCurrentState } from '@/views/view-picker/hooks/useCreateViewFromCurrentState';
|
||||
import { useGetAvailableFieldsForKanban } from '@/views/view-picker/hooks/useGetAvailableFieldsForKanban';
|
||||
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
|
||||
import { useViewPickerPersistView } from '@/views/view-picker/hooks/useViewPickerPersistView';
|
||||
import { useViewPickerStates } from '@/views/view-picker/hooks/useViewPickerStates';
|
||||
|
||||
const StyledIconAndNameContainer = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
margin-left: ${({ theme }) => theme.spacing(1)};
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
`;
|
||||
|
||||
const StyledSelectContainer = styled.div`
|
||||
display: flex;
|
||||
width: calc(100% - ${({ theme }) => theme.spacing(2)});
|
||||
margin: ${({ theme }) => theme.spacing(1)};
|
||||
color: ${({ theme }) => theme.font.color.light};
|
||||
user-select: none;
|
||||
`;
|
||||
import { viewPickerInputNameComponentState } from '@/views/view-picker/states/viewPickerInputNameComponentState';
|
||||
import { viewPickerIsDirtyComponentState } from '@/views/view-picker/states/viewPickerIsDirtyComponentState';
|
||||
import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState';
|
||||
import { viewPickerKanbanFieldMetadataIdComponentState } from '@/views/view-picker/states/viewPickerKanbanFieldMetadataIdComponentState';
|
||||
import { viewPickerSelectedIconComponentState } from '@/views/view-picker/states/viewPickerSelectedIconComponentState';
|
||||
import { viewPickerTypeComponentState } from '@/views/view-picker/states/viewPickerTypeComponentState';
|
||||
|
||||
const StyledNoKanbanFieldAvailableContainer = styled.div`
|
||||
color: ${({ theme }) => theme.font.color.light};
|
||||
@ -44,40 +39,32 @@ const StyledNoKanbanFieldAvailableContainer = styled.div`
|
||||
width: calc(100% - ${({ theme }) => theme.spacing(4)});
|
||||
`;
|
||||
|
||||
const StyledSaveButtonContainer = styled.div`
|
||||
display: flex;
|
||||
padding: ${({ theme }) => theme.spacing(1)};
|
||||
width: calc(100% - ${({ theme }) => theme.spacing(2)});
|
||||
`;
|
||||
export const ViewPickerCreateOrEditContent = () => {
|
||||
const { viewPickerMode, setViewPickerMode } = useViewPickerMode();
|
||||
const {
|
||||
viewPickerInputNameState,
|
||||
viewPickerSelectedIconState,
|
||||
viewPickerIsPersistingState,
|
||||
viewPickerKanbanFieldMetadataIdState,
|
||||
viewPickerTypeState,
|
||||
viewPickerIsDirtyState,
|
||||
} = useViewPickerStates();
|
||||
export const ViewPickerContentCreateMode = () => {
|
||||
const { setViewPickerMode } = useViewPickerMode();
|
||||
|
||||
const [viewPickerInputName, setViewPickerInputName] = useRecoilState(
|
||||
viewPickerInputNameState,
|
||||
const [viewPickerInputName, setViewPickerInputName] =
|
||||
useRecoilComponentStateV2(viewPickerInputNameComponentState);
|
||||
|
||||
const [viewPickerSelectedIcon, setViewPickerSelectedIcon] =
|
||||
useRecoilComponentStateV2(viewPickerSelectedIconComponentState);
|
||||
|
||||
const viewPickerIsPersisting = useRecoilComponentValueV2(
|
||||
viewPickerIsPersistingComponentState,
|
||||
);
|
||||
const [viewPickerSelectedIcon, setViewPickerSelectedIcon] = useRecoilState(
|
||||
viewPickerSelectedIconState,
|
||||
const setViewPickerIsDirty = useSetRecoilComponentStateV2(
|
||||
viewPickerIsDirtyComponentState,
|
||||
);
|
||||
const viewPickerIsPersisting = useRecoilValue(viewPickerIsPersistingState);
|
||||
const setViewPickerIsDirty = useSetRecoilState(viewPickerIsDirtyState);
|
||||
|
||||
const [viewPickerKanbanFieldMetadataId, setViewPickerKanbanFieldMetadataId] =
|
||||
useRecoilState(viewPickerKanbanFieldMetadataIdState);
|
||||
useRecoilComponentStateV2(viewPickerKanbanFieldMetadataIdComponentState);
|
||||
|
||||
const [viewPickerType, setViewPickerType] =
|
||||
useRecoilState(viewPickerTypeState);
|
||||
const [viewPickerType, setViewPickerType] = useRecoilComponentStateV2(
|
||||
viewPickerTypeComponentState,
|
||||
);
|
||||
|
||||
const setHotkeyScope = useSetHotkeyScope();
|
||||
|
||||
const { handleCreate, handleUpdate } = useViewPickerPersistView();
|
||||
const { createViewFromCurrentState } = useCreateViewFromCurrentState();
|
||||
|
||||
const { availableFieldsForKanban } = useGetAvailableFieldsForKanban();
|
||||
|
||||
@ -87,18 +74,15 @@ export const ViewPickerCreateOrEditContent = () => {
|
||||
if (viewPickerIsPersisting) {
|
||||
return;
|
||||
}
|
||||
if (viewPickerMode === 'create') {
|
||||
if (
|
||||
viewPickerType === ViewType.Kanban &&
|
||||
availableFieldsForKanban.length === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
await handleCreate();
|
||||
}
|
||||
if (viewPickerMode === 'edit') {
|
||||
await handleUpdate();
|
||||
|
||||
if (
|
||||
viewPickerType === ViewType.Kanban &&
|
||||
availableFieldsForKanban.length === 0
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
await createViewFromCurrentState();
|
||||
},
|
||||
ViewsHotkeyScope.ListDropdown,
|
||||
);
|
||||
@ -109,23 +93,17 @@ export const ViewPickerCreateOrEditContent = () => {
|
||||
};
|
||||
|
||||
const handleClose = async () => {
|
||||
if (viewPickerMode === 'edit') {
|
||||
await handleUpdate();
|
||||
}
|
||||
setViewPickerMode('list');
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<DropdownMenuHeader
|
||||
StartIcon={viewPickerMode === 'create' ? IconX : IconChevronLeft}
|
||||
onClick={handleClose}
|
||||
>
|
||||
{viewPickerMode === 'create' ? 'Create view' : 'Edit view'}
|
||||
<DropdownMenuHeader StartIcon={IconX} onClick={handleClose}>
|
||||
Create view
|
||||
</DropdownMenuHeader>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItemsContainer>
|
||||
<StyledIconAndNameContainer>
|
||||
<ViewPickerIconAndNameContainer>
|
||||
<IconPicker
|
||||
onChange={onIconChange}
|
||||
selectedIconKey={viewPickerSelectedIcon}
|
||||
@ -140,33 +118,31 @@ export const ViewPickerCreateOrEditContent = () => {
|
||||
}}
|
||||
autoFocus
|
||||
/>
|
||||
</StyledIconAndNameContainer>
|
||||
{viewPickerMode === 'create' && (
|
||||
<StyledSelectContainer>
|
||||
<Select
|
||||
disableBlur
|
||||
label="View type"
|
||||
fullWidth
|
||||
value={viewPickerType}
|
||||
onChange={(value) => {
|
||||
setViewPickerIsDirty(true);
|
||||
setViewPickerType(value);
|
||||
}}
|
||||
options={[
|
||||
{ value: ViewType.Table, label: 'Table', Icon: IconTable },
|
||||
{
|
||||
value: ViewType.Kanban,
|
||||
label: 'Kanban',
|
||||
Icon: IconLayoutKanban,
|
||||
},
|
||||
]}
|
||||
dropdownId={VIEW_PICKER_VIEW_TYPE_DROPDOWN_ID}
|
||||
/>
|
||||
</StyledSelectContainer>
|
||||
)}
|
||||
{viewPickerType === ViewType.Kanban && viewPickerMode === 'create' && (
|
||||
</ViewPickerIconAndNameContainer>
|
||||
<ViewPickerSelectContainer>
|
||||
<Select
|
||||
disableBlur
|
||||
label="View type"
|
||||
fullWidth
|
||||
value={viewPickerType}
|
||||
onChange={(value) => {
|
||||
setViewPickerIsDirty(true);
|
||||
setViewPickerType(value);
|
||||
}}
|
||||
options={[
|
||||
{ value: ViewType.Table, label: 'Table', Icon: IconTable },
|
||||
{
|
||||
value: ViewType.Kanban,
|
||||
label: 'Kanban',
|
||||
Icon: IconLayoutKanban,
|
||||
},
|
||||
]}
|
||||
dropdownId={VIEW_PICKER_VIEW_TYPE_DROPDOWN_ID}
|
||||
/>
|
||||
</ViewPickerSelectContainer>
|
||||
{viewPickerType === ViewType.Kanban && (
|
||||
<>
|
||||
<StyledSelectContainer>
|
||||
<ViewPickerSelectContainer>
|
||||
<Select
|
||||
disableBlur
|
||||
label="Stages"
|
||||
@ -186,7 +162,7 @@ export const ViewPickerCreateOrEditContent = () => {
|
||||
}
|
||||
dropdownId={VIEW_PICKER_KANBAN_FIELD_DROPDOWN_ID}
|
||||
/>
|
||||
</StyledSelectContainer>
|
||||
</ViewPickerSelectContainer>
|
||||
{availableFieldsForKanban.length === 0 && (
|
||||
<StyledNoKanbanFieldAvailableContainer>
|
||||
Set up a Select field on Companies to create a Kanban
|
||||
@ -197,9 +173,9 @@ export const ViewPickerCreateOrEditContent = () => {
|
||||
</DropdownMenuItemsContainer>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItemsContainer>
|
||||
<StyledSaveButtonContainer>
|
||||
<ViewPickerCreateOrEditButton />
|
||||
</StyledSaveButtonContainer>
|
||||
<ViewPickerSaveButtonContainer>
|
||||
<ViewPickerCreateButton />
|
||||
</ViewPickerSaveButtonContainer>
|
||||
</DropdownMenuItemsContainer>
|
||||
</>
|
||||
);
|
||||
@ -0,0 +1,100 @@
|
||||
import { Key } from 'ts-key-enum';
|
||||
import { IconChevronLeft } from 'twenty-ui';
|
||||
|
||||
import { IconPicker } from '@/ui/input/components/IconPicker';
|
||||
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 { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
|
||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { ViewsHotkeyScope } from '@/views/types/ViewsHotkeyScope';
|
||||
import { ViewPickerEditButton } from '@/views/view-picker/components/ViewPickerEditButton';
|
||||
import { ViewPickerIconAndNameContainer } from '@/views/view-picker/components/ViewPickerIconAndNameContainer';
|
||||
import { ViewPickerSaveButtonContainer } from '@/views/view-picker/components/ViewPickerSaveButtonContainer';
|
||||
import { useUpdateViewFromCurrentState } from '@/views/view-picker/hooks/useUpdateViewFromCurrentState';
|
||||
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
|
||||
import { viewPickerInputNameComponentState } from '@/views/view-picker/states/viewPickerInputNameComponentState';
|
||||
import { viewPickerIsDirtyComponentState } from '@/views/view-picker/states/viewPickerIsDirtyComponentState';
|
||||
import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState';
|
||||
import { viewPickerSelectedIconComponentState } from '@/views/view-picker/states/viewPickerSelectedIconComponentState';
|
||||
|
||||
export const ViewPickerContentEditMode = () => {
|
||||
const { setViewPickerMode } = useViewPickerMode();
|
||||
|
||||
const [viewPickerInputName, setViewPickerInputName] =
|
||||
useRecoilComponentStateV2(viewPickerInputNameComponentState);
|
||||
|
||||
const [viewPickerSelectedIcon, setViewPickerSelectedIcon] =
|
||||
useRecoilComponentStateV2(viewPickerSelectedIconComponentState);
|
||||
|
||||
const viewPickerIsPersisting = useRecoilComponentValueV2(
|
||||
viewPickerIsPersistingComponentState,
|
||||
);
|
||||
const setViewPickerIsDirty = useSetRecoilComponentStateV2(
|
||||
viewPickerIsDirtyComponentState,
|
||||
);
|
||||
|
||||
const setHotkeyScope = useSetHotkeyScope();
|
||||
|
||||
const { updateViewFromCurrentState } = useUpdateViewFromCurrentState();
|
||||
|
||||
useScopedHotkeys(
|
||||
Key.Enter,
|
||||
async () => {
|
||||
if (viewPickerIsPersisting) {
|
||||
return;
|
||||
}
|
||||
|
||||
await updateViewFromCurrentState();
|
||||
},
|
||||
ViewsHotkeyScope.ListDropdown,
|
||||
);
|
||||
|
||||
const onIconChange = ({ iconKey }: { iconKey: string }) => {
|
||||
setViewPickerIsDirty(true);
|
||||
setViewPickerSelectedIcon(iconKey);
|
||||
};
|
||||
|
||||
const handleClose = async () => {
|
||||
await updateViewFromCurrentState();
|
||||
|
||||
setViewPickerMode('list');
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<DropdownMenuHeader StartIcon={IconChevronLeft} onClick={handleClose}>
|
||||
Edit view
|
||||
</DropdownMenuHeader>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItemsContainer>
|
||||
<ViewPickerIconAndNameContainer>
|
||||
<IconPicker
|
||||
onChange={onIconChange}
|
||||
selectedIconKey={viewPickerSelectedIcon}
|
||||
disableBlur
|
||||
onClose={() => setHotkeyScope(ViewsHotkeyScope.ListDropdown)}
|
||||
/>
|
||||
<DropdownMenuInput
|
||||
value={viewPickerInputName}
|
||||
onChange={(event) => {
|
||||
setViewPickerIsDirty(true);
|
||||
setViewPickerInputName(event.target.value);
|
||||
}}
|
||||
autoFocus
|
||||
/>
|
||||
</ViewPickerIconAndNameContainer>
|
||||
</DropdownMenuItemsContainer>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItemsContainer>
|
||||
<ViewPickerSaveButtonContainer>
|
||||
<ViewPickerEditButton />
|
||||
</ViewPickerSaveButtonContainer>
|
||||
</DropdownMenuItemsContainer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,90 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { useGetAvailableFieldsForKanban } from '@/views/view-picker/hooks/useGetAvailableFieldsForKanban';
|
||||
import { viewPickerInputNameComponentState } from '@/views/view-picker/states/viewPickerInputNameComponentState';
|
||||
import { viewPickerIsDirtyComponentState } from '@/views/view-picker/states/viewPickerIsDirtyComponentState';
|
||||
import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState';
|
||||
import { viewPickerKanbanFieldMetadataIdComponentState } from '@/views/view-picker/states/viewPickerKanbanFieldMetadataIdComponentState';
|
||||
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 { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const ViewPickerContentEffect = () => {
|
||||
const setViewPickerSelectedIcon = useSetRecoilComponentStateV2(
|
||||
viewPickerSelectedIconComponentState,
|
||||
);
|
||||
const setViewPickerInputName = useSetRecoilComponentStateV2(
|
||||
viewPickerInputNameComponentState,
|
||||
);
|
||||
|
||||
const [viewPickerKanbanFieldMetadataId, setViewPickerKanbanFieldMetadataId] =
|
||||
useRecoilComponentStateV2(viewPickerKanbanFieldMetadataIdComponentState);
|
||||
|
||||
const setViewPickerType = useSetRecoilComponentStateV2(
|
||||
viewPickerTypeComponentState,
|
||||
);
|
||||
|
||||
const viewPickerReferenceViewId = useRecoilComponentValueV2(
|
||||
viewPickerReferenceViewIdComponentState,
|
||||
);
|
||||
|
||||
const viewPickerIsDirty = useRecoilComponentValueV2(
|
||||
viewPickerIsDirtyComponentState,
|
||||
);
|
||||
|
||||
const viewPickerIsPersisting = useRecoilComponentValueV2(
|
||||
viewPickerIsPersistingComponentState,
|
||||
);
|
||||
|
||||
const { viewsOnCurrentObject } = useGetCurrentView();
|
||||
const referenceView = viewsOnCurrentObject.find(
|
||||
(view) => view.id === viewPickerReferenceViewId,
|
||||
);
|
||||
|
||||
const { availableFieldsForKanban } = useGetAvailableFieldsForKanban();
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
isDefined(referenceView) &&
|
||||
!viewPickerIsPersisting &&
|
||||
!viewPickerIsDirty
|
||||
) {
|
||||
setViewPickerSelectedIcon(referenceView.icon);
|
||||
setViewPickerInputName(referenceView.name);
|
||||
setViewPickerType(referenceView.type);
|
||||
}
|
||||
}, [
|
||||
referenceView,
|
||||
setViewPickerInputName,
|
||||
setViewPickerSelectedIcon,
|
||||
setViewPickerType,
|
||||
viewPickerIsPersisting,
|
||||
viewPickerIsDirty,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
isDefined(referenceView) &&
|
||||
availableFieldsForKanban.length > 0 &&
|
||||
viewPickerKanbanFieldMetadataId === ''
|
||||
) {
|
||||
setViewPickerKanbanFieldMetadataId(
|
||||
referenceView.kanbanFieldMetadataId !== ''
|
||||
? referenceView.kanbanFieldMetadataId
|
||||
: availableFieldsForKanban[0].id,
|
||||
);
|
||||
}
|
||||
}, [
|
||||
referenceView,
|
||||
availableFieldsForKanban,
|
||||
viewPickerKanbanFieldMetadataId,
|
||||
setViewPickerKanbanFieldMetadataId,
|
||||
]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
@ -0,0 +1,86 @@
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { useCreateViewFromCurrentState } from '@/views/view-picker/hooks/useCreateViewFromCurrentState';
|
||||
import { useDeleteViewFromCurrentState } from '@/views/view-picker/hooks/useDeleteViewFromCurrentState';
|
||||
import { useGetAvailableFieldsForKanban } from '@/views/view-picker/hooks/useGetAvailableFieldsForKanban';
|
||||
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
|
||||
import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState';
|
||||
import { viewPickerKanbanFieldMetadataIdComponentState } from '@/views/view-picker/states/viewPickerKanbanFieldMetadataIdComponentState';
|
||||
import { viewPickerTypeComponentState } from '@/views/view-picker/states/viewPickerTypeComponentState';
|
||||
|
||||
export const ViewPickerCreateButton = () => {
|
||||
const { availableFieldsForKanban, navigateToSelectSettings } =
|
||||
useGetAvailableFieldsForKanban();
|
||||
|
||||
const { viewPickerMode } = useViewPickerMode();
|
||||
const viewPickerType = useRecoilComponentValueV2(
|
||||
viewPickerTypeComponentState,
|
||||
);
|
||||
const viewPickerIsPersisting = useRecoilComponentValueV2(
|
||||
viewPickerIsPersistingComponentState,
|
||||
);
|
||||
const viewPickerKanbanFieldMetadataId = useRecoilComponentValueV2(
|
||||
viewPickerKanbanFieldMetadataIdComponentState,
|
||||
);
|
||||
|
||||
const { createViewFromCurrentState } = useCreateViewFromCurrentState();
|
||||
const { deleteViewFromCurrentState } = useDeleteViewFromCurrentState();
|
||||
|
||||
const handleCreateButtonClick = () => {
|
||||
createViewFromCurrentState();
|
||||
};
|
||||
|
||||
if (viewPickerMode === 'edit') {
|
||||
return (
|
||||
<Button
|
||||
title="Delete"
|
||||
onClick={deleteViewFromCurrentState}
|
||||
accent="danger"
|
||||
fullWidth
|
||||
size="small"
|
||||
justify="center"
|
||||
focus={false}
|
||||
variant="secondary"
|
||||
disabled={viewPickerIsPersisting}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
viewPickerType === ViewType.Kanban &&
|
||||
availableFieldsForKanban.length === 0
|
||||
) {
|
||||
return (
|
||||
<Button
|
||||
title="Go to Settings"
|
||||
onClick={navigateToSelectSettings}
|
||||
size="small"
|
||||
accent="blue"
|
||||
fullWidth
|
||||
justify="center"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
viewPickerType === ViewType.Table ||
|
||||
viewPickerKanbanFieldMetadataId !== ''
|
||||
) {
|
||||
return (
|
||||
<Button
|
||||
title="Create"
|
||||
onClick={handleCreateButtonClick}
|
||||
accent="blue"
|
||||
fullWidth
|
||||
size="small"
|
||||
justify="center"
|
||||
disabled={
|
||||
viewPickerIsPersisting ||
|
||||
(viewPickerType === ViewType.Kanban &&
|
||||
viewPickerKanbanFieldMetadataId === '')
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
@ -1,83 +0,0 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { useGetAvailableFieldsForKanban } from '@/views/view-picker/hooks/useGetAvailableFieldsForKanban';
|
||||
import { useViewPickerStates } from '@/views/view-picker/hooks/useViewPickerStates';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const ViewPickerCreateOrEditContentEffect = () => {
|
||||
const {
|
||||
viewPickerSelectedIconState,
|
||||
viewPickerInputNameState,
|
||||
viewPickerReferenceViewIdState,
|
||||
viewPickerIsPersistingState,
|
||||
viewPickerKanbanFieldMetadataIdState,
|
||||
viewPickerTypeState,
|
||||
viewPickerIsDirtyState,
|
||||
} = useViewPickerStates();
|
||||
|
||||
const setViewPickerSelectedIcon = useSetRecoilState(
|
||||
viewPickerSelectedIconState,
|
||||
);
|
||||
const setViewPickerInputName = useSetRecoilState(viewPickerInputNameState);
|
||||
|
||||
const [viewPickerKanbanFieldMetadataId, setViewPickerKanbanFieldMetadataId] =
|
||||
useRecoilState(viewPickerKanbanFieldMetadataIdState);
|
||||
const setViewPickerType = useSetRecoilState(viewPickerTypeState);
|
||||
|
||||
const viewPickerReferenceViewId = useRecoilValue(
|
||||
viewPickerReferenceViewIdState,
|
||||
);
|
||||
|
||||
const viewPickerIsDirty = useRecoilValue(viewPickerIsDirtyState);
|
||||
|
||||
const viewPickerIsPersisting = useRecoilValue(viewPickerIsPersistingState);
|
||||
|
||||
const { viewsOnCurrentObject } = useGetCurrentView();
|
||||
const referenceView = viewsOnCurrentObject.find(
|
||||
(view) => view.id === viewPickerReferenceViewId,
|
||||
);
|
||||
|
||||
const { availableFieldsForKanban } = useGetAvailableFieldsForKanban();
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
isDefined(referenceView) &&
|
||||
!viewPickerIsPersisting &&
|
||||
!viewPickerIsDirty
|
||||
) {
|
||||
setViewPickerSelectedIcon(referenceView.icon);
|
||||
setViewPickerInputName(referenceView.name);
|
||||
setViewPickerType(referenceView.type);
|
||||
}
|
||||
}, [
|
||||
referenceView,
|
||||
setViewPickerInputName,
|
||||
setViewPickerSelectedIcon,
|
||||
setViewPickerType,
|
||||
viewPickerIsPersisting,
|
||||
viewPickerIsDirty,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
isDefined(referenceView) &&
|
||||
availableFieldsForKanban.length > 0 &&
|
||||
viewPickerKanbanFieldMetadataId === ''
|
||||
) {
|
||||
setViewPickerKanbanFieldMetadataId(
|
||||
referenceView.kanbanFieldMetadataId !== ''
|
||||
? referenceView.kanbanFieldMetadataId
|
||||
: availableFieldsForKanban[0].id,
|
||||
);
|
||||
}
|
||||
}, [
|
||||
referenceView,
|
||||
availableFieldsForKanban,
|
||||
viewPickerKanbanFieldMetadataId,
|
||||
setViewPickerKanbanFieldMetadataId,
|
||||
]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
@ -1,6 +1,5 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import {
|
||||
IconChevronDown,
|
||||
IconList,
|
||||
@ -11,18 +10,19 @@ import {
|
||||
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
|
||||
import { StyledDropdownButtonContainer } from '@/ui/layout/dropdown/components/StyledDropdownButtonContainer';
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { entityCountInCurrentViewComponentState } from '@/views/states/entityCountInCurrentViewComponentState';
|
||||
import { ViewsHotkeyScope } from '@/views/types/ViewsHotkeyScope';
|
||||
import { ViewPickerCreateOrEditContent } from '@/views/view-picker/components/ViewPickerCreateOrEditContent';
|
||||
import { ViewPickerCreateOrEditContentEffect } from '@/views/view-picker/components/ViewPickerCreateOrEditContentEffect';
|
||||
import { ViewPickerContentCreateMode } from '@/views/view-picker/components/ViewPickerContentCreateMode';
|
||||
import { ViewPickerContentEditMode } from '@/views/view-picker/components/ViewPickerContentEditMode';
|
||||
import { ViewPickerContentEffect } from '@/views/view-picker/components/ViewPickerContentEffect';
|
||||
import { ViewPickerListContent } from '@/views/view-picker/components/ViewPickerListContent';
|
||||
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
|
||||
import { useUpdateViewFromCurrentState } from '@/views/view-picker/hooks/useUpdateViewFromCurrentState';
|
||||
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
|
||||
import { useViewPickerPersistView } from '@/views/view-picker/hooks/useViewPickerPersistView';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
import { useViewStates } from '../../hooks/internal/useViewStates';
|
||||
|
||||
const StyledDropdownLabelAdornments = styled.span`
|
||||
align-items: center;
|
||||
color: ${({ theme }) => theme.grayScale.gray35};
|
||||
@ -50,14 +50,12 @@ const StyledViewName = styled.span`
|
||||
export const ViewPickerDropdown = () => {
|
||||
const theme = useTheme();
|
||||
|
||||
const { entityCountInCurrentViewState } = useViewStates();
|
||||
|
||||
const { currentViewWithCombinedFiltersAndSorts } = useGetCurrentView();
|
||||
|
||||
const { handleUpdate } = useViewPickerPersistView();
|
||||
const { updateViewFromCurrentState } = useUpdateViewFromCurrentState();
|
||||
|
||||
const entityCountInCurrentView = useRecoilValue(
|
||||
entityCountInCurrentViewState,
|
||||
const entityCountInCurrentView = useRecoilComponentValueV2(
|
||||
entityCountInCurrentViewComponentState,
|
||||
);
|
||||
|
||||
const { isDropdownOpen: isViewsListDropdownOpen } = useDropdown(
|
||||
@ -71,7 +69,7 @@ export const ViewPickerDropdown = () => {
|
||||
|
||||
const handleClickOutside = async () => {
|
||||
if (isViewsListDropdownOpen && viewPickerMode === 'edit') {
|
||||
await handleUpdate();
|
||||
await updateViewFromCurrentState();
|
||||
}
|
||||
setViewPickerMode('list');
|
||||
};
|
||||
@ -106,8 +104,13 @@ export const ViewPickerDropdown = () => {
|
||||
<ViewPickerListContent />
|
||||
) : (
|
||||
<>
|
||||
<ViewPickerCreateOrEditContent />
|
||||
<ViewPickerCreateOrEditContentEffect />
|
||||
{viewPickerMode === 'create-empty' ||
|
||||
viewPickerMode === 'create-from-current' ? (
|
||||
<ViewPickerContentCreateMode />
|
||||
) : (
|
||||
<ViewPickerContentEditMode />
|
||||
)}
|
||||
<ViewPickerContentEffect />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,36 +1,37 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { Button } from '@/ui/input/button/components/Button';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
import { useCreateViewFromCurrentState } from '@/views/view-picker/hooks/useCreateViewFromCurrentState';
|
||||
import { useDeleteViewFromCurrentState } from '@/views/view-picker/hooks/useDeleteViewFromCurrentState';
|
||||
import { useGetAvailableFieldsForKanban } from '@/views/view-picker/hooks/useGetAvailableFieldsForKanban';
|
||||
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
|
||||
import { useViewPickerPersistView } from '@/views/view-picker/hooks/useViewPickerPersistView';
|
||||
import { useViewPickerStates } from '@/views/view-picker/hooks/useViewPickerStates';
|
||||
import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState';
|
||||
import { viewPickerKanbanFieldMetadataIdComponentState } from '@/views/view-picker/states/viewPickerKanbanFieldMetadataIdComponentState';
|
||||
import { viewPickerTypeComponentState } from '@/views/view-picker/states/viewPickerTypeComponentState';
|
||||
|
||||
export const ViewPickerCreateOrEditButton = () => {
|
||||
export const ViewPickerEditButton = () => {
|
||||
const { availableFieldsForKanban, navigateToSelectSettings } =
|
||||
useGetAvailableFieldsForKanban();
|
||||
|
||||
const {
|
||||
viewPickerIsPersistingState,
|
||||
viewPickerKanbanFieldMetadataIdState,
|
||||
viewPickerTypeState,
|
||||
} = useViewPickerStates();
|
||||
|
||||
const { viewPickerMode } = useViewPickerMode();
|
||||
const viewPickerType = useRecoilValue(viewPickerTypeState);
|
||||
const viewPickerIsPersisting = useRecoilValue(viewPickerIsPersistingState);
|
||||
const viewPickerKanbanFieldMetadataId = useRecoilValue(
|
||||
viewPickerKanbanFieldMetadataIdState,
|
||||
const viewPickerType = useRecoilComponentValueV2(
|
||||
viewPickerTypeComponentState,
|
||||
);
|
||||
const viewPickerIsPersisting = useRecoilComponentValueV2(
|
||||
viewPickerIsPersistingComponentState,
|
||||
);
|
||||
const viewPickerKanbanFieldMetadataId = useRecoilComponentValueV2(
|
||||
viewPickerKanbanFieldMetadataIdComponentState,
|
||||
);
|
||||
|
||||
const { handleCreate, handleDelete } = useViewPickerPersistView();
|
||||
const { createViewFromCurrentState } = useCreateViewFromCurrentState();
|
||||
const { deleteViewFromCurrentState } = useDeleteViewFromCurrentState();
|
||||
|
||||
if (viewPickerMode === 'edit') {
|
||||
return (
|
||||
<Button
|
||||
title="Delete"
|
||||
onClick={handleDelete}
|
||||
onClick={deleteViewFromCurrentState}
|
||||
accent="danger"
|
||||
fullWidth
|
||||
size="small"
|
||||
@ -65,7 +66,7 @@ export const ViewPickerCreateOrEditButton = () => {
|
||||
return (
|
||||
<Button
|
||||
title="Create"
|
||||
onClick={handleCreate}
|
||||
onClick={createViewFromCurrentState}
|
||||
accent="blue"
|
||||
fullWidth
|
||||
size="small"
|
||||
@ -0,0 +1,10 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
const StyledIconAndNameContainer = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
margin-left: ${({ theme }) => theme.spacing(1)};
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
`;
|
||||
|
||||
export { StyledIconAndNameContainer as ViewPickerIconAndNameContainer };
|
||||
@ -1,7 +1,6 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { DropResult } from '@hello-pangea/dnd';
|
||||
import { MouseEvent, useCallback } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
import { IconLock, IconPencil, IconPlus, useIcons } from 'twenty-ui';
|
||||
|
||||
import { DraggableItem } from '@/ui/layout/draggable-list/components/DraggableItem';
|
||||
@ -11,11 +10,13 @@ import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownM
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { MenuItem } from '@/ui/navigation/menu-item/components/MenuItem';
|
||||
import { MenuItemDraggable } from '@/ui/navigation/menu-item/components/MenuItemDraggable';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
import { useChangeView } from '@/views/hooks/useChangeView';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { useHandleViews } from '@/views/hooks/useHandleViews';
|
||||
import { useUpdateView } from '@/views/hooks/useUpdateView';
|
||||
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
|
||||
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
|
||||
import { useViewPickerStates } from '@/views/view-picker/hooks/useViewPickerStates';
|
||||
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
|
||||
import { moveArrayItem } from '~/utils/array/moveArrayItem';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
@ -24,29 +25,27 @@ const StyledBoldDropdownMenuItemsContainer = styled(DropdownMenuItemsContainer)`
|
||||
`;
|
||||
|
||||
export const ViewPickerListContent = () => {
|
||||
const { selectView } = useHandleViews();
|
||||
|
||||
const { currentViewWithCombinedFiltersAndSorts, viewsOnCurrentObject } =
|
||||
useGetCurrentView();
|
||||
const { viewPickerReferenceViewIdState } = useViewPickerStates();
|
||||
const setViewPickerReferenceViewId = useSetRecoilState(
|
||||
viewPickerReferenceViewIdState,
|
||||
const setViewPickerReferenceViewId = useSetRecoilComponentStateV2(
|
||||
viewPickerReferenceViewIdComponentState,
|
||||
);
|
||||
|
||||
const { setViewPickerMode } = useViewPickerMode();
|
||||
|
||||
const { closeDropdown } = useDropdown(VIEW_PICKER_DROPDOWN_ID);
|
||||
const { updateView } = useHandleViews();
|
||||
const { updateView } = useUpdateView();
|
||||
const { changeView } = useChangeView();
|
||||
|
||||
const handleViewSelect = (viewId: string) => {
|
||||
selectView(viewId);
|
||||
changeView(viewId);
|
||||
closeDropdown();
|
||||
};
|
||||
|
||||
const handleAddViewButtonClick = () => {
|
||||
if (isDefined(currentViewWithCombinedFiltersAndSorts?.id)) {
|
||||
setViewPickerReferenceViewId(currentViewWithCombinedFiltersAndSorts.id);
|
||||
setViewPickerMode('create');
|
||||
setViewPickerMode('create-empty');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
const StyledSaveButtonContainer = styled.div`
|
||||
display: flex;
|
||||
padding: ${({ theme }) => theme.spacing(1)};
|
||||
width: calc(100% - ${({ theme }) => theme.spacing(2)});
|
||||
`;
|
||||
|
||||
export { StyledSaveButtonContainer as ViewPickerSaveButtonContainer };
|
||||
@ -0,0 +1,11 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
const StyledSelectContainer = styled.div`
|
||||
display: flex;
|
||||
width: calc(100% - ${({ theme }) => theme.spacing(2)});
|
||||
margin: ${({ theme }) => theme.spacing(1)};
|
||||
color: ${({ theme }) => theme.font.color.light};
|
||||
user-select: none;
|
||||
`;
|
||||
|
||||
export { StyledSelectContainer as ViewPickerSelectContainer };
|
||||
@ -1,19 +1,18 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
import { useDropdown } from '@/ui/layout/dropdown/hooks/useDropdown';
|
||||
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2';
|
||||
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';
|
||||
import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState';
|
||||
|
||||
export const useCloseAndResetViewPicker = () => {
|
||||
const { setViewPickerMode } = useViewPickerMode();
|
||||
const { viewPickerIsPersistingState } = useViewPickerStates();
|
||||
|
||||
const setViewPickerIsPersisting = useSetRecoilState(
|
||||
viewPickerIsPersistingState,
|
||||
const setViewPickerIsPersisting = useSetRecoilComponentStateV2(
|
||||
viewPickerIsPersistingComponentState,
|
||||
);
|
||||
|
||||
const { closeDropdown: closeViewPickerDropdown } = useDropdown(
|
||||
|
||||
@ -0,0 +1,118 @@
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useChangeView } from '@/views/hooks/useChangeView';
|
||||
import { useCreateViewFromCurrentView } from '@/views/hooks/useCreateViewFromCurrentView';
|
||||
import { useCloseAndResetViewPicker } from '@/views/view-picker/hooks/useCloseAndResetViewPicker';
|
||||
import { viewPickerInputNameComponentState } from '@/views/view-picker/states/viewPickerInputNameComponentState';
|
||||
import { viewPickerIsDirtyComponentState } from '@/views/view-picker/states/viewPickerIsDirtyComponentState';
|
||||
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 { viewPickerSelectedIconComponentState } from '@/views/view-picker/states/viewPickerSelectedIconComponentState';
|
||||
import { viewPickerTypeComponentState } from '@/views/view-picker/states/viewPickerTypeComponentState';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
export const useCreateViewFromCurrentState = (viewBarInstanceId?: string) => {
|
||||
const { closeAndResetViewPicker } = useCloseAndResetViewPicker();
|
||||
|
||||
const viewPickerInputNameCallbackState = useRecoilComponentCallbackStateV2(
|
||||
viewPickerInputNameComponentState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const viewPickerSelectedIconCallbackState = useRecoilComponentCallbackStateV2(
|
||||
viewPickerSelectedIconComponentState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const viewPickerTypeCallbackState = useRecoilComponentCallbackStateV2(
|
||||
viewPickerTypeComponentState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const viewPickerKanbanFieldMetadataIdCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
viewPickerKanbanFieldMetadataIdComponentState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const viewPickerIsPersistingCallbackState = useRecoilComponentCallbackStateV2(
|
||||
viewPickerIsPersistingComponentState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const viewPickerIsDirtyCallbackState = useRecoilComponentCallbackStateV2(
|
||||
viewPickerIsDirtyComponentState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const viewPickerModeCallbackState = useRecoilComponentCallbackStateV2(
|
||||
viewPickerModeComponentState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const { createViewFromCurrentView } =
|
||||
useCreateViewFromCurrentView(viewBarInstanceId);
|
||||
const { changeView } = useChangeView(viewBarInstanceId);
|
||||
|
||||
const createViewFromCurrentState = useRecoilCallback(
|
||||
({ snapshot, set }) =>
|
||||
async () => {
|
||||
const name = getSnapshotValue(
|
||||
snapshot,
|
||||
viewPickerInputNameCallbackState,
|
||||
);
|
||||
const iconKey = getSnapshotValue(
|
||||
snapshot,
|
||||
viewPickerSelectedIconCallbackState,
|
||||
);
|
||||
const type = getSnapshotValue(snapshot, viewPickerTypeCallbackState);
|
||||
const kanbanFieldMetadataId = getSnapshotValue(
|
||||
snapshot,
|
||||
viewPickerKanbanFieldMetadataIdCallbackState,
|
||||
);
|
||||
|
||||
const viewPickerMode = getSnapshotValue(
|
||||
snapshot,
|
||||
viewPickerModeCallbackState,
|
||||
);
|
||||
|
||||
const shouldCopyFiltersAndSorts =
|
||||
viewPickerMode === 'create-from-current';
|
||||
|
||||
const id = v4();
|
||||
|
||||
set(viewPickerIsPersistingCallbackState, true);
|
||||
set(viewPickerIsDirtyCallbackState, false);
|
||||
|
||||
await createViewFromCurrentView(
|
||||
{
|
||||
id,
|
||||
name,
|
||||
icon: iconKey,
|
||||
type,
|
||||
kanbanFieldMetadataId,
|
||||
},
|
||||
shouldCopyFiltersAndSorts,
|
||||
);
|
||||
|
||||
closeAndResetViewPicker();
|
||||
changeView(id);
|
||||
},
|
||||
[
|
||||
closeAndResetViewPicker,
|
||||
createViewFromCurrentView,
|
||||
changeView,
|
||||
viewPickerInputNameCallbackState,
|
||||
viewPickerIsDirtyCallbackState,
|
||||
viewPickerIsPersistingCallbackState,
|
||||
viewPickerKanbanFieldMetadataIdCallbackState,
|
||||
viewPickerSelectedIconCallbackState,
|
||||
viewPickerTypeCallbackState,
|
||||
viewPickerModeCallbackState,
|
||||
],
|
||||
);
|
||||
|
||||
return { createViewFromCurrentState };
|
||||
};
|
||||
@ -0,0 +1,78 @@
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useChangeView } from '@/views/hooks/useChangeView';
|
||||
import { useDeleteView } from '@/views/hooks/useDeleteView';
|
||||
import { useGetCurrentView } from '@/views/hooks/useGetCurrentView';
|
||||
import { useCloseAndResetViewPicker } from '@/views/view-picker/hooks/useCloseAndResetViewPicker';
|
||||
import { viewPickerIsDirtyComponentState } from '@/views/view-picker/states/viewPickerIsDirtyComponentState';
|
||||
import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState';
|
||||
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
|
||||
|
||||
export const useDeleteViewFromCurrentState = (viewBarInstanceId?: string) => {
|
||||
const { viewsOnCurrentObject, currentViewId } =
|
||||
useGetCurrentView(viewBarInstanceId);
|
||||
|
||||
const { closeAndResetViewPicker } = useCloseAndResetViewPicker();
|
||||
|
||||
const viewPickerIsPersistingCallbackState = useRecoilComponentCallbackStateV2(
|
||||
viewPickerIsPersistingComponentState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const viewPickerIsDirtyCallbackState = useRecoilComponentCallbackStateV2(
|
||||
viewPickerIsDirtyComponentState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const viewPickerReferenceViewIdCallbackState =
|
||||
useRecoilComponentCallbackStateV2(
|
||||
viewPickerReferenceViewIdComponentState,
|
||||
viewBarInstanceId,
|
||||
);
|
||||
|
||||
const { changeView } = useChangeView(viewBarInstanceId);
|
||||
|
||||
const { deleteView } = useDeleteView();
|
||||
|
||||
const deleteViewFromCurrentState = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
async () => {
|
||||
set(viewPickerIsPersistingCallbackState, true);
|
||||
closeAndResetViewPicker();
|
||||
set(viewPickerIsDirtyCallbackState, false);
|
||||
|
||||
const viewPickerReferenceViewId = getSnapshotValue(
|
||||
snapshot,
|
||||
viewPickerReferenceViewIdCallbackState,
|
||||
);
|
||||
|
||||
const shouldChangeView = viewPickerReferenceViewId === currentViewId;
|
||||
|
||||
if (shouldChangeView) {
|
||||
changeView(
|
||||
viewsOnCurrentObject.filter(
|
||||
(view) => view.id !== viewPickerReferenceViewId,
|
||||
)[0].id,
|
||||
);
|
||||
}
|
||||
|
||||
await deleteView(viewPickerReferenceViewId);
|
||||
},
|
||||
[
|
||||
currentViewId,
|
||||
closeAndResetViewPicker,
|
||||
changeView,
|
||||
deleteView,
|
||||
viewPickerIsDirtyCallbackState,
|
||||
viewPickerIsPersistingCallbackState,
|
||||
viewPickerReferenceViewIdCallbackState,
|
||||
viewsOnCurrentObject,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
deleteViewFromCurrentState,
|
||||
};
|
||||
};
|
||||
@ -5,14 +5,15 @@ import { useRecoilValue, useSetRecoilState } from 'recoil';
|
||||
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
|
||||
import { getObjectSlug } from '@/object-metadata/utils/getObjectSlug';
|
||||
import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState';
|
||||
import { useViewStates } from '@/views/hooks/internal/useViewStates';
|
||||
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
|
||||
import { viewObjectMetadataIdComponentState } from '@/views/states/viewObjectMetadataIdComponentState';
|
||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { isDefined } from '~/utils/isDefined';
|
||||
|
||||
export const useGetAvailableFieldsForKanban = () => {
|
||||
const { viewObjectMetadataIdState } = useViewStates();
|
||||
|
||||
const viewObjectMetadataId = useRecoilValue(viewObjectMetadataIdState);
|
||||
const viewObjectMetadataId = useRecoilComponentValueV2(
|
||||
viewObjectMetadataIdComponentState,
|
||||
);
|
||||
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
|
||||
const setNavigationMemorizedUrl = useSetRecoilState(
|
||||
navigationMemorizedUrlState,
|
||||
|
||||
@ -0,0 +1,80 @@
|
||||
import { getSnapshotValue } from '@/ui/utilities/recoil-scope/utils/getSnapshotValue';
|
||||
import { useRecoilComponentCallbackStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackStateV2';
|
||||
import { useChangeView } from '@/views/hooks/useChangeView';
|
||||
import { useUpdateView } from '@/views/hooks/useUpdateView';
|
||||
import { useCloseAndResetViewPicker } from '@/views/view-picker/hooks/useCloseAndResetViewPicker';
|
||||
import { viewPickerInputNameComponentState } from '@/views/view-picker/states/viewPickerInputNameComponentState';
|
||||
import { viewPickerIsDirtyComponentState } from '@/views/view-picker/states/viewPickerIsDirtyComponentState';
|
||||
import { viewPickerIsPersistingComponentState } from '@/views/view-picker/states/viewPickerIsPersistingComponentState';
|
||||
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
|
||||
import { viewPickerSelectedIconComponentState } from '@/views/view-picker/states/viewPickerSelectedIconComponentState';
|
||||
import { useRecoilCallback } from 'recoil';
|
||||
|
||||
export const useUpdateViewFromCurrentState = (viewBarInstanceId?: string) => {
|
||||
const { closeAndResetViewPicker } = useCloseAndResetViewPicker();
|
||||
|
||||
const viewPickerInputNameCallbackState = useRecoilComponentCallbackStateV2(
|
||||
viewPickerInputNameComponentState,
|
||||
);
|
||||
|
||||
const viewPickerSelectedIconCallbackState = useRecoilComponentCallbackStateV2(
|
||||
viewPickerSelectedIconComponentState,
|
||||
);
|
||||
|
||||
const viewPickerIsPersistingCallbackState = useRecoilComponentCallbackStateV2(
|
||||
viewPickerIsPersistingComponentState,
|
||||
);
|
||||
|
||||
const viewPickerIsDirtyCallbackState = useRecoilComponentCallbackStateV2(
|
||||
viewPickerIsDirtyComponentState,
|
||||
);
|
||||
|
||||
const viewPickerReferenceViewIdCallbackState =
|
||||
useRecoilComponentCallbackStateV2(viewPickerReferenceViewIdComponentState);
|
||||
|
||||
const { updateView } = useUpdateView();
|
||||
const { changeView } = useChangeView(viewBarInstanceId);
|
||||
|
||||
const updateViewFromCurrentState = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
async () => {
|
||||
set(viewPickerIsPersistingCallbackState, true);
|
||||
set(viewPickerIsDirtyCallbackState, false);
|
||||
closeAndResetViewPicker();
|
||||
|
||||
const viewPickerReferenceViewId = getSnapshotValue(
|
||||
snapshot,
|
||||
viewPickerReferenceViewIdCallbackState,
|
||||
);
|
||||
const viewPickerInputName = getSnapshotValue(
|
||||
snapshot,
|
||||
viewPickerInputNameCallbackState,
|
||||
);
|
||||
const viewPickerSelectedIcon = getSnapshotValue(
|
||||
snapshot,
|
||||
viewPickerSelectedIconCallbackState,
|
||||
);
|
||||
|
||||
await updateView({
|
||||
id: viewPickerReferenceViewId,
|
||||
name: viewPickerInputName,
|
||||
icon: viewPickerSelectedIcon,
|
||||
});
|
||||
changeView(viewPickerReferenceViewId);
|
||||
},
|
||||
[
|
||||
viewPickerIsPersistingCallbackState,
|
||||
viewPickerIsDirtyCallbackState,
|
||||
closeAndResetViewPicker,
|
||||
viewPickerReferenceViewIdCallbackState,
|
||||
viewPickerInputNameCallbackState,
|
||||
viewPickerSelectedIconCallbackState,
|
||||
updateView,
|
||||
changeView,
|
||||
],
|
||||
);
|
||||
|
||||
return {
|
||||
updateViewFromCurrentState,
|
||||
};
|
||||
};
|
||||
@ -1,12 +1,11 @@
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { useViewPickerStates } from '@/views/view-picker/hooks/useViewPickerStates';
|
||||
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
|
||||
import { viewPickerModeComponentState } from '@/views/view-picker/states/viewPickerModeComponentState';
|
||||
|
||||
export const useViewPickerMode = (viewBarComponentId?: string) => {
|
||||
const { viewPickerModeState } = useViewPickerStates(viewBarComponentId);
|
||||
|
||||
const [viewPickerMode, setViewPickerMode] =
|
||||
useRecoilState(viewPickerModeState);
|
||||
const [viewPickerMode, setViewPickerMode] = useRecoilComponentStateV2(
|
||||
viewPickerModeComponentState,
|
||||
viewBarComponentId,
|
||||
);
|
||||
|
||||
return {
|
||||
viewPickerMode,
|
||||
|
||||
@ -1,132 +0,0 @@
|
||||
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,
|
||||
viewPickerIsDirtyState,
|
||||
} = 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);
|
||||
set(viewPickerIsDirtyState, false);
|
||||
await createView({
|
||||
id,
|
||||
name,
|
||||
icon: iconKey,
|
||||
type,
|
||||
kanbanFieldMetadataId,
|
||||
});
|
||||
closeAndResetViewPicker();
|
||||
selectView(id);
|
||||
},
|
||||
[
|
||||
closeAndResetViewPicker,
|
||||
createView,
|
||||
selectView,
|
||||
viewPickerInputNameState,
|
||||
viewPickerIsDirtyState,
|
||||
viewPickerIsPersistingState,
|
||||
viewPickerKanbanFieldMetadataIdState,
|
||||
viewPickerSelectedIconState,
|
||||
viewPickerTypeState,
|
||||
],
|
||||
);
|
||||
|
||||
const handleDelete = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
async () => {
|
||||
set(viewPickerIsPersistingState, true);
|
||||
closeAndResetViewPicker();
|
||||
set(viewPickerIsDirtyState, false);
|
||||
const viewPickerReferenceViewId = getSnapshotValue(
|
||||
snapshot,
|
||||
viewPickerReferenceViewIdState,
|
||||
);
|
||||
|
||||
selectView(
|
||||
viewsOnCurrentObject.filter(
|
||||
(view) => view.id !== viewPickerReferenceViewId,
|
||||
)[0].id,
|
||||
);
|
||||
await removeView(viewPickerReferenceViewId);
|
||||
},
|
||||
[
|
||||
closeAndResetViewPicker,
|
||||
removeView,
|
||||
selectView,
|
||||
viewPickerIsDirtyState,
|
||||
viewPickerIsPersistingState,
|
||||
viewPickerReferenceViewIdState,
|
||||
viewsOnCurrentObject,
|
||||
],
|
||||
);
|
||||
|
||||
const handleUpdate = useRecoilCallback(
|
||||
({ set, snapshot }) =>
|
||||
async () => {
|
||||
set(viewPickerIsPersistingState, true);
|
||||
set(viewPickerIsDirtyState, false);
|
||||
closeAndResetViewPicker();
|
||||
|
||||
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);
|
||||
},
|
||||
[
|
||||
viewPickerIsPersistingState,
|
||||
viewPickerIsDirtyState,
|
||||
closeAndResetViewPicker,
|
||||
viewPickerReferenceViewIdState,
|
||||
viewPickerInputNameState,
|
||||
viewPickerSelectedIconState,
|
||||
updateView,
|
||||
selectView,
|
||||
],
|
||||
);
|
||||
|
||||
return { handleCreate, handleDelete, handleUpdate };
|
||||
};
|
||||
@ -1,55 +0,0 @@
|
||||
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 { viewPickerIsDirtyComponentState } from '@/views/view-picker/states/viewPickerIsDirtyComponentState';
|
||||
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,
|
||||
),
|
||||
viewPickerIsDirtyState: extractComponentState(
|
||||
viewPickerIsDirtyComponentState,
|
||||
componentId,
|
||||
),
|
||||
};
|
||||
};
|
||||
@ -1,6 +1,10 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const viewPickerInputNameComponentState = createComponentState<string>({
|
||||
key: 'viewPickerInputNameComponentState',
|
||||
defaultValue: '',
|
||||
});
|
||||
export const viewPickerInputNameComponentState = createComponentStateV2<string>(
|
||||
{
|
||||
key: 'viewPickerInputNameComponentState',
|
||||
defaultValue: '',
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
},
|
||||
);
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const viewPickerIsDirtyComponentState = createComponentState<boolean>({
|
||||
export const viewPickerIsDirtyComponentState = createComponentStateV2<boolean>({
|
||||
key: 'viewPickerIsDirtyComponentState',
|
||||
defaultValue: false,
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const viewPickerIsPersistingComponentState =
|
||||
createComponentState<boolean>({
|
||||
createComponentStateV2<boolean>({
|
||||
key: 'viewPickerIsPersistingComponentState',
|
||||
defaultValue: false,
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const viewPickerKanbanFieldMetadataIdComponentState =
|
||||
createComponentState<string>({
|
||||
createComponentStateV2<string>({
|
||||
key: 'viewPickerKanbanFieldMetadataIdComponentState',
|
||||
defaultValue: '',
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
import { ViewPickerMode } from '@/views/view-picker/types/ViewPickerMode';
|
||||
|
||||
export const viewPickerModeComponentState = createComponentState<
|
||||
'list' | 'edit' | 'create'
|
||||
>({
|
||||
key: 'viewEditModeComponentState',
|
||||
defaultValue: 'list',
|
||||
});
|
||||
export const viewPickerModeComponentState =
|
||||
createComponentStateV2<ViewPickerMode>({
|
||||
key: 'viewPickerModeComponentState',
|
||||
defaultValue: 'list',
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const viewPickerReferenceViewIdComponentState =
|
||||
createComponentState<string>({
|
||||
createComponentStateV2<string>({
|
||||
key: 'viewPickerReferenceViewIdComponentState',
|
||||
defaultValue: '',
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
|
||||
export const viewPickerSelectedIconComponentState =
|
||||
createComponentState<string>({
|
||||
createComponentStateV2<string>({
|
||||
key: 'viewPickerSelectedIconComponentState',
|
||||
defaultValue: '',
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
|
||||
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
|
||||
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
|
||||
import { ViewType } from '@/views/types/ViewType';
|
||||
|
||||
export const viewPickerTypeComponentState = createComponentState<ViewType>({
|
||||
export const viewPickerTypeComponentState = createComponentStateV2<ViewType>({
|
||||
key: 'viewPickerTypeComponentState',
|
||||
defaultValue: ViewType.Table,
|
||||
componentInstanceContext: ViewComponentInstanceContext,
|
||||
});
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
export type ViewPickerMode =
|
||||
| 'list'
|
||||
| 'edit'
|
||||
| 'create-empty'
|
||||
| 'create-from-current';
|
||||
Reference in New Issue
Block a user