@ -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>
|
||||
);
|
||||
@ -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',
|
||||
},
|
||||
};
|
||||
@ -20,15 +20,16 @@ import { ObjectFieldItem } from '../types/ObjectFieldItem';
|
||||
export const activeObjectItems = [
|
||||
{
|
||||
name: 'Companies',
|
||||
singularName: 'company',
|
||||
singularName: 'Company',
|
||||
Icon: IconBuildingSkyscraper,
|
||||
type: 'standard',
|
||||
fields: 23,
|
||||
instances: 165,
|
||||
description: 'Lorem ipsum',
|
||||
},
|
||||
{
|
||||
name: 'People',
|
||||
singularName: 'person',
|
||||
singularName: 'Person',
|
||||
Icon: IconUser,
|
||||
type: 'standard',
|
||||
fields: 16,
|
||||
|
||||
@ -3,6 +3,7 @@ import styled from '@emotion/styled';
|
||||
import { IconComponent } from '@/ui/display/icon/types/IconComponent';
|
||||
import { H2Title } from '@/ui/display/typography/components/H2Title';
|
||||
import { IconPicker } from '@/ui/input/components/IconPicker';
|
||||
import { Section } from '@/ui/layout/section/components/Section';
|
||||
|
||||
import ArrowRight from '../assets/ArrowRight.svg';
|
||||
|
||||
@ -33,7 +34,7 @@ export const SettingsObjectIconSection = ({
|
||||
setIconPicker,
|
||||
}: SettingsObjectIconSectionProps) => {
|
||||
return (
|
||||
<section>
|
||||
<Section>
|
||||
<H2Title
|
||||
title="Icon"
|
||||
description="The icon that will be displayed in the sidebar."
|
||||
@ -50,6 +51,6 @@ export const SettingsObjectIconSection = ({
|
||||
</StyledArrowContainer>
|
||||
<SettingsObjectIconWithLabel Icon={Icon} label="Workspaces" />
|
||||
</StyledContainer>
|
||||
</section>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
@ -13,6 +13,7 @@ import { InputHotkeyScope } from '../types/InputHotkeyScope';
|
||||
const MAX_ROWS = 5;
|
||||
|
||||
export enum AutosizeTextInputVariant {
|
||||
Default = 'default',
|
||||
Icon = 'icon',
|
||||
Button = 'button',
|
||||
}
|
||||
@ -24,6 +25,7 @@ type AutosizeTextInputProps = {
|
||||
onFocus?: () => void;
|
||||
variant?: AutosizeTextInputVariant;
|
||||
buttonTitle?: string;
|
||||
value?: string;
|
||||
};
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
@ -112,14 +114,15 @@ export const AutosizeTextInput = ({
|
||||
onValidate,
|
||||
minRows = 1,
|
||||
onFocus,
|
||||
variant = AutosizeTextInputVariant.Icon,
|
||||
variant = AutosizeTextInputVariant.Default,
|
||||
buttonTitle,
|
||||
value = '',
|
||||
}: AutosizeTextInputProps) => {
|
||||
const [isFocused, setIsFocused] = useState(false);
|
||||
const [isHidden, setIsHidden] = useState(
|
||||
variant === AutosizeTextInputVariant.Button,
|
||||
);
|
||||
const [text, setText] = useState('');
|
||||
const [text, setText] = useState(value);
|
||||
|
||||
const isSendButtonDisabled = !text;
|
||||
const words = text.split(/\s|\n/).filter((word) => word).length;
|
||||
|
||||
@ -23,6 +23,7 @@ type TextInputComponentProps = Omit<
|
||||
InputHTMLAttributes<HTMLInputElement>,
|
||||
'onChange'
|
||||
> & {
|
||||
className?: string;
|
||||
label?: string;
|
||||
onChange?: (text: string) => void;
|
||||
fullWidth?: boolean;
|
||||
@ -103,6 +104,7 @@ const INPUT_TYPE_PASSWORD = 'password';
|
||||
|
||||
const TextInputComponent = (
|
||||
{
|
||||
className,
|
||||
label,
|
||||
value,
|
||||
onChange,
|
||||
@ -160,7 +162,7 @@ const TextInputComponent = (
|
||||
};
|
||||
|
||||
return (
|
||||
<StyledContainer fullWidth={fullWidth ?? false}>
|
||||
<StyledContainer className={className} fullWidth={fullWidth ?? false}>
|
||||
{label && <StyledLabel>{label + (required ? '*' : '')}</StyledLabel>}
|
||||
<StyledInputContainer>
|
||||
<StyledInput
|
||||
|
||||
@ -2,6 +2,7 @@ import { useEffect } from 'react';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
|
||||
import { SettingsPageContainer } from '@/settings/components/SettingsPageContainer';
|
||||
import { SettingsObjectFormSection } from '@/settings/data-model/components/SettingsObjectFormSection';
|
||||
import { activeObjectItems } from '@/settings/data-model/constants/mockObjects';
|
||||
import { SettingsObjectIconSection } from '@/settings/data-model/object-edit/SettingsObjectIconSection';
|
||||
import { AppPath } from '@/types/AppPath';
|
||||
@ -34,10 +35,17 @@ export const SettingsObjectEdit = () => {
|
||||
]}
|
||||
/>
|
||||
{activeObject && (
|
||||
<SettingsObjectIconSection
|
||||
Icon={activeObject.Icon}
|
||||
iconKey={activeObject.Icon.name}
|
||||
/>
|
||||
<>
|
||||
<SettingsObjectIconSection
|
||||
Icon={activeObject.Icon}
|
||||
iconKey={activeObject.Icon.name}
|
||||
/>
|
||||
<SettingsObjectFormSection
|
||||
singularName={activeObject.singularName}
|
||||
pluralName={activeObject.name}
|
||||
description={activeObject.description}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</SettingsPageContainer>
|
||||
</SubMenuTopBarContainer>
|
||||
|
||||
Reference in New Issue
Block a user