feat: add Object Edit Settings section with Object preview (#4216)
* feat: add Object Edit Settings section with Object preview Closes #3834 * fix: fix preview card stories * test: improve getFieldDefaultPreviewValue tests * test: add getFieldPreviewValueFromRecord tests * test: add useFieldPreview tests * refactor: rename and move components * fix: restore RecordStoreDecorator
This commit is contained in:
@ -4,14 +4,12 @@ import styled from '@emotion/styled';
|
||||
import { Card } from '@/ui/layout/card/components/Card';
|
||||
import { CardContent } from '@/ui/layout/card/components/CardContent';
|
||||
|
||||
type SettingsObjectFieldTypeCardProps = {
|
||||
type SettingsDataModelPreviewFormCardProps = {
|
||||
className?: string;
|
||||
preview: ReactNode;
|
||||
form?: ReactNode;
|
||||
};
|
||||
|
||||
const StyledCard = styled(Card)``;
|
||||
|
||||
const StyledPreviewContainer = styled(CardContent)`
|
||||
background-color: ${({ theme }) => theme.background.transparent.lighter};
|
||||
`;
|
||||
@ -24,27 +22,20 @@ const StyledTitle = styled.h3`
|
||||
margin-bottom: ${({ theme }) => theme.spacing(4)};
|
||||
`;
|
||||
|
||||
const StyledPreviewContent = styled.div`
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
`;
|
||||
|
||||
const StyledFormContainer = styled(CardContent)`
|
||||
padding: 0;
|
||||
`;
|
||||
|
||||
export const SettingsObjectFieldTypeCard = ({
|
||||
export const SettingsDataModelPreviewFormCard = ({
|
||||
className,
|
||||
preview,
|
||||
form,
|
||||
}: SettingsObjectFieldTypeCardProps) => {
|
||||
return (
|
||||
<StyledCard className={className}>
|
||||
<StyledPreviewContainer divider={!!form}>
|
||||
<StyledTitle>Preview</StyledTitle>
|
||||
<StyledPreviewContent>{preview}</StyledPreviewContent>
|
||||
</StyledPreviewContainer>
|
||||
{!!form && <StyledFormContainer>{form}</StyledFormContainer>}
|
||||
</StyledCard>
|
||||
);
|
||||
};
|
||||
}: SettingsDataModelPreviewFormCardProps) => (
|
||||
<Card className={className} fullWidth>
|
||||
<StyledPreviewContainer divider={!!form}>
|
||||
<StyledTitle>Preview</StyledTitle>
|
||||
{preview}
|
||||
</StyledPreviewContainer>
|
||||
{!!form && <StyledFormContainer>{form}</StyledFormContainer>}
|
||||
</Card>
|
||||
);
|
||||
@ -1,165 +0,0 @@
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { parseFieldType } from '@/object-metadata/utils/parseFieldType';
|
||||
import { FieldDisplay } from '@/object-record/record-field/components/FieldDisplay';
|
||||
import { FieldContext } from '@/object-record/record-field/contexts/FieldContext';
|
||||
import { BooleanFieldInput } from '@/object-record/record-field/meta-types/input/components/BooleanFieldInput';
|
||||
import { RatingFieldInput } from '@/object-record/record-field/meta-types/input/components/RatingFieldInput';
|
||||
import { Tag } from '@/ui/display/tag/components/Tag';
|
||||
import { Card } from '@/ui/layout/card/components/Card';
|
||||
import { CardContent } from '@/ui/layout/card/components/CardContent';
|
||||
import { Field, FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
import { SettingsObjectFieldPreviewValueEffect } from '../components/SettingsObjectFieldPreviewValueEffect';
|
||||
import { useFieldPreview } from '../hooks/useFieldPreview';
|
||||
|
||||
import { SettingsObjectFieldSelectFormValues } from './SettingsObjectFieldSelectForm';
|
||||
|
||||
export type SettingsObjectFieldPreviewProps = {
|
||||
className?: string;
|
||||
fieldMetadata: Pick<Field, 'icon' | 'label' | 'type'> & { id?: string };
|
||||
objectMetadataId: string;
|
||||
relationObjectMetadataId?: string;
|
||||
selectOptions?: SettingsObjectFieldSelectFormValues;
|
||||
shrink?: boolean;
|
||||
};
|
||||
|
||||
const StyledCard = styled(Card)`
|
||||
border-radius: ${({ theme }) => theme.border.radius.md};
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
max-width: 480px;
|
||||
`;
|
||||
|
||||
const StyledCardContent = styled(CardContent)`
|
||||
display: grid;
|
||||
padding: ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
||||
|
||||
const StyledObjectSummary = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
justify-content: space-between;
|
||||
margin-bottom: ${({ theme }) => theme.spacing(2)};
|
||||
`;
|
||||
|
||||
const StyledObjectName = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
font-weight: ${({ theme }) => theme.font.weight.medium};
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
`;
|
||||
|
||||
const StyledFieldPreview = styled.div<{ shrink?: boolean }>`
|
||||
align-items: center;
|
||||
background-color: ${({ theme }) => theme.background.primary};
|
||||
border: 1px solid ${({ theme }) => theme.border.color.medium};
|
||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(2)};
|
||||
height: ${({ theme }) => theme.spacing(8)};
|
||||
overflow: hidden;
|
||||
padding: 0
|
||||
${({ shrink, theme }) => (shrink ? theme.spacing(1) : theme.spacing(2))};
|
||||
white-space: nowrap;
|
||||
`;
|
||||
|
||||
const StyledFieldLabel = styled.div`
|
||||
align-items: center;
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
display: flex;
|
||||
gap: ${({ theme }) => theme.spacing(1)};
|
||||
`;
|
||||
|
||||
export const SettingsObjectFieldPreview = ({
|
||||
className,
|
||||
fieldMetadata,
|
||||
objectMetadataId,
|
||||
relationObjectMetadataId,
|
||||
selectOptions,
|
||||
shrink,
|
||||
}: SettingsObjectFieldPreviewProps) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const {
|
||||
entityId,
|
||||
FieldIcon,
|
||||
fieldName,
|
||||
ObjectIcon,
|
||||
objectMetadataItem,
|
||||
relationObjectMetadataItem,
|
||||
value,
|
||||
} = useFieldPreview({
|
||||
fieldMetadata,
|
||||
objectMetadataId,
|
||||
relationObjectMetadataId,
|
||||
selectOptions,
|
||||
});
|
||||
|
||||
return (
|
||||
<StyledCard className={className}>
|
||||
<StyledCardContent>
|
||||
<StyledObjectSummary>
|
||||
<StyledObjectName>
|
||||
{!!ObjectIcon && (
|
||||
<ObjectIcon
|
||||
size={theme.icon.size.sm}
|
||||
stroke={theme.icon.stroke.md}
|
||||
/>
|
||||
)}
|
||||
{objectMetadataItem?.labelPlural}
|
||||
</StyledObjectName>
|
||||
{objectMetadataItem?.isCustom ? (
|
||||
<Tag color="orange" text="Custom" weight="medium" />
|
||||
) : (
|
||||
<Tag color="blue" text="Standard" weight="medium" />
|
||||
)}
|
||||
</StyledObjectSummary>
|
||||
<SettingsObjectFieldPreviewValueEffect
|
||||
entityId={entityId}
|
||||
fieldName={fieldName}
|
||||
value={value}
|
||||
/>
|
||||
<StyledFieldPreview shrink={shrink}>
|
||||
<StyledFieldLabel>
|
||||
{!!FieldIcon && (
|
||||
<FieldIcon
|
||||
size={theme.icon.size.md}
|
||||
stroke={theme.icon.stroke.sm}
|
||||
/>
|
||||
)}
|
||||
{fieldMetadata.label}:
|
||||
</StyledFieldLabel>
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
entityId,
|
||||
isLabelIdentifier: false,
|
||||
fieldDefinition: {
|
||||
type: parseFieldType(fieldMetadata.type),
|
||||
iconName: 'FieldIcon',
|
||||
fieldMetadataId: fieldMetadata.id || '',
|
||||
label: fieldMetadata.label,
|
||||
metadata: {
|
||||
fieldName,
|
||||
relationObjectMetadataNameSingular:
|
||||
relationObjectMetadataItem?.nameSingular,
|
||||
options: selectOptions,
|
||||
},
|
||||
},
|
||||
hotkeyScope: 'field-preview',
|
||||
}}
|
||||
>
|
||||
{fieldMetadata.type === FieldMetadataType.Boolean ? (
|
||||
<BooleanFieldInput readonly />
|
||||
) : fieldMetadata.type === FieldMetadataType.Rating ? (
|
||||
<RatingFieldInput readonly />
|
||||
) : (
|
||||
<FieldDisplay />
|
||||
)}
|
||||
</FieldContext.Provider>
|
||||
</StyledFieldPreview>
|
||||
</StyledCardContent>
|
||||
</StyledCard>
|
||||
);
|
||||
};
|
||||
@ -1,29 +0,0 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
import { recordStoreFamilySelector } from '@/object-record/record-store/states/selectors/recordStoreFamilySelector';
|
||||
|
||||
type SettingsObjectFieldPreviewValueEffectProps = {
|
||||
entityId: string;
|
||||
fieldName: string;
|
||||
value: unknown;
|
||||
};
|
||||
|
||||
export const SettingsObjectFieldPreviewValueEffect = ({
|
||||
entityId,
|
||||
fieldName,
|
||||
value,
|
||||
}: SettingsObjectFieldPreviewValueEffectProps) => {
|
||||
const setFieldValue = useSetRecoilState(
|
||||
recordStoreFamilySelector({
|
||||
recordId: entityId,
|
||||
fieldName,
|
||||
}),
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
setFieldValue(value);
|
||||
}, [value, setFieldValue]);
|
||||
|
||||
return null;
|
||||
};
|
||||
@ -1,183 +0,0 @@
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { RELATION_TYPES } from '@/settings/data-model/constants/RelationTypes';
|
||||
import { SETTINGS_FIELD_METADATA_TYPES } from '@/settings/data-model/constants/SettingsFieldMetadataTypes';
|
||||
import { H2Title } from '@/ui/display/typography/components/H2Title';
|
||||
import { Select } from '@/ui/input/components/Select';
|
||||
import { Section } from '@/ui/layout/section/components/Section';
|
||||
import { Field, FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
|
||||
import {
|
||||
SettingsObjectFieldCurrencyForm,
|
||||
SettingsObjectFieldCurrencyFormValues,
|
||||
} from './SettingsObjectFieldCurrencyForm';
|
||||
import {
|
||||
SettingsObjectFieldPreview,
|
||||
SettingsObjectFieldPreviewProps,
|
||||
} from './SettingsObjectFieldPreview';
|
||||
import {
|
||||
SettingsObjectFieldRelationForm,
|
||||
SettingsObjectFieldRelationFormValues,
|
||||
} from './SettingsObjectFieldRelationForm';
|
||||
import {
|
||||
SettingsObjectFieldSelectForm,
|
||||
SettingsObjectFieldSelectFormValues,
|
||||
} from './SettingsObjectFieldSelectForm';
|
||||
import { SettingsObjectFieldTypeCard } from './SettingsObjectFieldTypeCard';
|
||||
|
||||
export type SettingsObjectFieldTypeSelectSectionFormValues = {
|
||||
type: FieldMetadataType;
|
||||
currency: SettingsObjectFieldCurrencyFormValues;
|
||||
relation: SettingsObjectFieldRelationFormValues;
|
||||
select: SettingsObjectFieldSelectFormValues;
|
||||
};
|
||||
|
||||
type SettingsObjectFieldTypeSelectSectionProps = {
|
||||
disableCurrencyForm?: boolean;
|
||||
excludedFieldTypes?: FieldMetadataType[];
|
||||
fieldMetadata: Pick<Field, 'icon' | 'label'> & { id?: string };
|
||||
onChange: (
|
||||
values: Partial<SettingsObjectFieldTypeSelectSectionFormValues>,
|
||||
) => void;
|
||||
relationFieldMetadata?: Pick<Field, 'id' | 'isCustom'>;
|
||||
values: SettingsObjectFieldTypeSelectSectionFormValues;
|
||||
} & Pick<SettingsObjectFieldPreviewProps, 'objectMetadataId'>;
|
||||
|
||||
const StyledSettingsObjectFieldTypeCard = styled(SettingsObjectFieldTypeCard)`
|
||||
margin-top: ${({ theme }) => theme.spacing(4)};
|
||||
`;
|
||||
|
||||
const StyledSettingsObjectFieldPreview = styled(SettingsObjectFieldPreview)`
|
||||
display: grid;
|
||||
flex: 1 1 100%;
|
||||
`;
|
||||
|
||||
const StyledRelationImage = styled.img<{ flip?: boolean }>`
|
||||
transform: ${({ flip }) => (flip ? 'scaleX(-1)' : 'none')};
|
||||
width: 54px;
|
||||
`;
|
||||
|
||||
export const SettingsObjectFieldTypeSelectSection = ({
|
||||
disableCurrencyForm,
|
||||
excludedFieldTypes,
|
||||
fieldMetadata,
|
||||
objectMetadataId,
|
||||
onChange,
|
||||
relationFieldMetadata,
|
||||
values,
|
||||
}: SettingsObjectFieldTypeSelectSectionProps) => {
|
||||
const currencyFormConfig = values.currency;
|
||||
const relationFormConfig = values.relation;
|
||||
const selectFormConfig = values.select;
|
||||
|
||||
const fieldTypeOptions = Object.entries(SETTINGS_FIELD_METADATA_TYPES)
|
||||
.filter(([key]) => !excludedFieldTypes?.includes(key as FieldMetadataType))
|
||||
.map(([key, dataTypeConfig]) => ({
|
||||
value: key as FieldMetadataType,
|
||||
...dataTypeConfig,
|
||||
}));
|
||||
|
||||
return (
|
||||
<Section>
|
||||
<H2Title
|
||||
title="Type and values"
|
||||
description="The field's type and values."
|
||||
/>
|
||||
<Select
|
||||
fullWidth
|
||||
disabled={!!fieldMetadata?.id}
|
||||
dropdownId="object-field-type-select"
|
||||
value={values?.type}
|
||||
onChange={(value) => onChange({ type: value })}
|
||||
options={fieldTypeOptions}
|
||||
/>
|
||||
{!!values?.type &&
|
||||
[
|
||||
FieldMetadataType.Boolean,
|
||||
FieldMetadataType.Currency,
|
||||
FieldMetadataType.DateTime,
|
||||
FieldMetadataType.Select,
|
||||
FieldMetadataType.Link,
|
||||
FieldMetadataType.Number,
|
||||
FieldMetadataType.Rating,
|
||||
FieldMetadataType.Relation,
|
||||
FieldMetadataType.Text,
|
||||
].includes(values.type) && (
|
||||
<StyledSettingsObjectFieldTypeCard
|
||||
preview={
|
||||
<>
|
||||
<StyledSettingsObjectFieldPreview
|
||||
fieldMetadata={{
|
||||
...fieldMetadata,
|
||||
type: values.type,
|
||||
}}
|
||||
shrink={values.type === FieldMetadataType.Relation}
|
||||
objectMetadataId={objectMetadataId}
|
||||
relationObjectMetadataId={
|
||||
relationFormConfig?.objectMetadataId
|
||||
}
|
||||
selectOptions={selectFormConfig}
|
||||
/>
|
||||
{values.type === FieldMetadataType.Relation &&
|
||||
!!relationFormConfig?.type &&
|
||||
!!relationFormConfig.objectMetadataId && (
|
||||
<>
|
||||
<StyledRelationImage
|
||||
src={RELATION_TYPES[relationFormConfig.type].imageSrc}
|
||||
flip={
|
||||
RELATION_TYPES[relationFormConfig.type].isImageFlipped
|
||||
}
|
||||
alt={RELATION_TYPES[relationFormConfig.type].label}
|
||||
/>
|
||||
<StyledSettingsObjectFieldPreview
|
||||
fieldMetadata={{
|
||||
...relationFormConfig.field,
|
||||
label:
|
||||
relationFormConfig.field?.label || 'Field name',
|
||||
type: FieldMetadataType.Relation,
|
||||
id: relationFieldMetadata?.id,
|
||||
}}
|
||||
shrink
|
||||
objectMetadataId={relationFormConfig.objectMetadataId}
|
||||
relationObjectMetadataId={objectMetadataId}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
form={
|
||||
values.type === FieldMetadataType.Currency ? (
|
||||
<SettingsObjectFieldCurrencyForm
|
||||
disabled={disableCurrencyForm}
|
||||
values={currencyFormConfig}
|
||||
onChange={(nextValues) =>
|
||||
onChange({
|
||||
currency: { ...currencyFormConfig, ...nextValues },
|
||||
})
|
||||
}
|
||||
/>
|
||||
) : values.type === FieldMetadataType.Relation ? (
|
||||
<SettingsObjectFieldRelationForm
|
||||
disableFieldEdition={
|
||||
relationFieldMetadata && !relationFieldMetadata.isCustom
|
||||
}
|
||||
disableRelationEdition={!!relationFieldMetadata}
|
||||
values={relationFormConfig}
|
||||
onChange={(nextValues) =>
|
||||
onChange({
|
||||
relation: { ...relationFormConfig, ...nextValues },
|
||||
})
|
||||
}
|
||||
/>
|
||||
) : values.type === FieldMetadataType.Select ? (
|
||||
<SettingsObjectFieldSelectForm
|
||||
values={selectFormConfig}
|
||||
onChange={(nextValues) => onChange({ select: nextValues })}
|
||||
/>
|
||||
) : undefined
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
@ -1,128 +0,0 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { Field, FieldMetadataType } from '~/generated-metadata/graphql';
|
||||
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||
import { MemoryRouterDecorator } from '~/testing/decorators/MemoryRouterDecorator';
|
||||
import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator';
|
||||
import { RecordStoreDecorator } from '~/testing/decorators/RecordStoreDecorator';
|
||||
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import {
|
||||
mockedCompaniesMetadata,
|
||||
mockedPeopleMetadata,
|
||||
} from '~/testing/mock-data/metadata';
|
||||
|
||||
import { SettingsObjectFieldPreview } from '../SettingsObjectFieldPreview';
|
||||
|
||||
const meta: Meta<typeof SettingsObjectFieldPreview> = {
|
||||
title: 'Modules/Settings/DataModel/SettingsObjectFieldPreview',
|
||||
component: SettingsObjectFieldPreview,
|
||||
decorators: [
|
||||
RecordStoreDecorator,
|
||||
ComponentDecorator,
|
||||
ObjectMetadataItemsDecorator,
|
||||
SnackBarDecorator,
|
||||
],
|
||||
args: {
|
||||
fieldMetadata: mockedCompaniesMetadata.node.fields.edges.find(
|
||||
({ node }) => node.type === FieldMetadataType.Text,
|
||||
)?.node as Field,
|
||||
objectMetadataId: mockedCompaniesMetadata.node.id,
|
||||
},
|
||||
parameters: {
|
||||
records: [
|
||||
{
|
||||
id: `${mockedCompaniesMetadata.node.id}-field-form`,
|
||||
domainName: 'Test',
|
||||
idealCustomerProfile: true,
|
||||
annualRecurringRevenue: {
|
||||
amountMicros: 1000000,
|
||||
currency: 'USD',
|
||||
},
|
||||
updatedAt: '2021-08-05T14:00:00.000Z',
|
||||
linkedinLink: {
|
||||
label: 'LinkedIn',
|
||||
url: 'https://linkedin.com',
|
||||
},
|
||||
employees: 100,
|
||||
},
|
||||
],
|
||||
msw: graphqlMocks,
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof SettingsObjectFieldPreview>;
|
||||
|
||||
export const Text: Story = {};
|
||||
|
||||
export const Boolean: Story = {
|
||||
args: {
|
||||
fieldMetadata: mockedCompaniesMetadata.node.fields.edges.find(
|
||||
({ node }) => node.type === FieldMetadataType.Boolean,
|
||||
)?.node as Field,
|
||||
},
|
||||
};
|
||||
|
||||
export const Currency: Story = {
|
||||
args: {
|
||||
fieldMetadata: mockedCompaniesMetadata.node.fields.edges.find(
|
||||
({ node }) => node.type === FieldMetadataType.Currency,
|
||||
)?.node as Field,
|
||||
},
|
||||
};
|
||||
|
||||
export const Date: Story = {
|
||||
args: {
|
||||
fieldMetadata: mockedCompaniesMetadata.node.fields.edges.find(
|
||||
({ node }) => node.type === FieldMetadataType.DateTime,
|
||||
)?.node as Field,
|
||||
},
|
||||
};
|
||||
|
||||
export const Link: Story = {
|
||||
decorators: [MemoryRouterDecorator],
|
||||
args: {
|
||||
fieldMetadata: mockedCompaniesMetadata.node.fields.edges.find(
|
||||
({ node }) => node.type === FieldMetadataType.Link,
|
||||
)?.node as Field,
|
||||
},
|
||||
};
|
||||
|
||||
export const Number: Story = {
|
||||
args: {
|
||||
fieldMetadata: mockedCompaniesMetadata.node.fields.edges.find(
|
||||
({ node }) => node.type === FieldMetadataType.Number,
|
||||
)?.node as Field,
|
||||
},
|
||||
};
|
||||
|
||||
export const Rating: Story = {
|
||||
args: {
|
||||
fieldMetadata: {
|
||||
icon: 'IconHandClick',
|
||||
label: 'Engagement',
|
||||
type: FieldMetadataType.Rating,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const Relation: Story = {
|
||||
decorators: [MemoryRouterDecorator],
|
||||
args: {
|
||||
fieldMetadata: mockedPeopleMetadata.node.fields.edges.find(
|
||||
({ node }) => node.type === FieldMetadataType.Relation,
|
||||
)?.node as Field,
|
||||
objectMetadataId: mockedPeopleMetadata.node.id,
|
||||
relationObjectMetadataId: mockedCompaniesMetadata.node.id,
|
||||
},
|
||||
};
|
||||
|
||||
export const CustomObject: Story = {
|
||||
args: {
|
||||
fieldMetadata: mockedCompaniesMetadata.node.fields.edges.find(
|
||||
({ node }) => node.isCustom,
|
||||
)?.node as Field,
|
||||
objectMetadataId: mockedCompaniesMetadata.node.id,
|
||||
},
|
||||
};
|
||||
@ -1,132 +0,0 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { userEvent, within } from '@storybook/test';
|
||||
import { fn } from '@storybook/test';
|
||||
|
||||
import {
|
||||
FieldMetadataType,
|
||||
RelationMetadataType,
|
||||
} from '~/generated-metadata/graphql';
|
||||
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||
import { MemoryRouterDecorator } from '~/testing/decorators/MemoryRouterDecorator';
|
||||
import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator';
|
||||
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import {
|
||||
mockedCompaniesMetadata,
|
||||
mockedPeopleMetadata,
|
||||
} from '~/testing/mock-data/metadata';
|
||||
|
||||
import { fieldMetadataFormDefaultValues } from '../../hooks/useFieldMetadataForm';
|
||||
import {
|
||||
SettingsObjectFieldTypeSelectSection,
|
||||
SettingsObjectFieldTypeSelectSectionFormValues,
|
||||
} from '../SettingsObjectFieldTypeSelectSection';
|
||||
|
||||
const fieldMetadata = mockedCompaniesMetadata.node.fields.edges.find(
|
||||
({ node }) => node.type === FieldMetadataType.Text,
|
||||
)!.node;
|
||||
const { id: _id, ...fieldMetadataWithoutId } = fieldMetadata;
|
||||
|
||||
const meta: Meta<typeof SettingsObjectFieldTypeSelectSection> = {
|
||||
title: 'Modules/Settings/DataModel/SettingsObjectFieldTypeSelectSection',
|
||||
component: SettingsObjectFieldTypeSelectSection,
|
||||
decorators: [
|
||||
ComponentDecorator,
|
||||
ObjectMetadataItemsDecorator,
|
||||
SnackBarDecorator,
|
||||
],
|
||||
args: {
|
||||
fieldMetadata: fieldMetadataWithoutId,
|
||||
objectMetadataId: mockedCompaniesMetadata.node.id,
|
||||
onChange: fn(),
|
||||
values: fieldMetadataFormDefaultValues,
|
||||
},
|
||||
parameters: {
|
||||
container: { width: 512 },
|
||||
msw: graphqlMocks,
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof SettingsObjectFieldTypeSelectSection>;
|
||||
|
||||
export const Default: Story = {};
|
||||
|
||||
export const Disabled: Story = {
|
||||
args: {
|
||||
fieldMetadata,
|
||||
},
|
||||
};
|
||||
|
||||
export const WithOpenSelect: Story = {
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const inputField = await canvas.findByText('Text');
|
||||
|
||||
await userEvent.click(inputField);
|
||||
|
||||
const input = await canvas.findByText('Unique ID');
|
||||
await userEvent.click(input);
|
||||
|
||||
await userEvent.click(inputField);
|
||||
},
|
||||
};
|
||||
|
||||
const relationFieldMetadata = mockedPeopleMetadata.node.fields.edges.find(
|
||||
({ node }) => node.type === FieldMetadataType.Relation,
|
||||
)!.node;
|
||||
|
||||
export const WithRelationForm: Story = {
|
||||
decorators: [MemoryRouterDecorator],
|
||||
args: {
|
||||
fieldMetadata: mockedCompaniesMetadata.node.fields.edges.find(
|
||||
({ node }) => node.type === FieldMetadataType.Relation,
|
||||
)?.node,
|
||||
relationFieldMetadata,
|
||||
values: {
|
||||
...fieldMetadataFormDefaultValues,
|
||||
type: FieldMetadataType.Relation,
|
||||
relation: {
|
||||
field: relationFieldMetadata,
|
||||
objectMetadataId: mockedPeopleMetadata.node.id,
|
||||
type: RelationMetadataType.OneToMany,
|
||||
},
|
||||
} as unknown as SettingsObjectFieldTypeSelectSectionFormValues,
|
||||
},
|
||||
};
|
||||
|
||||
export const WithSelectForm: Story = {
|
||||
args: {
|
||||
fieldMetadata: { label: 'Industry', icon: 'IconBuildingFactory2' },
|
||||
values: {
|
||||
...fieldMetadataFormDefaultValues,
|
||||
type: FieldMetadataType.Select,
|
||||
select: [
|
||||
{
|
||||
color: 'pink',
|
||||
isDefault: true,
|
||||
label: '💊 Health',
|
||||
value: 'HEALTH',
|
||||
},
|
||||
{
|
||||
color: 'purple',
|
||||
label: '🏭 Industry',
|
||||
value: 'INDUSTRY',
|
||||
},
|
||||
{ color: 'sky', label: '🤖 SaaS', value: 'SAAS' },
|
||||
{
|
||||
color: 'turquoise',
|
||||
label: '🌿 Green tech',
|
||||
value: 'GREEN_TECH',
|
||||
},
|
||||
{
|
||||
color: 'yellow',
|
||||
label: '🚲 Mobility',
|
||||
value: 'MOBILITY',
|
||||
},
|
||||
{ color: 'green', label: '🌏 NGO', value: 'NGO' },
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user