@ -1,12 +1,28 @@
|
||||
import { ObjectFieldDataType } from '@/settings/data-model/types/ObjectFieldDataType';
|
||||
import { Field } from '~/generated/graphql';
|
||||
|
||||
import { formatMetadataFieldInput } from '../utils/formatMetadataFieldInput';
|
||||
|
||||
import { useCreateOneMetadataField } from './useCreateOneMetadataField';
|
||||
import { useDeleteOneMetadataField } from './useDeleteOneMetadataField';
|
||||
import { useUpdateOneMetadataField } from './useUpdateOneMetadataField';
|
||||
|
||||
export const useFieldMetadata = () => {
|
||||
const { createOneMetadataField } = useCreateOneMetadataField();
|
||||
const { updateOneMetadataField } = useUpdateOneMetadataField();
|
||||
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) =>
|
||||
updateOneMetadataField({
|
||||
fieldIdToUpdate: metadataField.id,
|
||||
@ -24,6 +40,7 @@ export const useFieldMetadata = () => {
|
||||
|
||||
return {
|
||||
activateField,
|
||||
createField,
|
||||
disableField,
|
||||
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 { validateMetadataLabel } from '@/metadata/utils/validateMetadataLabel';
|
||||
import { H2Title } from '@/ui/display/typography/components/H2Title';
|
||||
import { IconPicker } from '@/ui/input/components/IconPicker';
|
||||
import { TextArea } from '@/ui/input/components/TextArea';
|
||||
@ -13,8 +14,8 @@ type SettingsObjectFieldFormSectionProps = {
|
||||
iconKey?: string;
|
||||
onChange?: (
|
||||
formValues: Partial<{
|
||||
iconKey: string;
|
||||
name: string;
|
||||
icon: string;
|
||||
label: string;
|
||||
description: string;
|
||||
}>,
|
||||
) => void;
|
||||
@ -42,13 +43,17 @@ export const SettingsObjectFieldFormSection = ({
|
||||
<StyledInputsContainer>
|
||||
<IconPicker
|
||||
selectedIconKey={iconKey}
|
||||
onChange={(value) => onChange?.({ iconKey: value.iconKey })}
|
||||
onChange={(value) => onChange?.({ icon: value.iconKey })}
|
||||
variant="primary"
|
||||
/>
|
||||
<TextInput
|
||||
placeholder="Employees"
|
||||
value={name}
|
||||
onChange={(value) => onChange?.({ name: value })}
|
||||
onChange={(value) => {
|
||||
if (!value || validateMetadataLabel(value)) {
|
||||
onChange?.({ label: value });
|
||||
}
|
||||
}}
|
||||
disabled={disabled}
|
||||
fullWidth
|
||||
/>
|
||||
|
||||
@ -10,6 +10,9 @@ type SettingsObjectFieldTypeSelectSectionProps = {
|
||||
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 = ({
|
||||
type,
|
||||
onChange,
|
||||
@ -23,10 +26,12 @@ export const SettingsObjectFieldTypeSelectSection = ({
|
||||
dropdownScopeId="object-field-type-select"
|
||||
value={type}
|
||||
onChange={onChange}
|
||||
options={Object.entries(dataTypes).map(([key, dataType]) => ({
|
||||
value: key as ObjectFieldDataType,
|
||||
...dataType,
|
||||
}))}
|
||||
options={Object.entries(dataTypesWithoutRelation).map(
|
||||
([key, dataType]) => ({
|
||||
value: key as ObjectFieldDataType,
|
||||
...dataType,
|
||||
}),
|
||||
)}
|
||||
/>
|
||||
</Section>
|
||||
);
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
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 { TextArea } from '@/ui/input/components/TextArea';
|
||||
import { TextInput } from '@/ui/input/components/TextInput';
|
||||
@ -45,7 +45,7 @@ export const SettingsObjectFormSection = ({
|
||||
placeholder="Investor"
|
||||
value={singularName}
|
||||
onChange={(value) => {
|
||||
if (!value || validateMetadataObjectLabel(value)) {
|
||||
if (!value || validateMetadataLabel(value)) {
|
||||
onChange?.({ labelSingular: value });
|
||||
}
|
||||
}}
|
||||
@ -57,7 +57,7 @@ export const SettingsObjectFormSection = ({
|
||||
placeholder="Investors"
|
||||
value={pluralName}
|
||||
onChange={(value) => {
|
||||
if (!value || validateMetadataObjectLabel(value)) {
|
||||
if (!value || validateMetadataLabel(value)) {
|
||||
onChange?.({ labelPlural: value });
|
||||
}
|
||||
}}
|
||||
|
||||
@ -3,9 +3,7 @@ import {
|
||||
IconLink,
|
||||
IconNumbers,
|
||||
IconPlug,
|
||||
IconSocial,
|
||||
IconTextSize,
|
||||
IconUserCircle,
|
||||
} from '@/ui/display/icon';
|
||||
import { IconComponent } from '@/ui/display/icon/types/IconComponent';
|
||||
|
||||
@ -17,9 +15,7 @@ export const dataTypes: Record<
|
||||
> = {
|
||||
number: { label: 'Number', Icon: IconNumbers },
|
||||
text: { label: 'Text', Icon: IconTextSize },
|
||||
link: { label: 'Link', Icon: IconLink },
|
||||
teammate: { label: 'Team member', Icon: IconUserCircle },
|
||||
url: { label: 'Link', Icon: IconLink },
|
||||
boolean: { label: 'True/False', Icon: IconCheck },
|
||||
relation: { label: 'Relation', Icon: IconPlug },
|
||||
social: { label: 'Social', Icon: IconSocial },
|
||||
};
|
||||
|
||||
@ -1,42 +1,4 @@
|
||||
import {
|
||||
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,
|
||||
},
|
||||
];
|
||||
import { IconMouse2 } from '@/ui/display/icon';
|
||||
|
||||
export const standardObjects = [
|
||||
{
|
||||
@ -52,92 +14,3 @@ export const standardObjects = [
|
||||
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 =
|
||||
| 'boolean'
|
||||
| 'link'
|
||||
| 'number'
|
||||
| 'relation'
|
||||
| 'social'
|
||||
| 'teammate'
|
||||
| 'text';
|
||||
| 'text'
|
||||
| 'url';
|
||||
|
||||
@ -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,
|
||||
IconArchive,
|
||||
IconArchiveOff,
|
||||
IconArrowBack,
|
||||
IconArrowDown,
|
||||
IconArrowLeft,
|
||||
IconArrowRight,
|
||||
@ -17,7 +16,6 @@ export {
|
||||
IconBrandGithub,
|
||||
IconBrandGoogle,
|
||||
IconBrandLinkedin,
|
||||
IconBrandTwitter,
|
||||
IconBrandX,
|
||||
IconBriefcase,
|
||||
IconBuildingSkyscraper,
|
||||
@ -31,11 +29,9 @@ export {
|
||||
IconChevronsRight,
|
||||
IconChevronUp,
|
||||
IconCircleDot,
|
||||
IconCirclePlus,
|
||||
IconColorSwatch,
|
||||
IconMessageCircle as IconComment,
|
||||
IconCopy,
|
||||
IconCross,
|
||||
IconCurrencyDollar,
|
||||
IconDatabase,
|
||||
IconDotsVertical,
|
||||
@ -45,15 +41,11 @@ export {
|
||||
IconFileImport,
|
||||
IconFileUpload,
|
||||
IconForbid,
|
||||
IconFreeRights,
|
||||
IconGraph,
|
||||
IconGripVertical,
|
||||
IconHeadphones,
|
||||
IconHeart,
|
||||
IconHeartOff,
|
||||
IconHelpCircle,
|
||||
IconHierarchy2,
|
||||
IconInbox,
|
||||
IconLayoutKanban,
|
||||
IconLayoutSidebarLeftCollapse,
|
||||
IconLayoutSidebarRightCollapse,
|
||||
@ -62,7 +54,6 @@ export {
|
||||
IconLinkOff,
|
||||
IconList,
|
||||
IconLogout,
|
||||
IconLuggage,
|
||||
IconMail,
|
||||
IconMap,
|
||||
IconMinus,
|
||||
@ -72,7 +63,6 @@ export {
|
||||
IconNumbers,
|
||||
IconPencil,
|
||||
IconPhone,
|
||||
IconPlane,
|
||||
IconPlug,
|
||||
IconPlus,
|
||||
IconProgressCheck,
|
||||
@ -80,7 +70,6 @@ export {
|
||||
IconRobot,
|
||||
IconSearch,
|
||||
IconSettings,
|
||||
IconSocial,
|
||||
IconTag,
|
||||
IconTarget,
|
||||
IconTargetArrow,
|
||||
|
||||
Reference in New Issue
Block a user