feat: add Select field preview and form (#2655)

Closes #2432
This commit is contained in:
Thaïs
2023-11-28 23:44:21 +01:00
committed by GitHub
parent 0fa55b0634
commit bc787f72ba
18 changed files with 317 additions and 87 deletions

View File

@ -1,28 +1,29 @@
import { useContext } from 'react';
import { ChipFieldDisplay } from '@/ui/object/field/meta-types/display/components/ChipFieldDisplay';
import { FullNameFieldDisplay } from '@/ui/object/field/meta-types/display/components/FullNameFieldDisplay';
import { LinkFieldDisplay } from '@/ui/object/field/meta-types/display/components/LinkFieldDisplay';
import { RelationFieldDisplay } from '@/ui/object/field/meta-types/display/components/RelationFieldDisplay';
import { UuidFieldDisplay } from '@/ui/object/field/meta-types/display/components/UuidFieldDisplay';
import { isFieldFullName } from '@/ui/object/field/types/guards/isFieldFullName';
import { isFieldLink } from '@/ui/object/field/types/guards/isFieldLink';
import { isFieldUuid } from '@/ui/object/field/types/guards/isFieldUuid';
import { FieldContext } from '../contexts/FieldContext';
import { ChipFieldDisplay } from '../meta-types/display/components/ChipFieldDisplay';
import { CurrencyFieldDisplay } from '../meta-types/display/components/CurrencyFieldDisplay';
import { DateFieldDisplay } from '../meta-types/display/components/DateFieldDisplay';
import { EmailFieldDisplay } from '../meta-types/display/components/EmailFieldDisplay';
import { FullNameFieldDisplay } from '../meta-types/display/components/FullNameFieldDisplay';
import { LinkFieldDisplay } from '../meta-types/display/components/LinkFieldDisplay';
import { NumberFieldDisplay } from '../meta-types/display/components/NumberFieldDisplay';
import { PhoneFieldDisplay } from '../meta-types/display/components/PhoneFieldDisplay';
import { RelationFieldDisplay } from '../meta-types/display/components/RelationFieldDisplay';
import { SelectFieldDisplay } from '../meta-types/display/components/SelectFieldDisplay';
import { TextFieldDisplay } from '../meta-types/display/components/TextFieldDisplay';
import { UuidFieldDisplay } from '../meta-types/display/components/UuidFieldDisplay';
import { isFieldCurrency } from '../types/guards/isFieldCurrency';
import { isFieldDateTime } from '../types/guards/isFieldDateTime';
import { isFieldEmail } from '../types/guards/isFieldEmail';
import { isFieldFullName } from '../types/guards/isFieldFullName';
import { isFieldLink } from '../types/guards/isFieldLink';
import { isFieldNumber } from '../types/guards/isFieldNumber';
import { isFieldPhone } from '../types/guards/isFieldPhone';
import { isFieldRelation } from '../types/guards/isFieldRelation';
import { isFieldSelect } from '../types/guards/isFieldSelect';
import { isFieldText } from '../types/guards/isFieldText';
import { isFieldUuid } from '../types/guards/isFieldUuid';
export const FieldDisplay = () => {
const { fieldDefinition, isLabelIdentifier } = useContext(FieldContext);
@ -55,6 +56,8 @@ export const FieldDisplay = () => {
<FullNameFieldDisplay />
) : isFieldPhone(fieldDefinition) ? (
<PhoneFieldDisplay />
) : isFieldSelect(fieldDefinition) ? (
<SelectFieldDisplay />
) : (
<></>
)}

View File

@ -0,0 +1,9 @@
import { Tag } from '@/ui/display/tag/components/Tag';
import { useSelectField } from '../../hooks/useSelectField';
export const SelectFieldDisplay = () => {
const { fieldValue } = useSelectField();
return <Tag color={fieldValue.color} text={fieldValue.text} />;
};

View File

@ -0,0 +1,47 @@
import { useContext } from 'react';
import { useRecoilState } from 'recoil';
import { ThemeColor } from '@/ui/theme/constants/colors';
import { FieldContext } from '../../contexts/FieldContext';
import { useFieldInitialValue } from '../../hooks/useFieldInitialValue';
import { entityFieldsFamilySelector } from '../../states/selectors/entityFieldsFamilySelector';
import { FieldSelectValue } from '../../types/FieldMetadata';
import { assertFieldMetadata } from '../../types/guards/assertFieldMetadata';
import { isFieldSelect } from '../../types/guards/isFieldSelect';
import { isFieldSelectValue } from '../../types/guards/isFieldSelectValue';
export const useSelectField = () => {
const { entityId, fieldDefinition, hotkeyScope } = useContext(FieldContext);
assertFieldMetadata('ENUM', isFieldSelect, fieldDefinition);
const { fieldName } = fieldDefinition.metadata;
const [fieldValue, setFieldValue] = useRecoilState<FieldSelectValue>(
entityFieldsFamilySelector({
entityId: entityId,
fieldName: fieldName,
}),
);
const fieldSelectValue = isFieldSelectValue(fieldValue)
? fieldValue
: { color: 'green' as ThemeColor, text: '' };
const fieldInitialValue = useFieldInitialValue();
const initialValue = {
color: 'green' as ThemeColor,
text: fieldInitialValue?.isEmpty
? ''
: fieldInitialValue?.value ?? fieldSelectValue?.text ?? '',
};
return {
fieldDefinition,
fieldValue: fieldSelectValue,
initialValue,
setFieldValue,
hotkeyScope,
};
};

View File

@ -1,4 +1,5 @@
import { EntityForSelect } from '@/ui/input/relation-picker/types/EntityForSelect';
import { ThemeColor } from '@/ui/theme/constants/colors';
export type FieldUuidMetadata = {
objectMetadataNameSingular?: string;
@ -80,19 +81,24 @@ export type FieldRelationMetadata = {
relationObjectMetadataNamePlural: string;
};
export type FieldSelectMetadata = {
fieldName: string;
};
export type FieldMetadata =
| FieldBooleanMetadata
| FieldNumberMetadata
| FieldDateTimeMetadata
| FieldTextMetadata
| FieldUuidMetadata
| FieldCurrencyMetadata
| FieldLinkMetadata
| FieldPhoneMetadata
| FieldDateTimeMetadata
| FieldEmailMetadata
| FieldFullNameMetadata
| FieldLinkMetadata
| FieldNumberMetadata
| FieldPhoneMetadata
| FieldProbabilityMetadata
| FieldRelationMetadata
| FieldFullNameMetadata;
| FieldSelectMetadata
| FieldTextMetadata
| FieldUuidMetadata;
export type FieldTextValue = string;
export type FieldUUidValue = string;
@ -109,5 +115,6 @@ export type FieldCurrencyValue = {
};
export type FieldFullNameValue = { firstName: string; lastName: string };
export type FieldProbabilityValue = number;
export type FieldSelectValue = { color: ThemeColor; text: string };
export type FieldRelationValue = EntityForSelect | null;

View File

@ -11,6 +11,7 @@ import {
FieldPhoneMetadata,
FieldProbabilityMetadata,
FieldRelationMetadata,
FieldSelectMetadata,
FieldTextMetadata,
FieldUuidMetadata,
} from '../FieldMetadata';
@ -28,6 +29,8 @@ type AssertFieldMetadataFunction = <
? FieldDateTimeMetadata
: E extends 'EMAIL'
? FieldEmailMetadata
: E extends 'ENUM'
? FieldSelectMetadata
: E extends 'LINK'
? FieldLinkMetadata
: E extends 'NUMBER'

View File

@ -1,14 +0,0 @@
import { z } from 'zod';
import { mainColors, ThemeColor } from '@/ui/theme/constants/colors';
const enumColors = Object.keys(mainColors) as [ThemeColor, ...ThemeColor[]];
const enumValueSchema = z.object({
color: z.enum(enumColors),
text: z.string(),
});
export const isFieldEnumValue = (
fieldValue: unknown,
): fieldValue is z.infer<typeof enumValueSchema> =>
enumValueSchema.safeParse(fieldValue).success;

View File

@ -0,0 +1,6 @@
import { FieldDefinition } from '../FieldDefinition';
import { FieldMetadata, FieldSelectMetadata } from '../FieldMetadata';
export const isFieldSelect = (
field: FieldDefinition<FieldMetadata>,
): field is FieldDefinition<FieldSelectMetadata> => field.type === 'ENUM';

View File

@ -0,0 +1,14 @@
import { z } from 'zod';
import { mainColors, ThemeColor } from '@/ui/theme/constants/colors';
const selectColors = Object.keys(mainColors) as [ThemeColor, ...ThemeColor[]];
const selectValueSchema = z.object({
color: z.enum(selectColors),
text: z.string(),
});
export const isFieldSelectValue = (
fieldValue: unknown,
): fieldValue is z.infer<typeof selectValueSchema> =>
selectValueSchema.safeParse(fieldValue).success;