Added static state handling to Admin Settings

refs. https://github.com/TryGhost/Team/issues/3150
This commit is contained in:
Peter Zimon 2023-05-17 15:19:16 +02:00
parent 933b4bb4cb
commit 0bcfdbd7ce
7 changed files with 129 additions and 27 deletions

View File

@ -13,18 +13,21 @@ export const ButtonColors: ButtonColorsType = {
Red: 'Red'
};
export interface ButtonProps {
export interface IButton {
label: string;
key?: string;
color?: string;
fullWidth?: boolean;
link?: boolean;
onClick?: () => void;
}
const Button: React.FC<ButtonProps> = ({
const Button: React.FC<IButton> = ({
label,
color,
fullWidth,
link,
onClick,
...props
}) => {
let buttonColor: string;
@ -53,6 +56,7 @@ const Button: React.FC<ButtonProps> = ({
<button
className={`flex cursor-pointer items-center justify-center rounded-sm text-sm ${padding} ${fontWeight} ${fullWidth && !link ? 'w-full' : ''} ${buttonColor} `}
type="button"
onClick={onClick}
{...props}
>
{label}

View File

@ -16,10 +16,12 @@ type Story = StoryObj<typeof ButtonGroupMeta>;
const defaultButtons = [
{
label: 'Cancel',
key: 'cancel',
color: ButtonColors.Clear
},
{
label: 'Save',
key: 'save',
color: ButtonColors.Black
}
];
@ -34,10 +36,12 @@ export const Default: Story = {
const linkButtons = [
{
label: 'Cancel',
key: 'cancel',
color: ButtonColors.Clear
},
{
label: 'Save',
key: 'save',
color: ButtonColors.Green
}
];

View File

@ -1,19 +1,18 @@
import Button from './Button';
import React from 'react';
import {IButton} from './Button';
interface ButtonGroupProps {
buttons: Array<{
label: string,
color?: string,
}>;
buttons: Array<IButton>;
link?: boolean;
}
const ButtonGroup: React.FC<ButtonGroupProps> = ({buttons, link}) => {
return (
<div className={`flex items-center ${link ? 'gap-5' : 'gap-2'}`}>
{buttons.map(({color, label}) => (
<Button key={color} color={color} label={label} link={link} />
{buttons.map(({key, color, label, onClick}) => (
<Button key={key} color={color} label={label} link={link} onClick={onClick} />
))}
</div>
);

View File

@ -3,18 +3,25 @@ import React from 'react';
import Heading from './Heading';
interface ITextField {
title?: string,
value?: string,
placeholder?: string,
help?: React.ReactNode
title?: string;
value?: string;
placeholder?: string;
help?: React.ReactNode;
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
}
const TextField: React.FC<ITextField> = ({title, value, placeholder, help}) => {
const TextField: React.FC<ITextField> = ({title, value, placeholder, help, onChange, ...props}) => {
return (
<div className='flex flex-col gap-2'>
<div className='flex flex-col'>
{title && <Heading formLabel={true} grey={true}>{title}</Heading>}
<input className='-m-1 border-b border-grey-300 px-1 py-2 focus:border-grey-900' placeholder={placeholder} type='text' value={value} />
<span className='text-xs text-grey-700'>{help}</span>
<input
className='-m-1 border-b border-grey-300 px-1 py-2 focus:border-grey-900'
placeholder={placeholder}
type='text'
value={value}
onChange={onChange}
{...props} />
<span className='mt-2 inline-block text-xs text-grey-700'>{help}</span>
</div>
);
};

View File

@ -1,7 +1,9 @@
import React from 'react';
export type TSettingGroupStates = 'view' | 'edit' | 'unsaved' | 'error' | 'new';
interface SettingGroupProps {
state?: 'view' | 'edit' | 'unsaved' | 'error' | 'new';
state?: TSettingGroupStates;
children?: React.ReactNode;
}

View File

@ -1,8 +1,8 @@
import React from 'react';
import PublicationLanguage from './PublicationLanguage';
// import PublicationLanguage from './PublicationLanguage';
import SettingSection from '../../../admin-x-ds/settings/SettingSection';
import TimeZone from './TimeZone';
// import TimeZone from './TimeZone';
import TitleAndDescription from './TitleAndDescription';
const GeneralSettings: React.FC = () => {
@ -10,8 +10,8 @@ const GeneralSettings: React.FC = () => {
<>
<SettingSection title="General">
<TitleAndDescription />
<TimeZone />
<PublicationLanguage />
{/* <TimeZone /> */}
{/* <PublicationLanguage /> */}
</SettingSection>
</>
);

View File

@ -1,25 +1,111 @@
import ButtonGroup from '../../../admin-x-ds/global/ButtonGroup';
import React from 'react';
import React, {useState} from 'react';
import SettingGroup from '../../../admin-x-ds/settings/SettingGroup';
import SettingGroupHeader from '../../../admin-x-ds/settings/SettingGroupHeader';
import SettingGroupInputs from '../../../admin-x-ds/settings/SettingGroupInputs';
import SettingGroupValues from '../../../admin-x-ds/settings/SettingGroupValues';
import TextField from '../../../admin-x-ds/global/TextField';
import {ButtonColors} from '../../../admin-x-ds/global/Button';
import {TSettingGroupStates} from '../../../admin-x-ds/settings/SettingGroup';
const TitleAndDescription: React.FC = () => {
const buttons = [
const [isEditMode, setIsEditMode] = useState(false);
const [isEdited, setIsEdited] = useState(false);
const [siteTitle, setSiteTitleValue] = useState(`Dr. Evil's secret volcano lair`);
const [siteDescription, setSiteDescriptionValue] = useState(`I'm doing this for fun`);
const handleEditClick = () => {
setIsEditMode(true);
};
const handleCancelClick = () => {
setIsEditMode(false);
};
const handleTitleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setIsEdited(true);
setSiteTitleValue(e.target.value);
};
const handleDescriptionChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setIsEdited(true);
setSiteDescriptionValue(e.target.value);
};
const viewButtons = [
{
label: 'Edit',
key: 'edit',
color: ButtonColors.Green,
onClick: handleEditClick
}
];
const editButtons = [
{
label: 'Cancel',
key: 'cancel',
onClick: handleCancelClick
},
{
label: 'Save',
key: 'save',
color: ButtonColors.Green
}
];
const viewValues = [
{
heading: 'Site title',
key: 'site-title',
value: siteTitle
},
{
heading: 'Site description',
key: 'site-description',
value: siteDescription
}
];
const inputFields = (
<SettingGroupInputs columns={2}>
<TextField
help="The name of your site"
placeholder="Site title"
title="Site title"
value={siteTitle}
onChange={handleTitleChange}
/>
<TextField
help="Used in your theme, meta data and search results"
placeholder="Enter something"
title="Site description"
value={siteDescription}
onChange={handleDescriptionChange}
/>
</SettingGroupInputs>
);
let settingGroupState: TSettingGroupStates = 'view';
if (isEditMode) {
settingGroupState = 'edit';
}
if (isEdited) {
settingGroupState = 'unsaved';
}
return (
<SettingGroup>
<SettingGroupHeader
description="The details used to identify your publication around the web"
<SettingGroup state={settingGroupState}>
<SettingGroupHeader
description="The details used to identify your publication around the web"
title="Title & description"
>
<ButtonGroup buttons={buttons} link={true} />
<ButtonGroup buttons={isEditMode ? editButtons : viewButtons} link={true} />
</SettingGroupHeader>
{isEditMode ? inputFields : <SettingGroupValues columns={2} values={viewValues} />
}
</SettingGroup>
);
};