feat: add Object Edit form (#2090)

Closes #1910
This commit is contained in:
Thaïs
2023-10-17 21:03:59 +02:00
committed by GitHub
parent 54735c4880
commit 8894c52202
7 changed files with 103 additions and 11 deletions

View File

@ -0,0 +1,53 @@
import styled from '@emotion/styled';
import { H2Title } from '@/ui/display/typography/components/H2Title';
import { AutosizeTextInput } from '@/ui/input/components/AutosizeTextInput';
import { TextInput } from '@/ui/input/components/TextInput';
import { Section } from '@/ui/layout/section/components/Section';
type SettingsObjectFormSectionProps = {
singularName?: string;
pluralName?: string;
description?: string;
};
const StyledInputsContainer = styled.div`
display: flex;
gap: ${({ theme }) => theme.spacing(2)};
margin-bottom: ${({ theme }) => theme.spacing(2)};
width: 100%;
`;
const StyledTextInput = styled(TextInput)`
flex: 1 0 auto;
`;
export const SettingsObjectFormSection = ({
singularName,
pluralName,
description,
}: SettingsObjectFormSectionProps) => (
<Section>
<H2Title
title="Name and description"
description="Name in both singular (e.g., 'Invoice') and plural (e.g., 'Invoices') forms."
/>
<StyledInputsContainer>
<StyledTextInput
label="Singular"
placeholder="Invoice"
value={singularName}
/>
<StyledTextInput
label="Plural"
placeholder="Invoices"
value={pluralName}
/>
</StyledInputsContainer>
<AutosizeTextInput
placeholder="Write a description"
minRows={4}
value={description}
/>
</Section>
);

View File

@ -0,0 +1,24 @@
import { Meta, StoryObj } from '@storybook/react';
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
import { SettingsObjectFormSection } from '../SettingsObjectFormSection';
const meta: Meta<typeof SettingsObjectFormSection> = {
title: 'Modules/Settings/DataModel/SettingsObjectFormSection',
component: SettingsObjectFormSection,
decorators: [ComponentDecorator],
};
export default meta;
type Story = StoryObj<typeof SettingsObjectFormSection>;
export const Default: Story = {};
export const WithDefaultValues: Story = {
args: {
singularName: 'Company',
pluralName: 'Companies',
description: 'Lorem ipsum',
},
};

View File

@ -20,15 +20,16 @@ import { ObjectFieldItem } from '../types/ObjectFieldItem';
export const activeObjectItems = [ export const activeObjectItems = [
{ {
name: 'Companies', name: 'Companies',
singularName: 'company', singularName: 'Company',
Icon: IconBuildingSkyscraper, Icon: IconBuildingSkyscraper,
type: 'standard', type: 'standard',
fields: 23, fields: 23,
instances: 165, instances: 165,
description: 'Lorem ipsum',
}, },
{ {
name: 'People', name: 'People',
singularName: 'person', singularName: 'Person',
Icon: IconUser, Icon: IconUser,
type: 'standard', type: 'standard',
fields: 16, fields: 16,

View File

@ -3,6 +3,7 @@ import styled from '@emotion/styled';
import { IconComponent } from '@/ui/display/icon/types/IconComponent'; import { IconComponent } from '@/ui/display/icon/types/IconComponent';
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 { Section } from '@/ui/layout/section/components/Section';
import ArrowRight from '../assets/ArrowRight.svg'; import ArrowRight from '../assets/ArrowRight.svg';
@ -33,7 +34,7 @@ export const SettingsObjectIconSection = ({
setIconPicker, setIconPicker,
}: SettingsObjectIconSectionProps) => { }: SettingsObjectIconSectionProps) => {
return ( return (
<section> <Section>
<H2Title <H2Title
title="Icon" title="Icon"
description="The icon that will be displayed in the sidebar." description="The icon that will be displayed in the sidebar."
@ -50,6 +51,6 @@ export const SettingsObjectIconSection = ({
</StyledArrowContainer> </StyledArrowContainer>
<SettingsObjectIconWithLabel Icon={Icon} label="Workspaces" /> <SettingsObjectIconWithLabel Icon={Icon} label="Workspaces" />
</StyledContainer> </StyledContainer>
</section> </Section>
); );
}; };

View File

@ -13,6 +13,7 @@ import { InputHotkeyScope } from '../types/InputHotkeyScope';
const MAX_ROWS = 5; const MAX_ROWS = 5;
export enum AutosizeTextInputVariant { export enum AutosizeTextInputVariant {
Default = 'default',
Icon = 'icon', Icon = 'icon',
Button = 'button', Button = 'button',
} }
@ -24,6 +25,7 @@ type AutosizeTextInputProps = {
onFocus?: () => void; onFocus?: () => void;
variant?: AutosizeTextInputVariant; variant?: AutosizeTextInputVariant;
buttonTitle?: string; buttonTitle?: string;
value?: string;
}; };
const StyledContainer = styled.div` const StyledContainer = styled.div`
@ -112,14 +114,15 @@ export const AutosizeTextInput = ({
onValidate, onValidate,
minRows = 1, minRows = 1,
onFocus, onFocus,
variant = AutosizeTextInputVariant.Icon, variant = AutosizeTextInputVariant.Default,
buttonTitle, buttonTitle,
value = '',
}: AutosizeTextInputProps) => { }: AutosizeTextInputProps) => {
const [isFocused, setIsFocused] = useState(false); const [isFocused, setIsFocused] = useState(false);
const [isHidden, setIsHidden] = useState( const [isHidden, setIsHidden] = useState(
variant === AutosizeTextInputVariant.Button, variant === AutosizeTextInputVariant.Button,
); );
const [text, setText] = useState(''); const [text, setText] = useState(value);
const isSendButtonDisabled = !text; const isSendButtonDisabled = !text;
const words = text.split(/\s|\n/).filter((word) => word).length; const words = text.split(/\s|\n/).filter((word) => word).length;

View File

@ -23,6 +23,7 @@ type TextInputComponentProps = Omit<
InputHTMLAttributes<HTMLInputElement>, InputHTMLAttributes<HTMLInputElement>,
'onChange' 'onChange'
> & { > & {
className?: string;
label?: string; label?: string;
onChange?: (text: string) => void; onChange?: (text: string) => void;
fullWidth?: boolean; fullWidth?: boolean;
@ -103,6 +104,7 @@ const INPUT_TYPE_PASSWORD = 'password';
const TextInputComponent = ( const TextInputComponent = (
{ {
className,
label, label,
value, value,
onChange, onChange,
@ -160,7 +162,7 @@ const TextInputComponent = (
}; };
return ( return (
<StyledContainer fullWidth={fullWidth ?? false}> <StyledContainer className={className} fullWidth={fullWidth ?? false}>
{label && <StyledLabel>{label + (required ? '*' : '')}</StyledLabel>} {label && <StyledLabel>{label + (required ? '*' : '')}</StyledLabel>}
<StyledInputContainer> <StyledInputContainer>
<StyledInput <StyledInput

View File

@ -2,6 +2,7 @@ import { useEffect } from 'react';
import { useNavigate, useParams } from 'react-router-dom'; import { useNavigate, useParams } from 'react-router-dom';
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer'; import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
import { SettingsObjectFormSection } from '@/settings/data-model/components/SettingsObjectFormSection';
import { activeObjectItems } from '@/settings/data-model/constants/mockObjects'; import { activeObjectItems } from '@/settings/data-model/constants/mockObjects';
import { SettingsObjectIconSection } from '@/settings/data-model/object-edit/SettingsObjectIconSection'; import { SettingsObjectIconSection } from '@/settings/data-model/object-edit/SettingsObjectIconSection';
import { AppPath } from '@/types/AppPath'; import { AppPath } from '@/types/AppPath';
@ -34,10 +35,17 @@ export const SettingsObjectEdit = () => {
]} ]}
/> />
{activeObject && ( {activeObject && (
<SettingsObjectIconSection <>
Icon={activeObject.Icon} <SettingsObjectIconSection
iconKey={activeObject.Icon.name} Icon={activeObject.Icon}
/> iconKey={activeObject.Icon.name}
/>
<SettingsObjectFormSection
singularName={activeObject.singularName}
pluralName={activeObject.name}
description={activeObject.description}
/>
</>
)} )}
</SettingsPageContainer> </SettingsPageContainer>
</SubMenuTopBarContainer> </SubMenuTopBarContainer>