Remove step 1 of new object field (#7397)

fixes #7356 
fixes #6967 
fixes #7102
fixes #7121 
fixes #7505
This commit is contained in:
nitin
2024-10-09 14:54:49 +05:30
committed by GitHub
parent 9b9e03fbf6
commit 58cbcbfe70
46 changed files with 374 additions and 574 deletions

View File

@ -1,7 +1,7 @@
import { zodResolver } from '@hookform/resolvers/zod';
import { FormProvider, useForm } from 'react-hook-form';
import { useNavigate } from 'react-router-dom';
import { H2Title, IconHierarchy2 } from 'twenty-ui';
import { H2Title } from 'twenty-ui';
import { z } from 'zod';
import { useCreateOneObjectMetadataItem } from '@/object-metadata/hooks/useCreateOneObjectMetadataItem';
@ -69,7 +69,6 @@ export const SettingsNewObject = () => {
// eslint-disable-next-line react/jsx-props-no-spreading
<FormProvider {...formConfig}>
<SubMenuTopBarContainer
Icon={IconHierarchy2}
title="New Object"
links={[
{

View File

@ -1,6 +1,5 @@
import { useUpdateOneObjectMetadataItem } from '@/object-metadata/hooks/useUpdateOneObjectMetadataItem';
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { getDisabledFieldMetadataItems } from '@/object-metadata/utils/getDisabledFieldMetadataItems';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SettingsObjectSummaryCard } from '@/settings/data-model/object-details/components/SettingsObjectSummaryCard';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
@ -10,9 +9,8 @@ import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer'
import { Section } from '@/ui/layout/section/components/Section';
import { UndecoratedLink } from '@/ui/navigation/link/components/UndecoratedLink';
import styled from '@emotion/styled';
import { isNonEmptyArray } from '@sniptt/guards';
import { useNavigate } from 'react-router-dom';
import { H2Title, IconHierarchy2, IconPlus } from 'twenty-ui';
import { H2Title, IconPlus } from 'twenty-ui';
import { SettingsObjectFieldTable } from '~/pages/settings/data-model/SettingsObjectFieldTable';
const StyledDiv = styled.div`
@ -40,14 +38,10 @@ export const SettingsObjectDetailPageContent = ({
navigate(getSettingsPagePath(SettingsPath.Objects));
};
const disabledFieldMetadataItems =
getDisabledFieldMetadataItems(objectMetadataItem);
const shouldDisplayAddFieldButton = !objectMetadataItem.isRemote;
return (
<SubMenuTopBarContainer
Icon={IconHierarchy2}
title={objectMetadataItem.labelPlural}
links={[
{
@ -80,13 +74,7 @@ export const SettingsObjectDetailPageContent = ({
/>
{shouldDisplayAddFieldButton && (
<StyledDiv>
<UndecoratedLink
to={
isNonEmptyArray(disabledFieldMetadataItems)
? './new-field/step-1'
: './new-field/step-2'
}
>
<UndecoratedLink to={'./new-field/select'}>
<Button
Icon={IconPlus}
title="Add Field"

View File

@ -5,7 +5,7 @@ import pick from 'lodash.pick';
import { useEffect } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useNavigate, useParams } from 'react-router-dom';
import { H2Title, IconArchive, IconHierarchy2 } from 'twenty-ui';
import { H2Title, IconArchive } from 'twenty-ui';
import { z } from 'zod';
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
@ -107,7 +107,6 @@ export const SettingsObjectEdit = () => {
<RecordFieldValueSelectorContextProvider>
<FormProvider {...formConfig}>
<SubMenuTopBarContainer
Icon={IconHierarchy2}
title="Edit"
links={[
{

View File

@ -5,12 +5,7 @@ import pick from 'lodash.pick';
import { useEffect } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useNavigate, useParams } from 'react-router-dom';
import {
H2Title,
IconArchive,
IconArchiveOff,
IconHierarchy2,
} from 'twenty-ui';
import { H2Title, IconArchive, IconArchiveOff } from 'twenty-ui';
import { z } from 'zod';
import { useFieldMetadataItem } from '@/object-metadata/hooks/useFieldMetadataItem';
@ -186,7 +181,6 @@ export const SettingsObjectFieldEdit = () => {
{/* eslint-disable-next-line react/jsx-props-no-spreading */}
<FormProvider {...formConfig}>
<SubMenuTopBarContainer
Icon={IconHierarchy2}
title={fieldMetadataItem?.label}
links={[
{

View File

@ -11,7 +11,6 @@ import { FIELD_NAME_MAXIMUM_LENGTH } from '@/settings/data-model/constants/Field
import { SettingsDataModelFieldDescriptionForm } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldDescriptionForm';
import { SettingsDataModelFieldIconLabelForm } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldIconLabelForm';
import { SettingsDataModelFieldSettingsFormCard } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldSettingsFormCard';
import { SettingsDataModelFieldTypeSelect } from '@/settings/data-model/fields/forms/components/SettingsDataModelFieldTypeSelect';
import { settingsFieldFormSchema } from '@/settings/data-model/fields/forms/validation-schemas/settingsFieldFormSchema';
import { SettingsFieldType } from '@/settings/data-model/types/SettingsFieldType';
import { AppPath } from '@/types/AppPath';
@ -22,42 +21,36 @@ import { Section } from '@/ui/layout/section/components/Section';
import { View } from '@/views/types/View';
import { ViewType } from '@/views/types/ViewType';
import { useApolloClient } from '@apollo/client';
import styled from '@emotion/styled';
import { zodResolver } from '@hookform/resolvers/zod';
import pick from 'lodash.pick';
import { useEffect, useState } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useNavigate, useParams, useSearchParams } from 'react-router-dom';
import { H1Title, H1TitleFontColor, H2Title, IconHierarchy2 } from 'twenty-ui';
import { H2Title } from 'twenty-ui';
import { z } from 'zod';
import { FieldMetadataType } from '~/generated-metadata/graphql';
import { isDefined } from '~/utils/isDefined';
import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull';
// TODO: fix this type
type SettingsDataModelNewFieldFormValues = z.infer<
ReturnType<typeof settingsFieldFormSchema>
> &
any;
const StyledH1Title = styled(H1Title)`
margin-bottom: 0;
padding-top: ${({ theme }) => theme.spacing(3)};
`;
export const SettingsObjectNewFieldStep2 = () => {
export const SettingsObjectNewFieldConfigure = () => {
const navigate = useNavigate();
const { objectSlug = '' } = useParams();
const [searchParams] = useSearchParams();
const fieldType = searchParams.get('fieldType') as SettingsFieldType;
const fieldType =
(searchParams.get('fieldType') as SettingsFieldType) ||
FieldMetadataType.Text;
const { enqueueSnackBar } = useSnackBar();
const [isConfigureStep, setIsConfigureStep] = useState(false);
const { findActiveObjectMetadataItemBySlug } =
useFilteredObjectMetadataItems();
const activeObjectMetadataItem =
findActiveObjectMetadataItemBySlug(objectSlug);
const { createMetadataField } = useFieldMetadataItem();
const apolloClient = useApolloClient();
const formConfig = useForm<SettingsDataModelNewFieldFormValues>({
mode: 'onTouched',
@ -66,14 +59,14 @@ export const SettingsObjectNewFieldStep2 = () => {
activeObjectMetadataItem?.fields.map((value) => value.name),
),
),
defaultValues: {
type: fieldType,
icon: 'IconUsers',
label: '',
description: '',
},
});
useEffect(() => {
if (!activeObjectMetadataItem) {
navigate(AppPath.NotFound);
}
}, [activeObjectMetadataItem, navigate]);
const [, setObjectViews] = useState<View[]>([]);
const [, setRelationObjectViews] = useState<View[]>([]);
@ -85,7 +78,6 @@ export const SettingsObjectNewFieldStep2 = () => {
},
onCompleted: async (views) => {
if (isUndefinedOrNull(views)) return;
setObjectViews(views);
},
});
@ -103,15 +95,17 @@ export const SettingsObjectNewFieldStep2 = () => {
},
onCompleted: async (views) => {
if (isUndefinedOrNull(views)) return;
setRelationObjectViews(views);
},
});
const { createOneRelationMetadataItem: createOneRelationMetadata } =
useCreateOneRelationMetadataItem();
const apolloClient = useApolloClient();
useEffect(() => {
if (!activeObjectMetadataItem) {
navigate(AppPath.NotFound);
}
}, [activeObjectMetadataItem, navigate]);
if (!activeObjectMetadataItem) return null;
@ -160,17 +154,7 @@ export const SettingsObjectNewFieldStep2 = () => {
});
}
};
const excludedFieldTypes: SettingsFieldType[] = (
[
FieldMetadataType.Link,
FieldMetadataType.Numeric,
FieldMetadataType.RichText,
FieldMetadataType.Actor,
FieldMetadataType.Email,
FieldMetadataType.Phone,
] as const
).filter(isDefined);
if (!activeObjectMetadataItem) return null;
return (
<RecordFieldValueSelectorContextProvider>
@ -178,96 +162,57 @@ export const SettingsObjectNewFieldStep2 = () => {
{...formConfig}
>
<SubMenuTopBarContainer
Icon={IconHierarchy2}
title="2. Configure field"
links={[
{
children: 'Objects',
href: '/settings/objects',
},
{ children: 'Workspace', href: '/settings/workspace' },
{ children: 'Objects', href: '/settings/objects' },
{
children: activeObjectMetadataItem.labelPlural,
href: `/settings/objects/${objectSlug}`,
},
{
children: (
<SettingsDataModelNewFieldBreadcrumbDropDown
isConfigureStep={isConfigureStep}
onBreadcrumbClick={setIsConfigureStep}
/>
),
},
{ children: <SettingsDataModelNewFieldBreadcrumbDropDown /> },
]}
actionButton={
!activeObjectMetadataItem.isRemote && (
<SaveAndCancelButtons
isSaveDisabled={!canSave}
isCancelDisabled={isSubmitting}
onCancel={() => {
if (!isConfigureStep) {
navigate(`/settings/objects/${objectSlug}`);
} else {
setIsConfigureStep(false);
}
}}
onSave={formConfig.handleSubmit(handleSave)}
/>
)
<SaveAndCancelButtons
isSaveDisabled={!canSave}
isCancelDisabled={isSubmitting}
onCancel={() =>
navigate(`/settings/objects/${objectSlug}/new-field/select`)
}
onSave={formConfig.handleSubmit(handleSave)}
/>
}
>
<SettingsPageContainer>
<StyledH1Title
title={
!isConfigureStep
? '1. Select a field type'
: '2. Configure field'
}
fontColor={H1TitleFontColor.Primary}
/>
{!isConfigureStep ? (
<SettingsDataModelFieldTypeSelect
excludedFieldTypes={excludedFieldTypes}
<Section>
<H2Title
title="Icon and Name"
description="The name and icon of this field"
/>
<SettingsDataModelFieldIconLabelForm
maxLength={FIELD_NAME_MAXIMUM_LENGTH}
/>
</Section>
<Section>
<H2Title title="Values" description="The values of this field" />
<SettingsDataModelFieldSettingsFormCard
isCreatingField
fieldMetadataItem={{
icon: formConfig.watch('icon'),
label: formConfig.watch('label') || 'New Field',
type: fieldType as FieldMetadataType,
}}
onFieldTypeSelect={() => setIsConfigureStep(true)}
objectMetadataItem={activeObjectMetadataItem}
/>
) : (
<>
<Section>
<H2Title
title="Icon and Name"
description="The name and icon of this field"
/>
<SettingsDataModelFieldIconLabelForm
maxLength={FIELD_NAME_MAXIMUM_LENGTH}
/>
</Section>
<Section>
<H2Title
title="Values"
description="The values of this field"
/>
<SettingsDataModelFieldSettingsFormCard
isCreatingField
fieldMetadataItem={{
icon: formConfig.watch('icon'),
label: formConfig.watch('label') || 'Employees',
type: formConfig.watch('type'),
}}
objectMetadataItem={activeObjectMetadataItem}
/>
</Section>
<Section>
<H2Title
title="Description"
description="The description of this field"
/>
<SettingsDataModelFieldDescriptionForm />
</Section>
</>
)}
</Section>
<Section>
<H2Title
title="Description"
description="The description of this field"
/>
<SettingsDataModelFieldDescriptionForm />
</Section>
</SettingsPageContainer>
</SubMenuTopBarContainer>
</FormProvider>

View File

@ -0,0 +1,90 @@
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
import { RecordFieldValueSelectorContextProvider } from '@/object-record/record-store/contexts/RecordFieldValueSelectorContext';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SettingsDataModelNewFieldBreadcrumbDropDown } from '@/settings/data-model/components/SettingsDataModelNewFieldBreadcrumbDropDown';
import { SETTINGS_FIELD_TYPE_CONFIGS } from '@/settings/data-model/constants/SettingsFieldTypeConfigs';
import { SettingsObjectNewFieldSelector } from '@/settings/data-model/fields/forms/components/SettingsObjectNewFieldSelector';
import { SettingsFieldType } from '@/settings/data-model/types/SettingsFieldType';
import { AppPath } from '@/types/AppPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { zodResolver } from '@hookform/resolvers/zod';
import { useEffect } from 'react';
import { FormProvider, useForm } from 'react-hook-form';
import { useNavigate, useParams } from 'react-router-dom';
import { isDefined } from 'twenty-ui';
import { z } from 'zod';
import { FieldMetadataType } from '~/generated-metadata/graphql';
export const settingsDataModelFieldTypeFormSchema = z.object({
type: z.enum(
Object.keys(SETTINGS_FIELD_TYPE_CONFIGS) as [
SettingsFieldType,
...SettingsFieldType[],
],
),
});
export type SettingsDataModelFieldTypeFormValues = z.infer<
typeof settingsDataModelFieldTypeFormSchema
>;
export const SettingsObjectNewFieldSelect = () => {
const navigate = useNavigate();
const { objectSlug = '' } = useParams();
const { findActiveObjectMetadataItemBySlug } =
useFilteredObjectMetadataItems();
const activeObjectMetadataItem =
findActiveObjectMetadataItemBySlug(objectSlug);
const formMethods = useForm({
resolver: zodResolver(settingsDataModelFieldTypeFormSchema),
defaultValues: {
type: FieldMetadataType.Text,
},
});
const excludedFieldTypes: SettingsFieldType[] = (
[
FieldMetadataType.Link,
FieldMetadataType.Numeric,
FieldMetadataType.RichText,
FieldMetadataType.Actor,
FieldMetadataType.Email,
FieldMetadataType.Phone,
] as const
).filter(isDefined);
useEffect(() => {
if (!activeObjectMetadataItem) {
navigate(AppPath.NotFound);
}
}, [activeObjectMetadataItem, navigate]);
if (!activeObjectMetadataItem) return null;
return (
<RecordFieldValueSelectorContextProvider>
<FormProvider // eslint-disable-next-line react/jsx-props-no-spreading
{...formMethods}
>
<SubMenuTopBarContainer
title="1. Select a field type"
links={[
{ children: 'Workspace', href: '/settings/workspace' },
{ children: 'Objects', href: '/settings/objects' },
{
children: activeObjectMetadataItem.labelPlural,
href: `/settings/objects/${objectSlug}`,
},
{ children: <SettingsDataModelNewFieldBreadcrumbDropDown /> },
]}
>
<SettingsPageContainer>
<SettingsObjectNewFieldSelector
objectSlug={objectSlug}
excludedFieldTypes={excludedFieldTypes}
/>
</SettingsPageContainer>
</SubMenuTopBarContainer>
</FormProvider>
</RecordFieldValueSelectorContextProvider>
);
};

View File

@ -1,133 +0,0 @@
import styled from '@emotion/styled';
import { useEffect } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { H2Title, IconHierarchy2, IconPlus } from 'twenty-ui';
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
import { SaveAndCancelButtons } from '@/settings/components/SaveAndCancelButtons/SaveAndCancelButtons';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { useFieldMetadataItem } from '@/object-metadata/hooks/useFieldMetadataItem';
import { settingsObjectFieldsFamilyState } from '@/settings/data-model/object-details/states/settingsObjectFieldsFamilyState';
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { AppPath } from '@/types/AppPath';
import { SettingsPath } from '@/types/SettingsPath';
import { Button } from '@/ui/input/button/components/Button';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { Section } from '@/ui/layout/section/components/Section';
import { useRecoilState } from 'recoil';
import { SettingsObjectFieldTable } from '~/pages/settings/data-model/SettingsObjectFieldTable';
const StyledSection = styled(Section)`
display: flex;
flex-direction: column;
`;
const StyledAddCustomFieldButton = styled(Button)`
align-self: flex-end;
margin-top: ${({ theme }) => theme.spacing(2)};
`;
export const SettingsObjectNewFieldStep1 = () => {
const navigate = useNavigate();
const { objectSlug = '' } = useParams();
const { findActiveObjectMetadataItemBySlug } =
useFilteredObjectMetadataItems();
const activeObjectMetadataItem =
findActiveObjectMetadataItemBySlug(objectSlug);
const [settingsObjectFields] = useRecoilState(
settingsObjectFieldsFamilyState({
objectMetadataItemId: activeObjectMetadataItem?.id,
}),
);
const { activateMetadataField, deactivateMetadataField } =
useFieldMetadataItem();
const canSave = settingsObjectFields?.some(
(field, index) =>
field.isActive !== activeObjectMetadataItem?.fields[index].isActive,
);
const handleSave = async () => {
if (!activeObjectMetadataItem || !settingsObjectFields) {
return;
}
await Promise.all(
settingsObjectFields.map((fieldMetadataItem, index) => {
if (
fieldMetadataItem.isActive ===
activeObjectMetadataItem.fields[index].isActive
) {
return undefined;
}
return fieldMetadataItem.isActive
? activateMetadataField(fieldMetadataItem)
: deactivateMetadataField(fieldMetadataItem);
}),
);
navigate(`/settings/objects/${objectSlug}`);
};
useEffect(() => {
if (!activeObjectMetadataItem) {
navigate(AppPath.NotFound);
return;
}
}, [activeObjectMetadataItem, navigate]);
if (!activeObjectMetadataItem) return null;
return (
<SubMenuTopBarContainer
Icon={IconHierarchy2}
links={[
{
children: 'Workspace',
href: getSettingsPagePath(SettingsPath.Workspace),
},
{ children: 'Objects', href: '/settings/objects' },
{
children: activeObjectMetadataItem.labelPlural,
href: `/settings/objects/${objectSlug}`,
},
{ children: 'New Field' },
]}
actionButton={
!activeObjectMetadataItem.isRemote && (
<SaveAndCancelButtons
isSaveDisabled={!canSave}
onCancel={() => navigate(`/settings/objects/${objectSlug}`)}
onSave={handleSave}
/>
)
}
>
<SettingsPageContainer>
<StyledSection>
<H2Title
title="Check deactivated fields"
description="Before creating a custom field, check if it already exists in the deactivated section."
/>
<SettingsObjectFieldTable
objectMetadataItem={activeObjectMetadataItem}
mode="new-field"
/>
<StyledAddCustomFieldButton
Icon={IconPlus}
title="Add Custom Field"
size="small"
variant="secondary"
to={`/settings/objects/${objectSlug}/new-field/step-2`}
/>
</StyledSection>
</SettingsPageContainer>
</SubMenuTopBarContainer>
);
};

View File

@ -4,12 +4,10 @@ import { SettingsDataModelOverview } from '@/settings/data-model/graph-overview/
import { getSettingsPagePath } from '@/settings/utils/getSettingsPagePath';
import { SettingsPath } from '@/types/SettingsPath';
import { SubMenuTopBarContainer } from '@/ui/layout/page/SubMenuTopBarContainer';
import { IconHierarchy2 } from 'twenty-ui';
export const SettingsObjectOverview = () => {
return (
<SubMenuTopBarContainer
Icon={IconHierarchy2}
links={[
{
children: 'Workspace',

View File

@ -1,12 +1,6 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import {
H2Title,
IconChevronRight,
IconHierarchy2,
IconPlus,
IconSearch,
} from 'twenty-ui';
import { H2Title, IconChevronRight, IconPlus, IconSearch } from 'twenty-ui';
import { useDeleteOneObjectMetadataItem } from '@/object-metadata/hooks/useDeleteOneObjectMetadataItem';
import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems';
@ -133,7 +127,6 @@ export const SettingsObjects = () => {
);
return (
<SubMenuTopBarContainer
Icon={IconHierarchy2}
title="Data model"
actionButton={
<UndecoratedLink to={getSettingsPagePath(SettingsPath.NewObject)}>

View File

@ -1,5 +1,6 @@
import { Meta, StoryObj } from '@storybook/react';
import { userEvent, within } from '@storybook/test';
import { SettingsObjectNewFieldConfigure } from '~/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldConfigure';
import {
PageDecorator,
@ -7,15 +8,13 @@ import {
} from '~/testing/decorators/PageDecorator';
import { graphqlMocks } from '~/testing/graphqlMocks';
import { SettingsObjectNewFieldStep2 } from '../../SettingsObjectNewField/SettingsObjectNewFieldStep2';
const meta: Meta<PageDecoratorArgs> = {
title:
'Pages/Settings/DataModel/SettingsObjectNewField/SettingsObjectNewFieldStep2',
component: SettingsObjectNewFieldStep2,
'Pages/Settings/DataModel/SettingsObjectNewField/SettingsObjectNewFieldConfigure',
component: SettingsObjectNewFieldConfigure,
decorators: [PageDecorator],
args: {
routePath: '/settings/objects/:objectSlug/new-field/step-2',
routePath: '/settings/objects/:objectSlug/new-field/configure',
routeParams: { ':objectSlug': 'companies' },
},
parameters: {
@ -25,21 +24,11 @@ const meta: Meta<PageDecoratorArgs> = {
export default meta;
export type Story = StoryObj<typeof SettingsObjectNewFieldStep2>;
export type Story = StoryObj<typeof SettingsObjectNewFieldConfigure>;
export const Default: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await canvas.findByText('Objects');
await canvas.findByText('1. Select a field type');
const searchInput = await canvas.findByPlaceholderText('Search a type');
await userEvent.type(searchInput, 'Num');
const numberTypeButton = await canvas.findByText('Number');
await userEvent.click(numberTypeButton);
await canvas.findByText('2. Configure field');
@ -49,11 +38,10 @@ export const Default: Story = {
const descriptionInput = await canvas.findByPlaceholderText(
'Write a description',
);
await userEvent.type(descriptionInput, 'Test description');
const saveButton = await canvas.findByText('Save');
await new Promise((resolve) => setTimeout(resolve, 5000));
await userEvent.click(saveButton);
},
};

View File

@ -0,0 +1,41 @@
import { Meta, StoryObj } from '@storybook/react';
import { userEvent, within } from '@storybook/test';
import { SettingsObjectNewFieldSelect } from '~/pages/settings/data-model/SettingsObjectNewField/SettingsObjectNewFieldSelect';
import {
PageDecorator,
PageDecoratorArgs,
} from '~/testing/decorators/PageDecorator';
import { graphqlMocks } from '~/testing/graphqlMocks';
const meta: Meta<PageDecoratorArgs> = {
title:
'Pages/Settings/DataModel/SettingsObjectNewField/SettingsObjectNewFieldSelect',
component: SettingsObjectNewFieldSelect,
decorators: [PageDecorator],
args: {
routePath: '/settings/objects/:objectSlug/new-field/select',
routeParams: { ':objectSlug': 'companies' },
},
parameters: {
msw: graphqlMocks,
},
};
export default meta;
export type Story = StoryObj<typeof SettingsObjectNewFieldSelect>;
export const Default: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await canvas.findByText('Objects');
await canvas.findByText('1. Select a field type');
const searchInput = await canvas.findByPlaceholderText('Search a type');
await userEvent.type(searchInput, 'Rela');
await new Promise((resolve) => setTimeout(resolve, 1500));
await userEvent.clear(searchInput);
await userEvent.type(searchInput, 'Num');
await new Promise((resolve) => setTimeout(resolve, 1500));
},
};

View File

@ -1,38 +0,0 @@
import { Meta, StoryObj } from '@storybook/react';
import { within } from '@storybook/test';
import {
PageDecorator,
PageDecoratorArgs,
} from '~/testing/decorators/PageDecorator';
import { graphqlMocks } from '~/testing/graphqlMocks';
import { SettingsObjectNewFieldStep1 } from '../../SettingsObjectNewField/SettingsObjectNewFieldStep1';
const meta: Meta<PageDecoratorArgs> = {
title:
'Pages/Settings/DataModel/SettingsObjectNewField/SettingsObjectNewFieldStep1',
component: SettingsObjectNewFieldStep1,
decorators: [PageDecorator],
args: {
routePath: '/settings/objects/:objectSlug/new-field/step-1',
routeParams: { ':objectSlug': 'companies' },
},
parameters: {
msw: graphqlMocks,
},
};
export default meta;
export type Story = StoryObj<typeof SettingsObjectNewFieldStep1>;
export const Default: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await canvas.findByText('Objects');
await canvas.findByText('Companies');
await canvas.findByText('Check deactivated fields');
await canvas.findByText('Add Custom Field');
},
};