Skip to content

Commit

Permalink
Simplify multi-object picker logic with search (#8010)
Browse files Browse the repository at this point in the history
Simplifying the logic around multi-object pickers and search by getting
rid of the behaviour that keeped selected elements even when they did
not match the search filter (eg keeping selected record "Brian Chesky"
in dropdown even when search input is "Qonto"). This allows us to
simplify the fetch queries around the search to only do one query.

---------

Co-authored-by: Lucas Bordeau <[email protected]>
  • Loading branch information
ijreilly and lucasbordeau authored Nov 7, 2024
1 parent 2ab4aa1 commit ac233b7
Show file tree
Hide file tree
Showing 16 changed files with 214 additions and 514 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
import { useInlineCell } from '@/object-record/record-inline-cell/hooks/useInlineCell';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { ActivityTargetInlineCellEditModeMultiRecordsEffect } from '@/object-record/relation-picker/components/ActivityTargetInlineCellEditModeMultiRecordsEffect';
import { ActivityTargetInlineCellEditModeMultiRecordsSearchFilterEffect } from '@/object-record/relation-picker/components/ActivityTargetInlineCellEditModeMultiRecordsSearchFilterEffect';
import { MultiRecordSelect } from '@/object-record/relation-picker/components/MultiRecordSelect';
import { RelationPickerScope } from '@/object-record/relation-picker/scopes/RelationPickerScope';
import { prefillRecord } from '@/object-record/utils/prefillRecord';
Expand Down Expand Up @@ -287,6 +288,7 @@ export const ActivityTargetInlineCellEditMode = ({
<ActivityTargetInlineCellEditModeMultiRecordsEffect
selectedObjectRecordIds={selectedTargetObjectIds}
/>
<ActivityTargetInlineCellEditModeMultiRecordsSearchFilterEffect />
<MultiRecordSelect onSubmit={handleSubmit} onChange={handleChange} />
</RelationPickerScope>
</StyledSelectContainer>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import { useObjectRecordMultiSelectScopedStates } from '@/activities/hooks/useOb
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useRelationField } from '@/object-record/record-field/meta-types/hooks/useRelationField';
import { objectRecordMultiSelectComponentFamilyState } from '@/object-record/record-field/states/objectRecordMultiSelectComponentFamilyState';
import { ObjectRecordForSelect } from '@/object-record/relation-picker/hooks/useMultiObjectSearch';
import { useRelationPickerEntitiesOptions } from '@/object-record/relation-picker/hooks/useRelationPickerEntitiesOptions';
import { RelationPickerScopeInternalContext } from '@/object-record/relation-picker/scopes/scope-internal-context/RelationPickerScopeInternalContext';
import { EntityForSelect } from '@/object-record/relation-picker/types/EntityForSelect';
import { ObjectRecordForSelect } from '@/object-record/types/ObjectRecordForSelect';
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ObjectRecordForSelect } from '@/object-record/relation-picker/hooks/useMultiObjectSearch';
import { ObjectRecordForSelect } from '@/object-record/types/ObjectRecordForSelect';
import { createComponentFamilyState } from '@/ui/utilities/state/component-state/utils/createComponentFamilyState';

export type ObjectRecordAndSelected = ObjectRecordForSelect & {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { ObjectRecordForSelect } from '@/object-record/types/ObjectRecordForSelect';
import { createComponentState } from '@/ui/utilities/state/component-state/utils/createComponentState';

export const objectRecordMultiSelectMatchesFilterRecordsIdsComponentState =
createComponentState<ObjectRecordForSelect[]>({
key: 'objectRecordMultiSelectMatchesFilterRecordsIdsComponentState',
defaultValue: [],
});
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,11 @@ import {
} from 'recoil';

import { useObjectRecordMultiSelectScopedStates } from '@/activities/hooks/useObjectRecordMultiSelectScopedStates';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { objectRecordMultiSelectComponentFamilyState } from '@/object-record/record-field/states/objectRecordMultiSelectComponentFamilyState';
import { useRelationPickerScopedStates } from '@/object-record/relation-picker/hooks/internal/useRelationPickerScopedStates';
import {
ObjectRecordForSelect,
SelectedObjectRecordId,
useMultiObjectSearch,
} from '@/object-record/relation-picker/hooks/useMultiObjectSearch';
import { objectRecordMultiSelectMatchesFilterRecordsIdsComponentState } from '@/object-record/record-field/states/objectRecordMultiSelectMatchesFilterRecordsIdsComponentState';
import { RelationPickerScopeInternalContext } from '@/object-record/relation-picker/scopes/scope-internal-context/RelationPickerScopeInternalContext';
import { ObjectRecordForSelect } from '@/object-record/types/ObjectRecordForSelect';
import { SelectedObjectRecordId } from '@/object-record/types/SelectedObjectRecordId';
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';

Expand All @@ -30,43 +26,14 @@ export const ActivityTargetInlineCellEditModeMultiRecordsEffect = ({
const {
objectRecordsIdsMultiSelectState,
objectRecordMultiSelectCheckedRecordsIdsState,
recordMultiSelectIsLoadingState,
} = useObjectRecordMultiSelectScopedStates(scopeId);
const [objectRecordsIdsMultiSelect, setObjectRecordsIdsMultiSelect] =
useRecoilState(objectRecordsIdsMultiSelectState);

const setRecordMultiSelectIsLoading = useSetRecoilState(
recordMultiSelectIsLoadingState,
);

const relationPickerScopedId = useAvailableScopeIdOrThrow(
RelationPickerScopeInternalContext,
);

const { relationPickerSearchFilterState } = useRelationPickerScopedStates({
relationPickerScopedId,
});
const relationPickerSearchFilter = useRecoilValue(
relationPickerSearchFilterState,
const setObjectRecordMultiSelectCheckedRecordsIds = useSetRecoilState(
objectRecordMultiSelectCheckedRecordsIdsState,
);

const { filteredSelectedObjectRecords, loading, objectRecordsToSelect } =
useMultiObjectSearch({
searchFilterValue: relationPickerSearchFilter,
excludedObjects: [
CoreObjectNameSingular.Task,
CoreObjectNameSingular.Note,
],
selectedObjectRecordIds,
excludedObjectRecordIds: [],
limit: 10,
});

const [
objectRecordMultiSelectCheckedRecordsIds,
setObjectRecordMultiSelectCheckedRecordsIds,
] = useRecoilState(objectRecordMultiSelectCheckedRecordsIdsState);

const updateRecords = useRecoilCallback(
({ snapshot, set }) =>
(newRecords: ObjectRecordForSelect[]) => {
Expand All @@ -80,6 +47,10 @@ export const ActivityTargetInlineCellEditModeMultiRecordsEffect = ({
)
.getValue();

const objectRecordMultiSelectCheckedRecordsIds = snapshot
.getLoadable(objectRecordMultiSelectCheckedRecordsIdsState)
.getValue();

const newRecordWithSelected = {
...newRecord,
selected: objectRecordMultiSelectCheckedRecordsIds.some(
Expand All @@ -103,23 +74,25 @@ export const ActivityTargetInlineCellEditModeMultiRecordsEffect = ({
}
}
},
[objectRecordMultiSelectCheckedRecordsIds, scopeId],
[objectRecordMultiSelectCheckedRecordsIdsState, scopeId],
);

const matchesSearchFilterObjectRecords = useRecoilValue(
objectRecordMultiSelectMatchesFilterRecordsIdsComponentState({
scopeId,
}),
);

useEffect(() => {
const allRecords = [
...(filteredSelectedObjectRecords ?? []),
...(objectRecordsToSelect ?? []),
];
const allRecords = matchesSearchFilterObjectRecords ?? [];
updateRecords(allRecords);
const allRecordsIds = allRecords.map((record) => record.record.id);
if (!isDeeplyEqual(allRecordsIds, objectRecordsIdsMultiSelect)) {
setObjectRecordsIdsMultiSelect(allRecordsIds);
}
}, [
filteredSelectedObjectRecords,
matchesSearchFilterObjectRecords,
objectRecordsIdsMultiSelect,
objectRecordsToSelect,
setObjectRecordsIdsMultiSelect,
updateRecords,
]);
Expand All @@ -130,9 +103,5 @@ export const ActivityTargetInlineCellEditModeMultiRecordsEffect = ({
);
}, [selectedObjectRecordIds, setObjectRecordMultiSelectCheckedRecordsIds]);

useEffect(() => {
setRecordMultiSelectIsLoading(loading);
}, [loading, setRecordMultiSelectIsLoading]);

return <></>;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { useEffect } from 'react';
import { useRecoilValue, useSetRecoilState } from 'recoil';

import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { objectRecordMultiSelectMatchesFilterRecordsIdsComponentState } from '@/object-record/record-field/states/objectRecordMultiSelectMatchesFilterRecordsIdsComponentState';
import { useRelationPickerScopedStates } from '@/object-record/relation-picker/hooks/internal/useRelationPickerScopedStates';
import { useMultiObjectSearchMatchesSearchFilterQuery } from '@/object-record/relation-picker/hooks/useMultiObjectSearchMatchesSearchFilterQuery';
import { RelationPickerScopeInternalContext } from '@/object-record/relation-picker/scopes/scope-internal-context/RelationPickerScopeInternalContext';
import { useAvailableScopeIdOrThrow } from '@/ui/utilities/recoil-scope/scopes-internal/hooks/useAvailableScopeId';

export const ActivityTargetInlineCellEditModeMultiRecordsSearchFilterEffect =
() => {
const scopeId = useAvailableScopeIdOrThrow(
RelationPickerScopeInternalContext,
);

const setRecordMultiSelectMatchesFilterRecords = useSetRecoilState(
objectRecordMultiSelectMatchesFilterRecordsIdsComponentState({
scopeId,
}),
);

const relationPickerScopedId = useAvailableScopeIdOrThrow(
RelationPickerScopeInternalContext,
);

const { relationPickerSearchFilterState } = useRelationPickerScopedStates({
relationPickerScopedId,
});
const relationPickerSearchFilter = useRecoilValue(
relationPickerSearchFilterState,
);

const { matchesSearchFilterObjectRecords } =
useMultiObjectSearchMatchesSearchFilterQuery({
excludedObjects: [
CoreObjectNameSingular.Task,
CoreObjectNameSingular.Note,
],
searchFilterValue: relationPickerSearchFilter,
limit: 10,
});

useEffect(() => {
setRecordMultiSelectMatchesFilterRecords(
matchesSearchFilterObjectRecords,
);
}, [
setRecordMultiSelectMatchesFilterRecords,
matchesSearchFilterObjectRecords,
]);

return <></>;
};

This file was deleted.

Loading

0 comments on commit ac233b7

Please sign in to comment.