0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-03-04 02:01:58 -05:00

Wired mailgun and analytics settings in admin-x

refs https://github.com/TryGhost/Team/issues/3151

- updates textfield to have password type
- updates wiring for mailgun settings
- updates wiring for analytics settings
- fixes local value read or useSettingGroup
This commit is contained in:
Rishabh 2023-05-23 11:43:48 +05:30
parent ec56572764
commit a3e39ce61e
5 changed files with 133 additions and 55 deletions

View file

@ -45,6 +45,15 @@ export const WithHint: Story = {
} }
}; };
export const PasswordType: Story = {
args: {
title: 'Password',
type: 'password',
placeholder: 'Enter something',
hint: 'Here\'s some hint'
}
};
export const Error: Story = { export const Error: Story = {
args: { args: {
title: 'Title', title: 'Title',

View file

@ -3,9 +3,12 @@ import React from 'react';
import Heading from './Heading'; import Heading from './Heading';
import Hint from './Hint'; import Hint from './Hint';
type InputFieldType = 'text' | 'number' | 'email' | 'password' | 'checkbox' | 'radio' | 'file' | 'date' | 'time' | 'range' | 'search';
interface ITextField { interface ITextField {
inputRef?: React.RefObject<HTMLInputElement>; inputRef?: React.RefObject<HTMLInputElement>;
title?: string; title?: string;
type?: InputFieldType;
value?: string; value?: string;
error?: boolean; error?: boolean;
placeholder?: string; placeholder?: string;
@ -13,7 +16,9 @@ interface ITextField {
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void; onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
} }
const TextField: React.FC<ITextField> = ({inputRef, title, value, error, placeholder, hint, onChange, ...props}) => { const TextField: React.FC<ITextField> = ({
type = 'text', inputRef, title, value, error, placeholder, hint, onChange, ...props
}) => {
return ( return (
<div className='flex flex-col'> <div className='flex flex-col'>
{title && <Heading useLabelTag={true}>{title}</Heading>} {title && <Heading useLabelTag={true}>{title}</Heading>}
@ -22,7 +27,7 @@ const TextField: React.FC<ITextField> = ({inputRef, title, value, error, placeho
className={`-mx-1 -mt-0.5 h-10 border-b ${error ? `border-red` : `border-grey-500 hover:border-grey-600 focus:border-grey-900`} px-1 py-2 ${title && `mt-0`}`} className={`-mx-1 -mt-0.5 h-10 border-b ${error ? `border-red` : `border-grey-500 hover:border-grey-600 focus:border-grey-900`} px-1 py-2 ${title && `mt-0`}`}
defaultValue={value} defaultValue={value}
placeholder={placeholder} placeholder={placeholder}
type='text' type={type}
onChange={onChange} onChange={onChange}
{...props} /> {...props} />
{hint && <Hint color={error ? 'red' : ''}>{hint}</Hint>} {hint && <Hint color={error ? 'red' : ''}>{hint}</Hint>}

View file

@ -1,61 +1,111 @@
import Dropdown from '../../../admin-x-ds/global/Dropdown'; import Dropdown from '../../../admin-x-ds/global/Dropdown';
import Link from '../../../admin-x-ds/global/Link'; import Link from '../../../admin-x-ds/global/Link';
import React, {useState} from 'react'; import React from 'react';
import SettingGroup from '../../../admin-x-ds/settings/SettingGroup'; import SettingGroup from '../../../admin-x-ds/settings/SettingGroup';
import SettingGroupContent from '../../../admin-x-ds/settings/SettingGroupContent'; import SettingGroupContent from '../../../admin-x-ds/settings/SettingGroupContent';
import TextField from '../../../admin-x-ds/global/TextField'; import TextField from '../../../admin-x-ds/global/TextField';
import {TSettingGroupStates} from '../../../admin-x-ds/settings/SettingGroup'; import useSettingGroup from '../../../hooks/useSettingGroup';
const MAILGUN_REGIONS = [
{label: '🇺🇸 US', value: 'https://api.mailgun.net/v3'},
{label: '🇪🇺 EU', value: 'https://api.eu.mailgun.net/v3'}
];
const MailGun: React.FC = () => { const MailGun: React.FC = () => {
const [currentState, setCurrentState] = useState<TSettingGroupStates>('view'); const {
currentState,
handleSave,
handleCancel,
updateSetting,
getSettingValues,
handleStateChange
} = useSettingGroup();
const handleStateChange = (newState: TSettingGroupStates) => { const [mailgunRegion, mailgunDomain, mailgunApiKey] = getSettingValues([
setCurrentState(newState); 'mailgun_base_url', 'mailgun_domain', 'mailgun_api_key'
}; ]) as string[];
const isMailgunSetup = mailgunRegion && mailgunDomain && mailgunApiKey;
const data = isMailgunSetup ? [
{
heading: 'Mailgun region',
key: 'mailgun-region',
value: mailgunRegion
},
{
heading: 'Mailgun domain',
key: 'mailgun-domain',
value: mailgunDomain
},
{
heading: 'Mailgun private API key',
key: 'commenting',
value: mailgunApiKey
}
] : [
{
heading: 'Status',
key: 'status',
value: 'Mailgun is not set up'
}
];
const values = ( const values = (
<SettingGroupContent <SettingGroupContent
columns={2} columns={1}
values={[ values={data}
{
heading: 'Status',
key: 'status',
value: 'Mailgun is not set up'
}
]}
/> />
); );
const apiKeysHint = (
<>Find your Mailgun API keys <Link href="https://app.mailgun.com/app/account/security/api_keys" rel="noopener noreferrer" target="_blank">here</Link></>
);
const inputs = ( const inputs = (
<SettingGroupContent> <SettingGroupContent>
<div className='grid grid-cols-[0.25fr_0.75fr] gap-6'> <div className='grid grid-cols-[0.25fr_0.75fr] gap-6'>
<Dropdown <Dropdown
defaultSelectedOption='option-1' defaultSelectedOption={mailgunRegion}
options={[ options={MAILGUN_REGIONS}
{value: 'option-1', label: 'US'},
{value: 'option-2', label: 'EU'}
]}
title="Mailgun region" title="Mailgun region"
onSelect={() => {}} onSelect={(value) => {
updateSetting('mailgun_base_url', value);
}}
/> />
<TextField <TextField
title='Mailgun domain' title='Mailgun domain'
value={mailgunDomain}
onChange={(e) => {
updateSetting('mailgun_domain', e.target.value);
}}
/> />
<div className='col-span-2'> <div className='col-span-2'>
<TextField <TextField
hint={<>Find your Mailgun API keys <Link href="https://app.mailgun.com/app/account/security/api_keys" rel="noopener noreferrer" target="_blank">here</Link></>} hint={apiKeysHint}
title='Mailgun private API key' title='Mailgun private API key'
type='password'
value={mailgunApiKey}
onChange={(e) => {
updateSetting('mailgun_api_key', e.target.value);
}}
/> />
</div> </div>
</div> </div>
</SettingGroupContent> </SettingGroupContent>
); );
const groupDescription = (
<>The Mailgun API is used for bulk email newsletter delivery. <Link href='https://ghost.org/docs/faq/mailgun-newsletters/' target='_blank'>Why is this required?</Link></>
);
return ( return (
<SettingGroup <SettingGroup
description={<>The Mailgun API is used for bulk email newsletter delivery. <Link href='https://ghost.org/docs/faq/mailgun-newsletters/' target='_blank'>Why is this required?</Link></>} description={groupDescription}
state={currentState} state={currentState}
title='Mailgun' title='Mailgun'
onCancel={handleCancel}
onSave={handleSave}
onStateChange={handleStateChange} onStateChange={handleStateChange}
> >
{currentState === 'view' ? values : inputs} {currentState === 'view' ? values : inputs}

View file

@ -1,67 +1,81 @@
import Button from '../../../admin-x-ds/global/Button'; import Button from '../../../admin-x-ds/global/Button';
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 SettingGroup from '../../../admin-x-ds/settings/SettingGroup';
import SettingGroupContent from '../../../admin-x-ds/settings/SettingGroupContent'; import SettingGroupContent from '../../../admin-x-ds/settings/SettingGroupContent';
import Toggle from '../../../admin-x-ds/global/Toggle'; import Toggle from '../../../admin-x-ds/global/Toggle';
import {TSettingGroupStates} from '../../../admin-x-ds/settings/SettingGroup'; import useSettingGroup from '../../../hooks/useSettingGroup';
const Analytics: React.FC = () => { const Analytics: React.FC = () => {
const [currentState, setCurrentState] = useState<TSettingGroupStates>('view'); const {
currentState,
handleSave,
handleCancel,
updateSetting,
getSettingValues,
handleStateChange
} = useSettingGroup();
const handleStateChange = () => { const [trackEmailOpens, trackEmailClicks, trackMemberSources, outboundLinkTagging] = getSettingValues([
setCurrentState('unsaved'); 'email_track_opens', 'email_track_clicks', 'members_track_sources', 'outbound_link_tagging'
]) as boolean[];
const handleToggleChange = (key: string, e: React.ChangeEvent<HTMLInputElement>) => {
updateSetting(key, e.target.checked);
}; };
const inputs = ( const inputs = (
<SettingGroupContent columns={2}> <SettingGroupContent columns={2}>
<Toggle <Toggle
// direction='rtl' // direction='rtl'
checked={trackEmailOpens}
hint='Record when a member opens an email' hint='Record when a member opens an email'
id='newsletter-opens' id='newsletter-opens'
label='Newsletter opens' label='Newsletter opens'
onChange={handleStateChange} onChange={(e) => {
handleToggleChange('email_track_opens', e);
}}
/> />
<Toggle <Toggle
// direction='rtl' // direction='rtl'
checked={trackEmailClicks}
hint='Record when a member clicks on any link in an email' hint='Record when a member clicks on any link in an email'
id='newsletter-clicks' id='newsletter-clicks'
label='Newsletter clicks' label='Newsletter clicks'
onChange={handleStateChange} onChange={(e) => {
handleToggleChange('email_track_clicks', e);
}}
/> />
<Toggle <Toggle
// direction='rtl' // direction='rtl'
checked={trackMemberSources}
hint='Track the traffic sources and posts that drive the most member growth' hint='Track the traffic sources and posts that drive the most member growth'
id='member-sources' id='member-sources'
label='Member sources' label='Member sources'
onChange={handleStateChange} onChange={(e) => {
handleToggleChange('members_track_sources', e);
}}
/> />
<Toggle <Toggle
// direction='rtl' // direction='rtl'
checked={outboundLinkTagging}
hint='Make it easier for other sites to track the traffic you send them in their analytics' hint='Make it easier for other sites to track the traffic you send them in their analytics'
id='outbound-links' id='outbound-links'
label='Outbound link tagging' label='Outbound link tagging'
onChange={handleStateChange} onChange={(e) => {
handleToggleChange('outbound_link_tagging', e);
}}
/> />
</SettingGroupContent> </SettingGroupContent>
); );
const buttons = <ButtonGroup buttons={[
{
label: 'Cancel'
},
{
label: 'Save',
color: 'green'
}
]} link={true} />;
return ( return (
<SettingGroup <SettingGroup
customButtons={currentState === 'unsaved' ? buttons : <></>}
description='Decide what data you collect from your members' description='Decide what data you collect from your members'
state={currentState} state={currentState}
title='Analytics' title='Analytics'
onCancel={handleCancel}
onSave={handleSave}
onStateChange={handleStateChange}
> >
{inputs} {inputs}
<div className='mt-1'> <div className='mt-1'>

View file

@ -115,7 +115,7 @@ const useSettingGroup = (): SettingGroupHook => {
// function to get the values of the settings // function to get the values of the settings
const getSettingValues = (keys: string[]) => { const getSettingValues = (keys: string[]) => {
return keys.map((key) => { return keys.map((key) => {
return settings?.find(setting => setting.key === key)?.value; return localSettings?.find(setting => setting.key === key)?.value;
}); });
}; };