@ -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 = [
|
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,
|
||||||
|
|||||||
@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user