Skip to content

Commit

Permalink
refactor: improve Settings supported field types validation
Browse files Browse the repository at this point in the history
Related to: #4084, #4295
  • Loading branch information
thaisguigon committed Mar 15, 2024
1 parent 846da39 commit 5f2ab64
Show file tree
Hide file tree
Showing 11 changed files with 97 additions and 40 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { CurrencyCode } from '@/object-record/record-field/types/CurrencyCode';
import { DEFAULT_DATE_VALUE } from '@/settings/data-model/constants/DefaultDateValue';
import { SettingsSupportedFieldType } from '@/settings/data-model/types/SettingsSupportedFieldType';
import {
IconCalendarEvent,
IconCheck,
Expand All @@ -20,11 +21,15 @@ import { FieldMetadataType } from '~/generated-metadata/graphql';

DEFAULT_DATE_VALUE.setFullYear(DEFAULT_DATE_VALUE.getFullYear() + 2);

export const SETTINGS_FIELD_METADATA_TYPES: Partial<
Record<
FieldMetadataType,
{ label: string; Icon: IconComponent; defaultValue?: unknown }
>
export type SettingsFieldTypeConfig = {
label: string;
Icon: IconComponent;
defaultValue?: unknown;
};

export const SETTINGS_FIELD_TYPE_CONFIGS: Record<
SettingsSupportedFieldType,
SettingsFieldTypeConfig
> = {
[FieldMetadataType.Uuid]: {
label: 'Unique ID',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,38 @@
import { SETTINGS_FIELD_METADATA_TYPES } from '@/settings/data-model/constants/SettingsFieldMetadataTypes';
import omit from 'lodash.omit';

import {
SETTINGS_FIELD_TYPE_CONFIGS,
SettingsFieldTypeConfig,
} from '@/settings/data-model/constants/SettingsFieldTypeConfigs';
import { SettingsSupportedFieldType } from '@/settings/data-model/types/SettingsSupportedFieldType';
import { Select, SelectOption } from '@/ui/input/components/Select';
import { FieldMetadataType } from '~/generated-metadata/graphql';

type SettingsDataModelFieldTypeSelectProps = {
className?: string;
disabled?: boolean;
excludedFieldTypes?: FieldMetadataType[];
onChange?: ({ type }: { type: FieldMetadataType }) => void;
value?: FieldMetadataType;
excludedFieldTypes?: SettingsSupportedFieldType[];
onChange?: ({ type }: { type: SettingsSupportedFieldType }) => void;
value?: SettingsSupportedFieldType;
};

export const SettingsDataModelFieldTypeSelect = ({
className,
disabled,
excludedFieldTypes,
excludedFieldTypes = [],
onChange,
value,
}: SettingsDataModelFieldTypeSelectProps) => {
const fieldTypeOptions = Object.entries(SETTINGS_FIELD_METADATA_TYPES)
.filter(([key]) => !excludedFieldTypes?.includes(key as FieldMetadataType))
.map<SelectOption<FieldMetadataType>>(([key, dataTypeConfig]) => ({
Icon: dataTypeConfig.Icon,
label: dataTypeConfig.label,
value: key as FieldMetadataType,
}));
const fieldTypeConfigs = omit(
SETTINGS_FIELD_TYPE_CONFIGS,
excludedFieldTypes,
);
const fieldTypeOptions = Object.entries<SettingsFieldTypeConfig>(
fieldTypeConfigs,
).map<SelectOption<SettingsSupportedFieldType>>(([key, dataTypeConfig]) => ({
Icon: dataTypeConfig.Icon,
label: dataTypeConfig.label,
value: key as SettingsSupportedFieldType,
}));

return (
<Select
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { v4 } from 'uuid';
import { z } from 'zod';

import { CurrencyCode } from '@/object-record/record-field/types/CurrencyCode';
import { SettingsSupportedFieldType } from '@/settings/data-model/types/SettingsSupportedFieldType';
import { themeColorSchema } from '@/ui/theme/utils/themeColorSchema';
import {
FieldMetadataType,
Expand All @@ -17,7 +18,7 @@ type FormValues = {
description?: string;
icon: string;
label: string;
type: FieldMetadataType;
type: SettingsSupportedFieldType;
} & SettingsDataModelFieldSettingsFormValues;

export const fieldMetadataFormDefaultValues: FormValues = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { css, useTheme } from '@emotion/react';
import styled from '@emotion/styled';

import { SETTINGS_FIELD_METADATA_TYPES } from '@/settings/data-model/constants/SettingsFieldMetadataTypes';
import { SettingsSupportedFieldType } from '@/settings/data-model/types/SettingsSupportedFieldType';
import { getSettingsFieldTypeConfig } from '@/settings/data-model/utils/getSettingsFieldTypeConfig';
import { IconTwentyStar } from '@/ui/display/icon/components/IconTwentyStar';
import { IconComponent } from '@/ui/display/icon/types/IconComponent';
import { FieldMetadataType } from '~/generated-metadata/graphql';
Expand All @@ -10,10 +11,10 @@ type SettingsObjectFieldDataTypeProps = {
onClick?: () => void;
Icon?: IconComponent;
label?: string;
value: FieldMetadataType;
value: SettingsSupportedFieldType;
};

const StyledDataType = styled.div<{ value: FieldMetadataType }>`
const StyledDataType = styled.div<{ value: SettingsSupportedFieldType }>`
align-items: center;
border: 1px solid transparent;
border-radius: ${({ theme }) => theme.border.radius.sm};
Expand Down Expand Up @@ -49,11 +50,16 @@ const StyledLabelContainer = styled.div`
export const SettingsObjectFieldDataType = ({
onClick,
value,
Icon = SETTINGS_FIELD_METADATA_TYPES[value]?.Icon ?? IconTwentyStar,
label = SETTINGS_FIELD_METADATA_TYPES[value]?.label,
Icon: IconFromProps,
label: labelFromProps,
}: SettingsObjectFieldDataTypeProps) => {
const theme = useTheme();

const fieldTypeConfig = getSettingsFieldTypeConfig(value);
const Icon: IconComponent =
IconFromProps ?? fieldTypeConfig?.Icon ?? IconTwentyStar;
const label = labelFromProps ?? fieldTypeConfig?.label;

const StyledIcon = styled(Icon)`
flex: 1 0 auto;
`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import styled from '@emotion/styled';
import { useGetRelationMetadata } from '@/object-metadata/hooks/useGetRelationMetadata';
import { FieldMetadataItem } from '@/object-metadata/types/FieldMetadataItem';
import { getObjectSlug } from '@/object-metadata/utils/getObjectSlug';
import { SETTINGS_FIELD_METADATA_TYPES } from '@/settings/data-model/constants/SettingsFieldMetadataTypes';
import { FieldIdentifierType } from '@/settings/data-model/types/FieldIdentifierType';
import { isFieldTypeSupportedInSettings } from '@/settings/data-model/utils/isFieldTypeSupportedInSettings';
import { useIcons } from '@/ui/display/icon/hooks/useIcons';
import { TableCell } from '@/ui/layout/table/components/TableCell';
import { TableRow } from '@/ui/layout/table/components/TableRow';
Expand Down Expand Up @@ -49,10 +49,6 @@ export const SettingsObjectFieldItemTableRow = ({
const Icon = getIcon(fieldMetadataItem.icon);
const navigate = useNavigate();

// TODO: parse with zod and merge types with FieldType (create a subset of FieldType for example)
const fieldDataTypeIsSupported =
fieldMetadataItem.type in SETTINGS_FIELD_METADATA_TYPES;

const getRelationMetadata = useGetRelationMetadata();

const { relationObjectMetadataItem, relationType } =
Expand All @@ -61,7 +57,10 @@ export const SettingsObjectFieldItemTableRow = ({
[fieldMetadataItem, getRelationMetadata],
) ?? {};

if (!fieldDataTypeIsSupported) return null;
const fieldType = fieldMetadataItem.type;
const isFieldTypeSupported = isFieldTypeSupportedInSettings(fieldType);

if (!isFieldTypeSupported) return null;

const RelationIcon = relationType
? RELATION_TYPES[relationType].Icon
Expand Down Expand Up @@ -97,7 +96,7 @@ export const SettingsObjectFieldItemTableRow = ({
)
: undefined
}
value={fieldMetadataItem.type}
value={fieldType}
/>
</TableCell>
<StyledIconTableCell>{ActionIcon}</StyledIconTableCell>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { FieldMetadataType } from '~/generated-metadata/graphql';

export type SettingsSupportedFieldType = Exclude<
FieldMetadataType,
FieldMetadataType.Position
>;
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/getLabelIdentifierFieldMetadataItem';
import { isLabelIdentifierField } from '@/object-metadata/utils/isLabelIdentifierField';
import { SettingsObjectFieldSelectFormValues } from '@/settings/data-model/components/SettingsObjectFieldSelectForm';
import { SETTINGS_FIELD_METADATA_TYPES } from '@/settings/data-model/constants/SettingsFieldMetadataTypes';
import { getSettingsFieldTypeConfig } from '@/settings/data-model/utils/getSettingsFieldTypeConfig';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { isDefined } from '~/utils/isDefined';

Expand Down Expand Up @@ -39,12 +39,16 @@ export const getFieldDefaultPreviewValue = ({

if (!relationLabelIdentifierFieldMetadataItem) return null;

const { type: relationLabelIdentifierFieldType } =
relationLabelIdentifierFieldMetadataItem;
const relationFieldTypeConfig = getSettingsFieldTypeConfig(
relationLabelIdentifierFieldType,
);

const defaultRelationLabelIdentifierFieldValue =
relationLabelIdentifierFieldMetadataItem.type === FieldMetadataType.Text
relationLabelIdentifierFieldType === FieldMetadataType.Text
? relationObjectMetadataItem.labelSingular
: SETTINGS_FIELD_METADATA_TYPES[
relationLabelIdentifierFieldMetadataItem.type
]?.defaultValue;
: relationFieldTypeConfig?.defaultValue;

const defaultRelationRecord = {
[relationLabelIdentifierFieldMetadataItem.name]:
Expand All @@ -54,6 +58,7 @@ export const getFieldDefaultPreviewValue = ({
return defaultRelationRecord;
}

// Other fields
const isLabelIdentifier =
!!fieldMetadataItem.id &&
!!fieldMetadataItem.name &&
Expand All @@ -65,8 +70,9 @@ export const getFieldDefaultPreviewValue = ({
objectMetadataItem,
});

// Other fields
const fieldTypeConfig = getSettingsFieldTypeConfig(fieldMetadataItem.type);

return isLabelIdentifier && fieldMetadataItem.type === FieldMetadataType.Text
? objectMetadataItem.labelSingular
: SETTINGS_FIELD_METADATA_TYPES[fieldMetadataItem.type]?.defaultValue;
: fieldTypeConfig?.defaultValue;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { SETTINGS_FIELD_TYPE_CONFIGS } from '@/settings/data-model/constants/SettingsFieldTypeConfigs';
import { isFieldTypeSupportedInSettings } from '@/settings/data-model/utils/isFieldTypeSupportedInSettings';
import { FieldMetadataType } from '~/generated-metadata/graphql';

export const getSettingsFieldTypeConfig = (fieldType: FieldMetadataType) =>
isFieldTypeSupportedInSettings(fieldType)
? SETTINGS_FIELD_TYPE_CONFIGS[fieldType]
: undefined;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {
SETTINGS_FIELD_TYPE_CONFIGS,
SettingsSupportedFieldTypes,
} from '@/settings/data-model/constants/SettingsFieldTypeConfigs';
import { FieldMetadataType } from '~/generated-metadata/graphql';

export const isFieldTypeSupportedInSettings = (
fieldType: FieldMetadataType,
): fieldType is SettingsSupportedFieldTypes =>
fieldType in SETTINGS_FIELD_TYPE_CONFIGS;
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { SettingsObjectFieldFormSection } from '@/settings/data-model/components
import { SettingsDataModelFieldSettingsFormCard } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldSettingsFormCard';
import { SettingsDataModelFieldTypeSelect } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldTypeSelect';
import { useFieldMetadataForm } from '@/settings/data-model/fields/forms/hooks/useFieldMetadataForm';
import { isFieldTypeSupportedInSettings } from '@/settings/data-model/utils/isFieldTypeSupportedInSettings';
import { AppPath } from '@/types/AppPath';
import { IconArchive, IconSettings } from '@/ui/display/icon';
import { H2Title } from '@/ui/display/typography/components/H2Title';
Expand Down Expand Up @@ -112,11 +113,16 @@ export const SettingsObjectFieldEdit = () => {
(optionA, optionB) => optionA.position - optionB.position,
);

const fieldType = activeMetadataField.type;
const isFieldTypeSupported = isFieldTypeSupportedInSettings(fieldType);

if (!isFieldTypeSupported) return;

initForm({
icon: activeMetadataField.icon ?? undefined,
label: activeMetadataField.label,
description: activeMetadataField.description ?? undefined,
type: activeMetadataField.type,
type: fieldType,
...(currencyDefaultValue ? { currency: currencyDefaultValue } : {}),
relation: {
field: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { SettingsObjectFieldFormSection } from '@/settings/data-model/components
import { SettingsDataModelFieldSettingsFormCard } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldSettingsFormCard';
import { SettingsDataModelFieldTypeSelect } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldTypeSelect';
import { useFieldMetadataForm } from '@/settings/data-model/fields/forms/hooks/useFieldMetadataForm';
import { SettingsSupportedFieldType } from '@/settings/data-model/types/SettingsSupportedFieldType';
import { AppPath } from '@/types/AppPath';
import { IconSettings } from '@/ui/display/icon';
import { H2Title } from '@/ui/display/typography/components/H2Title';
Expand Down Expand Up @@ -259,7 +260,7 @@ export const SettingsObjectNewFieldStep2 = () => {
}
};

const excludedFieldTypes = [
const excludedFieldTypes: SettingsSupportedFieldType[] = [
FieldMetadataType.Currency,
FieldMetadataType.Email,
FieldMetadataType.FullName,
Expand Down

0 comments on commit 5f2ab64

Please sign in to comment.