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:
parent
ec56572764
commit
a3e39ce61e
5 changed files with 133 additions and 55 deletions
|
@ -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 = {
|
||||
args: {
|
||||
title: 'Title',
|
||||
|
|
|
@ -3,9 +3,12 @@ import React from 'react';
|
|||
import Heading from './Heading';
|
||||
import Hint from './Hint';
|
||||
|
||||
type InputFieldType = 'text' | 'number' | 'email' | 'password' | 'checkbox' | 'radio' | 'file' | 'date' | 'time' | 'range' | 'search';
|
||||
|
||||
interface ITextField {
|
||||
inputRef?: React.RefObject<HTMLInputElement>;
|
||||
title?: string;
|
||||
type?: InputFieldType;
|
||||
value?: string;
|
||||
error?: boolean;
|
||||
placeholder?: string;
|
||||
|
@ -13,16 +16,18 @@ interface ITextField {
|
|||
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 (
|
||||
<div className='flex flex-col'>
|
||||
{title && <Heading useLabelTag={true}>{title}</Heading>}
|
||||
<input
|
||||
ref={inputRef}
|
||||
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}
|
||||
placeholder={placeholder}
|
||||
type='text'
|
||||
ref={inputRef}
|
||||
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}
|
||||
placeholder={placeholder}
|
||||
type={type}
|
||||
onChange={onChange}
|
||||
{...props} />
|
||||
{hint && <Hint color={error ? 'red' : ''}>{hint}</Hint>}
|
||||
|
|
|
@ -1,61 +1,111 @@
|
|||
import Dropdown from '../../../admin-x-ds/global/Dropdown';
|
||||
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 SettingGroupContent from '../../../admin-x-ds/settings/SettingGroupContent';
|
||||
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 [currentState, setCurrentState] = useState<TSettingGroupStates>('view');
|
||||
const {
|
||||
currentState,
|
||||
handleSave,
|
||||
handleCancel,
|
||||
updateSetting,
|
||||
getSettingValues,
|
||||
handleStateChange
|
||||
} = useSettingGroup();
|
||||
|
||||
const handleStateChange = (newState: TSettingGroupStates) => {
|
||||
setCurrentState(newState);
|
||||
};
|
||||
const [mailgunRegion, mailgunDomain, mailgunApiKey] = getSettingValues([
|
||||
'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 = (
|
||||
<SettingGroupContent
|
||||
columns={2}
|
||||
values={[
|
||||
{
|
||||
heading: 'Status',
|
||||
key: 'status',
|
||||
value: 'Mailgun is not set up'
|
||||
}
|
||||
]}
|
||||
columns={1}
|
||||
values={data}
|
||||
/>
|
||||
);
|
||||
|
||||
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 = (
|
||||
<SettingGroupContent>
|
||||
<div className='grid grid-cols-[0.25fr_0.75fr] gap-6'>
|
||||
<Dropdown
|
||||
defaultSelectedOption='option-1'
|
||||
options={[
|
||||
{value: 'option-1', label: 'US'},
|
||||
{value: 'option-2', label: 'EU'}
|
||||
]}
|
||||
defaultSelectedOption={mailgunRegion}
|
||||
options={MAILGUN_REGIONS}
|
||||
title="Mailgun region"
|
||||
onSelect={() => {}}
|
||||
onSelect={(value) => {
|
||||
updateSetting('mailgun_base_url', value);
|
||||
}}
|
||||
/>
|
||||
<TextField
|
||||
<TextField
|
||||
title='Mailgun domain'
|
||||
value={mailgunDomain}
|
||||
onChange={(e) => {
|
||||
updateSetting('mailgun_domain', e.target.value);
|
||||
}}
|
||||
/>
|
||||
<div className='col-span-2'>
|
||||
<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></>}
|
||||
<TextField
|
||||
hint={apiKeysHint}
|
||||
title='Mailgun private API key'
|
||||
type='password'
|
||||
value={mailgunApiKey}
|
||||
onChange={(e) => {
|
||||
updateSetting('mailgun_api_key', e.target.value);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</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 (
|
||||
<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></>}
|
||||
state={currentState}
|
||||
title='Mailgun'
|
||||
<SettingGroup
|
||||
description={groupDescription}
|
||||
state={currentState}
|
||||
title='Mailgun'
|
||||
onCancel={handleCancel}
|
||||
onSave={handleSave}
|
||||
onStateChange={handleStateChange}
|
||||
>
|
||||
{currentState === 'view' ? values : inputs}
|
||||
|
|
|
@ -1,67 +1,81 @@
|
|||
import Button from '../../../admin-x-ds/global/Button';
|
||||
import ButtonGroup from '../../../admin-x-ds/global/ButtonGroup';
|
||||
import React, {useState} from 'react';
|
||||
import React from 'react';
|
||||
import SettingGroup from '../../../admin-x-ds/settings/SettingGroup';
|
||||
import SettingGroupContent from '../../../admin-x-ds/settings/SettingGroupContent';
|
||||
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 [currentState, setCurrentState] = useState<TSettingGroupStates>('view');
|
||||
const {
|
||||
currentState,
|
||||
handleSave,
|
||||
handleCancel,
|
||||
updateSetting,
|
||||
getSettingValues,
|
||||
handleStateChange
|
||||
} = useSettingGroup();
|
||||
|
||||
const handleStateChange = () => {
|
||||
setCurrentState('unsaved');
|
||||
const [trackEmailOpens, trackEmailClicks, trackMemberSources, outboundLinkTagging] = getSettingValues([
|
||||
'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 = (
|
||||
<SettingGroupContent columns={2}>
|
||||
<Toggle
|
||||
// direction='rtl'
|
||||
checked={trackEmailOpens}
|
||||
hint='Record when a member opens an email'
|
||||
id='newsletter-opens'
|
||||
label='Newsletter opens'
|
||||
onChange={handleStateChange}
|
||||
onChange={(e) => {
|
||||
handleToggleChange('email_track_opens', e);
|
||||
}}
|
||||
/>
|
||||
<Toggle
|
||||
// direction='rtl'
|
||||
checked={trackEmailClicks}
|
||||
hint='Record when a member clicks on any link in an email'
|
||||
id='newsletter-clicks'
|
||||
label='Newsletter clicks'
|
||||
onChange={handleStateChange}
|
||||
onChange={(e) => {
|
||||
handleToggleChange('email_track_clicks', e);
|
||||
}}
|
||||
/>
|
||||
<Toggle
|
||||
// direction='rtl'
|
||||
checked={trackMemberSources}
|
||||
hint='Track the traffic sources and posts that drive the most member growth'
|
||||
id='member-sources'
|
||||
label='Member sources'
|
||||
onChange={handleStateChange}
|
||||
onChange={(e) => {
|
||||
handleToggleChange('members_track_sources', e);
|
||||
}}
|
||||
/>
|
||||
<Toggle
|
||||
// direction='rtl'
|
||||
checked={outboundLinkTagging}
|
||||
hint='Make it easier for other sites to track the traffic you send them in their analytics'
|
||||
id='outbound-links'
|
||||
label='Outbound link tagging'
|
||||
onChange={handleStateChange}
|
||||
onChange={(e) => {
|
||||
handleToggleChange('outbound_link_tagging', e);
|
||||
}}
|
||||
/>
|
||||
</SettingGroupContent>
|
||||
);
|
||||
|
||||
const buttons = <ButtonGroup buttons={[
|
||||
{
|
||||
label: 'Cancel'
|
||||
},
|
||||
{
|
||||
label: 'Save',
|
||||
color: 'green'
|
||||
}
|
||||
]} link={true} />;
|
||||
|
||||
return (
|
||||
<SettingGroup
|
||||
customButtons={currentState === 'unsaved' ? buttons : <></>}
|
||||
description='Decide what data you collect from your members'
|
||||
state={currentState}
|
||||
title='Analytics'
|
||||
onCancel={handleCancel}
|
||||
onSave={handleSave}
|
||||
onStateChange={handleStateChange}
|
||||
>
|
||||
{inputs}
|
||||
<div className='mt-1'>
|
||||
|
|
|
@ -115,7 +115,7 @@ const useSettingGroup = (): SettingGroupHook => {
|
|||
// function to get the values of the settings
|
||||
const getSettingValues = (keys: string[]) => {
|
||||
return keys.map((key) => {
|
||||
return settings?.find(setting => setting.key === key)?.value;
|
||||
return localSettings?.find(setting => setting.key === key)?.value;
|
||||
});
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue