From 2b1945a3e1967aef1c2b1b9445152e7a187e4141 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tha=C3=AFs?= Date: Thu, 26 Oct 2023 11:04:16 +0200 Subject: [PATCH] feat: create custom object and update edited object names (#2220) Closes #2155, Closes #2153 --- front/package.json | 6 +++ front/src/generated-metadata/graphql.ts | 2 + .../metadata/hooks/useObjectMetadata.ts | 36 ++++++++++++---- .../hooks/useUpdateOneMetadataObject.ts | 8 +++- .../utils/formatMetadataObjectInput.ts | 18 ++++++++ .../modules/metadata/utils/getObjectSlug.ts | 7 ++++ .../utils/validateMetadataObjectLabel.ts | 4 ++ .../components/SettingsObjectFormSection.tsx | 13 +++++- front/src/modules/types/SettingsPath.ts | 10 ++--- .../settings/data-model/SettingsNewObject.tsx | 42 +++++++++++++++---- .../data-model/SettingsObjectDetail.tsx | 19 +++------ .../data-model/SettingsObjectEdit.tsx | 29 ++++++++----- .../data-model/SettingsObjectFieldEdit.tsx | 6 +-- .../SettingsObjectNewFieldStep1.tsx | 14 +++---- .../SettingsObjectNewFieldStep2.tsx | 6 +-- .../settings/data-model/SettingsObjects.tsx | 5 ++- .../SettingsObjectDetail.stories.tsx | 4 +- .../SettingsObjectEdit.stories.tsx | 4 +- .../SettingsObjectNewFieldStep1.stories.tsx | 4 +- .../SettingsObjectNewFieldStep2.stories.tsx | 4 +- front/yarn.lock | 36 ++++++++++++++++ .../dtos/update-object.input.ts | 10 +++++ 22 files changed, 214 insertions(+), 73 deletions(-) create mode 100644 front/src/modules/metadata/utils/formatMetadataObjectInput.ts create mode 100644 front/src/modules/metadata/utils/getObjectSlug.ts create mode 100644 front/src/modules/metadata/utils/validateMetadataObjectLabel.ts diff --git a/front/package.json b/front/package.json index 224f33ee4..2417f9433 100644 --- a/front/package.json +++ b/front/package.json @@ -37,7 +37,10 @@ "js-levenshtein": "^1.1.6", "jwt-decode": "^3.1.2", "libphonenumber-js": "^1.10.26", + "lodash.camelcase": "^4.3.0", "lodash.debounce": "^4.0.8", + "lodash.kebabcase": "^4.1.1", + "lodash.upperfirst": "^4.3.1", "luxon": "^3.3.0", "react": "^18.2.0", "react-data-grid": "7.0.0-beta.13", @@ -140,7 +143,10 @@ "@types/intl-tel-input": "^18.1.1", "@types/jest": "^27.5.2", "@types/js-cookie": "^3.0.3", + "@types/lodash.camelcase": "^4.3.7", "@types/lodash.debounce": "^4.0.7", + "@types/lodash.kebabcase": "^4.1.7", + "@types/lodash.upperfirst": "^4.3.7", "@types/luxon": "^3.3.0", "@types/react-datepicker": "^4.11.2", "@types/scroll-into-view": "^1.16.0", diff --git a/front/src/generated-metadata/graphql.ts b/front/src/generated-metadata/graphql.ts index 19cdc4da7..404cc3c7d 100644 --- a/front/src/generated-metadata/graphql.ts +++ b/front/src/generated-metadata/graphql.ts @@ -644,6 +644,8 @@ export type UpdateObjectInput = { isActive?: InputMaybe; labelPlural?: InputMaybe; labelSingular?: InputMaybe; + namePlural?: InputMaybe; + nameSingular?: InputMaybe; }; export type UpdateOneFieldInput = { diff --git a/front/src/modules/metadata/hooks/useObjectMetadata.ts b/front/src/modules/metadata/hooks/useObjectMetadata.ts index 4a41d4529..3612f9cf4 100644 --- a/front/src/modules/metadata/hooks/useObjectMetadata.ts +++ b/front/src/modules/metadata/hooks/useObjectMetadata.ts @@ -1,5 +1,8 @@ import { MetadataObject } from '../types/MetadataObject'; +import { formatMetadataObjectInput } from '../utils/formatMetadataObjectInput'; +import { getObjectSlug } from '../utils/getObjectSlug'; +import { useCreateOneMetadataObject } from './useCreateOneMetadataObject'; import { useFindManyMetadataObjects } from './useFindManyMetadataObjects'; import { useUpdateOneMetadataObject } from './useUpdateOneMetadataObject'; @@ -13,17 +16,30 @@ export const useObjectMetadata = () => { ({ isActive }) => !isActive, ); + const findActiveObjectBySlug = (slug: string) => + activeMetadataObjects.find( + (activeObject) => getObjectSlug(activeObject) === slug, + ); + + const { createOneMetadataObject } = useCreateOneMetadataObject(); const { updateOneMetadataObject } = useUpdateOneMetadataObject(); - const editObject = (metadataObject: MetadataObject) => + const createObject = ( + input: Pick< + MetadataObject, + 'labelPlural' | 'labelSingular' | 'icon' | 'description' + >, + ) => createOneMetadataObject(formatMetadataObjectInput(input)); + + const editObject = ( + input: Pick< + MetadataObject, + 'id' | 'labelPlural' | 'labelSingular' | 'icon' | 'description' + >, + ) => updateOneMetadataObject({ - idToUpdate: metadataObject.id, - updatePayload: { - description: metadataObject.description ?? null, - icon: metadataObject.icon, - labelPlural: metadataObject.labelPlural, - labelSingular: metadataObject.labelSingular, - }, + idToUpdate: input.id, + updatePayload: formatMetadataObjectInput(input), }); const activateObject = (metadataObject: MetadataObject) => @@ -40,9 +56,11 @@ export const useObjectMetadata = () => { return { activateObject, - disableObject, activeObjects: activeMetadataObjects, + createObject, disabledObjects: disabledMetadataObjects, + disableObject, editObject, + findActiveObjectBySlug, }; }; diff --git a/front/src/modules/metadata/hooks/useUpdateOneMetadataObject.ts b/front/src/modules/metadata/hooks/useUpdateOneMetadataObject.ts index 10a989f0b..bb2251635 100644 --- a/front/src/modules/metadata/hooks/useUpdateOneMetadataObject.ts +++ b/front/src/modules/metadata/hooks/useUpdateOneMetadataObject.ts @@ -29,7 +29,13 @@ export const useUpdateOneMetadataObject = () => { idToUpdate: UpdateOneMetadataObjectMutationVariables['idToUpdate']; updatePayload: Pick< UpdateOneMetadataObjectMutationVariables['updatePayload'], - 'description' | 'icon' | 'isActive' | 'labelPlural' | 'labelSingular' + | 'description' + | 'icon' + | 'isActive' + | 'labelPlural' + | 'labelSingular' + | 'namePlural' + | 'nameSingular' >; }) => { return await mutate({ diff --git a/front/src/modules/metadata/utils/formatMetadataObjectInput.ts b/front/src/modules/metadata/utils/formatMetadataObjectInput.ts new file mode 100644 index 000000000..c9e504b18 --- /dev/null +++ b/front/src/modules/metadata/utils/formatMetadataObjectInput.ts @@ -0,0 +1,18 @@ +import toCamelCase from 'lodash.camelcase'; +import upperFirst from 'lodash.upperfirst'; + +import { MetadataObject } from '../types/MetadataObject'; + +export const formatMetadataObjectInput = ( + input: Pick< + MetadataObject, + 'labelPlural' | 'labelSingular' | 'icon' | 'description' + >, +) => ({ + description: input.description?.trim() ?? null, + icon: input.icon, + labelPlural: input.labelPlural.trim(), + labelSingular: input.labelSingular.trim(), + namePlural: upperFirst(toCamelCase(input.labelPlural.trim())), + nameSingular: upperFirst(toCamelCase(input.labelSingular.trim())), +}); diff --git a/front/src/modules/metadata/utils/getObjectSlug.ts b/front/src/modules/metadata/utils/getObjectSlug.ts new file mode 100644 index 000000000..f7241b410 --- /dev/null +++ b/front/src/modules/metadata/utils/getObjectSlug.ts @@ -0,0 +1,7 @@ +import toKebabCase from 'lodash.kebabcase'; + +import { MetadataObject } from '../types/MetadataObject'; + +export const getObjectSlug = ( + metadataObject: Pick, +) => toKebabCase(metadataObject.labelPlural); diff --git a/front/src/modules/metadata/utils/validateMetadataObjectLabel.ts b/front/src/modules/metadata/utils/validateMetadataObjectLabel.ts new file mode 100644 index 000000000..be5c6560c --- /dev/null +++ b/front/src/modules/metadata/utils/validateMetadataObjectLabel.ts @@ -0,0 +1,4 @@ +const metadataObjectLabelValidationPattern = /^[a-zA-Z][a-zA-Z0-9 ]*$/; + +export const validateMetadataObjectLabel = (value: string) => + !!value.match(metadataObjectLabelValidationPattern); diff --git a/front/src/modules/settings/data-model/components/SettingsObjectFormSection.tsx b/front/src/modules/settings/data-model/components/SettingsObjectFormSection.tsx index 336846ff8..2d30fea59 100644 --- a/front/src/modules/settings/data-model/components/SettingsObjectFormSection.tsx +++ b/front/src/modules/settings/data-model/components/SettingsObjectFormSection.tsx @@ -1,5 +1,6 @@ import styled from '@emotion/styled'; +import { validateMetadataObjectLabel } from '@/metadata/utils/validateMetadataObjectLabel'; import { H2Title } from '@/ui/display/typography/components/H2Title'; import { TextArea } from '@/ui/input/components/TextArea'; import { TextInput } from '@/ui/input/components/TextInput'; @@ -43,7 +44,11 @@ export const SettingsObjectFormSection = ({ label="Singular" placeholder="Investor" value={singularName} - onChange={(value) => onChange?.({ labelSingular: value })} + onChange={(value) => { + if (!value || validateMetadataObjectLabel(value)) { + onChange?.({ labelSingular: value }); + } + }} disabled={disabled} fullWidth /> @@ -51,7 +56,11 @@ export const SettingsObjectFormSection = ({ label="Plural" placeholder="Investors" value={pluralName} - onChange={(value) => onChange?.({ labelPlural: value })} + onChange={(value) => { + if (!value || validateMetadataObjectLabel(value)) { + onChange?.({ labelPlural: value }); + } + }} disabled={disabled} fullWidth /> diff --git a/front/src/modules/types/SettingsPath.ts b/front/src/modules/types/SettingsPath.ts index c62f4b475..6f5b8df1a 100644 --- a/front/src/modules/types/SettingsPath.ts +++ b/front/src/modules/types/SettingsPath.ts @@ -2,11 +2,11 @@ export enum SettingsPath { ProfilePage = 'profile', Experience = 'profile/experience', Objects = 'objects', - ObjectDetail = 'objects/:pluralObjectName', - ObjectEdit = 'objects/:pluralObjectName/edit', - ObjectNewFieldStep1 = 'objects/:pluralObjectName/new-field/step-1', - ObjectNewFieldStep2 = 'objects/:pluralObjectName/new-field/step-2', - ObjectFieldEdit = 'objects/:pluralObjectName/:fieldName', + ObjectDetail = 'objects/:objectSlug', + ObjectEdit = 'objects/:objectSlug/edit', + ObjectNewFieldStep1 = 'objects/:objectSlug/new-field/step-1', + ObjectNewFieldStep2 = 'objects/:objectSlug/new-field/step-2', + ObjectFieldEdit = 'objects/:objectSlug/:fieldName', NewObject = 'objects/new', WorkspaceMembersPage = 'workspace-members', Workspace = 'workspace', diff --git a/front/src/pages/settings/data-model/SettingsNewObject.tsx b/front/src/pages/settings/data-model/SettingsNewObject.tsx index 9f279472d..1c07ad252 100644 --- a/front/src/pages/settings/data-model/SettingsNewObject.tsx +++ b/front/src/pages/settings/data-model/SettingsNewObject.tsx @@ -1,6 +1,7 @@ import { useState } from 'react'; import { useNavigate } from 'react-router-dom'; +import { useObjectMetadata } from '@/metadata/hooks/useObjectMetadata'; import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons'; import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; @@ -21,19 +22,33 @@ export const SettingsNewObject = () => { const [selectedObjectType, setSelectedObjectType] = useState('Standard'); - const [customFormValues, setCustomFormValues] = useState< - Partial<{ - labelPlural: string; - labelSingular: string; - description: string; - }> - >({}); + const { createObject } = useObjectMetadata(); + + const [customFormValues, setCustomFormValues] = useState<{ + description?: string; + icon?: string; + labelPlural: string; + labelSingular: string; + }>({ labelPlural: '', labelSingular: '' }); const canSave = selectedObjectType === 'Custom' && !!customFormValues.labelPlural && !!customFormValues.labelSingular; + const handleSave = async () => { + if (selectedObjectType === 'Custom') { + await createObject({ + labelPlural: customFormValues.labelPlural, + labelSingular: customFormValues.labelSingular, + description: customFormValues.description, + icon: customFormValues.icon, + }); + } + + navigate('/settings/objects'); + }; + return ( @@ -49,7 +64,7 @@ export const SettingsNewObject = () => { onCancel={() => { navigate('/settings/objects'); }} - onSave={() => undefined} + onSave={handleSave} />
@@ -64,7 +79,16 @@ export const SettingsNewObject = () => {
{selectedObjectType === 'Custom' && ( <> - + { + setCustomFormValues((previousValues) => ({ + ...previousValues, + icon: iconKey, + })); + }} + /> { const navigate = useNavigate(); - const { pluralObjectName = '' } = useParams(); - const { activeObjects, disableObject } = useObjectMetadata(); - const activeObject = activeObjects.find( - (activeObject) => activeObject.namePlural === pluralObjectName, - ); + const { objectSlug = '' } = useParams(); + const { activeObjects, disableObject, findActiveObjectBySlug } = + useObjectMetadata(); + const activeObject = findActiveObjectBySlug(objectSlug); useEffect(() => { if (activeObjects.length && !activeObject) { @@ -70,9 +69,7 @@ export const SettingsObjectDetail = () => { disableObject(activeObject); navigate('/settings/objects'); }} - onEdit={() => - navigate(`/settings/objects/${pluralObjectName}/edit`) - } + onEdit={() => navigate('./edit')} /> )}
@@ -97,11 +94,7 @@ export const SettingsObjectDetail = () => { - navigate( - `/settings/objects/${pluralObjectName}/${fieldItem.name}`, - ) - } + onEdit={() => navigate(`./${fieldItem.name}`)} onDisable={() => disableField(fieldItem)} /> } diff --git a/front/src/pages/settings/data-model/SettingsObjectEdit.tsx b/front/src/pages/settings/data-model/SettingsObjectEdit.tsx index 38cf5944c..a54cf9f13 100644 --- a/front/src/pages/settings/data-model/SettingsObjectEdit.tsx +++ b/front/src/pages/settings/data-model/SettingsObjectEdit.tsx @@ -2,6 +2,7 @@ import { useEffect, useState } from 'react'; import { useNavigate, useParams } from 'react-router-dom'; import { useObjectMetadata } from '@/metadata/hooks/useObjectMetadata'; +import { getObjectSlug } from '@/metadata/utils/getObjectSlug'; import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons'; import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; @@ -18,11 +19,10 @@ import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; export const SettingsObjectEdit = () => { const navigate = useNavigate(); - const { pluralObjectName = '' } = useParams(); - const { activeObjects, disableObject, editObject } = useObjectMetadata(); - const activeObject = activeObjects.find( - (activeObject) => activeObject.namePlural === pluralObjectName, - ); + const { objectSlug = '' } = useParams(); + const { activeObjects, disableObject, editObject, findActiveObjectBySlug } = + useObjectMetadata(); + const activeObject = findActiveObjectBySlug(objectSlug); const [formValues, setFormValues] = useState< Partial<{ @@ -62,6 +62,16 @@ export const SettingsObjectEdit = () => { const canSave = areRequiredFieldsFilled && hasChanges; + const handleSave = async () => { + if (!activeObject) return; + + const editedObject = { ...activeObject, ...formValues }; + + await editObject(editedObject); + + navigate(`/settings/objects/${getObjectSlug(editedObject)}`); + }; + return ( @@ -71,7 +81,7 @@ export const SettingsObjectEdit = () => { { children: 'Objects', href: '/settings/objects' }, { children: activeObject?.labelPlural ?? '', - href: `/settings/objects/${pluralObjectName}`, + href: `/settings/objects/${objectSlug}`, }, { children: 'Edit' }, ]} @@ -80,12 +90,9 @@ export const SettingsObjectEdit = () => { { - navigate(`/settings/objects/${pluralObjectName}`); - }} - onSave={() => { - editObject({ ...activeObject, ...formValues }); - navigate(`/settings/objects/${pluralObjectName}`); + navigate(`/settings/objects/${objectSlug}`); }} + onSave={handleSave} /> )} diff --git a/front/src/pages/settings/data-model/SettingsObjectFieldEdit.tsx b/front/src/pages/settings/data-model/SettingsObjectFieldEdit.tsx index 6ddd21432..fc97033de 100644 --- a/front/src/pages/settings/data-model/SettingsObjectFieldEdit.tsx +++ b/front/src/pages/settings/data-model/SettingsObjectFieldEdit.tsx @@ -7,7 +7,7 @@ import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer' import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; export const SettingsObjectFieldEdit = () => { - const { pluralObjectName = '', fieldName = '' } = useParams(); + const { objectSlug = '', fieldName = '' } = useParams(); return ( @@ -16,8 +16,8 @@ export const SettingsObjectFieldEdit = () => { links={[ { children: 'Objects', href: '/settings/objects' }, { - children: `${pluralObjectName}`, - href: `/settings/objects/${pluralObjectName}`, + children: `${objectSlug}`, + href: `/settings/objects/${objectSlug}`, }, { children: `${fieldName}`, diff --git a/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep1.tsx b/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep1.tsx index 5bf0103c3..df44c5839 100644 --- a/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep1.tsx +++ b/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep1.tsx @@ -35,11 +35,9 @@ const StyledAddCustomFieldButton = styled(Button)` export const SettingsObjectNewFieldStep1 = () => { const navigate = useNavigate(); - const { pluralObjectName = '' } = useParams(); - const { activeObjects } = useObjectMetadata(); - const activeObject = activeObjects.find( - (activeObject) => activeObject.namePlural === pluralObjectName, - ); + const { objectSlug = '' } = useParams(); + const { activeObjects, findActiveObjectBySlug } = useObjectMetadata(); + const activeObject = findActiveObjectBySlug(objectSlug); useEffect(() => { if (activeObjects.length && !activeObject) { @@ -63,7 +61,7 @@ export const SettingsObjectNewFieldStep1 = () => { { children: 'Objects', href: '/settings/objects' }, { children: activeObject?.labelPlural ?? '', - href: `/settings/objects/${pluralObjectName}`, + href: `/settings/objects/${objectSlug}`, }, { children: 'New Field' }, ]} @@ -71,7 +69,7 @@ export const SettingsObjectNewFieldStep1 = () => { { - navigate(`/settings/objects/${pluralObjectName}`); + navigate(`/settings/objects/${objectSlug}`); }} onSave={() => undefined} /> @@ -121,7 +119,7 @@ export const SettingsObjectNewFieldStep1 = () => { size="small" variant="secondary" onClick={() => - navigate(`/settings/objects/${pluralObjectName}/new-field/step-2`) + navigate(`/settings/objects/${objectSlug}/new-field/step-2`) } /> diff --git a/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx b/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx index 6f4034558..c1db3e37d 100644 --- a/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx +++ b/front/src/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldStep2.tsx @@ -15,9 +15,9 @@ import { Breadcrumb } from '@/ui/navigation/bread-crumb/components/Breadcrumb'; export const SettingsObjectNewFieldStep2 = () => { const navigate = useNavigate(); - const { pluralObjectName = '' } = useParams(); + const { objectSlug = '' } = useParams(); const activeObject = activeObjectItems.find( - (activeObject) => activeObject.name.toLowerCase() === pluralObjectName, + (activeObject) => activeObject.name.toLowerCase() === objectSlug, ); useEffect(() => { @@ -43,7 +43,7 @@ export const SettingsObjectNewFieldStep2 = () => { { children: 'Objects', href: '/settings/objects' }, { children: activeObject?.name ?? '', - href: `/settings/objects/${pluralObjectName}`, + href: `/settings/objects/${objectSlug}`, }, { children: 'New Field' }, ]} diff --git a/front/src/pages/settings/data-model/SettingsObjects.tsx b/front/src/pages/settings/data-model/SettingsObjects.tsx index 657d61287..0bf57dc7a 100644 --- a/front/src/pages/settings/data-model/SettingsObjects.tsx +++ b/front/src/pages/settings/data-model/SettingsObjects.tsx @@ -3,6 +3,7 @@ import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { useObjectMetadata } from '@/metadata/hooks/useObjectMetadata'; +import { getObjectSlug } from '@/metadata/utils/getObjectSlug'; import { SettingsHeaderContainer } from '@/settings/components/SettingsHeaderContainer'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { @@ -76,7 +77,9 @@ export const SettingsObjects = () => { /> } onClick={() => - navigate(`/settings/objects/${objectItem.namePlural}`) + navigate( + `/settings/objects/${getObjectSlug(objectItem)}`, + ) } /> ))} diff --git a/front/src/pages/settings/data-model/__stories__/SettingsObjectDetail.stories.tsx b/front/src/pages/settings/data-model/__stories__/SettingsObjectDetail.stories.tsx index 76c806355..a8766dd26 100644 --- a/front/src/pages/settings/data-model/__stories__/SettingsObjectDetail.stories.tsx +++ b/front/src/pages/settings/data-model/__stories__/SettingsObjectDetail.stories.tsx @@ -14,8 +14,8 @@ const meta: Meta = { component: SettingsObjectDetail, decorators: [PageDecorator], args: { - routePath: '/settings/objects/:pluralObjectName', - routeParams: { ':pluralObjectName': 'companies' }, + routePath: '/settings/objects/:objectSlug', + routeParams: { ':objectSlug': 'companies' }, }, parameters: { msw: graphqlMocks, diff --git a/front/src/pages/settings/data-model/__stories__/SettingsObjectEdit.stories.tsx b/front/src/pages/settings/data-model/__stories__/SettingsObjectEdit.stories.tsx index 9339776ee..138b3f281 100644 --- a/front/src/pages/settings/data-model/__stories__/SettingsObjectEdit.stories.tsx +++ b/front/src/pages/settings/data-model/__stories__/SettingsObjectEdit.stories.tsx @@ -14,8 +14,8 @@ const meta: Meta = { component: SettingsObjectEdit, decorators: [PageDecorator], args: { - routePath: '/settings/objects/:pluralObjectName/edit', - routeParams: { ':pluralObjectName': 'companies' }, + routePath: '/settings/objects/:objectSlug/edit', + routeParams: { ':objectSlug': 'companies' }, }, parameters: { msw: graphqlMocks, diff --git a/front/src/pages/settings/data-model/__stories__/SettingsObjectNewField/SettingsObjectNewFieldStep1.stories.tsx b/front/src/pages/settings/data-model/__stories__/SettingsObjectNewField/SettingsObjectNewFieldStep1.stories.tsx index 01998da80..2b57148d8 100644 --- a/front/src/pages/settings/data-model/__stories__/SettingsObjectNewField/SettingsObjectNewFieldStep1.stories.tsx +++ b/front/src/pages/settings/data-model/__stories__/SettingsObjectNewField/SettingsObjectNewFieldStep1.stories.tsx @@ -15,8 +15,8 @@ const meta: Meta = { component: SettingsObjectNewFieldStep1, decorators: [PageDecorator], args: { - routePath: '/settings/objects/:pluralObjectName/new-field/step-1', - routeParams: { ':pluralObjectName': 'companies' }, + routePath: '/settings/objects/:objectSlug/new-field/step-1', + routeParams: { ':objectSlug': 'companies' }, }, parameters: { msw: graphqlMocks, diff --git a/front/src/pages/settings/data-model/__stories__/SettingsObjectNewField/SettingsObjectNewFieldStep2.stories.tsx b/front/src/pages/settings/data-model/__stories__/SettingsObjectNewField/SettingsObjectNewFieldStep2.stories.tsx index 95d8889f2..b5a7090d4 100644 --- a/front/src/pages/settings/data-model/__stories__/SettingsObjectNewField/SettingsObjectNewFieldStep2.stories.tsx +++ b/front/src/pages/settings/data-model/__stories__/SettingsObjectNewField/SettingsObjectNewFieldStep2.stories.tsx @@ -15,8 +15,8 @@ const meta: Meta = { component: SettingsObjectNewFieldStep2, decorators: [PageDecorator], args: { - routePath: '/settings/objects/:pluralObjectName/new-field/step-2', - routeParams: { ':pluralObjectName': 'companies' }, + routePath: '/settings/objects/:objectSlug/new-field/step-2', + routeParams: { ':objectSlug': 'companies' }, }, parameters: { msw: graphqlMocks, diff --git a/front/yarn.lock b/front/yarn.lock index 7a49f909e..a0cd73286 100644 --- a/front/yarn.lock +++ b/front/yarn.lock @@ -5628,6 +5628,13 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== +"@types/lodash.camelcase@^4.3.7": + version "4.3.8" + resolved "https://registry.yarnpkg.com/@types/lodash.camelcase/-/lodash.camelcase-4.3.8.tgz#0cbf6b4d13ed2ba94310d114c7bec2d171fe4f44" + integrity sha512-jwsvMuU3ntB7w3a4L/oLW24qpBE9fobU5O/uCYWQctlvEOoWkXEgw/fkpY+onmT37IOQMVcVW9UiJ33CZE70ug== + dependencies: + "@types/lodash" "*" + "@types/lodash.debounce@^4.0.7": version "4.0.7" resolved "https://registry.yarnpkg.com/@types/lodash.debounce/-/lodash.debounce-4.0.7.tgz#0285879defb7cdb156ae633cecd62d5680eded9f" @@ -5635,6 +5642,13 @@ dependencies: "@types/lodash" "*" +"@types/lodash.kebabcase@^4.1.7": + version "4.1.8" + resolved "https://registry.yarnpkg.com/@types/lodash.kebabcase/-/lodash.kebabcase-4.1.8.tgz#81cf2a1f81f3ea640a3538da43ec54e13b57dfcc" + integrity sha512-ZwdT+S6Ejbl2KEw/nunwO63hMzABqzVdWonRMEuhKs0GfwqffaQ3tSJo+/wmDCCaGUHIiObsBFY59GUYjYMk5A== + dependencies: + "@types/lodash" "*" + "@types/lodash.mergewith@4.6.7": version "4.6.7" resolved "https://registry.yarnpkg.com/@types/lodash.mergewith/-/lodash.mergewith-4.6.7.tgz#eaa65aa5872abdd282f271eae447b115b2757212" @@ -5642,6 +5656,13 @@ dependencies: "@types/lodash" "*" +"@types/lodash.upperfirst@^4.3.7": + version "4.3.8" + resolved "https://registry.yarnpkg.com/@types/lodash.upperfirst/-/lodash.upperfirst-4.3.8.tgz#b488f406f2325f4271c6904f7f9fb560ad6be813" + integrity sha512-/R/drl34clakjVOVSgUryl7R18RgAuUWYXKuc3S7Aozw2DW+iqE6hvZJugMtdfzML0fGXs+UCDjafCkctlgIug== + dependencies: + "@types/lodash" "*" + "@types/lodash@*", "@types/lodash@^4.14.167": version "4.14.197" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.197.tgz#e95c5ddcc814ec3e84c891910a01e0c8a378c54b" @@ -13625,6 +13646,11 @@ locate-path@^7.1.0: dependencies: p-locate "^6.0.0" +lodash.camelcase@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" + integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== + lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" @@ -13635,6 +13661,11 @@ lodash.flattendeep@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" integrity sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ== +lodash.kebabcase@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz#8489b1cb0d29ff88195cceca448ff6d6cc295c36" + integrity sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g== + lodash.memoize@4.x, lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" @@ -13660,6 +13691,11 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== +lodash.upperfirst@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz#1365edf431480481ef0d1c68957a5ed99d49f7ce" + integrity sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg== + lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0, lodash@~4.17.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" diff --git a/server/src/metadata/object-metadata/dtos/update-object.input.ts b/server/src/metadata/object-metadata/dtos/update-object.input.ts index 79118195e..b712596b6 100644 --- a/server/src/metadata/object-metadata/dtos/update-object.input.ts +++ b/server/src/metadata/object-metadata/dtos/update-object.input.ts @@ -14,6 +14,16 @@ export class UpdateObjectInput { @Field({ nullable: true }) labelPlural?: string; + @IsString() + @IsOptional() + @Field({ nullable: true }) + nameSingular?: string; + + @IsString() + @IsOptional() + @Field({ nullable: true }) + namePlural?: string; + @IsString() @IsOptional() @Field({ nullable: true })