## Recoil to Jotai Migration — PR 13: Workflow, Page Layout, AI,
Activities, Settings, SSE & Remaining Modules

### Summary

This is the 13th PR in the [14-PR migration
series](packages/twenty-front/src/modules/ui/utilities/state/jotai/MIGRATION_PLAN.md)
to replace Recoil with Jotai as the state management library in
`twenty-front`. This PR migrates the remaining consumer code across all
modules — updating ~1,076 files with ~10k insertions/deletions.

### What changed

**New Jotai infrastructure (13 new files):**
- `createComponentSelectorV2` and `createComponentFamilySelectorV2` —
instance-scoped derived atoms, replacing Recoil's component selectors
- 6 new hooks: `useRecoilComponentSelectorValueV2`,
`useRecoilComponentFamilySelectorValueV2`,
`useRecoilComponentSelectorCallbackStateV2`,
`useRecoilComponentFamilySelectorCallbackStateV2`,
`useRecoilComponentStateCallbackStateV2`,
`useRecoilComponentFamilyStateCallbackStateV2`
- New types: `ComponentSelectorV2`, `ComponentFamilySelectorV2`,
`SelectorCallbacksV2`
- Extended `buildGetHelper` to support the new selector patterns

**State definition migrations:**
- `createState()` → `createStateV2()` (Jotai `atom()`)
- `createFamilyState()` → `createFamilyStateV2()` (Jotai `atom()` with
family cache)
- Recoil `selector`/`selectorFamily` → Jotai derived `atom()` via V2
utilities

**Hook migrations (~2,400 removed, ~1,545 added V2 equivalents):**
- `useRecoilValue` → `useRecoilValueV2`
- `useRecoilState` → `useRecoilStateV2`
- `useSetRecoilState` → `useSetRecoilStateV2`
- `useRecoilCallback` → `useCallback` + `jotaiStore.get/set`
- `useRecoilComponentValue` → `useRecoilComponentValueV2`
- `useSetRecoilComponentState` → `useSetRecoilComponentStateV2`
- `useRecoilComponentFamilyValue` → `useRecoilComponentFamilyValueV2` /
`useFamilySelectorValueV2`
- ~397 direct `import from 'recoil'` removed

**Deleted files (9 files):**
- `dateLocaleState.ts` — consolidated
- `currentAIChatThreadTitleStateV2.ts` — renamed to replace the original
- `isCommandMenuOpenedState.ts` — removed
- `filesFieldUploadState.ts` — replaced by V2
- `recordStoreFamilySelector.ts`, `recordStoreFieldValueSelector.ts`,
`recordStoreRecordsSelector.ts` — replaced by V2 equivalents
- `settingsAllRolesSelector.ts` — replaced by `useSettingsAllRoles` hook
- `settingsRoleIdsStateV2.ts` — consolidated

**Modules migrated:**
- Workflow (diagram, steps, variables, filters)
- Page Layout (widgets, fields, graph, tabs)
- AI (chat, agents, browsing context)
- Activities (rich text editor, targets, timeline)
- Action Menu (single/multiple record actions)
- Command Menu (navigation, history, pages, workflow)
- Context Store
- Record Board, Record Table, Record Calendar, Record Index
- Record Field, Record Filter, Record Sort, Record Group
- Record Drag, Record Picker, Record Store
- Views (view bar, view picker, filters, sorts)
- Settings (roles, permissions, SSO, security, data model, developers,
domains)
- SSE (event streams, subscriptions)
- Spreadsheet Import
- Auth, Favorites, Front Components, Information Banner
This commit is contained in:
Charles Bochet
2026-02-24 17:37:01 +01:00
committed by GitHub
parent c6ec764b23
commit 0f2af6a6cb
1326 changed files with 19248 additions and 19389 deletions
@@ -8,7 +8,7 @@ import { AdvancedFilterContext } from '@/object-record/advanced-filter/states/co
import { rootLevelRecordFilterGroupComponentSelector } from '@/object-record/advanced-filter/states/rootLevelRecordFilterGroupComponentSelector';
import { isRecordFilterGroupChildARecordFilterGroup } from '@/object-record/advanced-filter/utils/isRecordFilterGroupChildARecordFilterGroup';
import { type VariablePickerComponent } from '@/object-record/record-field/ui/form-types/types/VariablePickerComponent';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import styled from '@emotion/styled';
import { isDefined } from 'twenty-shared/utils';
@@ -41,7 +41,7 @@ export const AdvancedFilterCommandMenuContainer = ({
VariablePicker,
isWorkflowFindRecords,
}: AdvancedFilterCommandMenuContainerProps) => {
const rootRecordFilterGroup = useRecoilComponentValue(
const rootRecordFilterGroup = useRecoilComponentSelectorValueV2(
rootLevelRecordFilterGroupComponentSelector,
);
@@ -5,8 +5,8 @@ import { rootLevelRecordFilterGroupComponentSelector } from '@/object-record/adv
import { useUpsertRecordFilterGroup } from '@/object-record/record-filter-group/hooks/useUpsertRecordFilterGroup';
import { useCreateEmptyRecordFilterFromFieldMetadataItem } from '@/object-record/record-filter/hooks/useCreateEmptyRecordFilterFromFieldMetadataItem';
import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useSetRecoilComponentFamilyState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentFamilyState';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useSetRecoilComponentFamilyStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilComponentFamilyStateV2';
import { hasInitializedCurrentRecordFiltersComponentFamilyState } from '@/views/states/hasInitializedCurrentRecordFiltersComponentFamilyState';
import { useFamilySelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilySelectorValueV2';
import { t } from '@lingui/core/macro';
@@ -23,7 +23,7 @@ export const AdvancedFilterCommandMenuCreateRootFilterButton = ({
objectMetadataItem: ObjectMetadataItem;
}) => {
const { readonly } = useContext(AdvancedFilterContext);
const rootRecordFilterGroup = useRecoilComponentValue(
const rootRecordFilterGroup = useRecoilComponentSelectorValueV2(
rootLevelRecordFilterGroupComponentSelector,
);
@@ -49,7 +49,7 @@ export const AdvancedFilterCommandMenuCreateRootFilterButton = ({
useCreateEmptyRecordFilterFromFieldMetadataItem();
const setHasInitializedCurrentRecordFilters =
useSetRecoilComponentFamilyState(
useSetRecoilComponentFamilyStateV2(
hasInitializedCurrentRecordFiltersComponentFamilyState,
{},
);
@@ -4,7 +4,7 @@ import { getOperandLabel } from '@/object-record/object-filter-dropdown/utils/ge
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
import { SelectControl } from '@/ui/input/components/SelectControl';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { t } from '@lingui/core/macro';
import { useContext } from 'react';
import { isDefined } from 'twenty-shared/utils';
@@ -17,7 +17,7 @@ export const AdvancedFilterCommandMenuRecordFilterOperandSelect = ({
recordFilterId,
}: AdvancedFilterCommandMenuRecordFilterOperandSelectProps) => {
const { readonly, isWorkflowFindRecords } = useContext(AdvancedFilterContext);
const currentRecordFilters = useRecoilComponentValue(
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
@@ -9,7 +9,7 @@ import { FormTextFieldInput } from '@/object-record/record-field/ui/form-types/c
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { CURRENCIES } from '@/settings/data-model/constants/Currencies';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useContext } from 'react';
import { FieldActorSource } from 'twenty-shared/types';
import { type SelectOption } from 'twenty-ui/input';
@@ -33,7 +33,7 @@ export const AdvancedFilterCommandMenuValueFormCompositeFieldInput = ({
}) => {
const { VariablePicker } = useContext(AdvancedFilterContext);
const subFieldNameUsedInDropdown = useRecoilComponentValue(
const subFieldNameUsedInDropdown = useRecoilComponentValueV2(
subFieldNameUsedInDropdownComponentState,
);
@@ -1,6 +1,7 @@
import { formatFieldMetadataItemAsFieldDefinition } from '@/object-metadata/utils/formatFieldMetadataItemAsFieldDefinition';
import { AdvancedFilterCommandMenuValueFormCompositeFieldInput } from '@/object-record/advanced-filter/command-menu/components/AdvancedFilterCommandMenuValueFormCompositeFieldInput';
import { AdvancedFilterContext } from '@/object-record/advanced-filter/states/context/AdvancedFilterContext';
import { getAdvancedFilterObjectFilterDropdownComponentInstanceId } from '@/object-record/advanced-filter/utils/getAdvancedFilterObjectFilterDropdownComponentInstanceId';
import { shouldShowFilterTextInput } from '@/object-record/advanced-filter/utils/shouldShowFilterTextInput';
import { useApplyObjectFilterDropdownFilterValue } from '@/object-record/object-filter-dropdown/hooks/useApplyObjectFilterDropdownFilterValue';
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
@@ -18,7 +19,8 @@ import {
} from '@/object-record/record-field/ui/types/FieldMetadata';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { stringifyRelativeDateFilter } from '@/views/view-filter-value/utils/stringifyRelativeDateFilter';
import { WORKFLOW_TIMEZONE } from '@/workflow/constants/WorkflowTimeZone';
import { useFeatureFlagsMap } from '@/workspace/hooks/useFeatureFlagsMap';
@@ -41,12 +43,16 @@ export const AdvancedFilterCommandMenuValueFormInput = ({
isWorkflowFindRecords,
} = useContext(AdvancedFilterContext);
const currentRecordFilters = useRecoilComponentValue(
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
const subFieldNameUsedInDropdown = useRecoilComponentValue(
const dropdownInstanceId =
getAdvancedFilterObjectFilterDropdownComponentInstanceId(recordFilterId);
const subFieldNameUsedInDropdown = useRecoilComponentValueV2(
subFieldNameUsedInDropdownComponentState,
dropdownInstanceId,
);
const recordFilter = currentRecordFilters.find(
@@ -85,8 +91,9 @@ export const AdvancedFilterCommandMenuValueFormInput = ({
applyObjectFilterDropdownFilterValue(stringifyRelativeDateFilter(newValue));
};
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
const fieldMetadataItemUsedInDropdown = useRecoilComponentSelectorValueV2(
fieldMetadataItemUsedInDropdownComponentSelector,
dropdownInstanceId,
);
const fieldDefinition = fieldMetadataItemUsedInDropdown
@@ -19,7 +19,7 @@ import { isFilterOnActorWorkspaceMemberSubField } from '@/object-record/object-f
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { FieldMetadataType } from 'twenty-shared/types';
import { isExpectedSubFieldName } from 'twenty-shared/utils';
@@ -32,7 +32,7 @@ export const AdvancedFilterDropdownFilterInput = ({
filterDropdownId,
recordFilter,
}: AdvancedFilterDropdownFilterInputProps) => {
const subFieldNameUsedInDropdown = useRecoilComponentValue(
const subFieldNameUsedInDropdown = useRecoilComponentValueV2(
subFieldNameUsedInDropdownComponentState,
);
@@ -3,15 +3,16 @@ import { useObjectFilterDropdownFilterValue } from '@/object-record/object-filte
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
import { TextInput } from '@/ui/input/components/TextInput';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { t } from '@lingui/core/macro';
export const AdvancedFilterDropdownNumberInput = () => {
const selectedOperandInDropdown = useRecoilComponentValue(
const selectedOperandInDropdown = useRecoilComponentValueV2(
selectedOperandInDropdownComponentState,
);
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
const fieldMetadataItemUsedInDropdown = useRecoilComponentSelectorValueV2(
fieldMetadataItemUsedInDropdownComponentSelector,
);
@@ -1,7 +1,7 @@
import { AdvancedFilterFieldSelectMenu } from '@/object-record/advanced-filter/components/AdvancedFilterFieldSelectMenu';
import { AdvancedFilterSubFieldSelectMenu } from '@/object-record/advanced-filter/components/AdvancedFilterSubFieldSelectMenu';
import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateV2';
type AdvancedFilterFieldSelectDropdownContentProps = {
recordFilterId: string;
@@ -11,7 +11,7 @@ export const AdvancedFilterFieldSelectDropdownContent = ({
recordFilterId,
}: AdvancedFilterFieldSelectDropdownContentProps) => {
const [objectFilterDropdownIsSelectingCompositeField] =
useRecoilComponentState(
useRecoilComponentStateV2(
objectFilterDropdownIsSelectingCompositeFieldComponentState,
);
@@ -6,7 +6,7 @@ import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownM
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectableList';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { AdvancedFilterFieldSelectSearchInput } from '@/object-record/advanced-filter/components/AdvancedFilterFieldSelectSearchInput';
@@ -23,8 +23,8 @@ import { useFilterableFieldMetadataItems } from '@/object-record/record-filter/h
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuSectionLabel } from '@/ui/layout/dropdown/components/DropdownMenuSectionLabel';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilComponentStateV2';
import { useLingui } from '@lingui/react/macro';
import { useContext } from 'react';
import { getFilterTypeFromFieldType } from 'twenty-shared/utils';
@@ -41,8 +41,9 @@ export const AdvancedFilterFieldSelectMenu = ({
advancedFilterFieldSelectDropdownId,
} = useAdvancedFilterFieldSelectDropdown(recordFilterId);
const [objectFilterDropdownSearchInput] = useRecoilComponentState(
const [objectFilterDropdownSearchInput] = useRecoilComponentStateV2(
objectFilterDropdownSearchInputComponentState,
advancedFilterFieldSelectDropdownId,
);
const { objectMetadataItem } = useContext(AdvancedFilterContext);
@@ -50,7 +51,7 @@ export const AdvancedFilterFieldSelectMenu = ({
const { filterableFieldMetadataItems: filterableFieldMetadataItems } =
useFilterableFieldMetadataItems(objectMetadataItem.id);
const visibleRecordFields = useRecoilComponentValue(
const visibleRecordFields = useRecoilComponentSelectorValueV2(
visibleRecordFieldsComponentSelector,
);
@@ -90,17 +91,20 @@ export const AdvancedFilterFieldSelectMenu = ({
const { selectFieldUsedInAdvancedFilterDropdown } =
useSelectFieldUsedInAdvancedFilterDropdown();
const [, setObjectFilterDropdownSubMenuFieldType] = useRecoilComponentState(
const [, setObjectFilterDropdownSubMenuFieldType] = useRecoilComponentStateV2(
objectFilterDropdownSubMenuFieldTypeComponentState,
advancedFilterFieldSelectDropdownId,
);
const [, setObjectFilterDropdownIsSelectingCompositeField] =
useRecoilComponentState(
useRecoilComponentStateV2(
objectFilterDropdownIsSelectingCompositeFieldComponentState,
advancedFilterFieldSelectDropdownId,
);
const setFieldMetadataItemIdUsedInDropdown = useSetRecoilComponentState(
const setFieldMetadataItemIdUsedInDropdown = useSetRecoilComponentStateV2(
fieldMetadataItemIdUsedInDropdownComponentState,
advancedFilterFieldSelectDropdownId,
);
const handleFieldMetadataItemSelect = (
@@ -1,5 +1,5 @@
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateV2';
import styled from '@emotion/styled';
import { t } from '@lingui/core/macro';
@@ -31,7 +31,7 @@ export const StyledInput = styled.input`
export const AdvancedFilterFieldSelectSearchInput = () => {
const [objectFilterDropdownSearchInput, setObjectFilterDropdownSearchInput] =
useRecoilComponentState(objectFilterDropdownSearchInputComponentState);
useRecoilComponentStateV2(objectFilterDropdownSearchInputComponentState);
return (
<StyledInput
@@ -5,7 +5,7 @@ import { currentRecordFiltersComponentState } from '@/object-record/record-filte
import { getRecordFilterOperands } from '@/object-record/record-filter/utils/getRecordFilterOperands';
import { useUserTimezone } from '@/ui/input/components/internal/date/hooks/useUserTimezone';
import { SelectControl } from '@/ui/input/components/SelectControl';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import styled from '@emotion/styled';
import { t } from '@lingui/core/macro';
import { isDefined } from 'twenty-shared/utils';
@@ -21,7 +21,7 @@ type AdvancedFilterRecordFilterOperandSelectProps = {
export const AdvancedFilterRecordFilterOperandSelect = ({
recordFilterId,
}: AdvancedFilterRecordFilterOperandSelectProps) => {
const currentRecordFilters = useRecoilComponentValue(
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
@@ -10,7 +10,7 @@ import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { t } from '@lingui/core/macro';
import { isDefined } from 'twenty-shared/utils';
import { IconDotsVertical, IconTrash } from 'twenty-ui/display';
@@ -31,7 +31,7 @@ export const AdvancedFilterRecordFilterOptionsDropdown = ({
const { removeRecordFilter } = useRemoveRecordFilter();
const { removeRecordFilterGroup } = useRemoveRecordFilterGroup();
const currentRecordFilters = useRecoilComponentValue(
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
@@ -10,7 +10,7 @@ import { rootLevelRecordFilterGroupComponentSelector } from '@/object-record/adv
import { isRecordFilterGroupChildARecordFilterGroup } from '@/object-record/advanced-filter/utils/isRecordFilterGroupChildARecordFilterGroup';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import styled from '@emotion/styled';
import { isDefined } from 'twenty-shared/utils';
@@ -24,7 +24,7 @@ const StyledContainer = styled.div`
`;
export const AdvancedFilterRootRecordFilterGroup = () => {
const rootRecordFilterGroup = useRecoilComponentValue(
const rootRecordFilterGroup = useRecoilComponentSelectorValueV2(
rootLevelRecordFilterGroupComponentSelector,
);
@@ -1,6 +1,7 @@
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateV2';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { isDefined } from 'twenty-shared/utils';
@@ -23,7 +24,6 @@ import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/Gene
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { t } from '@lingui/core/macro';
import { IconChevronLeft, useIcons } from 'twenty-ui/display';
import { MenuItem } from 'twenty-ui/navigation';
@@ -37,19 +37,19 @@ export const AdvancedFilterSubFieldSelectMenu = ({
}: AdvancedFilterSubFieldSelectMenuProps) => {
const { getIcon } = useIcons();
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
const fieldMetadataItemUsedInDropdown = useRecoilComponentSelectorValueV2(
fieldMetadataItemUsedInDropdownComponentSelector,
);
const [, setObjectFilterDropdownIsSelectingCompositeField] =
useRecoilComponentState(
useRecoilComponentStateV2(
objectFilterDropdownIsSelectingCompositeFieldComponentState,
);
const [
objectFilterDropdownSubMenuFieldType,
setObjectFilterDropdownSubMenuFieldType,
] = useRecoilComponentState(
] = useRecoilComponentStateV2(
objectFilterDropdownSubMenuFieldTypeComponentState,
);
@@ -11,8 +11,8 @@ import { configurableViewFilterOperands } from '@/object-record/object-filter-dr
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { type DropdownOffset } from '@/ui/layout/dropdown/types/DropdownOffset';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilComponentStateV2';
import styled from '@emotion/styled';
import { isDefined } from 'twenty-shared/utils';
@@ -30,12 +30,13 @@ export const AdvancedFilterValueInput = ({
}: AdvancedFilterValueInputProps) => {
const dropdownId = `advanced-filter-view-filter-value-input-${recordFilterId}`;
const currentRecordFilters = useRecoilComponentValue(
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
const subFieldNameUsedInDropdown = useRecoilComponentValue(
const subFieldNameUsedInDropdown = useRecoilComponentValueV2(
subFieldNameUsedInDropdownComponentState,
dropdownId,
);
const recordFilter = currentRecordFilters.find(
@@ -44,17 +45,21 @@ export const AdvancedFilterValueInput = ({
const isDisabled = !recordFilter?.fieldMetadataId || !recordFilter.operand;
const setObjectFilterDropdownSearchInput = useSetRecoilComponentState(
const setObjectFilterDropdownSearchInput = useSetRecoilComponentStateV2(
objectFilterDropdownSearchInputComponentState,
dropdownId,
);
const setFieldMetadataItemIdUsedInDropdown = useSetRecoilComponentState(
const setFieldMetadataItemIdUsedInDropdown = useSetRecoilComponentStateV2(
fieldMetadataItemIdUsedInDropdownComponentState,
dropdownId,
);
const setObjectFilterDropdownCurrentRecordFilter = useSetRecoilComponentState(
objectFilterDropdownCurrentRecordFilterComponentState,
);
const setObjectFilterDropdownCurrentRecordFilter =
useSetRecoilComponentStateV2(
objectFilterDropdownCurrentRecordFilterComponentState,
dropdownId,
);
const operandHasNoInput =
recordFilter && !configurableViewFilterOperands.has(recordFilter.operand);
@@ -1,7 +1,7 @@
import { getAdvancedFilterInputPlaceholderText } from '@/object-record/advanced-filter/utils/getAdvancedFilterInputPlacedholderText';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { SelectControl } from '@/ui/input/components/SelectControl';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { isNonEmptyString } from '@sniptt/guards';
@@ -36,7 +36,7 @@ type AdvancedFilterValueInputDropdownButtonClickableSelectProps = {
export const AdvancedFilterValueInputDropdownButtonClickableSelect = ({
recordFilterId,
}: AdvancedFilterValueInputDropdownButtonClickableSelectProps) => {
const currentRecordFilters = useRecoilComponentValue(
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
@@ -2,7 +2,7 @@ import { currentRecordFilterGroupsComponentState } from '@/object-record/record-
import { type RecordFilterGroup } from '@/object-record/record-filter-group/types/RecordFilterGroup';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { isDefined } from 'twenty-shared/utils';
export const useChildRecordFiltersAndRecordFilterGroups = ({
@@ -10,11 +10,11 @@ export const useChildRecordFiltersAndRecordFilterGroups = ({
}: {
recordFilterGroupId?: string;
}) => {
const currentRecordFilters = useRecoilComponentValue(
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
const currentRecordFilterGroups = useRecoilComponentValue(
const currentRecordFilterGroups = useRecoilComponentValueV2(
currentRecordFilterGroupsComponentState,
);
@@ -3,13 +3,13 @@ import { getCompositeSubFieldLabel } from '@/object-record/object-filter-dropdow
import { isCompositeFieldType } from '@/object-record/object-filter-dropdown/utils/isCompositeFieldType';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { isValidSubFieldName } from '@/settings/data-model/utils/isValidSubFieldName';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { isNonEmptyString } from '@sniptt/guards';
import { isDefined } from 'twenty-shared/utils';
import { useIcons } from 'twenty-ui/display';
export const useRecordFilterField = (recordFilterId: string) => {
const currentRecordFilters = useRecoilComponentValue(
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
@@ -15,8 +15,8 @@ import { isCompositeTypeNonFilterableByAnySubField } from '@/object-record/recor
import { type CompositeFieldSubFieldName } from '@/settings/data-model/types/CompositeFieldSubFieldName';
import { usePushFocusItemToFocusStack } from '@/ui/utilities/focus/hooks/usePushFocusItemToFocusStack';
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilComponentStateV2';
import { getFilterTypeFromFieldType, isDefined } from 'twenty-shared/utils';
type SelectFilterParams = {
@@ -26,19 +26,19 @@ type SelectFilterParams = {
};
export const useSelectFieldUsedInAdvancedFilterDropdown = () => {
const setSelectedOperandInDropdown = useSetRecoilComponentState(
const setSelectedOperandInDropdown = useSetRecoilComponentStateV2(
selectedOperandInDropdownComponentState,
);
const setFieldMetadataItemIdUsedInDropdown = useSetRecoilComponentState(
const setFieldMetadataItemIdUsedInDropdown = useSetRecoilComponentStateV2(
fieldMetadataItemIdUsedInDropdownComponentState,
);
const setObjectFilterDropdownSearchInput = useSetRecoilComponentState(
const setObjectFilterDropdownSearchInput = useSetRecoilComponentStateV2(
objectFilterDropdownSearchInputComponentState,
);
const currentRecordFilters = useRecoilComponentValue(
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
@@ -47,13 +47,14 @@ export const useSelectFieldUsedInAdvancedFilterDropdown = () => {
const { getFieldMetadataItemByIdOrThrow } =
useGetFieldMetadataItemByIdOrThrow();
const setSubFieldNameUsedInDropdown = useSetRecoilComponentState(
const setSubFieldNameUsedInDropdown = useSetRecoilComponentStateV2(
subFieldNameUsedInDropdownComponentState,
);
const setObjectFilterDropdownCurrentRecordFilter = useSetRecoilComponentState(
objectFilterDropdownCurrentRecordFilterComponentState,
);
const setObjectFilterDropdownCurrentRecordFilter =
useSetRecoilComponentStateV2(
objectFilterDropdownCurrentRecordFilterComponentState,
);
const { upsertRecordFilter } = useUpsertRecordFilter();
const { getInitialFilterValue } = useGetInitialFilterValue();
@@ -6,91 +6,85 @@ import { subFieldNameUsedInDropdownComponentState } from '@/object-record/object
import { currentRecordFilterGroupsComponentState } from '@/object-record/record-filter-group/states/currentRecordFilterGroupsComponentState';
import { currentRecordFiltersComponentState } from '@/object-record/record-filter/states/currentRecordFiltersComponentState';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilCallback } from 'recoil';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useCallback } from 'react';
export const useSetAdvancedFilterDropdownStates = () => {
const rootLevelRecordFilterGroup = useRecoilComponentValue(
const rootLevelRecordFilterGroup = useRecoilComponentSelectorValueV2(
rootLevelRecordFilterGroupComponentSelector,
);
const currentRecordFilters = useRecoilComponentValue(
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
const currentRecordFilterGroups = useRecoilComponentValue(
const currentRecordFilterGroups = useRecoilComponentValueV2(
currentRecordFilterGroupsComponentState,
);
const setAdvancedFilterDropdownStates = useRecoilCallback(
({ set }) =>
() => {
const rootLevelRecordFilters = currentRecordFilters.filter(
(recordFilter) =>
recordFilter.recordFilterGroupId === rootLevelRecordFilterGroup?.id,
const setAdvancedFilterDropdownStates = useCallback(() => {
const rootLevelRecordFilters = currentRecordFilters.filter(
(recordFilter) =>
recordFilter.recordFilterGroupId === rootLevelRecordFilterGroup?.id,
);
const setAdvancedFilterStatesForRecordFilter = (
recordFilter: RecordFilter,
) => {
const instanceId =
getAdvancedFilterObjectFilterDropdownComponentInstanceId(
recordFilter.id,
);
const setAdvancedFilterStatesForRecordFilter = (
recordFilter: RecordFilter,
) => {
set(
objectFilterDropdownCurrentRecordFilterComponentState.atomFamily({
instanceId:
getAdvancedFilterObjectFilterDropdownComponentInstanceId(
recordFilter.id,
),
}),
recordFilter,
);
jotaiStore.set(
objectFilterDropdownCurrentRecordFilterComponentState.atomFamily({
instanceId,
}),
recordFilter,
);
set(
fieldMetadataItemIdUsedInDropdownComponentState.atomFamily({
instanceId:
getAdvancedFilterObjectFilterDropdownComponentInstanceId(
recordFilter.id,
),
}),
recordFilter.fieldMetadataId,
);
jotaiStore.set(
fieldMetadataItemIdUsedInDropdownComponentState.atomFamily({
instanceId,
}),
recordFilter.fieldMetadataId,
);
set(
subFieldNameUsedInDropdownComponentState.atomFamily({
instanceId:
getAdvancedFilterObjectFilterDropdownComponentInstanceId(
recordFilter.id,
),
}),
recordFilter.subFieldName,
);
};
jotaiStore.set(
subFieldNameUsedInDropdownComponentState.atomFamily({
instanceId,
}),
recordFilter.subFieldName,
);
};
for (const rootLevelRecordFilter of rootLevelRecordFilters) {
setAdvancedFilterStatesForRecordFilter(rootLevelRecordFilter);
}
for (const rootLevelRecordFilter of rootLevelRecordFilters) {
setAdvancedFilterStatesForRecordFilter(rootLevelRecordFilter);
}
const childRecordFilterGroups = currentRecordFilterGroups.filter(
(currentRecordGroupToFilter) =>
currentRecordGroupToFilter.parentRecordFilterGroupId ===
rootLevelRecordFilterGroup?.id,
);
const childRecordFilterGroups = currentRecordFilterGroups.filter(
(currentRecordGroupToFilter) =>
currentRecordGroupToFilter.parentRecordFilterGroupId ===
rootLevelRecordFilterGroup?.id,
);
for (const childRecordFilterGroup of childRecordFilterGroups) {
const recordFiltersInThisGroup = currentRecordFilters.filter(
(recordFilter) =>
recordFilter.recordFilterGroupId === childRecordFilterGroup.id,
);
for (const childRecordFilterGroup of childRecordFilterGroups) {
const recordFiltersInThisGroup = currentRecordFilters.filter(
(recordFilter) =>
recordFilter.recordFilterGroupId === childRecordFilterGroup.id,
);
for (const recordFilterInThisGroup of recordFiltersInThisGroup) {
setAdvancedFilterStatesForRecordFilter(recordFilterInThisGroup);
}
}
},
[
currentRecordFilterGroups,
currentRecordFilters,
rootLevelRecordFilterGroup,
],
);
for (const recordFilterInThisGroup of recordFiltersInThisGroup) {
setAdvancedFilterStatesForRecordFilter(recordFilterInThisGroup);
}
}
}, [
currentRecordFilterGroups,
currentRecordFilters,
rootLevelRecordFilterGroup,
]);
return {
setAdvancedFilterDropdownStates,
@@ -3,41 +3,38 @@ import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record
import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState';
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { useRecoilCallback } from 'recoil';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { useCallback } from 'react';
export const useSetRecordFilterUsedInAdvancedFilterDropdownRow = () => {
const setRecordFilterUsedInAdvancedFilterDropdownRow = useRecoilCallback(
({ set }) =>
(recordFilter: RecordFilter) => {
const advancedFilterRowObjectFilterDropdownComponentInstanceId =
getAdvancedFilterObjectFilterDropdownComponentInstanceId(
recordFilter.id,
);
set(
fieldMetadataItemIdUsedInDropdownComponentState.atomFamily({
instanceId:
advancedFilterRowObjectFilterDropdownComponentInstanceId,
}),
recordFilter.fieldMetadataId,
const setRecordFilterUsedInAdvancedFilterDropdownRow = useCallback(
(recordFilter: RecordFilter) => {
const advancedFilterRowObjectFilterDropdownComponentInstanceId =
getAdvancedFilterObjectFilterDropdownComponentInstanceId(
recordFilter.id,
);
set(
selectedOperandInDropdownComponentState.atomFamily({
instanceId:
advancedFilterRowObjectFilterDropdownComponentInstanceId,
}),
recordFilter.operand,
);
jotaiStore.set(
fieldMetadataItemIdUsedInDropdownComponentState.atomFamily({
instanceId: advancedFilterRowObjectFilterDropdownComponentInstanceId,
}),
recordFilter.fieldMetadataId,
);
set(
objectFilterDropdownCurrentRecordFilterComponentState.atomFamily({
instanceId:
advancedFilterRowObjectFilterDropdownComponentInstanceId,
}),
recordFilter,
);
},
jotaiStore.set(
selectedOperandInDropdownComponentState.atomFamily({
instanceId: advancedFilterRowObjectFilterDropdownComponentInstanceId,
}),
recordFilter.operand,
);
jotaiStore.set(
objectFilterDropdownCurrentRecordFilterComponentState.atomFamily({
instanceId: advancedFilterRowObjectFilterDropdownComponentInstanceId,
}),
recordFilter,
);
},
[],
);
@@ -1,17 +1,20 @@
import { type RecordFilterGroup } from '@/object-record/record-filter-group/types/RecordFilterGroup';
import { RecordFilterGroupsComponentInstanceContext } from '@/object-record/record-filter-group/states/context/RecordFilterGroupsComponentInstanceContext';
import { currentRecordFilterGroupsComponentState } from '@/object-record/record-filter-group/states/currentRecordFilterGroupsComponentState';
import { createComponentSelector } from '@/ui/utilities/state/component-state/utils/createComponentSelector';
import { createComponentSelectorV2 } from '@/ui/utilities/state/jotai/utils/createComponentSelectorV2';
import { isDefined } from 'twenty-shared/utils';
export const rootLevelRecordFilterGroupComponentSelector =
createComponentSelector({
createComponentSelectorV2<RecordFilterGroup | undefined>({
key: 'rootLevelRecordFilterGroupComponentSelector',
componentInstanceContext: RecordFilterGroupsComponentInstanceContext,
get:
({ instanceId }) =>
(componentStateKey) =>
({ get }) => {
const currentRecordFilterGroups = get(
currentRecordFilterGroupsComponentState.atomFamily({ instanceId }),
);
currentRecordFilterGroupsComponentState,
componentStateKey,
) as RecordFilterGroup[];
const rootLevelRecordFilterGroup = currentRecordFilterGroups.find(
(recordFilterGroup) =>
@@ -20,5 +23,4 @@ export const rootLevelRecordFilterGroupComponentSelector =
return rootLevelRecordFilterGroup;
},
componentInstanceContext: RecordFilterGroupsComponentInstanceContext,
});
@@ -8,8 +8,7 @@ import {
import { type Unmasked } from '@apollo/client/masking';
import { isNonEmptyArray } from '@apollo/client/utilities';
import { isNonEmptyString } from '@sniptt/guards';
import { useMemo } from 'react';
import { useRecoilCallback, useRecoilState, useSetRecoilState } from 'recoil';
import { useCallback, useMemo } from 'react';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { type ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
@@ -30,6 +29,9 @@ import {
import { cursorFamilyState } from '@/object-record/states/cursorFamilyState';
import { hasNextPageFamilyState } from '@/object-record/states/hasNextPageFamilyState';
import { isFetchingMoreRecordsFamilyState } from '@/object-record/states/isFetchingMoreRecordsFamilyState';
import { useFamilyRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilyRecoilValueV2';
import { useSetFamilyRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetFamilyRecoilStateV2';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { capitalize, isDefined } from 'twenty-shared/utils';
export type UseFindManyRecordsParams<T> = ObjectMetadataItemIdentifier &
@@ -86,10 +88,14 @@ export const useFetchMoreRecordsWithPagination = <
orderBy,
});
const [hasNextPage] = useRecoilState(hasNextPageFamilyState(queryIdentifier));
const hasNextPage = useFamilyRecoilValueV2(
hasNextPageFamilyState,
queryIdentifier,
);
const setIsFetchingMoreObjects = useSetRecoilState(
isFetchingMoreRecordsFamilyState(queryIdentifier),
const setIsFetchingMoreObjects = useSetFamilyRecoilStateV2(
isFetchingMoreRecordsFamilyState,
queryIdentifier,
);
const { handleFindManyRecordsError } = useHandleFindManyRecordsError({
@@ -98,115 +104,108 @@ export const useFetchMoreRecordsWithPagination = <
// TODO: put this into a util inspired from https://github.com/apollographql/apollo-client/blob/master/src/utilities/policies/pagination.ts
// This function is equivalent to merge function + read function in field policy
const fetchMoreRecords = useRecoilCallback(
({ snapshot, set }) =>
async () => {
const hasNextPageLocal = snapshot
.getLoadable(hasNextPageFamilyState(queryIdentifier))
.getValue();
const fetchMoreRecords = useCallback(async () => {
const hasNextPageLocal = jotaiStore.get(
hasNextPageFamilyState.atomFamily(queryIdentifier),
);
const lastCursorLocal = snapshot
.getLoadable(cursorFamilyState(queryIdentifier))
.getValue();
const lastCursorLocal = jotaiStore.get(
cursorFamilyState.atomFamily(queryIdentifier),
);
// Remote objects does not support hasNextPage. We cannot rely on it to fetch more records.
if (
hasNextPageLocal ||
(!isAggregationEnabled(objectMetadataItem) && !error)
) {
setIsFetchingMoreObjects(true);
// Remote objects does not support hasNextPage. We cannot rely on it to fetch more records.
if (
hasNextPageLocal ||
(!isAggregationEnabled(objectMetadataItem) && !error)
) {
setIsFetchingMoreObjects(true);
try {
const { data: fetchMoreDataResult } = await fetchMore({
variables: {
filter,
orderBy,
lastCursor: isNonEmptyString(lastCursorLocal)
? lastCursorLocal
: undefined,
try {
const { data: fetchMoreDataResult } = await fetchMore({
variables: {
filter,
orderBy,
lastCursor: isNonEmptyString(lastCursorLocal)
? lastCursorLocal
: undefined,
},
updateQuery: (prev, { fetchMoreResult }) => {
const previousEdges = prev?.[objectMetadataItem.namePlural]?.edges;
const nextEdges =
fetchMoreResult?.[objectMetadataItem.namePlural]?.edges;
let newEdges: RecordGqlEdge[] = previousEdges ?? [];
if (isNonEmptyArray(nextEdges)) {
newEdges = filterUniqueRecordEdgesByCursor([
...newEdges,
...(fetchMoreResult?.[objectMetadataItem.namePlural]?.edges ??
[]),
]);
}
const pageInfo =
fetchMoreResult?.[objectMetadataItem.namePlural]?.pageInfo;
if (isDefined(pageInfo)) {
jotaiStore.set(
cursorFamilyState.atomFamily(queryIdentifier),
pageInfo.endCursor ?? '',
);
jotaiStore.set(
hasNextPageFamilyState.atomFamily(queryIdentifier),
pageInfo.hasNextPage ?? false,
);
}
const records = getRecordsFromRecordConnection({
recordConnection: {
edges: newEdges,
pageInfo,
},
updateQuery: (prev, { fetchMoreResult }) => {
const previousEdges =
prev?.[objectMetadataItem.namePlural]?.edges;
const nextEdges =
fetchMoreResult?.[objectMetadataItem.namePlural]?.edges;
let newEdges: RecordGqlEdge[] = previousEdges ?? [];
}) as T[];
if (isNonEmptyArray(nextEdges)) {
newEdges = filterUniqueRecordEdgesByCursor([
...newEdges,
...(fetchMoreResult?.[objectMetadataItem.namePlural]
?.edges ?? []),
]);
}
const pageInfo =
fetchMoreResult?.[objectMetadataItem.namePlural]?.pageInfo;
if (isDefined(pageInfo)) {
set(
cursorFamilyState(queryIdentifier),
pageInfo.endCursor ?? '',
);
set(
hasNextPageFamilyState(queryIdentifier),
pageInfo.hasNextPage ?? false,
);
}
const records = getRecordsFromRecordConnection({
recordConnection: {
edges: newEdges,
pageInfo,
},
}) as T[];
onCompleted?.(records, {
pageInfo,
totalCount:
fetchMoreResult?.[objectMetadataItem.namePlural]
?.totalCount,
});
return Object.assign({}, prev, {
[objectMetadataItem.namePlural]: {
__typename: `${capitalize(
objectMetadataItem.nameSingular,
)}Connection`,
edges: newEdges,
pageInfo:
fetchMoreResult?.[objectMetadataItem.namePlural].pageInfo,
totalCount:
fetchMoreResult?.[objectMetadataItem.namePlural]
.totalCount,
},
} as RecordGqlOperationFindManyResult);
},
onCompleted?.(records, {
pageInfo,
totalCount:
fetchMoreResult?.[objectMetadataItem.namePlural]?.totalCount,
});
return {
data: fetchMoreDataResult?.[objectMetadataItem.namePlural],
};
} catch (error) {
handleFindManyRecordsError(error as ApolloError);
return { error: error as ApolloError };
} finally {
setIsFetchingMoreObjects(false);
}
}
},
[
objectMetadataItem,
error,
setIsFetchingMoreObjects,
fetchMore,
filter,
orderBy,
onCompleted,
handleFindManyRecordsError,
queryIdentifier,
],
);
return Object.assign({}, prev, {
[objectMetadataItem.namePlural]: {
__typename: `${capitalize(
objectMetadataItem.nameSingular,
)}Connection`,
edges: newEdges,
pageInfo:
fetchMoreResult?.[objectMetadataItem.namePlural].pageInfo,
totalCount:
fetchMoreResult?.[objectMetadataItem.namePlural].totalCount,
},
} as RecordGqlOperationFindManyResult);
},
});
return {
data: fetchMoreDataResult?.[objectMetadataItem.namePlural],
};
} catch (error) {
handleFindManyRecordsError(error as ApolloError);
return { error: error as ApolloError };
} finally {
setIsFetchingMoreObjects(false);
}
}
}, [
objectMetadataItem,
error,
setIsFetchingMoreObjects,
fetchMore,
filter,
orderBy,
onCompleted,
handleFindManyRecordsError,
queryIdentifier,
]);
const totalCount = data?.[objectMetadataItem.namePlural]?.totalCount;
@@ -4,7 +4,8 @@ import { type RecordGqlOperationFindManyResult } from '@/object-record/graphql/t
import { cursorFamilyState } from '@/object-record/states/cursorFamilyState';
import { hasNextPageFamilyState } from '@/object-record/states/hasNextPageFamilyState';
import { type OnFindManyRecordsCompleted } from '@/object-record/types/OnFindManyRecordsCompleted';
import { useRecoilCallback } from 'recoil';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { useCallback } from 'react';
import { isDefined } from 'twenty-shared/utils';
export const useHandleFindManyRecordsCompleted = <T>({
@@ -16,28 +17,30 @@ export const useHandleFindManyRecordsCompleted = <T>({
objectMetadataItem: ObjectMetadataItem;
onCompleted?: OnFindManyRecordsCompleted<T>;
}) => {
const handleFindManyRecordsCompleted = useRecoilCallback(
({ set }) =>
(data: RecordGqlOperationFindManyResult) => {
const pageInfo = data?.[objectMetadataItem.namePlural]?.pageInfo;
const handleFindManyRecordsCompleted = useCallback(
(data: RecordGqlOperationFindManyResult) => {
const pageInfo = data?.[objectMetadataItem.namePlural]?.pageInfo;
const records = getRecordsFromRecordConnection({
recordConnection: data?.[objectMetadataItem.namePlural],
}) as T[];
const records = getRecordsFromRecordConnection({
recordConnection: data?.[objectMetadataItem.namePlural],
}) as T[];
onCompleted?.(records, {
pageInfo,
totalCount: data?.[objectMetadataItem.namePlural]?.totalCount,
});
onCompleted?.(records, {
pageInfo,
totalCount: data?.[objectMetadataItem.namePlural]?.totalCount,
});
if (isDefined(data?.[objectMetadataItem.namePlural])) {
set(cursorFamilyState(queryIdentifier), pageInfo.endCursor ?? '');
set(
hasNextPageFamilyState(queryIdentifier),
pageInfo.hasNextPage ?? false,
);
}
},
if (isDefined(data?.[objectMetadataItem.namePlural])) {
jotaiStore.set(
cursorFamilyState.atomFamily(queryIdentifier),
pageInfo.endCursor ?? '',
);
jotaiStore.set(
hasNextPageFamilyState.atomFamily(queryIdentifier),
pageInfo.hasNextPage ?? false,
);
}
},
[objectMetadataItem.namePlural, onCompleted, queryIdentifier],
);
@@ -8,7 +8,7 @@ import {
import { type Unmasked } from '@apollo/client/masking';
import { isNonEmptyArray } from '@apollo/client/utilities';
import { isNonEmptyString } from '@sniptt/guards';
import { useRecoilCallback } from 'recoil';
import { useCallback } from 'react';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { type ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
@@ -29,6 +29,7 @@ import {
import { DEFAULT_SEARCH_REQUEST_LIMIT } from '@/object-record/constants/DefaultSearchRequestLimit';
import { cursorFamilyState } from '@/object-record/states/cursorFamilyState';
import { hasNextPageFamilyState } from '@/object-record/states/hasNextPageFamilyState';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { capitalize, isDefined } from 'twenty-shared/utils';
export type UseFindManyRecordsParams<T> = ObjectMetadataItemIdentifier &
@@ -89,99 +90,96 @@ export const useLazyFetchMoreRecordsWithPagination = <
// TODO: put this into a util inspired from https://github.com/apollographql/apollo-client/blob/master/src/utilities/policies/pagination.ts
// This function is equivalent to merge function + read function in field policy
const fetchMoreRecordsLazy = useRecoilCallback(
({ snapshot, set }) =>
async (limit = DEFAULT_SEARCH_REQUEST_LIMIT) => {
const hasNextPageLocal = snapshot
.getLoadable(hasNextPageFamilyState(queryIdentifier))
.getValue();
const fetchMoreRecordsLazy = useCallback(
async (limit = DEFAULT_SEARCH_REQUEST_LIMIT) => {
const hasNextPageLocal = jotaiStore.get(
hasNextPageFamilyState.atomFamily(queryIdentifier),
);
const lastCursorLocal = snapshot
.getLoadable(cursorFamilyState(queryIdentifier))
.getValue();
const lastCursorLocal = jotaiStore.get(
cursorFamilyState.atomFamily(queryIdentifier),
);
// Remote objects does not support hasNextPage. We cannot rely on it to fetch more records.
if (
hasNextPageLocal ||
(!isAggregationEnabled(objectMetadataItem) && !error)
) {
try {
const { data: fetchMoreDataResult } = await fetchMore({
variables: {
limit,
filter,
orderBy,
lastCursor: isNonEmptyString(lastCursorLocal)
? lastCursorLocal
: undefined,
},
updateQuery: (prev, { fetchMoreResult }) => {
const previousEdges =
prev?.[objectMetadataItem.namePlural]?.edges;
const nextEdges =
fetchMoreResult?.[objectMetadataItem.namePlural]?.edges;
// Remote objects does not support hasNextPage. We cannot rely on it to fetch more records.
if (
hasNextPageLocal ||
(!isAggregationEnabled(objectMetadataItem) && !error)
) {
try {
const { data: fetchMoreDataResult } = await fetchMore({
variables: {
limit,
filter,
orderBy,
lastCursor: isNonEmptyString(lastCursorLocal)
? lastCursorLocal
: undefined,
},
updateQuery: (prev, { fetchMoreResult }) => {
const previousEdges =
prev?.[objectMetadataItem.namePlural]?.edges;
const nextEdges =
fetchMoreResult?.[objectMetadataItem.namePlural]?.edges;
let newEdges: RecordGqlEdge[] = previousEdges ?? [];
let newEdges: RecordGqlEdge[] = previousEdges ?? [];
if (isNonEmptyArray(nextEdges)) {
newEdges = filterUniqueRecordEdgesByCursor([
...newEdges,
...(fetchMoreResult?.[objectMetadataItem.namePlural]
?.edges ?? []),
]);
}
if (isNonEmptyArray(nextEdges)) {
newEdges = filterUniqueRecordEdgesByCursor([
...newEdges,
...(fetchMoreResult?.[objectMetadataItem.namePlural]?.edges ??
[]),
]);
}
const pageInfo =
fetchMoreResult?.[objectMetadataItem.namePlural]?.pageInfo;
const pageInfo =
fetchMoreResult?.[objectMetadataItem.namePlural]?.pageInfo;
if (isDefined(pageInfo)) {
set(
cursorFamilyState(queryIdentifier),
pageInfo.endCursor ?? '',
);
set(
hasNextPageFamilyState(queryIdentifier),
pageInfo.hasNextPage ?? false,
);
}
if (isDefined(pageInfo)) {
jotaiStore.set(
cursorFamilyState.atomFamily(queryIdentifier),
pageInfo.endCursor ?? '',
);
jotaiStore.set(
hasNextPageFamilyState.atomFamily(queryIdentifier),
pageInfo.hasNextPage ?? false,
);
}
return Object.assign({}, prev, {
[objectMetadataItem.namePlural]: {
__typename: `${capitalize(
objectMetadataItem.nameSingular,
)}Connection`,
edges: newEdges,
pageInfo:
fetchMoreResult?.[objectMetadataItem.namePlural].pageInfo,
totalCount:
fetchMoreResult?.[objectMetadataItem.namePlural]
.totalCount,
},
} as RecordGqlOperationFindManyResult);
},
});
return {
data: fetchMoreDataResult?.[objectMetadataItem.namePlural],
totalCount:
fetchMoreDataResult?.[objectMetadataItem.namePlural]
?.totalCount,
records: getRecordsFromRecordConnection({
recordConnection: {
edges:
fetchMoreDataResult?.[objectMetadataItem.namePlural]?.edges,
return Object.assign({}, prev, {
[objectMetadataItem.namePlural]: {
__typename: `${capitalize(
objectMetadataItem.nameSingular,
)}Connection`,
edges: newEdges,
pageInfo:
fetchMoreDataResult?.[objectMetadataItem.namePlural]
?.pageInfo,
fetchMoreResult?.[objectMetadataItem.namePlural].pageInfo,
totalCount:
fetchMoreResult?.[objectMetadataItem.namePlural].totalCount,
},
}) as T[],
};
} catch (error) {
handleFindManyRecordsError(error as ApolloError);
return { error: error as ApolloError };
}
} as RecordGqlOperationFindManyResult);
},
});
return {
data: fetchMoreDataResult?.[objectMetadataItem.namePlural],
totalCount:
fetchMoreDataResult?.[objectMetadataItem.namePlural]?.totalCount,
records: getRecordsFromRecordConnection({
recordConnection: {
edges:
fetchMoreDataResult?.[objectMetadataItem.namePlural]?.edges,
pageInfo:
fetchMoreDataResult?.[objectMetadataItem.namePlural]
?.pageInfo,
},
}) as T[],
};
} catch (error) {
handleFindManyRecordsError(error as ApolloError);
return { error: error as ApolloError };
}
},
}
},
[
queryIdentifier,
objectMetadataItem,
@@ -1,5 +1,5 @@
import { useLazyQuery } from '@apollo/client';
import { useRecoilCallback } from 'recoil';
import { useCallback } from 'react';
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
@@ -13,6 +13,7 @@ import { useObjectPermissionsForObject } from '@/object-record/hooks/useObjectPe
import { cursorFamilyState } from '@/object-record/states/cursorFamilyState';
import { hasNextPageFamilyState } from '@/object-record/states/hasNextPageFamilyState';
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { getQueryIdentifier } from '@/object-record/utils/getQueryIdentifier';
import { QUERY_DEFAULT_LIMIT_RECORDS } from 'twenty-shared/constants';
import { isDefined } from 'twenty-shared/utils';
@@ -80,70 +81,67 @@ export const useLazyFindManyRecords = <T extends ObjectRecord = ObjectRecord>({
objectMetadataItem,
});
const findManyRecordsLazy = useRecoilCallback(
({ set }) =>
async () => {
if (!hasReadPermission) {
set(hasNextPageFamilyState(queryIdentifier), false);
set(cursorFamilyState(queryIdentifier), '');
const findManyRecordsLazy = useCallback(async () => {
if (!hasReadPermission) {
jotaiStore.set(hasNextPageFamilyState.atomFamily(queryIdentifier), false);
jotaiStore.set(cursorFamilyState.atomFamily(queryIdentifier), '');
return {
data: null,
records: null,
totalCount: 0,
hasNextPage: false,
error: undefined,
};
}
return {
data: null,
records: null,
totalCount: 0,
hasNextPage: false,
error: undefined,
};
}
const result = await findManyRecords();
if (isDefined(result?.error)) {
handleFindManyRecordsError(result.error);
}
const result = await findManyRecords();
if (isDefined(result?.error)) {
handleFindManyRecordsError(result.error);
}
const hasNextPage =
result?.data?.[objectMetadataItem.namePlural]?.pageInfo.hasNextPage ??
false;
const hasNextPage =
result?.data?.[objectMetadataItem.namePlural]?.pageInfo.hasNextPage ??
false;
const lastCursor =
result?.data?.[objectMetadataItem.namePlural]?.pageInfo.endCursor ??
'';
const lastCursor =
result?.data?.[objectMetadataItem.namePlural]?.pageInfo.endCursor ?? '';
set(hasNextPageFamilyState(queryIdentifier), hasNextPage);
set(cursorFamilyState(queryIdentifier), lastCursor);
jotaiStore.set(
hasNextPageFamilyState.atomFamily(queryIdentifier),
hasNextPage,
);
jotaiStore.set(cursorFamilyState.atomFamily(queryIdentifier), lastCursor);
const records = getRecordsFromRecordConnection({
recordConnection: {
edges: result?.data?.[objectMetadataItem.namePlural]?.edges ?? [],
pageInfo: result?.data?.[objectMetadataItem.namePlural]
?.pageInfo ?? {
hasNextPage: false,
hasPreviousPage: false,
startCursor: '',
endCursor: '',
},
},
});
const totalCount =
result?.data?.[objectMetadataItem.namePlural]?.totalCount ?? 0;
return {
data: result?.data,
records,
totalCount,
hasNextPage,
error: result?.error,
};
const records = getRecordsFromRecordConnection({
recordConnection: {
edges: result?.data?.[objectMetadataItem.namePlural]?.edges ?? [],
pageInfo: result?.data?.[objectMetadataItem.namePlural]?.pageInfo ?? {
hasNextPage: false,
hasPreviousPage: false,
startCursor: '',
endCursor: '',
},
},
[
hasReadPermission,
findManyRecords,
objectMetadataItem.namePlural,
queryIdentifier,
handleFindManyRecordsError,
],
);
});
const totalCount =
result?.data?.[objectMetadataItem.namePlural]?.totalCount ?? 0;
return {
data: result?.data,
records,
totalCount,
hasNextPage,
error: result?.error,
};
}, [
hasReadPermission,
findManyRecords,
objectMetadataItem.namePlural,
queryIdentifier,
handleFindManyRecordsError,
]);
return {
findManyRecordsLazy,
@@ -1,5 +1,5 @@
import { useLazyQuery } from '@apollo/client';
import { useRecoilCallback } from 'recoil';
import { useCallback } from 'react';
import { useApolloCoreClient } from '@/object-metadata/hooks/useApolloCoreClient';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
@@ -60,8 +60,8 @@ export const useLazyFindManyRecordsWithOffset = ({
},
);
const findManyRecordsLazyWithOffset = useRecoilCallback(
() => async (limit: number, offset: number) => {
const findManyRecordsLazyWithOffset = useCallback(
async (limit: number, offset: number) => {
if (!hasReadPermission) {
return {
data: null,
@@ -8,7 +8,7 @@ import { MultipleSelectDropdown } from '@/object-record/select/components/Multip
import { useRecordsForSelect } from '@/object-record/select/hooks/useRecordsForSelect';
import { type SelectableItem } from '@/object-record/select/types/SelectableItem';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { type RelationFilterValue } from '@/views/view-filter-value/types/RelationFilterValue';
import { t } from '@lingui/core/macro';
import {
@@ -37,7 +37,7 @@ export const ObjectFilterDropdownActorSelect = ({
const { applyObjectFilterDropdownFilterValue } =
useApplyObjectFilterDropdownFilterValue();
const objectFilterDropdownSearchInput = useRecoilComponentValue(
const objectFilterDropdownSearchInput = useRecoilComponentValueV2(
objectFilterDropdownSearchInputComponentState,
);
@@ -1,13 +1,13 @@
import { anyFieldFilterValueComponentState } from '@/object-record/record-filter/states/anyFieldFilterValueComponentState';
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateV2';
import { useLingui } from '@lingui/react/macro';
export const ObjectFilterDropdownAnyFieldSearchInput = () => {
const { t } = useLingui();
const [anyFieldFilterSearchValue, setAnyFieldFilterSearchValue] =
useRecoilComponentState(anyFieldFilterValueComponentState);
useRecoilComponentStateV2(anyFieldFilterValueComponentState);
const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const inputValue = event.target.value;
@@ -3,13 +3,13 @@ import { DATE_PICKER_DROPDOWN_CONTENT_WIDTH } from '@/object-record/object-filte
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { getFilterTypeFromFieldType, isDefined } from 'twenty-shared/utils';
export const ObjectFilterDropdownContentWrapper = ({
children,
}: React.PropsWithChildren) => {
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
const fieldMetadataItemUsedInDropdown = useRecoilComponentSelectorValueV2(
fieldMetadataItemUsedInDropdownComponentSelector,
);
@@ -10,7 +10,8 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useLingui } from '@lingui/react/macro';
import { isNonEmptyString } from '@sniptt/guards';
import { type ChangeEvent, useState } from 'react';
@@ -23,16 +24,17 @@ export const MAX_ITEMS_TO_DISPLAY = 5;
export const ObjectFilterDropdownCountrySelect = () => {
const [searchText, setSearchText] = useState('');
const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValue(
const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValueV2(
objectFilterDropdownCurrentRecordFilterComponentState,
);
const { applyObjectFilterDropdownFilterValue } =
useApplyObjectFilterDropdownFilterValue();
const fieldMetadataItemUsedInFilterDropdown = useRecoilComponentValue(
fieldMetadataItemUsedInDropdownComponentSelector,
);
const fieldMetadataItemUsedInFilterDropdown =
useRecoilComponentSelectorValueV2(
fieldMetadataItemUsedInDropdownComponentSelector,
);
const countries = useCountries();
@@ -9,7 +9,8 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useLingui } from '@lingui/react/macro';
import { isNonEmptyString } from '@sniptt/guards';
import { type ChangeEvent, useState } from 'react';
@@ -22,16 +23,17 @@ export const MAX_ITEMS_TO_DISPLAY = 3;
export const ObjectFilterDropdownCurrencySelect = () => {
const [searchText, setSearchText] = useState('');
const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValue(
const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValueV2(
objectFilterDropdownCurrentRecordFilterComponentState,
);
const { applyObjectFilterDropdownFilterValue } =
useApplyObjectFilterDropdownFilterValue();
const fieldMetadataItemUsedInFilterDropdown = useRecoilComponentValue(
fieldMetadataItemUsedInDropdownComponentSelector,
);
const fieldMetadataItemUsedInFilterDropdown =
useRecoilComponentSelectorValueV2(
fieldMetadataItemUsedInDropdownComponentSelector,
);
const currenciesAsSelectableItems = CURRENCIES.map(
turnCurrencyIntoSelectableItem,
@@ -7,31 +7,30 @@ import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
import { getRelativeDateDisplayValue } from '@/object-record/object-filter-dropdown/utils/getRelativeDateDisplayValue';
import { DatePicker } from '@/ui/input/components/internal/date/components/DatePicker';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
import { UserContext } from '@/users/contexts/UserContext';
import { stringifyRelativeDateFilter } from '@/views/view-filter-value/utils/stringifyRelativeDateFilter';
import { useContext } from 'react';
import { useRecoilValue } from 'recoil';
import { type FirstDayOfTheWeek, ViewFilterOperand } from 'twenty-shared/types';
import {
isDefined,
type RelativeDateFilter,
resolveDateFilter,
} from 'twenty-shared/utils';
import { dateLocaleState } from '~/localization/states/dateLocaleState';
import { dateLocaleStateV2 } from '~/localization/states/dateLocaleStateV2';
import { formatDateString } from '~/utils/string/formatDateString';
export const ObjectFilterDropdownDateInput = () => {
const { dateFormat, timeZone } = useContext(UserContext);
const dateLocale = useRecoilValue(dateLocaleState);
const dateLocale = useRecoilValueV2(dateLocaleStateV2);
const currentWorkspaceMember = useRecoilValueV2(currentWorkspaceMemberState);
const selectedOperandInDropdown = useRecoilComponentValue(
const selectedOperandInDropdown = useRecoilComponentValueV2(
selectedOperandInDropdownComponentState,
);
const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValue(
const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValueV2(
objectFilterDropdownCurrentRecordFilterComponentState,
);
@@ -6,12 +6,11 @@ import { useApplyObjectFilterDropdownFilterValue } from '@/object-record/object-
import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState';
import { getRelativeDateDisplayValue } from '@/object-record/object-filter-dropdown/utils/getRelativeDateDisplayValue';
import { DateTimePicker } from '@/ui/input/components/internal/date/components/DateTimePicker';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
import { UserContext } from '@/users/contexts/UserContext';
import { stringifyRelativeDateFilter } from '@/views/view-filter-value/utils/stringifyRelativeDateFilter';
import { useContext } from 'react';
import { useRecoilValue } from 'recoil';
import { ViewFilterOperand, type FirstDayOfTheWeek } from 'twenty-shared/types';
import {
isDefined,
@@ -22,17 +21,17 @@ import {
import { useUserTimezone } from '@/ui/input/components/internal/date/hooks/useUserTimezone';
import { isNonEmptyString } from '@sniptt/guards';
import { Temporal } from 'temporal-polyfill';
import { dateLocaleState } from '~/localization/states/dateLocaleState';
import { dateLocaleStateV2 } from '~/localization/states/dateLocaleStateV2';
import { formatDateTimeString } from '~/utils/string/formatDateTimeString';
export const ObjectFilterDropdownDateTimeInput = () => {
const { dateFormat, timeFormat, timeZone } = useContext(UserContext);
const dateLocale = useRecoilValue(dateLocaleState);
const dateLocale = useRecoilValueV2(dateLocaleStateV2);
const currentWorkspaceMember = useRecoilValueV2(currentWorkspaceMemberState);
const { userTimezone } = useUserTimezone();
const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValue(
const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValueV2(
objectFilterDropdownCurrentRecordFilterComponentState,
);
@@ -17,7 +17,8 @@ import { NUMBER_FILTER_TYPES } from '@/object-record/object-filter-dropdown/cons
import { TEXT_FILTER_TYPES } from '@/object-record/object-filter-dropdown/constants/TextFilterTypes';
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { getFilterTypeFromFieldType, isDefined } from 'twenty-shared/utils';
type ObjectFilterDropdownFilterInputProps = {
@@ -33,11 +34,11 @@ export const ObjectFilterDropdownFilterInput = ({
const isWholeDayFilterEnabled =
featureFlags.IS_DATE_TIME_WHOLE_DAY_FILTER_ENABLED ?? false;
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
const fieldMetadataItemUsedInDropdown = useRecoilComponentSelectorValueV2(
fieldMetadataItemUsedInDropdownComponentSelector,
);
const selectedOperandInDropdown = useRecoilComponentValue(
const selectedOperandInDropdown = useRecoilComponentValueV2(
selectedOperandInDropdownComponentState,
);
@@ -3,7 +3,7 @@ import { DropdownMenuHeader } from '@/ui/layout/dropdown/components/DropdownMenu
import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components/DropdownMenuHeader/internal/DropdownMenuHeaderLeftComponent';
import { DropdownComponentInstanceContext } from '@/ui/layout/dropdown/contexts/DropdownComponentInstanceContext';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { ViewBarFilterDropdownFilterInputMenuHeader } from '@/views/components/ViewBarFilterDropdownFilterInputMenuHeader';
import { ViewBarFilterDropdownIds } from '@/views/constants/ViewBarFilterDropdownIds';
import { useContext } from 'react';
@@ -11,7 +11,7 @@ import { IconX } from 'twenty-ui/display';
// TODO: we shouldn't guess in which parent we are, this should be splitted in two components, one for each case
export const ObjectFilterDropdownFilterInputHeader = () => {
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
const fieldMetadataItemUsedInDropdown = useRecoilComponentSelectorValueV2(
fieldMetadataItemUsedInDropdownComponentSelector,
);
@@ -11,7 +11,8 @@ import { getRecordFilterOperands } from '@/object-record/record-filter/utils/get
import { useUserTimezone } from '@/ui/input/components/internal/date/hooks/useUserTimezone';
import { DropdownMenuInnerSelect } from '@/ui/layout/dropdown/components/DropdownMenuInnerSelect';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { getFilterTypeFromFieldType, isDefined } from 'twenty-shared/utils';
import { type SelectOption } from 'twenty-ui/input';
@@ -19,15 +20,15 @@ const OBJECT_FILTER_DROPDOWN_INNER_SELECT_OPERAND_DROPDOWN_ID =
'object-filter-dropdown-inner-select-operand-dropdown';
export const ObjectFilterDropdownInnerSelectOperandDropdown = () => {
const selectedOperandInDropdown = useRecoilComponentValue(
const selectedOperandInDropdown = useRecoilComponentValueV2(
selectedOperandInDropdownComponentState,
);
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
const fieldMetadataItemUsedInDropdown = useRecoilComponentSelectorValueV2(
fieldMetadataItemUsedInDropdownComponentSelector,
);
const subFieldNameUsedInDropdown = useRecoilComponentValue(
const subFieldNameUsedInDropdown = useRecoilComponentValueV2(
subFieldNameUsedInDropdownComponentState,
);
@@ -6,7 +6,7 @@ import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-recor
import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
type ObjectFilterDropdownNumberInputProps = {
filterDropdownId: string;
@@ -15,7 +15,7 @@ type ObjectFilterDropdownNumberInputProps = {
export const ObjectFilterDropdownNumberInput = ({
filterDropdownId,
}: ObjectFilterDropdownNumberInputProps) => {
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
const fieldMetadataItemUsedInDropdown = useRecoilComponentSelectorValueV2(
fieldMetadataItemUsedInDropdownComponentSelector,
);
@@ -17,7 +17,7 @@ import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { t } from '@lingui/core/macro';
import { isNonEmptyString } from '@sniptt/guards';
@@ -36,11 +36,11 @@ export const ObjectFilterDropdownOptionSelect = ({
}: {
focusId: string;
}) => {
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
const fieldMetadataItemUsedInDropdown = useRecoilComponentSelectorValueV2(
fieldMetadataItemUsedInDropdownComponentSelector,
);
const objectFilterDropdownSearchInput = useRecoilComponentValue(
const objectFilterDropdownSearchInput = useRecoilComponentValueV2(
objectFilterDropdownSearchInputComponentState,
);
@@ -48,7 +48,7 @@ export const ObjectFilterDropdownOptionSelect = ({
ObjectFilterDropdownComponentInstanceContext,
);
const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValue(
const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValueV2(
objectFilterDropdownCurrentRecordFilterComponentState,
);
@@ -12,7 +12,8 @@ import { MultipleSelectDropdown } from '@/object-record/select/components/Multip
import { useRecordsForSelect } from '@/object-record/select/hooks/useRecordsForSelect';
import { type SelectableItem } from '@/object-record/select/types/SelectableItem';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { type RelationFilterValue } from '@/views/view-filter-value/types/RelationFilterValue';
import {
arrayOfUuidOrVariableSchema,
@@ -39,9 +40,10 @@ export const ObjectFilterDropdownRecordSelect = ({
recordFilterId,
dropdownId,
}: ObjectFilterDropdownRecordSelectProps) => {
const fieldMetadataItemUsedInFilterDropdown = useRecoilComponentValue(
fieldMetadataItemUsedInDropdownComponentSelector,
);
const fieldMetadataItemUsedInFilterDropdown =
useRecoilComponentSelectorValueV2(
fieldMetadataItemUsedInDropdownComponentSelector,
);
const allowRequestsToTwentyIcons = useRecoilValueV2(
allowRequestsToTwentyIconsState,
@@ -53,15 +55,15 @@ export const ObjectFilterDropdownRecordSelect = ({
const { applyObjectFilterDropdownFilterValue } =
useApplyObjectFilterDropdownFilterValue();
const selectedOperandInDropdown = useRecoilComponentValue(
const selectedOperandInDropdown = useRecoilComponentValueV2(
selectedOperandInDropdownComponentState,
);
const objectFilterDropdownSearchInput = useRecoilComponentValue(
const objectFilterDropdownSearchInput = useRecoilComponentValueV2(
objectFilterDropdownSearchInputComponentState,
);
const currentRecordFilters = useRecoilComponentValue(
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
@@ -4,23 +4,24 @@ import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-recor
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilComponentStateV2';
export const ObjectFilterDropdownSearchInput = () => {
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
const fieldMetadataItemUsedInDropdown = useRecoilComponentSelectorValueV2(
fieldMetadataItemUsedInDropdownComponentSelector,
);
const selectedOperandInDropdown = useRecoilComponentValue(
const selectedOperandInDropdown = useRecoilComponentValueV2(
selectedOperandInDropdownComponentState,
);
const objectFilterDropdownSearchInput = useRecoilComponentValue(
const objectFilterDropdownSearchInput = useRecoilComponentValueV2(
objectFilterDropdownSearchInputComponentState,
);
const setObjectFilterDropdownSearchInput = useSetRecoilComponentState(
const setObjectFilterDropdownSearchInput = useSetRecoilComponentStateV2(
objectFilterDropdownSearchInputComponentState,
);
@@ -7,7 +7,8 @@ import { MultipleSelectDropdown } from '@/object-record/select/components/Multip
import { type SelectableItem } from '@/object-record/select/types/SelectableItem';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/GenericDropdownContentWidth';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { t } from '@lingui/core/macro';
import { isNonEmptyString } from '@sniptt/guards';
import { isDefined } from 'twenty-shared/utils';
@@ -20,15 +21,16 @@ export const ObjectFilterDropdownSourceSelect = ({
}: {
dropdownId: string;
}) => {
const objectFilterDropdownSearchInput = useRecoilComponentValue(
const objectFilterDropdownSearchInput = useRecoilComponentValueV2(
objectFilterDropdownSearchInputComponentState,
);
const fieldMetadataItemUsedInFilterDropdown = useRecoilComponentValue(
fieldMetadataItemUsedInDropdownComponentSelector,
);
const fieldMetadataItemUsedInFilterDropdown =
useRecoilComponentSelectorValueV2(
fieldMetadataItemUsedInDropdownComponentSelector,
);
const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValue(
const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValueV2(
objectFilterDropdownCurrentRecordFilterComponentState,
);
@@ -6,7 +6,7 @@ import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-recor
import { DropdownMenuInput } from '@/ui/layout/dropdown/components/DropdownMenuInput';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
type ObjectFilterDropdownTextInputProps = {
filterDropdownId: string;
@@ -15,7 +15,7 @@ type ObjectFilterDropdownTextInputProps = {
export const ObjectFilterDropdownTextInput = ({
filterDropdownId,
}: ObjectFilterDropdownTextInputProps) => {
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
const fieldMetadataItemUsedInDropdown = useRecoilComponentSelectorValueV2(
fieldMetadataItemUsedInDropdownComponentSelector,
);
@@ -1,20 +1,23 @@
import { useCallback } from 'react';
import { useUpsertObjectFilterDropdownCurrentFilter } from '@/object-record/object-filter-dropdown/hooks/useUpsertObjectFilterDropdownCurrentFilter';
import { fieldMetadataItemUsedInDropdownComponentSelector } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemUsedInDropdownComponentSelector';
import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState';
import { useCreateRecordFilterFromObjectFilterDropdownCurrentStates } from '@/object-record/record-filter/hooks/useCreateRecordFilterFromObjectFilterDropdownCurrentStates';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { useRecoilCallback } from 'recoil';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { useRecoilComponentSelectorCallbackStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorCallbackStateV2';
import { useRecoilComponentStateCallbackStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateCallbackStateV2';
import { isDefined } from 'twenty-shared/utils';
export const useApplyObjectFilterDropdownFilterValue = () => {
const objectFilterDropdownCurrentRecordFilterCallbackState =
useRecoilComponentCallbackState(
const objectFilterDropdownCurrentRecordFilterAtom =
useRecoilComponentStateCallbackStateV2(
objectFilterDropdownCurrentRecordFilterComponentState,
);
const fieldMetadataItemUsedInDropdownCallbackState =
useRecoilComponentCallbackState(
const fieldMetadataItemUsedInDropdownAtom =
useRecoilComponentSelectorCallbackStateV2(
fieldMetadataItemUsedInDropdownComponentSelector,
);
@@ -24,51 +27,50 @@ export const useApplyObjectFilterDropdownFilterValue = () => {
const { upsertObjectFilterDropdownCurrentFilter } =
useUpsertObjectFilterDropdownCurrentFilter();
const applyObjectFilterDropdownFilterValue = useRecoilCallback(
({ snapshot }) =>
(newFilterValue: string, newDisplayValue?: string) => {
const objectFilterDropdownCurrentRecordFilter = snapshot
.getLoadable(objectFilterDropdownCurrentRecordFilterCallbackState)
.getValue();
const applyObjectFilterDropdownFilterValue = useCallback(
(newFilterValue: string, newDisplayValue?: string) => {
const objectFilterDropdownCurrentRecordFilter = jotaiStore.get(
objectFilterDropdownCurrentRecordFilterAtom,
) as RecordFilter | undefined | null;
const fieldMetadataItemUsedInDropdown = snapshot
.getLoadable(fieldMetadataItemUsedInDropdownCallbackState)
.getValue();
const fieldMetadataItemUsedInDropdown = jotaiStore.get(
fieldMetadataItemUsedInDropdownAtom,
);
const objectFilterDropdownFilterNotYetCreated = !isDefined(
objectFilterDropdownCurrentRecordFilter,
);
const objectFilterDropdownFilterNotYetCreated = !isDefined(
objectFilterDropdownCurrentRecordFilter,
);
if (objectFilterDropdownFilterNotYetCreated) {
if (!isDefined(fieldMetadataItemUsedInDropdown)) {
throw new Error(
`Field metadata item is not defined in object filter dropdown when setting a filter value to create it, this should not happen.`,
);
}
const { newRecordFilterFromObjectFilterDropdownStates } =
createRecordFilterFromObjectFilterDropdownCurrentStates();
const newCurrentRecordFilter = {
...newRecordFilterFromObjectFilterDropdownStates,
value: newFilterValue,
displayValue: newDisplayValue ?? newFilterValue,
} satisfies RecordFilter;
upsertObjectFilterDropdownCurrentFilter(newCurrentRecordFilter);
} else {
const newCurrentRecordFilter = {
...objectFilterDropdownCurrentRecordFilter,
value: newFilterValue,
displayValue: newDisplayValue ?? newFilterValue,
} satisfies RecordFilter;
upsertObjectFilterDropdownCurrentFilter(newCurrentRecordFilter);
if (objectFilterDropdownFilterNotYetCreated) {
if (!isDefined(fieldMetadataItemUsedInDropdown)) {
throw new Error(
`Field metadata item is not defined in object filter dropdown when setting a filter value to create it, this should not happen.`,
);
}
},
const { newRecordFilterFromObjectFilterDropdownStates } =
createRecordFilterFromObjectFilterDropdownCurrentStates();
const newCurrentRecordFilter = {
...newRecordFilterFromObjectFilterDropdownStates,
value: newFilterValue,
displayValue: newDisplayValue ?? newFilterValue,
} satisfies RecordFilter;
upsertObjectFilterDropdownCurrentFilter(newCurrentRecordFilter);
} else {
const newCurrentRecordFilter = {
...objectFilterDropdownCurrentRecordFilter,
value: newFilterValue,
displayValue: newDisplayValue ?? newFilterValue,
} satisfies RecordFilter;
upsertObjectFilterDropdownCurrentFilter(newCurrentRecordFilter);
}
},
[
objectFilterDropdownCurrentRecordFilterCallbackState,
fieldMetadataItemUsedInDropdownCallbackState,
objectFilterDropdownCurrentRecordFilterAtom,
fieldMetadataItemUsedInDropdownAtom,
createRecordFilterFromObjectFilterDropdownCurrentStates,
upsertObjectFilterDropdownCurrentFilter,
],
@@ -10,8 +10,9 @@ import { useGetRelativeDateFilterWithUserTimezone } from '@/object-record/record
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand';
import { useUserTimezone } from '@/ui/input/components/internal/date/hooks/useUserTimezone';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilComponentStateV2';
import { stringifyRelativeDateFilter } from '@/views/view-filter-value/utils/stringifyRelativeDateFilter';
import { useFeatureFlagsMap } from '@/workspace/hooks/useFeatureFlagsMap';
@@ -23,11 +24,11 @@ import {
export const useApplyObjectFilterDropdownOperand = () => {
const { userTimezone } = useUserTimezone();
const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValue(
const objectFilterDropdownCurrentRecordFilter = useRecoilComponentValueV2(
objectFilterDropdownCurrentRecordFilterComponentState,
);
const setSelectedOperandInDropdown = useSetRecoilComponentState(
const setSelectedOperandInDropdown = useSetRecoilComponentStateV2(
selectedOperandInDropdownComponentState,
);
@@ -35,7 +36,7 @@ export const useApplyObjectFilterDropdownOperand = () => {
objectFilterDropdownCurrentRecordFilter,
);
const fieldMetadataItemUsedInDropdown = useRecoilComponentValue(
const fieldMetadataItemUsedInDropdown = useRecoilComponentSelectorValueV2(
fieldMetadataItemUsedInDropdownComponentSelector,
);
@@ -1,32 +1,30 @@
import { useCallback } from 'react';
import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState';
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { useRecoilCallback } from 'recoil';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { useRecoilComponentStateCallbackStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateCallbackStateV2';
export const useEmptyRecordFilter = (componentInstanceId?: string) => {
const objectFilterDropdownSearchInputCallbackState =
useRecoilComponentCallbackState(
const objectFilterDropdownSearchInputAtom =
useRecoilComponentStateCallbackStateV2(
objectFilterDropdownSearchInputComponentState,
componentInstanceId,
);
const objectFilterDropdownCurrentRecordFilter =
useRecoilComponentCallbackState(
const objectFilterDropdownCurrentRecordFilterAtom =
useRecoilComponentStateCallbackStateV2(
objectFilterDropdownCurrentRecordFilterComponentState,
componentInstanceId,
);
const emptyRecordFilter = useRecoilCallback(
({ set }) =>
() => {
set(objectFilterDropdownSearchInputCallbackState, '');
set(objectFilterDropdownCurrentRecordFilter, undefined);
},
[
objectFilterDropdownSearchInputCallbackState,
objectFilterDropdownCurrentRecordFilter,
],
);
const emptyRecordFilter = useCallback(() => {
jotaiStore.set(objectFilterDropdownSearchInputAtom, '');
jotaiStore.set(objectFilterDropdownCurrentRecordFilterAtom, undefined);
}, [
objectFilterDropdownSearchInputAtom,
objectFilterDropdownCurrentRecordFilterAtom,
]);
return {
emptyRecordFilter,
@@ -2,19 +2,20 @@ import { objectFilterDropdownSearchInputComponentState } from '@/object-record/o
import { visibleRecordFieldsComponentSelector } from '@/object-record/record-field/states/visibleRecordFieldsComponentSelector';
import { useFilterableFieldMetadataItemsInRecordIndexContext } from '@/object-record/record-filter/hooks/useFilterableFieldMetadataItemsInRecordIndexContext';
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
export const useFilterDropdownSelectableFieldMetadataItems = () => {
const { recordIndexId } = useRecordIndexContextOrThrow();
const objectFilterDropdownSearchInput = useRecoilComponentValue(
const objectFilterDropdownSearchInput = useRecoilComponentValueV2(
objectFilterDropdownSearchInputComponentState,
);
const { filterableFieldMetadataItems } =
useFilterableFieldMetadataItemsInRecordIndexContext();
const visibleRecordFields = useRecoilComponentValue(
const visibleRecordFields = useRecoilComponentSelectorValueV2(
visibleRecordFieldsComponentSelector,
recordIndexId,
);
@@ -1,8 +1,8 @@
import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
export const useObjectFilterDropdownFilterValue = () => {
const currentRecordFilter = useRecoilComponentValue(
const currentRecordFilter = useRecoilComponentValueV2(
objectFilterDropdownCurrentRecordFilterComponentState,
);
@@ -1,3 +1,5 @@
import { useCallback } from 'react';
import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState';
import { objectFilterDropdownAnyFieldSearchIsSelectedComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownAnyFieldSearchIsSelectedComponentState';
import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState';
@@ -5,73 +7,68 @@ import { objectFilterDropdownFilterIsSelectedComponentState } from '@/object-rec
import { objectFilterDropdownIsSelectingCompositeFieldComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownIsSelectingCompositeFieldComponentState';
import { objectFilterDropdownSearchInputComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownSearchInputComponentState';
import { selectedOperandInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/selectedOperandInDropdownComponentState';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { useRecoilCallback } from 'recoil';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { useRecoilComponentStateCallbackStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateCallbackStateV2';
export const useResetFilterDropdown = (componentInstanceId?: string) => {
const objectFilterDropdownSearchInputCallbackState =
useRecoilComponentCallbackState(
const objectFilterDropdownSearchInputAtom =
useRecoilComponentStateCallbackStateV2(
objectFilterDropdownSearchInputComponentState,
componentInstanceId,
);
const fieldMetadataItemIdUsedInDropdownCallbackState =
useRecoilComponentCallbackState(
const fieldMetadataItemIdUsedInDropdownAtom =
useRecoilComponentStateCallbackStateV2(
fieldMetadataItemIdUsedInDropdownComponentState,
componentInstanceId,
);
const selectedOperandInDropdownCallbackState =
useRecoilComponentCallbackState(
selectedOperandInDropdownComponentState,
componentInstanceId,
);
const selectedOperandInDropdownAtom = useRecoilComponentStateCallbackStateV2(
selectedOperandInDropdownComponentState,
componentInstanceId,
);
const objectFilterDropdownFilterIsSelectedCallbackState =
useRecoilComponentCallbackState(
const objectFilterDropdownFilterIsSelectedAtom =
useRecoilComponentStateCallbackStateV2(
objectFilterDropdownFilterIsSelectedComponentState,
componentInstanceId,
);
const objectFilterDropdownAnyFieldSearchIsSelectedCallbackState =
useRecoilComponentCallbackState(
const objectFilterDropdownAnyFieldSearchIsSelectedAtom =
useRecoilComponentStateCallbackStateV2(
objectFilterDropdownAnyFieldSearchIsSelectedComponentState,
componentInstanceId,
);
const objectFilterDropdownIsSelectingCompositeFieldCallbackState =
useRecoilComponentCallbackState(
const objectFilterDropdownIsSelectingCompositeFieldAtom =
useRecoilComponentStateCallbackStateV2(
objectFilterDropdownIsSelectingCompositeFieldComponentState,
componentInstanceId,
);
const objectFilterDropdownCurrentRecordFilterCallbackState =
useRecoilComponentCallbackState(
const objectFilterDropdownCurrentRecordFilterAtom =
useRecoilComponentStateCallbackStateV2(
objectFilterDropdownCurrentRecordFilterComponentState,
componentInstanceId,
);
const resetFilterDropdown = useRecoilCallback(
({ set }) =>
() => {
set(objectFilterDropdownSearchInputCallbackState, '');
set(selectedOperandInDropdownCallbackState, null);
set(objectFilterDropdownFilterIsSelectedCallbackState, false);
set(objectFilterDropdownIsSelectingCompositeFieldCallbackState, false);
set(fieldMetadataItemIdUsedInDropdownCallbackState, null);
set(objectFilterDropdownCurrentRecordFilterCallbackState, null);
set(objectFilterDropdownAnyFieldSearchIsSelectedCallbackState, false);
},
[
objectFilterDropdownSearchInputCallbackState,
selectedOperandInDropdownCallbackState,
objectFilterDropdownFilterIsSelectedCallbackState,
objectFilterDropdownIsSelectingCompositeFieldCallbackState,
fieldMetadataItemIdUsedInDropdownCallbackState,
objectFilterDropdownCurrentRecordFilterCallbackState,
objectFilterDropdownAnyFieldSearchIsSelectedCallbackState,
],
);
const resetFilterDropdown = useCallback(() => {
jotaiStore.set(objectFilterDropdownSearchInputAtom, '');
jotaiStore.set(selectedOperandInDropdownAtom, null);
jotaiStore.set(objectFilterDropdownFilterIsSelectedAtom, false);
jotaiStore.set(objectFilterDropdownIsSelectingCompositeFieldAtom, false);
jotaiStore.set(fieldMetadataItemIdUsedInDropdownAtom, null);
jotaiStore.set(objectFilterDropdownCurrentRecordFilterAtom, null);
jotaiStore.set(objectFilterDropdownAnyFieldSearchIsSelectedAtom, false);
}, [
objectFilterDropdownSearchInputAtom,
selectedOperandInDropdownAtom,
objectFilterDropdownFilterIsSelectedAtom,
objectFilterDropdownIsSelectingCompositeFieldAtom,
fieldMetadataItemIdUsedInDropdownAtom,
objectFilterDropdownCurrentRecordFilterAtom,
objectFilterDropdownAnyFieldSearchIsSelectedAtom,
]);
return {
resetFilterDropdown,
@@ -1,28 +1,29 @@
import { useCallback } from 'react';
import { objectFilterDropdownCurrentRecordFilterComponentState } from '@/object-record/object-filter-dropdown/states/objectFilterDropdownCurrentRecordFilterComponentState';
import { useUpsertRecordFilter } from '@/object-record/record-filter/hooks/useUpsertRecordFilter';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { useRecoilCallback } from 'recoil';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { useRecoilComponentStateCallbackStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateCallbackStateV2';
export const useUpsertObjectFilterDropdownCurrentFilter = () => {
const objectFilterDropdownCurrentRecordFilterCallbackState =
useRecoilComponentCallbackState(
const objectFilterDropdownCurrentRecordFilterAtom =
useRecoilComponentStateCallbackStateV2(
objectFilterDropdownCurrentRecordFilterComponentState,
);
const { upsertRecordFilter } = useUpsertRecordFilter();
const upsertObjectFilterDropdownCurrentFilter = useRecoilCallback(
({ set }) =>
(recordFilterToUpsert: RecordFilter) => {
upsertRecordFilter(recordFilterToUpsert);
const upsertObjectFilterDropdownCurrentFilter = useCallback(
(recordFilterToUpsert: RecordFilter) => {
upsertRecordFilter(recordFilterToUpsert);
set(
objectFilterDropdownCurrentRecordFilterCallbackState,
recordFilterToUpsert,
);
},
[objectFilterDropdownCurrentRecordFilterCallbackState, upsertRecordFilter],
jotaiStore.set(
objectFilterDropdownCurrentRecordFilterAtom,
recordFilterToUpsert,
);
},
[objectFilterDropdownCurrentRecordFilterAtom, upsertRecordFilter],
);
return {
@@ -1,8 +1,8 @@
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const fieldMetadataItemIdUsedInDropdownComponentState =
createComponentState<string | null>({
createComponentStateV2<string | null>({
key: 'fieldMetadataItemIdUsedInDropdownComponentState',
defaultValue: null,
componentInstanceContext: ObjectFilterDropdownComponentInstanceContext,
@@ -1,25 +1,22 @@
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { type FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
import { fieldMetadataItemIdUsedInDropdownComponentState } from '@/object-record/object-filter-dropdown/states/fieldMetadataItemIdUsedInDropdownComponentState';
import { createComponentSelector } from '@/ui/utilities/state/component-state/utils/createComponentSelector';
import { createComponentSelectorV2 } from '@/ui/utilities/state/jotai/utils/createComponentSelectorV2';
export const fieldMetadataItemUsedInDropdownComponentSelector =
createComponentSelector<FieldMetadataItem | null | undefined>({
createComponentSelectorV2<FieldMetadataItem | null | undefined>({
key: 'fieldMetadataItemUsedInDropdownComponentSelector',
componentInstanceContext: ObjectFilterDropdownComponentInstanceContext,
get:
({ instanceId }) =>
(componentStateKey) =>
({ get }) => {
const fieldMetadataItemIdUsedInDropdown = get(
fieldMetadataItemIdUsedInDropdownComponentState.atomFamily({
instanceId,
}),
fieldMetadataItemIdUsedInDropdownComponentState,
componentStateKey,
);
const objectMetadataItems = jotaiStore.get(
objectMetadataItemsState.atom,
);
const objectMetadataItems = get(objectMetadataItemsState);
const correspondingFieldMetadataItem = objectMetadataItems
.flatMap((objectMetadataItem) => objectMetadataItem.fields)
@@ -30,5 +27,4 @@ export const fieldMetadataItemUsedInDropdownComponentSelector =
return correspondingFieldMetadataItem;
},
componentInstanceContext: ObjectFilterDropdownComponentInstanceContext,
});
@@ -1,8 +1,8 @@
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const isObjectFilterDropdownOperandSelectUnfoldedComponentState =
createComponentState<boolean>({
createComponentStateV2<boolean>({
key: 'isObjectFilterDropdownOperandSelectUnfoldedComponentState',
defaultValue: false,
componentInstanceContext: ObjectFilterDropdownComponentInstanceContext,
@@ -1,8 +1,8 @@
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const isObjectFilterDropdownUnfoldedComponentState =
createComponentState<boolean>({
createComponentStateV2<boolean>({
key: 'isObjectFilterDropdownUnfoldedComponentState',
defaultValue: false,
componentInstanceContext: ObjectFilterDropdownComponentInstanceContext,
@@ -1,8 +1,8 @@
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const objectFilterDropdownAnyFieldSearchIsSelectedComponentState =
createComponentState<boolean>({
createComponentStateV2<boolean>({
key: 'objectFilterDropdownAnyFieldSearchIsSelectedComponentState',
defaultValue: false,
componentInstanceContext: ObjectFilterDropdownComponentInstanceContext,
@@ -1,9 +1,9 @@
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
import { type RecordFilter } from '@/object-record/record-filter/types/RecordFilter';
export const objectFilterDropdownCurrentRecordFilterComponentState =
createComponentState<RecordFilter | undefined | null>({
createComponentStateV2<RecordFilter | undefined | null>({
key: 'objectFilterDropdownCurrentRecordFilterComponentState',
defaultValue: undefined,
componentInstanceContext: ObjectFilterDropdownComponentInstanceContext,
@@ -1,8 +1,8 @@
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const objectFilterDropdownFilterIsSelectedComponentState =
createComponentState<boolean>({
createComponentStateV2<boolean>({
key: 'objectFilterDropdownFilterIsSelectedComponentState',
defaultValue: false,
componentInstanceContext: ObjectFilterDropdownComponentInstanceContext,
@@ -1,8 +1,8 @@
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const objectFilterDropdownIsSelectingCompositeFieldComponentState =
createComponentState<boolean>({
createComponentStateV2<boolean>({
key: 'objectFilterDropdownIsSelectingCompositeFieldComponentState',
defaultValue: false,
componentInstanceContext: ObjectFilterDropdownComponentInstanceContext,
@@ -1,8 +1,8 @@
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const objectFilterDropdownSearchInputComponentState =
createComponentState<string>({
createComponentStateV2<string>({
key: 'objectFilterDropdownSearchInputComponentState',
defaultValue: '',
componentInstanceContext: ObjectFilterDropdownComponentInstanceContext,
@@ -1,8 +1,8 @@
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const objectFilterDropdownSelectedOptionValuesComponentState =
createComponentState<string[]>({
createComponentStateV2<string[]>({
key: 'objectFilterDropdownSelectedOptionValuesComponentState',
defaultValue: [],
componentInstanceContext: ObjectFilterDropdownComponentInstanceContext,
@@ -1,9 +1,9 @@
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
import { type CompositeFilterableFieldType } from '@/object-record/record-filter/types/CompositeFilterableFieldType';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const objectFilterDropdownSubMenuFieldTypeComponentState =
createComponentState<CompositeFilterableFieldType | null>({
createComponentStateV2<CompositeFilterableFieldType | null>({
key: 'objectFilterDropdownSubMenuFieldTypeComponentState',
defaultValue: null,
componentInstanceContext: ObjectFilterDropdownComponentInstanceContext,
@@ -1,9 +1,9 @@
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
import { type ViewFilterOperand } from 'twenty-shared/types';
export const selectedOperandInDropdownComponentState =
createComponentState<ViewFilterOperand | null>({
createComponentStateV2<ViewFilterOperand | null>({
key: 'selectedOperandInDropdownComponentState',
defaultValue: null,
componentInstanceContext: ObjectFilterDropdownComponentInstanceContext,
@@ -1,8 +1,8 @@
import { ObjectFilterDropdownComponentInstanceContext } from '@/object-record/object-filter-dropdown/states/contexts/ObjectFilterDropdownComponentInstanceContext';
import { type CompositeFieldSubFieldName } from '@/settings/data-model/types/CompositeFieldSubFieldName';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const subFieldNameUsedInDropdownComponentState = createComponentState<
export const subFieldNameUsedInDropdownComponentState = createComponentStateV2<
CompositeFieldSubFieldName | null | undefined
>({
key: 'subFieldNameUsedInDropdownComponentState',
@@ -10,9 +10,9 @@ import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownM
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import { useUpdateCurrentView } from '@/views/hooks/useUpdateCurrentView';
import { useGetAvailableFieldsForCalendar } from '@/views/view-picker/hooks/useGetAvailableFieldsForCalendar';
import { useSetRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilStateV2';
import { useLingui } from '@lingui/react/macro';
import { useState } from 'react';
import { useSetRecoilState } from 'recoil';
import { isFieldMetadataDateKind } from 'twenty-shared/utils';
import { IconChevronLeft, IconSettings, useIcons } from 'twenty-ui/display';
import { MenuItem, MenuItemSelect } from 'twenty-ui/navigation';
@@ -29,7 +29,7 @@ export const ObjectOptionsDropdownCalendarFieldsContent = () => {
const { updateCurrentView } = useUpdateCurrentView();
const { navigateToDateFieldSettings } = useGetAvailableFieldsForCalendar();
const setRecordIndexCalendarFieldMetadataId = useSetRecoilState(
const setRecordIndexCalendarFieldMetadataId = useSetRecoilStateV2(
recordIndexCalendarFieldMetadataIdState,
);
const availableFieldsForCalendar = objectMetadataItem.fields.filter((field) =>
@@ -9,9 +9,10 @@ import { SelectableList } from '@/ui/layout/selectable-list/components/Selectabl
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
import { useSetRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilStateV2';
import { useUpdateCurrentView } from '@/views/hooks/useUpdateCurrentView';
import { t } from '@lingui/core/macro';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { Pill } from 'twenty-ui/components';
import {
IconCalendarMonth,
@@ -24,10 +25,10 @@ import { ViewCalendarLayout } from '~/generated-metadata/graphql';
export const ObjectOptionsDropdownCalendarViewContent = () => {
const { resetContent } = useObjectOptionsDropdown();
const recordIndexCalendarLayout = useRecoilValue(
const recordIndexCalendarLayout = useRecoilValueV2(
recordIndexCalendarLayoutState,
);
const setRecordIndexCalendarLayout = useSetRecoilState(
const setRecordIndexCalendarLayout = useSetRecoilStateV2(
recordIndexCalendarLayoutState,
);
const { updateCurrentView } = useUpdateCurrentView();
@@ -11,16 +11,15 @@ import { GenericDropdownContentWidth } from '@/ui/layout/dropdown/constants/Gene
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilComponentStateV2';
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import { ViewKey } from '@/views/types/ViewKey';
import { ViewType, viewTypeIconMapping } from '@/views/types/ViewType';
import { useDestroyViewFromCurrentState } from '@/views/view-picker/hooks/useDestroyViewFromCurrentState';
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
import { useLingui } from '@lingui/react/macro';
import { useRecoilValue } from 'recoil';
import { capitalize, isDefined } from 'twenty-shared/utils';
import {
AppTooltip,
@@ -55,7 +54,7 @@ export const ObjectOptionsDropdownCustomView = ({
}
: null;
const recordGroupFieldMetadata = useRecoilComponentValue(
const recordGroupFieldMetadata = useRecoilComponentValueV2(
recordIndexGroupFieldMetadataItemComponentState,
);
@@ -67,7 +66,7 @@ export const ObjectOptionsDropdownCustomView = ({
const isDefaultView = currentView?.key === ViewKey.Index;
const recordIndexCalendarLayout = useRecoilValue(
const recordIndexCalendarLayout = useRecoilValueV2(
recordIndexCalendarLayoutState,
);
@@ -80,8 +79,9 @@ export const ObjectOptionsDropdownCustomView = ({
const visibleFieldsCount = visibleBoardFields.length;
const { destroyViewFromCurrentState } = useDestroyViewFromCurrentState();
const setViewPickerReferenceViewId = useSetRecoilComponentState(
const setViewPickerReferenceViewId = useSetRecoilComponentStateV2(
viewPickerReferenceViewIdComponentState,
recordIndexId,
);
const handleDelete = () => {
@@ -8,7 +8,7 @@ import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import { useOpenCreateViewDropdown } from '@/views/hooks/useOpenCreateViewDropown';
@@ -29,7 +29,7 @@ export const ObjectOptionsDropdownDefaultView = () => {
const { currentView } = useGetCurrentViewOnly();
const visibleRecordFields = useRecoilComponentValue(
const visibleRecordFields = useRecoilComponentSelectorValueV2(
visibleRecordFieldsComponentSelector,
recordIndexId,
);
@@ -14,9 +14,10 @@ import { DropdownMenuHeaderLeftComponent } from '@/ui/layout/dropdown/components
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState';
import { useRecoilComponentFamilyValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useRecoilComponentFamilySelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentFamilySelectorValueV2';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useSetRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilStateV2';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useLingui } from '@lingui/react/macro';
import { useLocation } from 'react-router-dom';
import { VIEW_GROUP_VISIBLE_OPTIONS_MAX } from 'twenty-shared/constants';
@@ -35,15 +36,15 @@ export const ObjectOptionsDropdownHiddenRecordGroupsContent = () => {
viewType,
} = useObjectOptionsDropdown();
const recordGroupFieldMetadata = useRecoilComponentValue(
const recordGroupFieldMetadata = useRecoilComponentValueV2(
recordIndexGroupFieldMetadataItemComponentState,
);
const hiddenRecordGroupIds = useRecoilComponentValue(
const hiddenRecordGroupIds = useRecoilComponentSelectorValueV2(
hiddenRecordGroupIdsComponentSelector,
);
const visibleRecordGroupIds = useRecoilComponentFamilyValue(
const visibleRecordGroupIds = useRecoilComponentFamilySelectorValueV2(
visibleRecordGroupIdsComponentFamilySelector,
viewType,
);
@@ -13,7 +13,6 @@ import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import { useUpdateCurrentView } from '@/views/hooks/useUpdateCurrentView';
@@ -22,9 +21,9 @@ import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { ViewType, viewTypeIconMapping } from '@/views/types/ViewType';
import { useGetAvailableFieldsForCalendar } from '@/views/view-picker/hooks/useGetAvailableFieldsForCalendar';
import { useGetAvailableFieldsToGroupRecordsBy } from '@/views/view-picker/hooks/useGetAvailableFieldsToGroupRecordsBy';
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
import { useLingui } from '@lingui/react/macro';
import { useCallback } from 'react';
import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
import {
IconBaselineDensitySmall,
@@ -61,11 +60,13 @@ export const ObjectOptionsDropdownLayoutContent = () => {
[updateCurrentView],
);
const recordIndexOpenRecordIn = useRecoilValue(recordIndexOpenRecordInState);
const recordIndexCalendarLayout = useRecoilValue(
const recordIndexOpenRecordIn = useRecoilValueV2(
recordIndexOpenRecordInState,
);
const recordIndexCalendarLayout = useRecoilValueV2(
recordIndexCalendarLayoutState,
);
const recordGroupFieldMetadata = useRecoilComponentValue(
const recordGroupFieldMetadata = useRecoilComponentValueV2(
recordIndexGroupFieldMetadataItemComponentState,
);
@@ -12,10 +12,10 @@ import { SelectableList } from '@/ui/layout/selectable-list/components/Selectabl
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import { ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { t } from '@lingui/core/macro';
import { useRecoilValue } from 'recoil';
import {
IconChevronLeft,
IconLayoutNavbar,
@@ -25,7 +25,9 @@ import { MenuItemSelect } from 'twenty-ui/navigation';
export const ObjectOptionsDropdownLayoutOpenInContent = () => {
const { onContentChange } = useObjectOptionsDropdown();
const recordIndexOpenRecordIn = useRecoilValue(recordIndexOpenRecordInState);
const recordIndexOpenRecordIn = useRecoilValueV2(
recordIndexOpenRecordInState,
);
const { currentView } = useGetCurrentViewOnly();
const { setAndPersistOpenRecordIn } = useUpdateObjectViewOptions();
const { objectMetadataItem } = useRecordIndexContextOrThrow();
@@ -3,9 +3,9 @@ import { IconPicker } from '@/ui/input/components/IconPicker';
import { TextInput } from '@/ui/input/components/TextInput';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilComponentStateV2';
import { type View } from '@/views/types/View';
import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPickerDropdownId';
import { useUpdateViewFromCurrentState } from '@/views/view-picker/hooks/useUpdateViewFromCurrentState';
@@ -60,12 +60,12 @@ export const ObjectOptionsDropdownMenuViewName = ({
currentView,
}: ObjectOptionsDropdownMenuViewNameProps) => {
const [viewPickerSelectedIcon, setViewPickerSelectedIcon] =
useRecoilComponentState(viewPickerSelectedIconComponentState);
useRecoilComponentStateV2(viewPickerSelectedIconComponentState);
const viewPickerIsPersisting = useRecoilComponentValue(
const viewPickerIsPersisting = useRecoilComponentValueV2(
viewPickerIsPersistingComponentState,
);
const setViewPickerIsDirty = useSetRecoilComponentState(
const setViewPickerIsDirty = useSetRecoilComponentStateV2(
viewPickerIsDirtyComponentState,
);
@@ -15,7 +15,8 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { navigationMemorizedUrlState } from '@/ui/navigation/states/navigationMemorizedUrlState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useSetRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilStateV2';
import { ViewType } from '@/views/types/ViewType';
import { useLingui } from '@lingui/react/macro';
@@ -47,11 +48,11 @@ export const ObjectOptionsDropdownRecordGroupFieldsContent = () => {
objectNameSingular: objectMetadataItem.nameSingular,
});
const hiddenRecordGroupIds = useRecoilComponentValue(
const hiddenRecordGroupIds = useRecoilComponentSelectorValueV2(
hiddenRecordGroupIdsComponentSelector,
);
const recordGroupFieldMetadata = useRecoilComponentValue(
const recordGroupFieldMetadata = useRecoilComponentValueV2(
recordIndexGroupFieldMetadataItemComponentState,
);
@@ -12,8 +12,8 @@ import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/Drop
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { t } from '@lingui/core/macro';
import {
@@ -27,11 +27,11 @@ import { MenuItemSelect } from 'twenty-ui/navigation';
export const ObjectOptionsDropdownRecordGroupSortContent = () => {
const { currentContentId, onContentChange } = useObjectOptionsDropdown();
const hiddenRecordGroupIds = useRecoilComponentValue(
const hiddenRecordGroupIds = useRecoilComponentSelectorValueV2(
hiddenRecordGroupIdsComponentSelector,
);
const [recordGroupSort, setRecordGroupSort] = useRecoilComponentState(
const [recordGroupSort, setRecordGroupSort] = useRecoilComponentStateV2(
recordIndexRecordGroupSortComponentState,
);
@@ -17,9 +17,9 @@ import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownM
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
import { useRecoilComponentFamilyValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValue';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useRecoilComponentFamilySelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentFamilySelectorValueV2';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useGetCurrentViewOnly } from '@/views/hooks/useGetCurrentViewOnly';
import { useGetAvailableFieldsToGroupRecordsBy } from '@/views/view-picker/hooks/useGetAvailableFieldsToGroupRecordsBy';
import { useLingui } from '@lingui/react/macro';
@@ -48,27 +48,27 @@ export const ObjectOptionsDropdownRecordGroupsContent = () => {
const { currentView } = useGetCurrentViewOnly();
const recordGroupFieldMetadata = useRecoilComponentValue(
const recordGroupFieldMetadata = useRecoilComponentValueV2(
recordIndexGroupFieldMetadataItemComponentState,
);
const visibleRecordGroupIds = useRecoilComponentFamilyValue(
const visibleRecordGroupIds = useRecoilComponentFamilySelectorValueV2(
visibleRecordGroupIdsComponentFamilySelector,
viewType,
);
const hiddenRecordGroupIds = useRecoilComponentValue(
const hiddenRecordGroupIds = useRecoilComponentSelectorValueV2(
hiddenRecordGroupIdsComponentSelector,
);
const hideEmptyRecordGroup = useRecoilComponentValue(
const hideEmptyRecordGroup = useRecoilComponentValueV2(
recordIndexShouldHideEmptyRecordGroupsComponentState,
);
const shouldHideEmptyGroups =
hideEmptyRecordGroup ?? currentView?.shouldHideEmptyGroups ?? false;
const recordGroupSort = useRecoilComponentValue(
const recordGroupSort = useRecoilComponentValueV2(
recordIndexRecordGroupSortComponentState,
);
@@ -1,6 +1,5 @@
import { type OnDragEndResponder } from '@hello-pangea/dnd';
import { useCallback, useMemo } from 'react';
import { useRecoilState } from 'recoil';
import { useColumnDefinitionsFromObjectMetadata } from '@/object-metadata/hooks/useColumnDefinitionsFromObjectMetadata';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
@@ -12,7 +11,8 @@ import { type RecordField } from '@/object-record/record-field/types/RecordField
import { type FieldMetadata } from '@/object-record/record-field/ui/types/FieldMetadata';
import { recordIndexFieldDefinitionsState } from '@/object-record/record-index/states/recordIndexFieldDefinitionsState';
import { type ColumnDefinition } from '@/object-record/record-table/types/ColumnDefinition';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilStateV2';
import { useSaveCurrentViewFields } from '@/views/hooks/useSaveCurrentViewFields';
import { mapRecordFieldToViewField } from '@/views/utils/mapRecordFieldToViewField';
import { produce } from 'immer';
@@ -32,7 +32,7 @@ export const useObjectOptionsForBoard = ({
recordBoardId,
}: useObjectOptionsForBoardParams) => {
const [recordIndexFieldDefinitions, setRecordIndexFieldDefinitions] =
useRecoilState(recordIndexFieldDefinitionsState);
useRecoilStateV2(recordIndexFieldDefinitionsState);
const { saveViewFields } = useSaveCurrentViewFields();
@@ -130,7 +130,7 @@ export const useObjectOptionsForBoard = ({
],
);
const currentRecordFields = useRecoilComponentValue(
const currentRecordFields = useRecoilComponentValueV2(
currentRecordFieldsComponentState,
recordBoardId,
);
@@ -4,7 +4,7 @@ import { useReorderVisibleRecordFields } from '@/object-record/record-field/hook
import { useSaveCurrentViewFields } from '@/views/hooks/useSaveCurrentViewFields';
import { mapRecordFieldToViewField } from '@/views/utils/mapRecordFieldToViewField';
import { useRecoilCallback } from 'recoil';
import { useCallback } from 'react';
export const useProcessOptionDropdownDragEnd = (recordTableId: string) => {
const { reorderVisibleRecordFields } =
@@ -12,8 +12,8 @@ export const useProcessOptionDropdownDragEnd = (recordTableId: string) => {
const { saveViewFields } = useSaveCurrentViewFields();
const processOptionDropdownDragEnd: OnDragEndResponder = useRecoilCallback(
() => async (result) => {
const processOptionDropdownDragEnd: OnDragEndResponder = useCallback(
async (result) => {
if (
!result.destination ||
result.destination.index === 1 ||
@@ -1,6 +1,6 @@
import { objectOptionsDropdownSearchInputComponentState } from '@/object-record/object-options-dropdown/states/objectOptionsDropdownSearchInputComponentState';
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateV2';
import { useMemo } from 'react';
import { FieldMetadataType } from '~/generated-metadata/graphql';
@@ -8,7 +8,7 @@ export const useSearchRecordGroupField = () => {
const { objectMetadataItem } = useRecordIndexContextOrThrow();
const [recordGroupFieldSearchInput, setRecordGroupFieldSearchInput] =
useRecoilComponentState(objectOptionsDropdownSearchInputComponentState);
useRecoilComponentStateV2(objectOptionsDropdownSearchInputComponentState);
const filteredRecordGroupFieldMetadataItems = useMemo(() => {
const searchInputLowerCase =
@@ -13,13 +13,15 @@ import { convertCoreViewToView } from '@/views/utils/convertCoreViewToView';
import { convertViewTypeToCore } from '@/views/utils/convertViewTypeToCore';
import { useGetAvailableFieldsForCalendar } from '@/views/view-picker/hooks/useGetAvailableFieldsForCalendar';
import { useGetAvailableFieldsToGroupRecordsBy } from '@/views/view-picker/hooks/useGetAvailableFieldsToGroupRecordsBy';
import { useRecoilCallback, useSetRecoilState } from 'recoil';
import { useSetRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilStateV2';
import { useStore } from 'jotai';
import { useCallback } from 'react';
import { assertUnreachable, isDefined } from 'twenty-shared/utils';
import { ViewCalendarLayout } from '~/generated-metadata/graphql';
export const useSetViewTypeFromLayoutOptionsMenu = () => {
const { updateCurrentView } = useUpdateCurrentView();
const setRecordIndexViewType = useSetRecoilState(recordIndexViewTypeState);
const setRecordIndexViewType = useSetRecoilStateV2(recordIndexViewTypeState);
const { availableFieldsForGrouping } =
useGetAvailableFieldsToGroupRecordsBy();
const { objectMetadataItem } = useRecordIndexContextOrThrow();
@@ -28,137 +30,137 @@ export const useSetViewTypeFromLayoutOptionsMenu = () => {
const { availableFieldsForCalendar } = useGetAvailableFieldsForCalendar();
const setAndPersistViewType = useRecoilCallback(
({ snapshot }) =>
async (viewType: ViewType) => {
const currentViewId = snapshot
.getLoadable(
contextStoreCurrentViewIdComponentState.atomFamily({
instanceId: MAIN_CONTEXT_STORE_INSTANCE_ID,
}),
)
.getValue();
const store = useStore();
const existingCoreViews = jotaiStore.get(coreViewsState.atom);
const setAndPersistViewType = useCallback(
async (viewType: ViewType) => {
const currentViewId = store.get(
contextStoreCurrentViewIdComponentState.atomFamily({
instanceId: MAIN_CONTEXT_STORE_INSTANCE_ID,
}),
);
if (!isDefined(currentViewId)) {
throw new Error('No view id found');
const existingCoreViews = jotaiStore.get(coreViewsState.atom);
if (!isDefined(currentViewId)) {
throw new Error('No view id found');
}
const currentCoreView = existingCoreViews.find(
(coreView) => coreView.id === currentViewId,
);
if (!isDefined(currentCoreView)) {
throw new Error('No current view found');
}
const currentView = convertCoreViewToView(currentCoreView);
const updateCurrentViewParams: Partial<GraphQLView> = {};
updateCurrentViewParams.type = viewType;
switch (viewType) {
case ViewType.Kanban: {
if (availableFieldsForGrouping.length === 0) {
throw new Error('No fields for kanban - should not happen');
}
const mainGroupByFieldMetadataId = availableFieldsForGrouping[0].id;
updateCurrentViewParams.mainGroupByFieldMetadataId =
mainGroupByFieldMetadataId;
if (shouldChangeIcon(currentView.icon, currentView.type)) {
updateCurrentViewParams.icon =
viewTypeIconMapping(viewType).displayName;
}
setRecordIndexViewType(viewType);
jotaiStore.set(coreViewsState.atom, [
...existingCoreViews.filter(
(coreView) => coreView.id !== currentView.id,
),
{
...currentCoreView,
type: convertViewTypeToCore(viewType),
mainGroupByFieldMetadataId,
},
]);
await updateCurrentView(updateCurrentViewParams);
return;
}
const currentCoreView = existingCoreViews.find(
(coreView) => coreView.id === currentViewId,
);
if (!isDefined(currentCoreView)) {
throw new Error('No current view found');
case ViewType.Table: {
if (shouldChangeIcon(currentView.icon, currentView.type)) {
updateCurrentViewParams.icon =
viewTypeIconMapping(viewType).displayName;
}
updateCurrentViewParams.mainGroupByFieldMetadataId = null;
await updateCurrentView(updateCurrentViewParams);
setRecordIndexViewType(viewType);
jotaiStore.set(coreViewsState.atom, [
...existingCoreViews.filter(
(coreView) => coreView.id !== currentView.id,
),
{
...currentCoreView,
mainGroupByFieldMetadataId: null,
type: convertViewTypeToCore(viewType),
},
]);
return;
}
const currentView = convertCoreViewToView(currentCoreView);
const updateCurrentViewParams: Partial<GraphQLView> = {};
updateCurrentViewParams.type = viewType;
switch (viewType) {
case ViewType.Kanban: {
if (availableFieldsForGrouping.length === 0) {
throw new Error('No fields for kanban - should not happen');
}
const mainGroupByFieldMetadataId = availableFieldsForGrouping[0].id;
updateCurrentViewParams.mainGroupByFieldMetadataId =
mainGroupByFieldMetadataId;
if (shouldChangeIcon(currentView.icon, currentView.type)) {
updateCurrentViewParams.icon =
viewTypeIconMapping(viewType).displayName;
}
setRecordIndexViewType(viewType);
jotaiStore.set(coreViewsState.atom, [
...existingCoreViews.filter(
(coreView) => coreView.id !== currentView.id,
),
{
...currentCoreView,
type: convertViewTypeToCore(viewType),
mainGroupByFieldMetadataId,
},
]);
await updateCurrentView(updateCurrentViewParams);
return;
case ViewType.Calendar: {
if (availableFieldsForCalendar.length === 0) {
throw new Error('No date fields for calendar');
}
case ViewType.Table: {
if (shouldChangeIcon(currentView.icon, currentView.type)) {
updateCurrentViewParams.icon =
viewTypeIconMapping(viewType).displayName;
}
updateCurrentViewParams.mainGroupByFieldMetadataId = null;
await updateCurrentView(updateCurrentViewParams);
setRecordIndexViewType(viewType);
jotaiStore.set(coreViewsState.atom, [
...existingCoreViews.filter(
(coreView) => coreView.id !== currentView.id,
),
{
...currentCoreView,
mainGroupByFieldMetadataId: null,
type: convertViewTypeToCore(viewType),
},
]);
return;
}
case ViewType.Calendar: {
if (availableFieldsForCalendar.length === 0) {
throw new Error('No date fields for calendar');
}
const calendarFieldMetadataId = availableFieldsForCalendar[0].id;
const calendarFieldMetadataId = availableFieldsForCalendar[0].id;
setRecordIndexViewType(viewType);
jotaiStore.set(coreViewsState.atom, [
...existingCoreViews.filter(
(coreView) => coreView.id !== currentView.id,
),
{
...currentCoreView,
mainGroupByFieldMetadataId: null,
type: convertViewTypeToCore(viewType),
calendarLayout: ViewCalendarLayout.MONTH,
calendarFieldMetadataId,
},
]);
setRecordIndexViewType(viewType);
jotaiStore.set(coreViewsState.atom, [
...existingCoreViews.filter(
(coreView) => coreView.id !== currentView.id,
),
{
...currentCoreView,
mainGroupByFieldMetadataId: null,
type: convertViewTypeToCore(viewType),
calendarLayout: ViewCalendarLayout.MONTH,
calendarFieldMetadataId,
},
]);
loadRecordIndexStates(
{
...currentView,
type: viewType,
calendarFieldMetadataId,
calendarLayout: ViewCalendarLayout.MONTH,
},
objectMetadataItem,
);
loadRecordIndexStates(
{
...currentView,
type: viewType,
calendarFieldMetadataId,
calendarLayout: ViewCalendarLayout.MONTH,
},
objectMetadataItem,
);
if (shouldChangeIcon(currentView.icon, currentView.type)) {
updateCurrentViewParams.icon =
viewTypeIconMapping(viewType).displayName;
}
updateCurrentViewParams.calendarLayout = ViewCalendarLayout.MONTH;
updateCurrentViewParams.calendarFieldMetadataId =
calendarFieldMetadataId;
updateCurrentViewParams.mainGroupByFieldMetadataId = null;
return await updateCurrentView(updateCurrentViewParams);
}
case ViewType.FieldsWidget: {
return;
}
default: {
return assertUnreachable(viewType);
if (shouldChangeIcon(currentView.icon, currentView.type)) {
updateCurrentViewParams.icon =
viewTypeIconMapping(viewType).displayName;
}
updateCurrentViewParams.calendarLayout = ViewCalendarLayout.MONTH;
updateCurrentViewParams.calendarFieldMetadataId =
calendarFieldMetadataId;
updateCurrentViewParams.mainGroupByFieldMetadataId = null;
return await updateCurrentView(updateCurrentViewParams);
}
},
case ViewType.FieldsWidget: {
return;
}
default: {
return assertUnreachable(viewType);
}
}
},
[
availableFieldsForGrouping,
setRecordIndexViewType,
store,
updateCurrentView,
availableFieldsForCalendar,
loadRecordIndexStates,
@@ -1,6 +1,7 @@
import { recordIndexOpenRecordInState } from '@/object-record/record-index/states/recordIndexOpenRecordInState';
import { recordIndexOpenRecordInStateV2 } from '@/object-record/record-index/states/recordIndexOpenRecordInStateV2';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilComponentStateV2';
import { useSetRecoilStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilStateV2';
import { useStore } from 'jotai';
import { useUpdateCurrentView } from '@/views/hooks/useUpdateCurrentView';
import { type GraphQLView } from '@/views/types/GraphQLView';
@@ -8,20 +9,19 @@ import { type ViewOpenRecordInType } from '@/views/types/ViewOpenRecordInType';
import { viewPickerInputNameComponentState } from '@/views/view-picker/states/viewPickerInputNameComponentState';
import { viewPickerSelectedIconComponentState } from '@/views/view-picker/states/viewPickerSelectedIconComponentState';
import { useCallback } from 'react';
import { useSetRecoilState } from 'recoil';
export const useUpdateObjectViewOptions = () => {
const store = useStore();
const setRecordIndexOpenRecordIn = useSetRecoilState(
const setRecordIndexOpenRecordIn = useSetRecoilStateV2(
recordIndexOpenRecordInState,
);
const setRecordIndexViewName = useSetRecoilComponentState(
const setRecordIndexViewName = useSetRecoilComponentStateV2(
viewPickerInputNameComponentState,
);
const setRecordIndexViewIcon = useSetRecoilComponentState(
const setRecordIndexViewIcon = useSetRecoilComponentStateV2(
viewPickerSelectedIconComponentState,
);
@@ -1,8 +1,8 @@
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
import { ViewComponentInstanceContext } from '@/views/states/contexts/ViewComponentInstanceContext';
export const objectOptionsDropdownSearchInputComponentState =
createComponentState<string>({
createComponentStateV2<string>({
key: 'objectOptionsDropdownSearchInputComponentState',
defaultValue: '',
componentInstanceContext: ViewComponentInstanceContext,
@@ -25,10 +25,9 @@ import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDrop
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { selectedItemIdComponentState } from '@/ui/layout/selectable-list/states/selectedItemIdComponentState';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilComponentStateV2';
import { useFamilySelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useFamilySelectorValueV2';
import { Trans, useLingui } from '@lingui/react/macro';
@@ -42,7 +41,7 @@ export const ObjectSortDropdownButton = () => {
const { resetRecordSortDropdownSearchInput } =
useResetRecordSortDropdownSearchInput();
const setObjectSortDropdownSearchInput = useSetRecoilComponentState(
const setObjectSortDropdownSearchInput = useSetRecoilComponentStateV2(
objectSortDropdownSearchInputComponentState,
);
@@ -50,7 +49,7 @@ export const ObjectSortDropdownButton = () => {
const { recordIndexId, objectMetadataItem } = useRecordIndexContextOrThrow();
const objectSortDropdownSearchInput = useRecoilComponentValue(
const objectSortDropdownSearchInput = useRecoilComponentValueV2(
objectSortDropdownSearchInputComponentState,
);
@@ -63,7 +62,7 @@ export const ObjectSortDropdownButton = () => {
const { getIcon } = useIcons();
const visibleRecordFields = useRecoilComponentValue(
const visibleRecordFields = useRecoilComponentSelectorValueV2(
visibleRecordFieldsComponentSelector,
recordIndexId,
);
@@ -130,9 +129,9 @@ export const ObjectSortDropdownButton = () => {
};
const [selectedRecordSortDirection, setSelectedRecordSortDirection] =
useRecoilComponentState(selectedRecordSortDirectionComponentState);
useRecoilComponentStateV2(selectedRecordSortDirectionComponentState);
const setIsRecordSortDirectionMenuUnfolded = useSetRecoilComponentState(
const setIsRecordSortDirectionMenuUnfolded = useSetRecoilComponentStateV2(
isRecordSortDirectionDropdownMenuUnfoldedComponentState,
);
@@ -1,20 +1,19 @@
import { objectSortDropdownSearchInputComponentState } from '@/object-record/object-sort-dropdown/states/objectSortDropdownSearchInputComponentState';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { useRecoilCallback } from 'recoil';
import { useRecoilComponentStateCallbackStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateCallbackStateV2';
import { useStore } from 'jotai';
import { useCallback } from 'react';
export const useResetRecordSortDropdownSearchInput = () => {
const objectSortDropdownSearchInputCallbackState =
useRecoilComponentCallbackState(
useRecoilComponentStateCallbackStateV2(
objectSortDropdownSearchInputComponentState,
);
const resetRecordSortDropdownSearchInput = useRecoilCallback(
({ set }) =>
() => {
set(objectSortDropdownSearchInputCallbackState, '');
},
[objectSortDropdownSearchInputCallbackState],
);
const store = useStore();
const resetRecordSortDropdownSearchInput = useCallback(() => {
store.set(objectSortDropdownSearchInputCallbackState, '');
}, [objectSortDropdownSearchInputCallbackState, store]);
return {
resetRecordSortDropdownSearchInput,
@@ -1,15 +1,15 @@
import { isRecordSortDirectionDropdownMenuUnfoldedComponentState } from '@/object-record/object-sort-dropdown/states/isRecordSortDirectionDropdownMenuUnfoldedComponentState';
import { selectedRecordSortDirectionComponentState } from '@/object-record/object-sort-dropdown/states/selectedRecordSortDirectionComponentState';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilComponentStateV2';
import { ViewSortDirection } from '~/generated-metadata/graphql';
export const useResetSortDropdown = () => {
const setIsRecordSortDirectionDropdownMenuUnfolded =
useSetRecoilComponentState(
useSetRecoilComponentStateV2(
isRecordSortDirectionDropdownMenuUnfoldedComponentState,
);
const setSelectedRecordSortDirection = useSetRecoilComponentState(
const setSelectedRecordSortDirection = useSetRecoilComponentStateV2(
selectedRecordSortDirectionComponentState,
);
@@ -1,8 +1,8 @@
import { ObjectSortDropdownComponentInstanceContext } from '@/object-record/object-sort-dropdown/states/context/ObjectSortDropdownComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const isRecordSortDirectionDropdownMenuUnfoldedComponentState =
createComponentState<boolean>({
createComponentStateV2<boolean>({
key: 'isRecordSortDirectionDropdownMenuUnfoldedComponentState',
defaultValue: false,
componentInstanceContext: ObjectSortDropdownComponentInstanceContext,
@@ -1,8 +1,8 @@
import { ObjectSortDropdownComponentInstanceContext } from '@/object-record/object-sort-dropdown/states/context/ObjectSortDropdownComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
export const objectSortDropdownSearchInputComponentState =
createComponentState<string>({
createComponentStateV2<string>({
key: 'objectSortDropdownSearchInputComponentState',
defaultValue: '',
componentInstanceContext: ObjectSortDropdownComponentInstanceContext,
@@ -1,9 +1,9 @@
import { ObjectSortDropdownComponentInstanceContext } from '@/object-record/object-sort-dropdown/states/context/ObjectSortDropdownComponentInstanceContext';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';
import { createComponentStateV2 } from '@/ui/utilities/state/jotai/utils/createComponentStateV2';
import { ViewSortDirection } from '~/generated-metadata/graphql';
export const selectedRecordSortDirectionComponentState =
createComponentState<ViewSortDirection>({
createComponentStateV2<ViewSortDirection>({
key: 'selectedRecordSortDirectionComponentState',
defaultValue: ViewSortDirection.ASC,
componentInstanceContext: ObjectSortDropdownComponentInstanceContext,
@@ -8,7 +8,7 @@ import { recordBoardSelectedRecordIdsComponentSelector } from '@/object-record/r
import { useResetFocusStackToRecordIndex } from '@/object-record/record-index/hooks/useResetFocusStackToRecordIndex';
import { PageFocusId } from '@/types/PageFocusId';
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
export const RecordBoardBodyEscapeHotkeyEffect = () => {
const { recordBoardId } = useContext(RecordBoardContext);
@@ -18,7 +18,7 @@ export const RecordBoardBodyEscapeHotkeyEffect = () => {
const { unfocusBoardCard } = useFocusedRecordBoardCard(recordBoardId);
const { resetFocusStackToRecordIndex } = useResetFocusStackToRecordIndex();
const selectedRecordIds = useRecoilComponentValue(
const selectedRecordIds = useRecoilComponentSelectorValueV2(
recordBoardSelectedRecordIdsComponentSelector,
recordBoardId,
);
@@ -11,15 +11,16 @@ import { isDraggingRecordComponentState } from '@/object-record/record-drag/stat
import { MODAL_BACKDROP_CLICK_OUTSIDE_ID } from '@/ui/layout/modal/constants/ModalBackdropClickOutsideId';
import { PAGE_ACTION_CONTAINER_CLICK_OUTSIDE_ID } from '@/ui/layout/page/constants/PageActionContainerClickOutsideId';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useContext } from 'react';
import { LINK_CHIP_CLICK_OUTSIDE_ID } from 'twenty-ui/components';
export const RecordBoardClickOutsideEffect = () => {
const { recordBoardId } = useContext(RecordBoardContext);
const isDraggingRecord = useRecoilComponentValue(
const isDraggingRecord = useRecoilComponentValueV2(
isDraggingRecordComponentState,
recordBoardId,
);
const { deactivateBoardCard } = useActiveRecordBoardCard(recordBoardId);
@@ -1,6 +1,6 @@
import { RecordBoardColumn } from '@/object-record/record-board/record-board-column/components/RecordBoardColumn';
import { visibleRecordGroupIdsComponentFamilySelector } from '@/object-record/record-group/states/selectors/visibleRecordGroupIdsComponentFamilySelector';
import { useRecoilComponentFamilyValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValue';
import { useRecoilComponentFamilySelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentFamilySelectorValueV2';
import { ViewType } from '@/views/types/ViewType';
import styled from '@emotion/styled';
@@ -13,7 +13,7 @@ const StyledColumnContainer = styled.div`
`;
export const RecordBoardColumns = () => {
const visibleRecordGroupIds = useRecoilComponentFamilyValue(
const visibleRecordGroupIds = useRecoilComponentFamilySelectorValueV2(
visibleRecordGroupIdsComponentFamilySelector,
ViewType.Kanban,
);
@@ -14,7 +14,6 @@ import { RecordIndexRemoveSortingModal } from '@/object-record/record-index/comp
import { RECORD_INDEX_REMOVE_SORTING_MODAL_ID } from '@/object-record/record-index/constants/RecordIndexRemoveSortingModalId';
import { isModalOpenedComponentState } from '@/ui/layout/modal/states/isModalOpenedComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { isDefined } from 'twenty-shared/utils';
@@ -36,7 +35,7 @@ export const RecordBoardContainer = ({
objectMetadataItem.id,
);
const recordIndexGroupFieldMetadataItem = useRecoilComponentValue(
const recordIndexGroupFieldMetadataItem = useRecoilComponentValueV2(
recordIndexGroupFieldMetadataItemComponentState,
);
@@ -1,3 +1,5 @@
import { useStore } from 'jotai';
import { useListenToObjectRecordOperationBrowserEvent } from '@/browser-event/hooks/useListenToObjectRecordOperationBrowserEvent';
import { useGetShouldInitializeRecordBoardForUpdateInputs } from '@/object-record/record-board/hooks/useGetShouldInitializeRecordBoardForUpdateInputs';
import { useRemoveRecordsFromBoard } from '@/object-record/record-board/hooks/useRemoveRecordsFromBoard';
@@ -8,12 +10,14 @@ import { recordIndexGroupFieldMetadataItemComponentState } from '@/object-record
import { recordIndexRecordIdsByGroupComponentFamilyState } from '@/object-record/record-index/states/recordIndexRecordIdsByGroupComponentFamilyState';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { type ObjectRecordOperationBrowserEventDetail } from '@/browser-event/types/ObjectRecordOperationBrowserEventDetail';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
import { useRecoilCallback } from 'recoil';
import { useRecoilComponentFamilySelectorCallbackStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentFamilySelectorCallbackStateV2';
import { useRecoilComponentFamilyStateCallbackStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentFamilyStateCallbackStateV2';
import { useRecoilComponentStateCallbackStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateCallbackStateV2';
import { useCallback } from 'react';
import { isDefined } from 'twenty-shared/utils';
export const RecordBoardDataChangedEffect = () => {
const store = useStore();
const { objectMetadataItem } = useRecordIndexContextOrThrow();
const { triggerRecordBoardInitialQuery } =
useTriggerRecordBoardInitialQuery();
@@ -21,143 +25,139 @@ export const RecordBoardDataChangedEffect = () => {
useGetShouldInitializeRecordBoardForUpdateInputs();
const recordGroupFromGroupValueCallbackState =
useRecoilComponentCallbackState(
useRecoilComponentFamilySelectorCallbackStateV2(
recordGroupFromGroupValueComponentFamilySelector,
);
const recordIndexGroupFieldMetadataItemCallbackState =
useRecoilComponentCallbackState(
const recordIndexGroupFieldMetadataItemAtom =
useRecoilComponentStateCallbackStateV2(
recordIndexGroupFieldMetadataItemComponentState,
);
const recordIndexRecordIdsByGroupCallbackState =
useRecoilComponentCallbackState(
useRecoilComponentFamilyStateCallbackStateV2(
recordIndexRecordIdsByGroupComponentFamilyState,
);
const { removeRecordsFromBoard } = useRemoveRecordsFromBoard();
const handleObjectRecordOperation = useRecoilCallback(
({ snapshot }) =>
(
objectRecordOperationEventDetail: ObjectRecordOperationBrowserEventDetail,
) => {
const objectRecordOperation =
objectRecordOperationEventDetail.operation;
const handleObjectRecordOperation = useCallback(
(
objectRecordOperationEventDetail: ObjectRecordOperationBrowserEventDetail,
) => {
const objectRecordOperation = objectRecordOperationEventDetail.operation;
switch (objectRecordOperation.type) {
case 'update-one':
case 'update-many':
{
const updateInputs =
objectRecordOperation.type === 'update-one'
? [objectRecordOperation.result.updateInput]
: objectRecordOperation.result.updateInputs;
switch (objectRecordOperation.type) {
case 'update-one':
case 'update-many':
{
const updateInputs =
objectRecordOperation.type === 'update-one'
? [objectRecordOperation.result.updateInput]
: objectRecordOperation.result.updateInputs;
const shouldInitializeForUpdateOperation =
getShouldInitializeRecordBoardForUpdateInputs(updateInputs);
const shouldInitializeForUpdateOperation =
getShouldInitializeRecordBoardForUpdateInputs(updateInputs);
if (shouldInitializeForUpdateOperation) {
triggerRecordBoardInitialQuery();
}
}
break;
case 'create-one': {
if (objectRecordOperation.createdRecord.position === 'first') {
if (shouldInitializeForUpdateOperation) {
triggerRecordBoardInitialQuery();
} else {
const createdRecordPosition =
objectRecordOperation.createdRecord.position;
if (!isDefined(createdRecordPosition)) {
return;
}
const recordIndexGroupFieldMetadataItem = getSnapshotValue(
snapshot,
recordIndexGroupFieldMetadataItemCallbackState,
);
if (!isDefined(recordIndexGroupFieldMetadataItem)) {
return;
}
const recordGroupValue =
objectRecordOperation.createdRecord[
recordIndexGroupFieldMetadataItem.name
];
const recordGroupDefinitionFromGroupValue = getSnapshotValue(
snapshot,
recordGroupFromGroupValueCallbackState({ recordGroupValue }),
);
if (!isDefined(recordGroupDefinitionFromGroupValue)) {
return;
}
const recordIdsForGroup = getSnapshotValue(
snapshot,
recordIndexRecordIdsByGroupCallbackState(
recordGroupDefinitionFromGroupValue.id,
),
);
const recordIdsWithoutCreatedRecord = recordIdsForGroup.filter(
(recordId) =>
recordId !== objectRecordOperation.createdRecord.id,
);
const groupIsEmpty = recordIdsWithoutCreatedRecord.length === 0;
if (groupIsEmpty) {
triggerRecordBoardInitialQuery();
return;
}
const firstRecordIdInGroup = recordIdsWithoutCreatedRecord[0];
const firstExistingRecordInGroup = getSnapshotValue(
snapshot,
recordStoreFamilyState(firstRecordIdInGroup),
);
if (!isDefined(firstExistingRecordInGroup)) {
return;
}
if (createdRecordPosition < firstExistingRecordInGroup.position) {
triggerRecordBoardInitialQuery();
}
}
break;
}
case 'delete-one': {
const removedRecordId = objectRecordOperation.deletedRecordId;
removeRecordsFromBoard({
recordIdsToRemove: [removedRecordId],
});
return;
}
case 'delete-many': {
const removedRecordIds = objectRecordOperation.deletedRecordIds;
removeRecordsFromBoard({
recordIdsToRemove: removedRecordIds,
});
return;
}
case 'restore-many':
case 'restore-one': {
return;
}
default: {
break;
case 'create-one': {
if (objectRecordOperation.createdRecord.position === 'first') {
triggerRecordBoardInitialQuery();
} else {
const createdRecordPosition =
objectRecordOperation.createdRecord.position;
if (!isDefined(createdRecordPosition)) {
return;
}
const recordIndexGroupFieldMetadataItem = store.get(
recordIndexGroupFieldMetadataItemAtom,
);
if (!isDefined(recordIndexGroupFieldMetadataItem)) {
return;
}
const recordGroupValue =
objectRecordOperation.createdRecord[
recordIndexGroupFieldMetadataItem.name
];
const recordGroupDefinitionFromGroupValue = store.get(
recordGroupFromGroupValueCallbackState({ recordGroupValue }),
);
if (!isDefined(recordGroupDefinitionFromGroupValue)) {
return;
}
const recordIdsForGroup = store.get(
recordIndexRecordIdsByGroupCallbackState(
recordGroupDefinitionFromGroupValue.id,
),
);
const recordIdsWithoutCreatedRecord = recordIdsForGroup.filter(
(recordId) => recordId !== objectRecordOperation.createdRecord.id,
);
const groupIsEmpty = recordIdsWithoutCreatedRecord.length === 0;
if (groupIsEmpty) {
triggerRecordBoardInitialQuery();
return;
}
const firstRecordIdInGroup = recordIdsWithoutCreatedRecord[0];
const firstExistingRecordInGroup = store.get(
recordStoreFamilyState.atomFamily(firstRecordIdInGroup),
) as { position?: number } | null | undefined;
if (!isDefined(firstExistingRecordInGroup)) {
return;
}
if (
createdRecordPosition < (firstExistingRecordInGroup.position ?? 0)
) {
triggerRecordBoardInitialQuery();
}
}
break;
}
},
case 'delete-one': {
const removedRecordId = objectRecordOperation.deletedRecordId;
removeRecordsFromBoard({
recordIdsToRemove: [removedRecordId],
});
return;
}
case 'delete-many': {
const removedRecordIds = objectRecordOperation.deletedRecordIds;
removeRecordsFromBoard({
recordIdsToRemove: removedRecordIds,
});
return;
}
case 'restore-many':
case 'restore-one': {
return;
}
default: {
triggerRecordBoardInitialQuery();
}
}
},
[
store,
triggerRecordBoardInitialQuery,
getShouldInitializeRecordBoardForUpdateInputs,
recordIndexGroupFieldMetadataItemCallbackState,
recordIndexGroupFieldMetadataItemAtom,
recordGroupFromGroupValueCallbackState,
recordIndexRecordIdsByGroupCallbackState,
removeRecordsFromBoard,
@@ -8,84 +8,83 @@ import { originalDragSelectionComponentState } from '@/object-record/record-drag
import { RECORD_INDEX_REMOVE_SORTING_MODAL_ID } from '@/object-record/record-index/constants/RecordIndexRemoveSortingModalId';
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
import { useModal } from '@/ui/layout/modal/hooks/useModal';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue';
import { useRecoilComponentStateCallbackStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateCallbackStateV2';
import { useRecoilComponentSelectorCallbackStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorCallbackStateV2';
import { useStore } from 'jotai';
import {
DragDropContext,
type DragStart,
type OnDragEndResponder,
} from '@hello-pangea/dnd';
import { useContext } from 'react';
import { useRecoilCallback } from 'recoil';
import { useCallback, useContext } from 'react';
export const RecordBoardDragDropContext = ({
children,
}: React.PropsWithChildren) => {
const { recordBoardId } = useContext(RecordBoardContext);
const currentRecordSortCallbackState = useRecoilComponentCallbackState(
const currentRecordSortsAtom = useRecoilComponentStateCallbackStateV2(
currentRecordSortsComponentState,
);
const recordBoardSelectedRecordIdsSelector = useRecoilComponentCallbackState(
recordBoardSelectedRecordIdsComponentSelector,
recordBoardId,
);
const originalDragSelectionCallbackState = useRecoilComponentCallbackState(
const recordBoardSelectedRecordIdsAtom =
useRecoilComponentSelectorCallbackStateV2(
recordBoardSelectedRecordIdsComponentSelector,
recordBoardId,
);
const store = useStore();
const originalDragSelectionAtom = useRecoilComponentStateCallbackStateV2(
originalDragSelectionComponentState,
recordBoardId,
);
const { startRecordDrag } = useStartRecordDrag();
const { endRecordDrag } = useEndRecordDrag();
const { startRecordDrag } = useStartRecordDrag(recordBoardId);
const { endRecordDrag } = useEndRecordDrag(recordBoardId);
const { processBoardCardDrop } = useProcessBoardCardDrop();
const { openModal } = useModal();
const handleDragStart = useRecoilCallback(
({ snapshot }) =>
(start: DragStart) => {
const currentSelectedRecordIds = getSnapshotValue(
snapshot,
recordBoardSelectedRecordIdsSelector,
);
const handleDragStart = useCallback(
(start: DragStart) => {
const currentSelectedRecordIds = store.get(
recordBoardSelectedRecordIdsAtom,
);
startRecordDrag(start, currentSelectedRecordIds);
},
[recordBoardSelectedRecordIdsSelector, startRecordDrag],
startRecordDrag(start, currentSelectedRecordIds);
},
[recordBoardSelectedRecordIdsAtom, startRecordDrag, store],
);
const handleDragEnd: OnDragEndResponder = useRecoilCallback(
({ snapshot }) =>
(result) => {
endRecordDrag();
const handleDragEnd: OnDragEndResponder = useCallback(
(result) => {
endRecordDrag();
if (!result.destination) return;
if (!result.destination) return;
const currentRecordSorts = getSnapshotValue(
snapshot,
currentRecordSortCallbackState,
);
const currentRecordSorts = store.get(currentRecordSortsAtom);
if (currentRecordSorts.length > 0) {
openModal(RECORD_INDEX_REMOVE_SORTING_MODAL_ID);
return;
}
if (currentRecordSorts.length > 0) {
openModal(RECORD_INDEX_REMOVE_SORTING_MODAL_ID);
return;
}
const originalSelection = getSnapshotValue(
snapshot,
originalDragSelectionCallbackState,
);
const originalSelection = store.get(
originalDragSelectionAtom,
) as string[];
processBoardCardDrop(result, originalSelection);
},
processBoardCardDrop(result, originalSelection);
},
[
processBoardCardDrop,
originalDragSelectionCallbackState,
originalDragSelectionAtom,
endRecordDrag,
currentRecordSortCallbackState,
currentRecordSortsAtom,
openModal,
store,
],
);
@@ -10,9 +10,9 @@ import { recordBoardShouldFetchMoreComponentState } from '@/object-record/record
import { visibleRecordGroupIdsComponentFamilySelector } from '@/object-record/record-group/states/selectors/visibleRecordGroupIdsComponentFamilySelector';
import { recordIndexRecordGroupsAreInInitialLoadingComponentState } from '@/object-record/record-index/states/recordIndexRecordGroupsAreInInitialLoadingComponentState';
import { useScrollWrapperHTMLElement } from '@/ui/utilities/scroll/hooks/useScrollWrapperHTMLElement';
import { useRecoilComponentFamilyValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValue';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentFamilySelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentFamilySelectorValueV2';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { ViewType } from '@/views/types/ViewType';
const StyledFetchMoreTriggerDiv = styled.div<{ width: number }>`
@@ -21,15 +21,15 @@ const StyledFetchMoreTriggerDiv = styled.div<{ width: number }>`
`;
export const RecordBoardFetchMoreInViewTriggerComponent = () => {
const [shouldFetchMore, setShouldFetchMore] = useRecoilComponentState(
const [shouldFetchMore, setShouldFetchMore] = useRecoilComponentStateV2(
recordBoardShouldFetchMoreComponentState,
);
const isInitialLoading = useRecoilComponentValue(
const isInitialLoading = useRecoilComponentValueV2(
recordIndexRecordGroupsAreInInitialLoadingComponentState,
);
const isFetchingMore = useRecoilComponentValue(
const isFetchingMore = useRecoilComponentValueV2(
recordBoardIsFetchingMoreComponentState,
);
@@ -40,7 +40,7 @@ export const RecordBoardFetchMoreInViewTriggerComponent = () => {
root: scrollWrapperHTMLElement,
});
const visibleRecordGroupIds = useRecoilComponentFamilyValue(
const visibleRecordGroupIds = useRecoilComponentFamilySelectorValueV2(
visibleRecordGroupIdsComponentFamilySelector,
ViewType.Kanban,
);
@@ -2,7 +2,7 @@ import { RecordBoardColumnHeaderWrapper } from '@/object-record/record-board/rec
import { RecordGroupContext } from '@/object-record/record-group/states/context/RecordGroupContext';
import { visibleRecordGroupIdsComponentFamilySelector } from '@/object-record/record-group/states/selectors/visibleRecordGroupIdsComponentFamilySelector';
import { RecordIndexGroupAggregatesDataLoader } from '@/object-record/record-index/components/RecordIndexGroupAggregatesDataLoader';
import { useRecoilComponentFamilyValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentFamilyValue';
import { useRecoilComponentFamilySelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentFamilySelectorValueV2';
import { ViewType } from '@/views/types/ViewType';
import styled from '@emotion/styled';
@@ -26,7 +26,7 @@ const StyledHeaderContainer = styled.div`
`;
export const RecordBoardHeader = () => {
const visibleRecordGroupIds = useRecoilComponentFamilyValue(
const visibleRecordGroupIds = useRecoilComponentFamilySelectorValueV2(
visibleRecordGroupIdsComponentFamilySelector,
ViewType.Kanban,
);
@@ -12,9 +12,9 @@ import { useRecordIndexGroupCommonQueryVariables } from '@/object-record/record-
import { recordIndexRecordGroupsAreInInitialLoadingComponentState } from '@/object-record/record-index/states/recordIndexRecordGroupsAreInInitialLoadingComponentState';
import { getQueryIdentifier } from '@/object-record/utils/getQueryIdentifier';
import { useScrollWrapperHTMLElement } from '@/ui/utilities/scroll/hooks/useScrollWrapperHTMLElement';
import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateV2';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilComponentStateV2';
import { useEffect } from 'react';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
@@ -23,17 +23,17 @@ export const RecordBoardQueryEffect = () => {
const { objectMetadataItem } = useRecordIndexContextOrThrow();
const [lastRecordBoardQueryIdentifier, setLastRecordBoardQueryIdentifier] =
useRecoilComponentState(lastRecordBoardQueryIdentifierComponentState);
useRecoilComponentStateV2(lastRecordBoardQueryIdentifierComponentState);
const [lastRecordGroupIds, setLastRecordGroupIds] = useRecoilComponentState(
const [lastRecordGroupIds, setLastRecordGroupIds] = useRecoilComponentStateV2(
lastRecordGroupIdsComponentState,
);
const [recordIndexRecordGroupsAreInInitialLoading] = useRecoilComponentState(
const recordIndexRecordGroupsAreInInitialLoading = useRecoilComponentValueV2(
recordIndexRecordGroupsAreInInitialLoadingComponentState,
);
const setRecordBoardCurrentGroupByQueryOffset = useSetRecoilComponentState(
const setRecordBoardCurrentGroupByQueryOffset = useSetRecoilComponentStateV2(
recordBoardCurrentGroupByQueryOffsetComponentState,
);
@@ -51,11 +51,11 @@ export const RecordBoardQueryEffect = () => {
const { scrollWrapperHTMLElement } = useScrollWrapperHTMLElement();
const [shouldFetchMore] = useRecoilComponentState(
const [shouldFetchMore] = useRecoilComponentStateV2(
recordBoardShouldFetchMoreComponentState,
);
const recordBoardIsFetchingMore = useRecoilComponentValue(
const recordBoardIsFetchingMore = useRecoilComponentValueV2(
recordBoardIsFetchingMoreComponentState,
);
@@ -64,7 +64,9 @@ export const RecordBoardQueryEffect = () => {
const { triggerRecordBoardInitialQuery } =
useTriggerRecordBoardInitialQuery();
const recordGroupdIds = useRecoilComponentValue(recordGroupIdsComponentState);
const recordGroupdIds = useRecoilComponentValueV2(
recordGroupIdsComponentState,
);
const recordGroupIdsHaveChanged = !isDeeplyEqual(
[...recordGroupdIds].sort(),
[...lastRecordGroupIds].sort(),
@@ -1,16 +1,21 @@
import { useEffect } from 'react';
import { useContext, useEffect } from 'react';
import { RecordBoardContext } from '@/object-record/record-board/contexts/RecordBoardContext';
import { focusedRecordBoardCardIndexesComponentState } from '@/object-record/record-board/states/focusedRecordBoardCardIndexesComponentState';
import { isRecordBoardCardFocusActiveComponentState } from '@/object-record/record-board/states/isRecordBoardCardFocusActiveComponentState';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
export const RecordBoardScrollToFocusedCardEffect = () => {
const focusedCardIndexes = useRecoilComponentValue(
const { recordBoardId } = useContext(RecordBoardContext);
const focusedCardIndexes = useRecoilComponentValueV2(
focusedRecordBoardCardIndexesComponentState,
recordBoardId,
);
const isFocusActive = useRecoilComponentValue(
const isFocusActive = useRecoilComponentValueV2(
isRecordBoardCardFocusActiveComponentState,
recordBoardId,
);
useEffect(() => {
@@ -2,16 +2,20 @@ import { useEffect } from 'react';
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { recordBoardSelectedRecordIdsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardSelectedRecordIdsComponentSelector';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState';
import { useRecordIndexContextOrThrow } from '@/object-record/record-index/contexts/RecordIndexContext';
import { useRecoilComponentSelectorValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentSelectorValueV2';
import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/jotai/hooks/useSetRecoilComponentStateV2';
export const RecordBoardSelectRecordsEffect = () => {
const selectedRecordIds = useRecoilComponentValue(
const { recordIndexId } = useRecordIndexContextOrThrow();
const selectedRecordIds = useRecoilComponentSelectorValueV2(
recordBoardSelectedRecordIdsComponentSelector,
);
const setContextStoreTargetedRecords = useSetRecoilComponentState(
const setContextStoreTargetedRecords = useSetRecoilComponentStateV2(
contextStoreTargetedRecordsRuleComponentState,
recordIndexId,
);
useEffect(() => {
@@ -1,60 +1,62 @@
import { useCallback } from 'react';
import { useStore } from 'jotai';
import { activeRecordBoardCardIndexesComponentState } from '@/object-record/record-board/states/activeRecordBoardCardIndexesComponentState';
import { isRecordBoardCardActiveComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardActiveComponentFamilyState';
import { type BoardCardIndexes } from '@/object-record/record-board/types/BoardCardIndexes';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { useRecoilCallback } from 'recoil';
import { useRecoilComponentFamilyStateCallbackStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentFamilyStateCallbackStateV2';
import { useRecoilComponentStateCallbackStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateCallbackStateV2';
import { isDefined } from 'twenty-shared/utils';
export const useActiveRecordBoardCard = (recordBoardId?: string) => {
const isCardActiveState = useRecoilComponentCallbackState(
const isCardActiveState = useRecoilComponentFamilyStateCallbackStateV2(
isRecordBoardCardActiveComponentFamilyState,
recordBoardId,
);
const activeBoardCardIndexesState = useRecoilComponentCallbackState(
const activeBoardCardIndexesState = useRecoilComponentStateCallbackStateV2(
activeRecordBoardCardIndexesComponentState,
recordBoardId,
);
const deactivateBoardCard = useRecoilCallback(
({ set, snapshot }) =>
() => {
const activeBoardCardIndexes = snapshot
.getLoadable(activeBoardCardIndexesState)
.getValue();
const store = useStore();
if (!isDefined(activeBoardCardIndexes)) {
return;
}
const deactivateBoardCard = useCallback(() => {
const activeBoardCardIndexes = store.get(activeBoardCardIndexesState) as
| BoardCardIndexes
| null
| undefined;
set(activeBoardCardIndexesState, null);
set(isCardActiveState(activeBoardCardIndexes), false);
},
[activeBoardCardIndexesState, isCardActiveState],
);
if (!isDefined(activeBoardCardIndexes)) {
return;
}
const activateBoardCard = useRecoilCallback(
({ set, snapshot }) =>
(boardCardIndexes: BoardCardIndexes) => {
const activeBoardCardIndexes = snapshot
.getLoadable(activeBoardCardIndexesState)
.getValue();
store.set(activeBoardCardIndexesState, null);
store.set(isCardActiveState(activeBoardCardIndexes), false);
}, [activeBoardCardIndexesState, isCardActiveState, store]);
if (
activeBoardCardIndexes?.rowIndex === boardCardIndexes.rowIndex &&
activeBoardCardIndexes?.columnIndex === boardCardIndexes.columnIndex
) {
return;
}
const activateBoardCard = useCallback(
(boardCardIndexes: BoardCardIndexes) => {
const activeBoardCardIndexes = store.get(activeBoardCardIndexesState) as
| BoardCardIndexes
| null
| undefined;
if (isDefined(activeBoardCardIndexes)) {
set(isCardActiveState(activeBoardCardIndexes), false);
}
if (
activeBoardCardIndexes?.rowIndex === boardCardIndexes.rowIndex &&
activeBoardCardIndexes?.columnIndex === boardCardIndexes.columnIndex
) {
return;
}
set(activeBoardCardIndexesState, boardCardIndexes);
set(isCardActiveState(boardCardIndexes), true);
},
[activeBoardCardIndexesState, isCardActiveState],
if (isDefined(activeBoardCardIndexes)) {
store.set(isCardActiveState(activeBoardCardIndexes), false);
}
store.set(activeBoardCardIndexesState, boardCardIndexes);
store.set(isCardActiveState(boardCardIndexes), true);
},
[activeBoardCardIndexesState, isCardActiveState, store],
);
return {
@@ -6,22 +6,25 @@ import { type BoardCardIndexes } from '@/object-record/record-board/types/BoardC
import { usePushFocusItemToFocusStack } from '@/ui/utilities/focus/hooks/usePushFocusItemToFocusStack';
import { useRemoveFocusItemFromFocusStackById } from '@/ui/utilities/focus/hooks/useRemoveFocusItemFromFocusStackById';
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState';
import { useRecoilCallback } from 'recoil';
import { useStore } from 'jotai';
import { useRecoilComponentFamilyStateCallbackStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentFamilyStateCallbackStateV2';
import { useRecoilComponentStateCallbackStateV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentStateCallbackStateV2';
import { useCallback } from 'react';
import { isDefined } from 'twenty-shared/utils';
export const useFocusedRecordBoardCard = (recordBoardId?: string) => {
const isCardFocusedState = useRecoilComponentCallbackState(
const store = useStore();
const isCardFocusedAtom = useRecoilComponentFamilyStateCallbackStateV2(
isRecordBoardCardFocusedComponentFamilyState,
recordBoardId,
);
const focusedBoardCardIndexesState = useRecoilComponentCallbackState(
const focusedBoardCardIndexesAtom = useRecoilComponentStateCallbackStateV2(
focusedRecordBoardCardIndexesComponentState,
recordBoardId,
);
const isCardFocusActiveState = useRecoilComponentCallbackState(
const isCardFocusActiveAtom = useRecoilComponentStateCallbackStateV2(
isRecordBoardCardFocusActiveComponentState,
recordBoardId,
);
@@ -30,85 +33,83 @@ export const useFocusedRecordBoardCard = (recordBoardId?: string) => {
const { removeFocusItemFromFocusStackById } =
useRemoveFocusItemFromFocusStackById();
const unfocusBoardCard = useRecoilCallback(
({ set, snapshot }) =>
() => {
const focusedBoardCardIndexes = snapshot
.getLoadable(focusedBoardCardIndexesState)
.getValue();
const unfocusBoardCard = useCallback(() => {
const focusedBoardCardIndexes = store.get(focusedBoardCardIndexesAtom) as
| BoardCardIndexes
| null
| undefined;
if (!isDefined(focusedBoardCardIndexes)) {
return;
}
if (!isDefined(focusedBoardCardIndexes)) {
return;
}
const focusId = getRecordBoardCardFocusId({
const focusId = getRecordBoardCardFocusId({
recordBoardId: recordBoardId || '',
cardIndexes: focusedBoardCardIndexes,
});
removeFocusItemFromFocusStackById({
focusId,
});
store.set(focusedBoardCardIndexesAtom, null);
store.set(isCardFocusedAtom(focusedBoardCardIndexes), false);
store.set(isCardFocusActiveAtom, false);
}, [
store,
focusedBoardCardIndexesAtom,
isCardFocusedAtom,
isCardFocusActiveAtom,
recordBoardId,
removeFocusItemFromFocusStackById,
]);
const focusBoardCard = useCallback(
(boardCardIndexes: BoardCardIndexes) => {
const focusedBoardCardIndexes = store.get(focusedBoardCardIndexesAtom) as
| BoardCardIndexes
| null
| undefined;
if (
isDefined(focusedBoardCardIndexes) &&
(focusedBoardCardIndexes.rowIndex !== boardCardIndexes.rowIndex ||
focusedBoardCardIndexes.columnIndex !== boardCardIndexes.columnIndex)
) {
store.set(isCardFocusedAtom(focusedBoardCardIndexes), false);
const currentFocusId = getRecordBoardCardFocusId({
recordBoardId: recordBoardId || '',
cardIndexes: focusedBoardCardIndexes,
});
removeFocusItemFromFocusStackById({
focusId,
focusId: currentFocusId,
});
}
set(focusedBoardCardIndexesState, null);
set(isCardFocusedState(focusedBoardCardIndexes), false);
set(isCardFocusActiveState, false);
},
const focusId = getRecordBoardCardFocusId({
recordBoardId: recordBoardId || '',
cardIndexes: boardCardIndexes,
});
pushFocusItemToFocusStack({
focusId,
component: {
type: FocusComponentType.RECORD_BOARD_CARD,
instanceId: focusId,
},
});
store.set(focusedBoardCardIndexesAtom, boardCardIndexes);
store.set(isCardFocusedAtom(boardCardIndexes), true);
store.set(isCardFocusActiveAtom, true);
},
[
focusedBoardCardIndexesState,
isCardFocusedState,
isCardFocusActiveState,
recordBoardId,
removeFocusItemFromFocusStackById,
],
);
const focusBoardCard = useRecoilCallback(
({ set, snapshot }) =>
(boardCardIndexes: BoardCardIndexes) => {
const focusedBoardCardIndexes = snapshot
.getLoadable(focusedBoardCardIndexesState)
.getValue();
if (
isDefined(focusedBoardCardIndexes) &&
(focusedBoardCardIndexes.rowIndex !== boardCardIndexes.rowIndex ||
focusedBoardCardIndexes.columnIndex !==
boardCardIndexes.columnIndex)
) {
set(isCardFocusedState(focusedBoardCardIndexes), false);
const currentFocusId = getRecordBoardCardFocusId({
recordBoardId: recordBoardId || '',
cardIndexes: focusedBoardCardIndexes,
});
removeFocusItemFromFocusStackById({
focusId: currentFocusId,
});
}
const focusId = getRecordBoardCardFocusId({
recordBoardId: recordBoardId || '',
cardIndexes: boardCardIndexes,
});
pushFocusItemToFocusStack({
focusId,
component: {
type: FocusComponentType.RECORD_BOARD_CARD,
instanceId: focusId,
},
});
set(focusedBoardCardIndexesState, boardCardIndexes);
set(isCardFocusedState(boardCardIndexes), true);
set(isCardFocusActiveState, true);
},
[
focusedBoardCardIndexesState,
isCardFocusedState,
isCardFocusActiveState,
store,
focusedBoardCardIndexesAtom,
isCardFocusedAtom,
isCardFocusActiveAtom,
recordBoardId,
pushFocusItemToFocusStack,
removeFocusItemFromFocusStackById,
@@ -4,7 +4,7 @@ import { useRecordIndexContextOrThrow } from '@/object-record/record-index/conte
import { recordIndexGroupFieldMetadataItemComponentState } from '@/object-record/record-index/states/recordIndexGroupFieldMetadataComponentState';
import { currentRecordSortsComponentState } from '@/object-record/record-sort/states/currentRecordSortsComponentState';
import { type ObjectRecordOperationUpdateInput } from '@/object-record/types/ObjectRecordOperationUpdateInput';
import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilComponentValueV2';
import { FieldMetadataType } from 'twenty-shared/types';
import { isDefined, mapById } from 'twenty-shared/utils';
@@ -15,15 +15,15 @@ export const useGetShouldInitializeRecordBoardForUpdateInputs = () => {
objectMetadataItem,
});
const currentRecordSorts = useRecoilComponentValue(
const currentRecordSorts = useRecoilComponentValueV2(
currentRecordSortsComponentState,
);
const currentRecordFilters = useRecoilComponentValue(
const currentRecordFilters = useRecoilComponentValueV2(
currentRecordFiltersComponentState,
);
const recordIndexGroupFieldMetadataItem = useRecoilComponentValue(
const recordIndexGroupFieldMetadataItem = useRecoilComponentValueV2(
recordIndexGroupFieldMetadataItemComponentState,
);

Some files were not shown because too many files have changed in this diff Show More