@ -1,12 +1,28 @@
|
|||||||
|
import { ObjectFieldDataType } from '@/settings/data-model/types/ObjectFieldDataType';
|
||||||
import { Field } from '~/generated/graphql';
|
import { Field } from '~/generated/graphql';
|
||||||
|
|
||||||
|
import { formatMetadataFieldInput } from '../utils/formatMetadataFieldInput';
|
||||||
|
|
||||||
|
import { useCreateOneMetadataField } from './useCreateOneMetadataField';
|
||||||
import { useDeleteOneMetadataField } from './useDeleteOneMetadataField';
|
import { useDeleteOneMetadataField } from './useDeleteOneMetadataField';
|
||||||
import { useUpdateOneMetadataField } from './useUpdateOneMetadataField';
|
import { useUpdateOneMetadataField } from './useUpdateOneMetadataField';
|
||||||
|
|
||||||
export const useFieldMetadata = () => {
|
export const useFieldMetadata = () => {
|
||||||
|
const { createOneMetadataField } = useCreateOneMetadataField();
|
||||||
const { updateOneMetadataField } = useUpdateOneMetadataField();
|
const { updateOneMetadataField } = useUpdateOneMetadataField();
|
||||||
const { deleteOneMetadataField } = useDeleteOneMetadataField();
|
const { deleteOneMetadataField } = useDeleteOneMetadataField();
|
||||||
|
|
||||||
|
const createField = (
|
||||||
|
input: Pick<Field, 'label' | 'icon' | 'description'> & {
|
||||||
|
objectId: string;
|
||||||
|
type: ObjectFieldDataType;
|
||||||
|
},
|
||||||
|
) =>
|
||||||
|
createOneMetadataField({
|
||||||
|
...formatMetadataFieldInput(input),
|
||||||
|
objectId: input.objectId,
|
||||||
|
});
|
||||||
|
|
||||||
const activateField = (metadataField: Field) =>
|
const activateField = (metadataField: Field) =>
|
||||||
updateOneMetadataField({
|
updateOneMetadataField({
|
||||||
fieldIdToUpdate: metadataField.id,
|
fieldIdToUpdate: metadataField.id,
|
||||||
@ -24,6 +40,7 @@ export const useFieldMetadata = () => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
activateField,
|
activateField,
|
||||||
|
createField,
|
||||||
disableField,
|
disableField,
|
||||||
eraseField,
|
eraseField,
|
||||||
};
|
};
|
||||||
|
|||||||
17
front/src/modules/metadata/utils/formatMetadataFieldInput.ts
Normal file
17
front/src/modules/metadata/utils/formatMetadataFieldInput.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import toCamelCase from 'lodash.camelcase';
|
||||||
|
import upperFirst from 'lodash.upperfirst';
|
||||||
|
|
||||||
|
import { ObjectFieldDataType } from '@/settings/data-model/types/ObjectFieldDataType';
|
||||||
|
import { Field } from '~/generated-metadata/graphql';
|
||||||
|
|
||||||
|
export const formatMetadataFieldInput = (
|
||||||
|
input: Pick<Field, 'label' | 'icon' | 'description'> & {
|
||||||
|
type: ObjectFieldDataType;
|
||||||
|
},
|
||||||
|
) => ({
|
||||||
|
description: input.description?.trim() ?? null,
|
||||||
|
icon: input.icon,
|
||||||
|
label: input.label.trim(),
|
||||||
|
name: upperFirst(toCamelCase(input.label.trim())),
|
||||||
|
type: input.type,
|
||||||
|
});
|
||||||
@ -0,0 +1,4 @@
|
|||||||
|
const metadataLabelValidationPattern = /^[a-zA-Z][a-zA-Z0-9 ]*$/;
|
||||||
|
|
||||||
|
export const validateMetadataLabel = (value: string) =>
|
||||||
|
!!value.match(metadataLabelValidationPattern);
|
||||||
@ -1,4 +0,0 @@
|
|||||||
const metadataObjectLabelValidationPattern = /^[a-zA-Z][a-zA-Z0-9 ]*$/;
|
|
||||||
|
|
||||||
export const validateMetadataObjectLabel = (value: string) =>
|
|
||||||
!!value.match(metadataObjectLabelValidationPattern);
|
|
||||||
@ -1,5 +1,6 @@
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
import { validateMetadataLabel } from '@/metadata/utils/validateMetadataLabel';
|
||||||
import { H2Title } from '@/ui/display/typography/components/H2Title';
|
import { H2Title } from '@/ui/display/typography/components/H2Title';
|
||||||
import { IconPicker } from '@/ui/input/components/IconPicker';
|
import { IconPicker } from '@/ui/input/components/IconPicker';
|
||||||
import { TextArea } from '@/ui/input/components/TextArea';
|
import { TextArea } from '@/ui/input/components/TextArea';
|
||||||
@ -13,8 +14,8 @@ type SettingsObjectFieldFormSectionProps = {
|
|||||||
iconKey?: string;
|
iconKey?: string;
|
||||||
onChange?: (
|
onChange?: (
|
||||||
formValues: Partial<{
|
formValues: Partial<{
|
||||||
iconKey: string;
|
icon: string;
|
||||||
name: string;
|
label: string;
|
||||||
description: string;
|
description: string;
|
||||||
}>,
|
}>,
|
||||||
) => void;
|
) => void;
|
||||||
@ -42,13 +43,17 @@ export const SettingsObjectFieldFormSection = ({
|
|||||||
<StyledInputsContainer>
|
<StyledInputsContainer>
|
||||||
<IconPicker
|
<IconPicker
|
||||||
selectedIconKey={iconKey}
|
selectedIconKey={iconKey}
|
||||||
onChange={(value) => onChange?.({ iconKey: value.iconKey })}
|
onChange={(value) => onChange?.({ icon: value.iconKey })}
|
||||||
variant="primary"
|
variant="primary"
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
placeholder="Employees"
|
placeholder="Employees"
|
||||||
value={name}
|
value={name}
|
||||||
onChange={(value) => onChange?.({ name: value })}
|
onChange={(value) => {
|
||||||
|
if (!value || validateMetadataLabel(value)) {
|
||||||
|
onChange?.({ label: value });
|
||||||
|
}
|
||||||
|
}}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -10,6 +10,9 @@ type SettingsObjectFieldTypeSelectSectionProps = {
|
|||||||
onChange: (value: ObjectFieldDataType) => void;
|
onChange: (value: ObjectFieldDataType) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO: remove "relation" type for now, add it back when the backend is ready.
|
||||||
|
const { relation: _, ...dataTypesWithoutRelation } = dataTypes;
|
||||||
|
|
||||||
export const SettingsObjectFieldTypeSelectSection = ({
|
export const SettingsObjectFieldTypeSelectSection = ({
|
||||||
type,
|
type,
|
||||||
onChange,
|
onChange,
|
||||||
@ -23,10 +26,12 @@ export const SettingsObjectFieldTypeSelectSection = ({
|
|||||||
dropdownScopeId="object-field-type-select"
|
dropdownScopeId="object-field-type-select"
|
||||||
value={type}
|
value={type}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
options={Object.entries(dataTypes).map(([key, dataType]) => ({
|
options={Object.entries(dataTypesWithoutRelation).map(
|
||||||
value: key as ObjectFieldDataType,
|
([key, dataType]) => ({
|
||||||
...dataType,
|
value: key as ObjectFieldDataType,
|
||||||
}))}
|
...dataType,
|
||||||
|
}),
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
</Section>
|
</Section>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
import { validateMetadataObjectLabel } from '@/metadata/utils/validateMetadataObjectLabel';
|
import { validateMetadataLabel } from '@/metadata/utils/validateMetadataLabel';
|
||||||
import { H2Title } from '@/ui/display/typography/components/H2Title';
|
import { H2Title } from '@/ui/display/typography/components/H2Title';
|
||||||
import { TextArea } from '@/ui/input/components/TextArea';
|
import { TextArea } from '@/ui/input/components/TextArea';
|
||||||
import { TextInput } from '@/ui/input/components/TextInput';
|
import { TextInput } from '@/ui/input/components/TextInput';
|
||||||
@ -45,7 +45,7 @@ export const SettingsObjectFormSection = ({
|
|||||||
placeholder="Investor"
|
placeholder="Investor"
|
||||||
value={singularName}
|
value={singularName}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
if (!value || validateMetadataObjectLabel(value)) {
|
if (!value || validateMetadataLabel(value)) {
|
||||||
onChange?.({ labelSingular: value });
|
onChange?.({ labelSingular: value });
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@ -57,7 +57,7 @@ export const SettingsObjectFormSection = ({
|
|||||||
placeholder="Investors"
|
placeholder="Investors"
|
||||||
value={pluralName}
|
value={pluralName}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
if (!value || validateMetadataObjectLabel(value)) {
|
if (!value || validateMetadataLabel(value)) {
|
||||||
onChange?.({ labelPlural: value });
|
onChange?.({ labelPlural: value });
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
|||||||
@ -3,9 +3,7 @@ import {
|
|||||||
IconLink,
|
IconLink,
|
||||||
IconNumbers,
|
IconNumbers,
|
||||||
IconPlug,
|
IconPlug,
|
||||||
IconSocial,
|
|
||||||
IconTextSize,
|
IconTextSize,
|
||||||
IconUserCircle,
|
|
||||||
} from '@/ui/display/icon';
|
} from '@/ui/display/icon';
|
||||||
import { IconComponent } from '@/ui/display/icon/types/IconComponent';
|
import { IconComponent } from '@/ui/display/icon/types/IconComponent';
|
||||||
|
|
||||||
@ -17,9 +15,7 @@ export const dataTypes: Record<
|
|||||||
> = {
|
> = {
|
||||||
number: { label: 'Number', Icon: IconNumbers },
|
number: { label: 'Number', Icon: IconNumbers },
|
||||||
text: { label: 'Text', Icon: IconTextSize },
|
text: { label: 'Text', Icon: IconTextSize },
|
||||||
link: { label: 'Link', Icon: IconLink },
|
url: { label: 'Link', Icon: IconLink },
|
||||||
teammate: { label: 'Team member', Icon: IconUserCircle },
|
|
||||||
boolean: { label: 'True/False', Icon: IconCheck },
|
boolean: { label: 'True/False', Icon: IconCheck },
|
||||||
relation: { label: 'Relation', Icon: IconPlug },
|
relation: { label: 'Relation', Icon: IconPlug },
|
||||||
social: { label: 'Social', Icon: IconSocial },
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,42 +1,4 @@
|
|||||||
import {
|
import { IconMouse2 } from '@/ui/display/icon';
|
||||||
IconBrandLinkedin,
|
|
||||||
IconBrandTwitter,
|
|
||||||
IconBuildingSkyscraper,
|
|
||||||
IconCurrencyDollar,
|
|
||||||
IconFreeRights,
|
|
||||||
IconGraph,
|
|
||||||
IconHeadphones,
|
|
||||||
IconLink,
|
|
||||||
IconLuggage,
|
|
||||||
IconMouse2,
|
|
||||||
IconPlane,
|
|
||||||
IconTarget,
|
|
||||||
IconUser,
|
|
||||||
IconUserCircle,
|
|
||||||
IconUsers,
|
|
||||||
} from '@/ui/display/icon';
|
|
||||||
|
|
||||||
import { ObjectFieldItem } from '../types/ObjectFieldItem';
|
|
||||||
|
|
||||||
export const activeObjectItems = [
|
|
||||||
{
|
|
||||||
name: 'Companies',
|
|
||||||
singularName: 'Company',
|
|
||||||
Icon: IconBuildingSkyscraper,
|
|
||||||
type: 'standard',
|
|
||||||
fields: 23,
|
|
||||||
instances: 165,
|
|
||||||
description: 'Lorem ipsum',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'People',
|
|
||||||
singularName: 'Person',
|
|
||||||
Icon: IconUser,
|
|
||||||
type: 'standard',
|
|
||||||
fields: 16,
|
|
||||||
instances: 462,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const standardObjects = [
|
export const standardObjects = [
|
||||||
{
|
{
|
||||||
@ -52,92 +14,3 @@ export const standardObjects = [
|
|||||||
description: 'Individuals who interact with your website',
|
description: 'Individuals who interact with your website',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export const disabledObjectItems = [
|
|
||||||
{
|
|
||||||
name: 'Travels',
|
|
||||||
Icon: IconLuggage,
|
|
||||||
type: 'custom',
|
|
||||||
fields: 23,
|
|
||||||
instances: 165,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Flights',
|
|
||||||
Icon: IconPlane,
|
|
||||||
type: 'custom',
|
|
||||||
fields: 23,
|
|
||||||
instances: 165,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const activeFieldItems: ObjectFieldItem[] = [
|
|
||||||
{
|
|
||||||
name: 'People',
|
|
||||||
Icon: IconUser,
|
|
||||||
type: 'standard',
|
|
||||||
dataType: 'relation',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'URL',
|
|
||||||
Icon: IconLink,
|
|
||||||
type: 'standard',
|
|
||||||
dataType: 'text',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Linkedin',
|
|
||||||
Icon: IconBrandLinkedin,
|
|
||||||
type: 'standard',
|
|
||||||
dataType: 'social',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Account Owner',
|
|
||||||
Icon: IconUserCircle,
|
|
||||||
type: 'standard',
|
|
||||||
dataType: 'teammate',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Employees',
|
|
||||||
Icon: IconUsers,
|
|
||||||
type: 'custom',
|
|
||||||
dataType: 'number',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const disabledFieldItems: ObjectFieldItem[] = [
|
|
||||||
{
|
|
||||||
name: 'ICP',
|
|
||||||
Icon: IconTarget,
|
|
||||||
type: 'standard',
|
|
||||||
dataType: 'boolean',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Twitter',
|
|
||||||
Icon: IconBrandTwitter,
|
|
||||||
type: 'standard',
|
|
||||||
dataType: 'social',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Annual revenue',
|
|
||||||
Icon: IconCurrencyDollar,
|
|
||||||
type: 'standard',
|
|
||||||
dataType: 'number',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Is public',
|
|
||||||
Icon: IconGraph,
|
|
||||||
type: 'standard',
|
|
||||||
dataType: 'boolean',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Free tier?',
|
|
||||||
Icon: IconFreeRights,
|
|
||||||
type: 'custom',
|
|
||||||
dataType: 'boolean',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'Priority support',
|
|
||||||
Icon: IconHeadphones,
|
|
||||||
type: 'custom',
|
|
||||||
dataType: 'boolean',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|||||||
@ -1,8 +1,6 @@
|
|||||||
export type ObjectFieldDataType =
|
export type ObjectFieldDataType =
|
||||||
| 'boolean'
|
| 'boolean'
|
||||||
| 'link'
|
|
||||||
| 'number'
|
| 'number'
|
||||||
| 'relation'
|
| 'relation'
|
||||||
| 'social'
|
| 'text'
|
||||||
| 'teammate'
|
| 'url';
|
||||||
| 'text';
|
|
||||||
|
|||||||
@ -1,10 +0,0 @@
|
|||||||
import { IconComponent } from '@/ui/display/icon/types/IconComponent';
|
|
||||||
|
|
||||||
import { ObjectFieldDataType } from './ObjectFieldDataType';
|
|
||||||
|
|
||||||
export type ObjectFieldItem = {
|
|
||||||
name: string;
|
|
||||||
Icon: IconComponent;
|
|
||||||
type: 'standard' | 'custom';
|
|
||||||
dataType: ObjectFieldDataType;
|
|
||||||
};
|
|
||||||
@ -5,7 +5,6 @@ export {
|
|||||||
IconAlertTriangle,
|
IconAlertTriangle,
|
||||||
IconArchive,
|
IconArchive,
|
||||||
IconArchiveOff,
|
IconArchiveOff,
|
||||||
IconArrowBack,
|
|
||||||
IconArrowDown,
|
IconArrowDown,
|
||||||
IconArrowLeft,
|
IconArrowLeft,
|
||||||
IconArrowRight,
|
IconArrowRight,
|
||||||
@ -17,7 +16,6 @@ export {
|
|||||||
IconBrandGithub,
|
IconBrandGithub,
|
||||||
IconBrandGoogle,
|
IconBrandGoogle,
|
||||||
IconBrandLinkedin,
|
IconBrandLinkedin,
|
||||||
IconBrandTwitter,
|
|
||||||
IconBrandX,
|
IconBrandX,
|
||||||
IconBriefcase,
|
IconBriefcase,
|
||||||
IconBuildingSkyscraper,
|
IconBuildingSkyscraper,
|
||||||
@ -31,11 +29,9 @@ export {
|
|||||||
IconChevronsRight,
|
IconChevronsRight,
|
||||||
IconChevronUp,
|
IconChevronUp,
|
||||||
IconCircleDot,
|
IconCircleDot,
|
||||||
IconCirclePlus,
|
|
||||||
IconColorSwatch,
|
IconColorSwatch,
|
||||||
IconMessageCircle as IconComment,
|
IconMessageCircle as IconComment,
|
||||||
IconCopy,
|
IconCopy,
|
||||||
IconCross,
|
|
||||||
IconCurrencyDollar,
|
IconCurrencyDollar,
|
||||||
IconDatabase,
|
IconDatabase,
|
||||||
IconDotsVertical,
|
IconDotsVertical,
|
||||||
@ -45,15 +41,11 @@ export {
|
|||||||
IconFileImport,
|
IconFileImport,
|
||||||
IconFileUpload,
|
IconFileUpload,
|
||||||
IconForbid,
|
IconForbid,
|
||||||
IconFreeRights,
|
|
||||||
IconGraph,
|
|
||||||
IconGripVertical,
|
IconGripVertical,
|
||||||
IconHeadphones,
|
|
||||||
IconHeart,
|
IconHeart,
|
||||||
IconHeartOff,
|
IconHeartOff,
|
||||||
IconHelpCircle,
|
IconHelpCircle,
|
||||||
IconHierarchy2,
|
IconHierarchy2,
|
||||||
IconInbox,
|
|
||||||
IconLayoutKanban,
|
IconLayoutKanban,
|
||||||
IconLayoutSidebarLeftCollapse,
|
IconLayoutSidebarLeftCollapse,
|
||||||
IconLayoutSidebarRightCollapse,
|
IconLayoutSidebarRightCollapse,
|
||||||
@ -62,7 +54,6 @@ export {
|
|||||||
IconLinkOff,
|
IconLinkOff,
|
||||||
IconList,
|
IconList,
|
||||||
IconLogout,
|
IconLogout,
|
||||||
IconLuggage,
|
|
||||||
IconMail,
|
IconMail,
|
||||||
IconMap,
|
IconMap,
|
||||||
IconMinus,
|
IconMinus,
|
||||||
@ -72,7 +63,6 @@ export {
|
|||||||
IconNumbers,
|
IconNumbers,
|
||||||
IconPencil,
|
IconPencil,
|
||||||
IconPhone,
|
IconPhone,
|
||||||
IconPlane,
|
|
||||||
IconPlug,
|
IconPlug,
|
||||||
IconPlus,
|
IconPlus,
|
||||||
IconProgressCheck,
|
IconProgressCheck,
|
||||||
@ -80,7 +70,6 @@ export {
|
|||||||
IconRobot,
|
IconRobot,
|
||||||
IconSearch,
|
IconSearch,
|
||||||
IconSettings,
|
IconSettings,
|
||||||
IconSocial,
|
|
||||||
IconTag,
|
IconTag,
|
||||||
IconTarget,
|
IconTarget,
|
||||||
IconTargetArrow,
|
IconTargetArrow,
|
||||||
|
|||||||
@ -26,10 +26,10 @@ export const SettingsNewObject = () => {
|
|||||||
|
|
||||||
const [customFormValues, setCustomFormValues] = useState<{
|
const [customFormValues, setCustomFormValues] = useState<{
|
||||||
description?: string;
|
description?: string;
|
||||||
icon?: string;
|
icon: string;
|
||||||
labelPlural: string;
|
labelPlural: string;
|
||||||
labelSingular: string;
|
labelSingular: string;
|
||||||
}>({ labelPlural: '', labelSingular: '' });
|
}>({ icon: 'IconPigMoney', labelPlural: '', labelSingular: '' });
|
||||||
|
|
||||||
const canSave =
|
const canSave =
|
||||||
selectedObjectType === 'Custom' &&
|
selectedObjectType === 'Custom' &&
|
||||||
|
|||||||
@ -75,7 +75,7 @@ export const SettingsObjectDetail = () => {
|
|||||||
<Section>
|
<Section>
|
||||||
<H2Title
|
<H2Title
|
||||||
title="Fields"
|
title="Fields"
|
||||||
description={`Customise the fields available in the ${activeObject?.nameSingular} views and their display order in the ${activeObject?.nameSingular} detail view and menus.`}
|
description={`Customise the fields available in the ${activeObject?.labelSingular} views and their display order in the ${activeObject?.labelSingular} detail view and menus.`}
|
||||||
/>
|
/>
|
||||||
<Table>
|
<Table>
|
||||||
<StyledObjectFieldTableRow>
|
<StyledObjectFieldTableRow>
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { useNavigate, useParams } from 'react-router-dom';
|
import { useNavigate, useParams } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { useFieldMetadata } from '@/metadata/hooks/useFieldMetadata';
|
||||||
|
import { useObjectMetadata } from '@/metadata/hooks/useObjectMetadata';
|
||||||
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
|
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
|
||||||
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
|
import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer';
|
||||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||||
import { SettingsObjectFieldFormSection } from '@/settings/data-model/components/SettingsObjectFieldFormSection';
|
import { SettingsObjectFieldFormSection } from '@/settings/data-model/components/SettingsObjectFieldFormSection';
|
||||||
import { SettingsObjectFieldTypeSelectSection } from '@/settings/data-model/components/SettingsObjectFieldTypeSelectSection';
|
import { SettingsObjectFieldTypeSelectSection } from '@/settings/data-model/components/SettingsObjectFieldTypeSelectSection';
|
||||||
import { activeObjectItems } from '@/settings/data-model/constants/mockObjects';
|
|
||||||
import { ObjectFieldDataType } from '@/settings/data-model/types/ObjectFieldDataType';
|
import { ObjectFieldDataType } from '@/settings/data-model/types/ObjectFieldDataType';
|
||||||
import { AppPath } from '@/types/AppPath';
|
import { AppPath } from '@/types/AppPath';
|
||||||
import { IconSettings } from '@/ui/display/icon';
|
import { IconSettings } from '@/ui/display/icon';
|
||||||
@ -16,23 +17,30 @@ import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb';
|
|||||||
export const SettingsObjectNewFieldStep2 = () => {
|
export const SettingsObjectNewFieldStep2 = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { objectSlug = '' } = useParams();
|
const { objectSlug = '' } = useParams();
|
||||||
const activeObject = activeObjectItems.find(
|
const { findActiveObjectBySlug } = useObjectMetadata();
|
||||||
(activeObject) => activeObject.name.toLowerCase() === objectSlug,
|
const activeObject = findActiveObjectBySlug(objectSlug);
|
||||||
);
|
const { createField } = useFieldMetadata();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!activeObject) navigate(AppPath.NotFound);
|
if (!activeObject) navigate(AppPath.NotFound);
|
||||||
}, [activeObject, navigate]);
|
}, [activeObject, navigate]);
|
||||||
|
|
||||||
const [formValues, setFormValues] = useState<
|
const [formValues, setFormValues] = useState<{
|
||||||
Partial<{
|
description?: string;
|
||||||
iconKey: string;
|
icon: string;
|
||||||
name: string;
|
label: string;
|
||||||
description: string;
|
type: ObjectFieldDataType;
|
||||||
}> & { type: ObjectFieldDataType }
|
}>({ icon: 'IconUsers', label: '', type: 'number' });
|
||||||
>({ type: 'number' });
|
|
||||||
|
|
||||||
const canSave = !!formValues.name;
|
const canSave = !!formValues.label;
|
||||||
|
|
||||||
|
const handleSave = async () => {
|
||||||
|
if (!activeObject) return;
|
||||||
|
|
||||||
|
await createField({ ...formValues, objectId: activeObject.id });
|
||||||
|
|
||||||
|
navigate(`/settings/objects/${objectSlug}`);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
|
<SubMenuTopBarContainer Icon={IconSettings} title="Settings">
|
||||||
@ -42,7 +50,7 @@ export const SettingsObjectNewFieldStep2 = () => {
|
|||||||
links={[
|
links={[
|
||||||
{ children: 'Objects', href: '/settings/objects' },
|
{ children: 'Objects', href: '/settings/objects' },
|
||||||
{
|
{
|
||||||
children: activeObject?.name ?? '',
|
children: activeObject?.labelPlural ?? '',
|
||||||
href: `/settings/objects/${objectSlug}`,
|
href: `/settings/objects/${objectSlug}`,
|
||||||
},
|
},
|
||||||
{ children: 'New Field' },
|
{ children: 'New Field' },
|
||||||
@ -51,14 +59,14 @@ export const SettingsObjectNewFieldStep2 = () => {
|
|||||||
<SaveAndCancelButtons
|
<SaveAndCancelButtons
|
||||||
isSaveDisabled={!canSave}
|
isSaveDisabled={!canSave}
|
||||||
onCancel={() => {
|
onCancel={() => {
|
||||||
navigate('/settings/objects');
|
navigate(`/settings/objects/${objectSlug}`);
|
||||||
}}
|
}}
|
||||||
onSave={() => undefined}
|
onSave={handleSave}
|
||||||
/>
|
/>
|
||||||
</SettingsHeaderContainer>
|
</SettingsHeaderContainer>
|
||||||
<SettingsObjectFieldFormSection
|
<SettingsObjectFieldFormSection
|
||||||
iconKey={formValues.iconKey}
|
iconKey={formValues.icon}
|
||||||
name={formValues.name}
|
name={formValues.label}
|
||||||
description={formValues.description}
|
description={formValues.description}
|
||||||
onChange={(values) =>
|
onChange={(values) =>
|
||||||
setFormValues((previousValues) => ({
|
setFormValues((previousValues) => ({
|
||||||
|
|||||||
Reference in New Issue
Block a user