fix: prevent flashing of search results during input (#7592)
solves #7511 --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
committed by
GitHub
parent
653085f1e6
commit
1a57dd654f
@ -1,5 +1,3 @@
|
|||||||
import styled from '@emotion/styled';
|
|
||||||
|
|
||||||
import { useOpenCopilotRightDrawer } from '@/activities/copilot/right-drawer/hooks/useOpenCopilotRightDrawer';
|
import { useOpenCopilotRightDrawer } from '@/activities/copilot/right-drawer/hooks/useOpenCopilotRightDrawer';
|
||||||
import { copilotQueryState } from '@/activities/copilot/right-drawer/states/copilotQueryState';
|
import { copilotQueryState } from '@/activities/copilot/right-drawer/states/copilotQueryState';
|
||||||
import { useOpenActivityRightDrawer } from '@/activities/hooks/useOpenActivityRightDrawer';
|
import { useOpenActivityRightDrawer } from '@/activities/hooks/useOpenActivityRightDrawer';
|
||||||
@ -29,13 +27,14 @@ import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useLis
|
|||||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||||
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
|
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
|
||||||
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
|
||||||
|
import styled from '@emotion/styled';
|
||||||
import { isNonEmptyString } from '@sniptt/guards';
|
import { isNonEmptyString } from '@sniptt/guards';
|
||||||
import { useMemo, useRef } from 'react';
|
import { useMemo, useRef } from 'react';
|
||||||
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
|
import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil';
|
||||||
import { Key } from 'ts-key-enum';
|
import { Key } from 'ts-key-enum';
|
||||||
import { Avatar, IconNotes, IconSparkles, IconX, isDefined } from 'twenty-ui';
|
import { Avatar, IconNotes, IconSparkles, IconX, isDefined } from 'twenty-ui';
|
||||||
|
import { useDebounce } from 'use-debounce';
|
||||||
import { getLogoUrlFromDomainName } from '~/utils';
|
import { getLogoUrlFromDomainName } from '~/utils';
|
||||||
import { generateILikeFiltersForCompositeFields } from '~/utils/array/generateILikeFiltersForCompositeFields';
|
|
||||||
|
|
||||||
const SEARCH_BAR_HEIGHT = 56;
|
const SEARCH_BAR_HEIGHT = 56;
|
||||||
const SEARCH_BAR_PADDING = 3;
|
const SEARCH_BAR_PADDING = 3;
|
||||||
@ -131,7 +130,6 @@ const StyledEmpty = styled.div`
|
|||||||
export const CommandMenu = () => {
|
export const CommandMenu = () => {
|
||||||
const { toggleCommandMenu, onItemClick, closeCommandMenu } = useCommandMenu();
|
const { toggleCommandMenu, onItemClick, closeCommandMenu } = useCommandMenu();
|
||||||
const commandMenuRef = useRef<HTMLDivElement>(null);
|
const commandMenuRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
const openActivityRightDrawer = useOpenActivityRightDrawer({
|
const openActivityRightDrawer = useOpenActivityRightDrawer({
|
||||||
objectNameSingular: CoreObjectNameSingular.Note,
|
objectNameSingular: CoreObjectNameSingular.Note,
|
||||||
});
|
});
|
||||||
@ -139,9 +137,9 @@ export const CommandMenu = () => {
|
|||||||
const [commandMenuSearch, setCommandMenuSearch] = useRecoilState(
|
const [commandMenuSearch, setCommandMenuSearch] = useRecoilState(
|
||||||
commandMenuSearchState,
|
commandMenuSearchState,
|
||||||
);
|
);
|
||||||
|
const [deferredCommandMenuSearch] = useDebounce(commandMenuSearch, 300); // 200ms - 500ms
|
||||||
const commandMenuCommands = useRecoilValue(commandMenuCommandsState);
|
const commandMenuCommands = useRecoilValue(commandMenuCommandsState);
|
||||||
const { closeKeyboardShortcutMenu } = useKeyboardShortcutMenu();
|
const { closeKeyboardShortcutMenu } = useKeyboardShortcutMenu();
|
||||||
|
|
||||||
const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setCommandMenuSearch(event.target.value);
|
setCommandMenuSearch(event.target.value);
|
||||||
};
|
};
|
||||||
@ -167,99 +165,45 @@ export const CommandMenu = () => {
|
|||||||
[closeCommandMenu],
|
[closeCommandMenu],
|
||||||
);
|
);
|
||||||
|
|
||||||
const isWorkspaceMigratedForSearch = useIsFeatureEnabled(
|
const { loading: isPeopleLoading, records: people } =
|
||||||
'IS_WORKSPACE_MIGRATED_FOR_SEARCH',
|
useSearchRecords<Person>({
|
||||||
);
|
skip: !isCommandMenuOpened,
|
||||||
|
objectNameSingular: CoreObjectNameSingular.Person,
|
||||||
|
limit: 3,
|
||||||
|
searchInput: deferredCommandMenuSearch ?? undefined,
|
||||||
|
});
|
||||||
|
|
||||||
const isSearchEnabled =
|
const { loading: isCompaniesLoading, records: companies } =
|
||||||
useIsFeatureEnabled('IS_SEARCH_ENABLED') && isWorkspaceMigratedForSearch;
|
useSearchRecords<Company>({
|
||||||
|
skip: !isCommandMenuOpened,
|
||||||
|
objectNameSingular: CoreObjectNameSingular.Company,
|
||||||
|
limit: 3,
|
||||||
|
searchInput: deferredCommandMenuSearch ?? undefined,
|
||||||
|
});
|
||||||
|
|
||||||
const { records: peopleFromFindMany } = useFindManyRecords<Person>({
|
const { loading: isNotesLoading, records: notes } = useFindManyRecords<Note>({
|
||||||
skip: !isCommandMenuOpened || isSearchEnabled,
|
|
||||||
objectNameSingular: CoreObjectNameSingular.Person,
|
|
||||||
filter: commandMenuSearch
|
|
||||||
? makeOrFilterVariables([
|
|
||||||
...generateILikeFiltersForCompositeFields(commandMenuSearch, 'name', [
|
|
||||||
'firstName',
|
|
||||||
'lastName',
|
|
||||||
]),
|
|
||||||
...generateILikeFiltersForCompositeFields(
|
|
||||||
commandMenuSearch,
|
|
||||||
'emails',
|
|
||||||
['primaryEmail'],
|
|
||||||
),
|
|
||||||
])
|
|
||||||
: undefined,
|
|
||||||
limit: 3,
|
|
||||||
});
|
|
||||||
const { records: peopleFromSearch } = useSearchRecords<Person>({
|
|
||||||
skip: !isCommandMenuOpened || !isSearchEnabled,
|
|
||||||
objectNameSingular: CoreObjectNameSingular.Person,
|
|
||||||
limit: 3,
|
|
||||||
searchInput: commandMenuSearch ?? undefined,
|
|
||||||
});
|
|
||||||
|
|
||||||
const people = isSearchEnabled ? peopleFromSearch : peopleFromFindMany;
|
|
||||||
|
|
||||||
const { records: companiesFromSearch } = useSearchRecords<Company>({
|
|
||||||
skip: !isCommandMenuOpened || !isSearchEnabled,
|
|
||||||
objectNameSingular: CoreObjectNameSingular.Company,
|
|
||||||
limit: 3,
|
|
||||||
searchInput: commandMenuSearch ?? undefined,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { records: companiesFromFindMany } = useFindManyRecords<Company>({
|
|
||||||
skip: !isCommandMenuOpened || isSearchEnabled,
|
|
||||||
objectNameSingular: CoreObjectNameSingular.Company,
|
|
||||||
filter: commandMenuSearch
|
|
||||||
? {
|
|
||||||
name: { ilike: `%${commandMenuSearch}%` },
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
limit: 3,
|
|
||||||
});
|
|
||||||
|
|
||||||
const companies = isSearchEnabled
|
|
||||||
? companiesFromSearch
|
|
||||||
: companiesFromFindMany;
|
|
||||||
|
|
||||||
const { records: notes } = useFindManyRecords<Note>({
|
|
||||||
skip: !isCommandMenuOpened,
|
skip: !isCommandMenuOpened,
|
||||||
objectNameSingular: CoreObjectNameSingular.Note,
|
objectNameSingular: CoreObjectNameSingular.Note,
|
||||||
filter: commandMenuSearch
|
filter: deferredCommandMenuSearch
|
||||||
? makeOrFilterVariables([
|
? makeOrFilterVariables([
|
||||||
{ title: { ilike: `%${commandMenuSearch}%` } },
|
{ title: { ilike: `%${deferredCommandMenuSearch}%` } },
|
||||||
{ body: { ilike: `%${commandMenuSearch}%` } },
|
{ body: { ilike: `%${deferredCommandMenuSearch}%` } },
|
||||||
])
|
])
|
||||||
: undefined,
|
: undefined,
|
||||||
limit: 3,
|
limit: 3,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { records: opportunitiesFromFindMany } = useFindManyRecords({
|
const { loading: isOpportunitiesLoading, records: opportunities } =
|
||||||
skip: !isCommandMenuOpened || isSearchEnabled,
|
useSearchRecords<Opportunity>({
|
||||||
objectNameSingular: CoreObjectNameSingular.Opportunity,
|
skip: !isCommandMenuOpened,
|
||||||
filter: commandMenuSearch
|
objectNameSingular: CoreObjectNameSingular.Opportunity,
|
||||||
? {
|
limit: 3,
|
||||||
name: { ilike: `%${commandMenuSearch}%` },
|
searchInput: deferredCommandMenuSearch ?? undefined,
|
||||||
}
|
});
|
||||||
: undefined,
|
|
||||||
limit: 3,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { records: opportunitiesFromSearch } = useSearchRecords<Opportunity>({
|
|
||||||
skip: !isCommandMenuOpened || !isSearchEnabled,
|
|
||||||
objectNameSingular: CoreObjectNameSingular.Opportunity,
|
|
||||||
limit: 3,
|
|
||||||
searchInput: commandMenuSearch ?? undefined,
|
|
||||||
});
|
|
||||||
|
|
||||||
const opportunities = isSearchEnabled
|
|
||||||
? opportunitiesFromSearch
|
|
||||||
: opportunitiesFromFindMany;
|
|
||||||
|
|
||||||
const peopleCommands = useMemo(
|
const peopleCommands = useMemo(
|
||||||
() =>
|
() =>
|
||||||
people.map(({ id, name: { firstName, lastName } }) => ({
|
people?.map(({ id, name: { firstName, lastName } }) => ({
|
||||||
id,
|
id,
|
||||||
label: `${firstName} ${lastName}`,
|
label: `${firstName} ${lastName}`,
|
||||||
to: `object/person/${id}`,
|
to: `object/person/${id}`,
|
||||||
@ -269,7 +213,7 @@ export const CommandMenu = () => {
|
|||||||
|
|
||||||
const companyCommands = useMemo(
|
const companyCommands = useMemo(
|
||||||
() =>
|
() =>
|
||||||
companies.map(({ id, name }) => ({
|
companies?.map(({ id, name }) => ({
|
||||||
id,
|
id,
|
||||||
label: name ?? '',
|
label: name ?? '',
|
||||||
to: `object/company/${id}`,
|
to: `object/company/${id}`,
|
||||||
@ -279,7 +223,7 @@ export const CommandMenu = () => {
|
|||||||
|
|
||||||
const opportunityCommands = useMemo(
|
const opportunityCommands = useMemo(
|
||||||
() =>
|
() =>
|
||||||
opportunities.map(({ id, name }) => ({
|
opportunities?.map(({ id, name }) => ({
|
||||||
id,
|
id,
|
||||||
label: name ?? '',
|
label: name ?? '',
|
||||||
to: `object/opportunity/${id}`,
|
to: `object/opportunity/${id}`,
|
||||||
@ -289,7 +233,7 @@ export const CommandMenu = () => {
|
|||||||
|
|
||||||
const noteCommands = useMemo(
|
const noteCommands = useMemo(
|
||||||
() =>
|
() =>
|
||||||
notes.map((note) => ({
|
notes?.map((note) => ({
|
||||||
id: note.id,
|
id: note.id,
|
||||||
label: note.title ?? '',
|
label: note.title ?? '',
|
||||||
to: '',
|
to: '',
|
||||||
@ -299,12 +243,20 @@ export const CommandMenu = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const otherCommands = useMemo(() => {
|
const otherCommands = useMemo(() => {
|
||||||
return [
|
const commandsArray: Command[] = [];
|
||||||
...peopleCommands,
|
if (peopleCommands?.length > 0) {
|
||||||
...companyCommands,
|
commandsArray.push(...(peopleCommands as Command[]));
|
||||||
...opportunityCommands,
|
}
|
||||||
...noteCommands,
|
if (companyCommands?.length > 0) {
|
||||||
] as Command[];
|
commandsArray.push(...(companyCommands as Command[]));
|
||||||
|
}
|
||||||
|
if (opportunityCommands?.length > 0) {
|
||||||
|
commandsArray.push(...(opportunityCommands as Command[]));
|
||||||
|
}
|
||||||
|
if (noteCommands?.length > 0) {
|
||||||
|
commandsArray.push(...(noteCommands as Command[]));
|
||||||
|
}
|
||||||
|
return commandsArray;
|
||||||
}, [peopleCommands, companyCommands, noteCommands, opportunityCommands]);
|
}, [peopleCommands, companyCommands, noteCommands, opportunityCommands]);
|
||||||
|
|
||||||
const checkInShortcuts = (cmd: Command, search: string) => {
|
const checkInShortcuts = (cmd: Command, search: string) => {
|
||||||
@ -322,17 +274,17 @@ export const CommandMenu = () => {
|
|||||||
|
|
||||||
const matchingNavigateCommand = commandMenuCommands.filter(
|
const matchingNavigateCommand = commandMenuCommands.filter(
|
||||||
(cmd) =>
|
(cmd) =>
|
||||||
(commandMenuSearch.length > 0
|
(deferredCommandMenuSearch.length > 0
|
||||||
? checkInShortcuts(cmd, commandMenuSearch) ||
|
? checkInShortcuts(cmd, deferredCommandMenuSearch) ||
|
||||||
checkInLabels(cmd, commandMenuSearch)
|
checkInLabels(cmd, deferredCommandMenuSearch)
|
||||||
: true) && cmd.type === CommandType.Navigate,
|
: true) && cmd.type === CommandType.Navigate,
|
||||||
);
|
);
|
||||||
|
|
||||||
const matchingCreateCommand = commandMenuCommands.filter(
|
const matchingCreateCommand = commandMenuCommands.filter(
|
||||||
(cmd) =>
|
(cmd) =>
|
||||||
(commandMenuSearch.length > 0
|
(deferredCommandMenuSearch.length > 0
|
||||||
? checkInShortcuts(cmd, commandMenuSearch) ||
|
? checkInShortcuts(cmd, deferredCommandMenuSearch) ||
|
||||||
checkInLabels(cmd, commandMenuSearch)
|
checkInLabels(cmd, deferredCommandMenuSearch)
|
||||||
: true) && cmd.type === CommandType.Create,
|
: true) && cmd.type === CommandType.Create,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -352,7 +304,7 @@ export const CommandMenu = () => {
|
|||||||
label: 'Open Copilot',
|
label: 'Open Copilot',
|
||||||
type: CommandType.Navigate,
|
type: CommandType.Navigate,
|
||||||
onCommandClick: () => {
|
onCommandClick: () => {
|
||||||
setCopilotQuery(commandMenuSearch);
|
setCopilotQuery(deferredCommandMenuSearch);
|
||||||
openCopilotRightDrawer();
|
openCopilotRightDrawer();
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -363,10 +315,23 @@ export const CommandMenu = () => {
|
|||||||
.map((cmd) => cmd.id)
|
.map((cmd) => cmd.id)
|
||||||
.concat(matchingCreateCommand.map((cmd) => cmd.id))
|
.concat(matchingCreateCommand.map((cmd) => cmd.id))
|
||||||
.concat(matchingNavigateCommand.map((cmd) => cmd.id))
|
.concat(matchingNavigateCommand.map((cmd) => cmd.id))
|
||||||
.concat(people.map((person) => person.id))
|
.concat(people?.map((person) => person.id))
|
||||||
.concat(companies.map((company) => company.id))
|
.concat(companies?.map((company) => company.id))
|
||||||
.concat(opportunities.map((opportunity) => opportunity.id))
|
.concat(opportunities?.map((opportunity) => opportunity.id))
|
||||||
.concat(notes.map((note) => note.id));
|
.concat(notes?.map((note) => note.id));
|
||||||
|
|
||||||
|
const isNoResults =
|
||||||
|
!matchingCreateCommand.length &&
|
||||||
|
!matchingNavigateCommand.length &&
|
||||||
|
!people?.length &&
|
||||||
|
!companies?.length &&
|
||||||
|
!notes?.length &&
|
||||||
|
!opportunities?.length;
|
||||||
|
const isLoading =
|
||||||
|
isPeopleLoading ||
|
||||||
|
isNotesLoading ||
|
||||||
|
isOpportunitiesLoading ||
|
||||||
|
isCompaniesLoading;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -410,14 +375,9 @@ export const CommandMenu = () => {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{!matchingCreateCommand.length &&
|
{isNoResults && !isLoading && (
|
||||||
!matchingNavigateCommand.length &&
|
<StyledEmpty>No results found</StyledEmpty>
|
||||||
!people.length &&
|
)}
|
||||||
!companies.length &&
|
|
||||||
!notes.length &&
|
|
||||||
!opportunities.length && (
|
|
||||||
<StyledEmpty>No results found</StyledEmpty>
|
|
||||||
)}
|
|
||||||
{isCopilotEnabled && (
|
{isCopilotEnabled && (
|
||||||
<CommandGroup heading="Copilot">
|
<CommandGroup heading="Copilot">
|
||||||
<SelectableItem itemId={copilotCommand.id}>
|
<SelectableItem itemId={copilotCommand.id}>
|
||||||
@ -425,8 +385,8 @@ export const CommandMenu = () => {
|
|||||||
id={copilotCommand.id}
|
id={copilotCommand.id}
|
||||||
Icon={copilotCommand.Icon}
|
Icon={copilotCommand.Icon}
|
||||||
label={`${copilotCommand.label} ${
|
label={`${copilotCommand.label} ${
|
||||||
commandMenuSearch.length > 2
|
deferredCommandMenuSearch.length > 2
|
||||||
? `"${commandMenuSearch}"`
|
? `"${deferredCommandMenuSearch}"`
|
||||||
: ''
|
: ''
|
||||||
}`}
|
}`}
|
||||||
onClick={copilotCommand.onCommandClick}
|
onClick={copilotCommand.onCommandClick}
|
||||||
@ -467,7 +427,7 @@ export const CommandMenu = () => {
|
|||||||
))}
|
))}
|
||||||
</CommandGroup>
|
</CommandGroup>
|
||||||
<CommandGroup heading="People">
|
<CommandGroup heading="People">
|
||||||
{people.map((person) => (
|
{people?.map((person) => (
|
||||||
<SelectableItem itemId={person.id} key={person.id}>
|
<SelectableItem itemId={person.id} key={person.id}>
|
||||||
<CommandMenuItem
|
<CommandMenuItem
|
||||||
id={person.id}
|
id={person.id}
|
||||||
@ -493,7 +453,7 @@ export const CommandMenu = () => {
|
|||||||
))}
|
))}
|
||||||
</CommandGroup>
|
</CommandGroup>
|
||||||
<CommandGroup heading="Companies">
|
<CommandGroup heading="Companies">
|
||||||
{companies.map((company) => (
|
{companies?.map((company) => (
|
||||||
<SelectableItem itemId={company.id} key={company.id}>
|
<SelectableItem itemId={company.id} key={company.id}>
|
||||||
<CommandMenuItem
|
<CommandMenuItem
|
||||||
id={company.id}
|
id={company.id}
|
||||||
@ -514,7 +474,7 @@ export const CommandMenu = () => {
|
|||||||
))}
|
))}
|
||||||
</CommandGroup>
|
</CommandGroup>
|
||||||
<CommandGroup heading="Opportunities">
|
<CommandGroup heading="Opportunities">
|
||||||
{opportunities.map((opportunity) => (
|
{opportunities?.map((opportunity) => (
|
||||||
<SelectableItem
|
<SelectableItem
|
||||||
itemId={opportunity.id}
|
itemId={opportunity.id}
|
||||||
key={opportunity.id}
|
key={opportunity.id}
|
||||||
@ -522,14 +482,14 @@ export const CommandMenu = () => {
|
|||||||
<CommandMenuItem
|
<CommandMenuItem
|
||||||
id={opportunity.id}
|
id={opportunity.id}
|
||||||
key={opportunity.id}
|
key={opportunity.id}
|
||||||
label={opportunity.name}
|
label={opportunity.name ?? ''}
|
||||||
to={`object/opportunity/${opportunity.id}`}
|
to={`object/opportunity/${opportunity.id}`}
|
||||||
Icon={() => (
|
Icon={() => (
|
||||||
<Avatar
|
<Avatar
|
||||||
type="rounded"
|
type="rounded"
|
||||||
avatarUrl={null}
|
avatarUrl={null}
|
||||||
placeholderColorSeed={opportunity.id}
|
placeholderColorSeed={opportunity.id}
|
||||||
placeholder={opportunity.name}
|
placeholder={opportunity.name ?? ''}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@ -537,7 +497,7 @@ export const CommandMenu = () => {
|
|||||||
))}
|
))}
|
||||||
</CommandGroup>
|
</CommandGroup>
|
||||||
<CommandGroup heading="Notes">
|
<CommandGroup heading="Notes">
|
||||||
{notes.map((note) => (
|
{notes?.map((note) => (
|
||||||
<SelectableItem itemId={note.id} key={note.id}>
|
<SelectableItem itemId={note.id} key={note.id}>
|
||||||
<CommandMenuItem
|
<CommandMenuItem
|
||||||
id={note.id}
|
id={note.id}
|
||||||
|
|||||||
@ -1,6 +1,3 @@
|
|||||||
import { useQuery, WatchQueryFetchPolicy } from '@apollo/client';
|
|
||||||
import { useRecoilValue } from 'recoil';
|
|
||||||
|
|
||||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||||
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
|
||||||
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
|
import { ObjectMetadataItemIdentifier } from '@/object-metadata/types/ObjectMetadataItemIdentifier';
|
||||||
@ -13,7 +10,9 @@ import { ObjectRecord } from '@/object-record/types/ObjectRecord';
|
|||||||
import { getSearchRecordsQueryResponseField } from '@/object-record/utils/getSearchRecordsQueryResponseField';
|
import { getSearchRecordsQueryResponseField } from '@/object-record/utils/getSearchRecordsQueryResponseField';
|
||||||
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
import { SnackBarVariant } from '@/ui/feedback/snack-bar-manager/components/SnackBar';
|
||||||
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
|
||||||
|
import { useQuery, WatchQueryFetchPolicy } from '@apollo/client';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
|
import { useRecoilValue } from 'recoil';
|
||||||
import { logError } from '~/utils/logError';
|
import { logError } from '~/utils/logError';
|
||||||
|
|
||||||
export type UseSearchRecordsParams = ObjectMetadataItemIdentifier &
|
export type UseSearchRecordsParams = ObjectMetadataItemIdentifier &
|
||||||
@ -43,10 +42,8 @@ export const useSearchRecords = <T extends ObjectRecord = ObjectRecord>({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const { enqueueSnackBar } = useSnackBar();
|
const { enqueueSnackBar } = useSnackBar();
|
||||||
|
const { data, loading, error, previousData } =
|
||||||
const { data, loading, error } = useQuery<RecordGqlOperationSearchResult>(
|
useQuery<RecordGqlOperationSearchResult>(searchRecordsQuery, {
|
||||||
searchRecordsQuery,
|
|
||||||
{
|
|
||||||
skip:
|
skip:
|
||||||
skip || !objectMetadataItem || !currentWorkspaceMember || !searchInput,
|
skip || !objectMetadataItem || !currentWorkspaceMember || !searchInput,
|
||||||
variables: {
|
variables: {
|
||||||
@ -66,14 +63,15 @@ export const useSearchRecords = <T extends ObjectRecord = ObjectRecord>({
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
const effectiveData = loading ? previousData : data;
|
||||||
|
|
||||||
const queryResponseField = getSearchRecordsQueryResponseField(
|
const queryResponseField = getSearchRecordsQueryResponseField(
|
||||||
objectMetadataItem.namePlural,
|
objectMetadataItem.namePlural,
|
||||||
);
|
);
|
||||||
|
|
||||||
const result = data?.[queryResponseField];
|
const result = effectiveData?.[queryResponseField];
|
||||||
|
|
||||||
const records = useMemo(
|
const records = useMemo(
|
||||||
() =>
|
() =>
|
||||||
|
|||||||
Reference in New Issue
Block a user