mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 14:03:48 +03:00
Added static state handling to Admin Settings
refs. https://github.com/TryGhost/Team/issues/3150
This commit is contained in:
parent
933b4bb4cb
commit
0bcfdbd7ce
@ -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}
|
||||
|
@ -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
|
||||
}
|
||||
];
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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>
|
||||
</>
|
||||
);
|
||||
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user