feat: add Relation Field Card plus button in Show Page (#3229)

Closes #3124
This commit is contained in:
Thaïs
2024-01-09 06:29:01 -03:00
committed by GitHub
parent dc94d26997
commit ed06cc0310
12 changed files with 306 additions and 209 deletions

View File

@ -1,7 +1,5 @@
import { useEffect } from 'react';
import { useQuery } from '@apollo/client';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { useObjectNameSingularFromPlural } from '@/object-metadata/hooks/useObjectNameSingularFromPlural';
import { FieldDefinition } from '@/object-record/field/types/FieldDefinition';
import { FieldRelationMetadata } from '@/object-record/field/types/FieldMetadata';
@ -13,7 +11,7 @@ import { IconForbid } from '@/ui/display/icon';
export type RelationPickerProps = {
recordId?: string;
onSubmit: (newUser: EntityForSelect | null) => void;
onSubmit: (selectedEntity: EntityForSelect | null) => void;
onCancel?: () => void;
width?: number;
excludeRecordIds?: string[];
@ -30,32 +28,24 @@ export const RelationPicker = ({
initialSearchFilter,
fieldDefinition,
}: RelationPickerProps) => {
const { relationPickerSearchFilter, setRelationPickerSearchFilter } =
useRelationPicker();
const {
relationPickerSearchFilter,
setRelationPickerSearchFilter,
identifiersMapper,
searchQuery,
} = useRelationPicker();
useEffect(() => {
setRelationPickerSearchFilter(initialSearchFilter ?? '');
}, [initialSearchFilter, setRelationPickerSearchFilter]);
// TODO: refactor useFilteredSearchEntityQuery
const { findManyRecordsQuery } = useObjectMetadataItem({
objectNameSingular:
fieldDefinition.metadata.relationObjectMetadataNameSingular,
});
const useFindManyQuery = (options: any) =>
useQuery(findManyRecordsQuery, options);
const { identifiersMapper, searchQuery } = useRelationPicker();
const { objectNameSingular: relationObjectNameSingular } =
useObjectNameSingularFromPlural({
objectNamePlural:
fieldDefinition.metadata.relationObjectMetadataNamePlural,
});
const records = useFilteredSearchEntityQuery({
queryHook: useFindManyQuery,
const entities = useFilteredSearchEntityQuery({
filters: [
{
fieldNames:
@ -76,19 +66,18 @@ export const RelationPicker = ({
objectNameSingular: relationObjectNameSingular,
});
const handleEntitySelected = async (selectedUser: any | null | undefined) => {
onSubmit(selectedUser ?? null);
};
const handleEntitySelected = (selectedEntity: any | null | undefined) =>
onSubmit(selectedEntity ?? null);
return (
<SingleEntitySelect
EmptyIcon={IconForbid}
emptyLabel={'No ' + fieldDefinition.label}
entitiesToSelect={records.entitiesToSelect}
loading={records.loading}
entitiesToSelect={entities.entitiesToSelect}
loading={entities.loading}
onCancel={onCancel}
onEntitySelected={handleEntitySelected}
selectedEntity={records.selectedEntities[0]}
selectedEntity={entities.selectedEntities[0]}
width={width}
/>
);

View File

@ -1,32 +1,16 @@
import { useRef } from 'react';
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
import { isDefined } from '~/utils/isDefined';
import { useEntitySelectSearch } from '../hooks/useEntitySelectSearch';
import {
SingleEntitySelectBase,
SingleEntitySelectBaseProps,
} from './SingleEntitySelectBase';
SingleEntitySelectMenuItemsWithSearch,
SingleEntitySelectMenuItemsWithSearchProps,
} from '@/object-record/relation-picker/components/SingleEntitySelectMenuItemsWithSearch';
import { DropdownMenu } from '@/ui/layout/dropdown/components/DropdownMenu';
import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
export type SingleEntitySelectProps = {
disableBackgroundBlur?: boolean;
onCreate?: () => void;
width?: number;
} & Pick<
SingleEntitySelectBaseProps,
| 'EmptyIcon'
| 'emptyLabel'
| 'entitiesToSelect'
| 'loading'
| 'onCancel'
| 'onEntitySelected'
| 'selectedEntity'
>;
} & SingleEntitySelectMenuItemsWithSearchProps;
export const SingleEntitySelect = ({
EmptyIcon,
@ -42,10 +26,6 @@ export const SingleEntitySelect = ({
}: SingleEntitySelectProps) => {
const containerRef = useRef<HTMLDivElement>(null);
const { searchFilter, handleSearchFilterChange } = useEntitySelectSearch();
const showCreateButton = isDefined(onCreate) && searchFilter !== '';
useListenClickOutside({
refs: [containerRef],
callback: (event) => {
@ -62,13 +42,7 @@ export const SingleEntitySelect = ({
width={width}
data-select-disable
>
<DropdownMenuSearchInput
value={searchFilter}
onChange={handleSearchFilterChange}
autoFocus
/>
<DropdownMenuSeparator />
<SingleEntitySelectBase
<SingleEntitySelectMenuItemsWithSearch
{...{
EmptyIcon,
emptyLabel,
@ -78,7 +52,6 @@ export const SingleEntitySelect = ({
onCreate,
onEntitySelected,
selectedEntity,
showCreateButton,
}}
/>
</DropdownMenu>

View File

@ -5,6 +5,8 @@ import { Key } from 'ts-key-enum';
import { SelectableMenuItemSelect } from '@/object-record/relation-picker/components/SelectableMenuItemSelect';
import { IconPlus } from '@/ui/display/icon';
import { IconComponent } from '@/ui/display/icon/types/IconComponent';
import { CreateNewButton } from '@/ui/input/relation-picker/components/CreateNewButton';
import { DropdownMenuSkeletonItem } from '@/ui/input/relation-picker/components/skeletons/DropdownMenuSkeletonItem';
import { DropdownMenuItemsContainer } from '@/ui/layout/dropdown/components/DropdownMenuItemsContainer';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
@ -13,12 +15,10 @@ import { MenuItemSelect } from '@/ui/navigation/menu-item/components/MenuItemSel
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import { assertNotNull } from '~/utils/assert';
import { CreateNewButton } from '../../../ui/input/relation-picker/components/CreateNewButton';
import { DropdownMenuSkeletonItem } from '../../../ui/input/relation-picker/components/skeletons/DropdownMenuSkeletonItem';
import { EntityForSelect } from '../types/EntityForSelect';
import { RelationPickerHotkeyScope } from '../types/RelationPickerHotkeyScope';
export type SingleEntitySelectBaseProps = {
export type SingleEntitySelectMenuItemsProps = {
EmptyIcon?: IconComponent;
emptyLabel?: string;
entitiesToSelect: EntityForSelect[];
@ -35,7 +35,7 @@ export type SingleEntitySelectBaseProps = {
onAllEntitySelected?: () => void;
};
export const SingleEntitySelectBase = ({
export const SingleEntitySelectMenuItems = ({
EmptyIcon,
emptyLabel,
entitiesToSelect,
@ -50,7 +50,7 @@ export const SingleEntitySelectBase = ({
isAllEntitySelected,
isAllEntitySelectShown,
onAllEntitySelected,
}: SingleEntitySelectBaseProps) => {
}: SingleEntitySelectMenuItemsProps) => {
const containerRef = useRef<HTMLDivElement>(null);
const entitiesInDropdown = [selectedEntity, ...entitiesToSelect].filter(

View File

@ -0,0 +1,61 @@
import {
SingleEntitySelectMenuItems,
SingleEntitySelectMenuItemsProps,
} from '@/object-record/relation-picker/components/SingleEntitySelectMenuItems';
import { DropdownMenuSearchInput } from '@/ui/layout/dropdown/components/DropdownMenuSearchInput';
import { DropdownMenuSeparator } from '@/ui/layout/dropdown/components/DropdownMenuSeparator';
import { isDefined } from '~/utils/isDefined';
import { useEntitySelectSearch } from '../hooks/useEntitySelectSearch';
export type SingleEntitySelectMenuItemsWithSearchProps = {
onCreate?: () => void;
} & Pick<
SingleEntitySelectMenuItemsProps,
| 'EmptyIcon'
| 'emptyLabel'
| 'entitiesToSelect'
| 'loading'
| 'onCancel'
| 'onEntitySelected'
| 'selectedEntity'
>;
export const SingleEntitySelectMenuItemsWithSearch = ({
EmptyIcon,
emptyLabel,
entitiesToSelect,
loading,
onCancel,
onCreate,
onEntitySelected,
selectedEntity,
}: SingleEntitySelectMenuItemsWithSearchProps) => {
const { searchFilter, handleSearchFilterChange } = useEntitySelectSearch();
const showCreateButton = isDefined(onCreate) && searchFilter !== '';
return (
<>
<DropdownMenuSearchInput
value={searchFilter}
onChange={handleSearchFilterChange}
autoFocus
/>
<DropdownMenuSeparator />
<SingleEntitySelectMenuItems
{...{
EmptyIcon,
emptyLabel,
entitiesToSelect,
loading,
onCancel,
onCreate,
onEntitySelected,
selectedEntity,
showCreateButton,
}}
/>
</>
);
};