mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-03-11 02:12:21 -05:00
Added confirmation modal after setting portal email address (#17231)
refs https://github.com/TryGhost/Product/issues/3545
This commit is contained in:
parent
e397368393
commit
4ffdab3c82
6 changed files with 42 additions and 21 deletions
|
@ -1,11 +1,12 @@
|
|||
import React, {createContext, useCallback, useContext, useEffect, useState} from 'react';
|
||||
import {Config, Setting, SiteData} from '../../types/api';
|
||||
import {ServicesContext} from './ServiceProvider';
|
||||
import {SettingsResponseType} from '../../utils/api';
|
||||
|
||||
// Define the Settings Context
|
||||
interface SettingsContextProps {
|
||||
settings: Setting[] | null;
|
||||
saveSettings: (updatedSettings: Setting[]) => Promise<Setting[]>;
|
||||
saveSettings: (updatedSettings: Setting[]) => Promise<SettingsResponseType>;
|
||||
siteData: SiteData | null;
|
||||
config: Config | null;
|
||||
settingsLoaded: boolean;
|
||||
|
@ -20,7 +21,7 @@ const SettingsContext = createContext<SettingsContextProps>({
|
|||
siteData: null,
|
||||
config: null,
|
||||
settingsLoaded: false,
|
||||
saveSettings: async () => []
|
||||
saveSettings: async () => ({settings: []})
|
||||
});
|
||||
|
||||
function serialiseSettingsData(settings: Setting[]): Setting[] {
|
||||
|
@ -121,10 +122,13 @@ const SettingsProvider: React.FC<SettingsProviderProps> = ({children}) => {
|
|||
|
||||
setSettings(newSettings);
|
||||
|
||||
return newSettings;
|
||||
return {
|
||||
settings: newSettings,
|
||||
meta: data.meta
|
||||
};
|
||||
} catch (error) {
|
||||
// Log error in settings API
|
||||
return [];
|
||||
return {settings: []};
|
||||
}
|
||||
}, [api]);
|
||||
|
||||
|
@ -139,3 +143,4 @@ const SettingsProvider: React.FC<SettingsProviderProps> = ({children}) => {
|
|||
};
|
||||
|
||||
export {SettingsContext, SettingsProvider};
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import AccountPage from './portal/AccountPage';
|
||||
import ConfirmationModal from '../../../admin-x-ds/global/modal/ConfirmationModal';
|
||||
import LookAndFeel from './portal/LookAndFeel';
|
||||
import NiceModal, {useModal} from '@ebay/nice-modal-react';
|
||||
import PortalPreview from './portal/PortalPreview';
|
||||
|
@ -9,6 +10,7 @@ import useForm, {Dirtyable} from '../../../hooks/useForm';
|
|||
import {PreviewModalContent} from '../../../admin-x-ds/global/modal/PreviewModal';
|
||||
import {Setting, SettingValue, Tier} from '../../../types/api';
|
||||
import {SettingsContext} from '../../providers/SettingsProvider';
|
||||
import {fullEmailAddress} from '../../../utils/helpers';
|
||||
import {useTiers} from '../../providers/ServiceProvider';
|
||||
|
||||
const Sidebar: React.FC<{
|
||||
|
@ -61,7 +63,7 @@ const PortalModal: React.FC = () => {
|
|||
const modal = useModal();
|
||||
|
||||
const [selectedPreviewTab, setSelectedPreviewTab] = useState('signup');
|
||||
const {settings, saveSettings} = useContext(SettingsContext);
|
||||
const {settings, saveSettings, siteData} = useContext(SettingsContext);
|
||||
const {data: tiers, update: updateTiers} = useTiers();
|
||||
|
||||
const {formState, saveState, handleSave, updateForm} = useForm({
|
||||
|
@ -72,7 +74,23 @@ const PortalModal: React.FC = () => {
|
|||
|
||||
onSave: async () => {
|
||||
await updateTiers(formState.tiers.filter(tier => tier.dirty));
|
||||
await saveSettings(formState.settings.filter(setting => setting.dirty));
|
||||
const {meta, settings: currentSettings} = await saveSettings(formState.settings.filter(setting => setting.dirty));
|
||||
|
||||
if (meta?.sent_email_verification) {
|
||||
const newEmail = formState.settings.find(setting => setting.key === 'members_support_address')?.value;
|
||||
const currentEmail = currentSettings.find(setting => setting.key === 'members_support_address')?.value;
|
||||
|
||||
NiceModal.show(ConfirmationModal, {
|
||||
title: 'Confirm email address',
|
||||
prompt: <>
|
||||
We've sent a confirmation email to <strong>{newEmail}</strong>.
|
||||
Until verified, your support address will remain {fullEmailAddress(currentEmail?.toString() || 'noreply', siteData!)}.
|
||||
</>,
|
||||
okLabel: 'Close',
|
||||
cancelLabel: '',
|
||||
onOk: confirmModal => confirmModal?.remove()
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import React, {FocusEventHandler, useContext, useState} from 'react';
|
|||
import TextField from '../../../../admin-x-ds/global/form/TextField';
|
||||
import {Setting, SettingValue} from '../../../../types/api';
|
||||
import {SettingsContext} from '../../../providers/SettingsProvider';
|
||||
import {getEmailDomain, getSettingValues} from '../../../../utils/helpers';
|
||||
import {fullEmailAddress, getEmailDomain, getSettingValues} from '../../../../utils/helpers';
|
||||
|
||||
const AccountPage: React.FC<{
|
||||
localSettings: Setting[]
|
||||
|
@ -14,16 +14,7 @@ const AccountPage: React.FC<{
|
|||
const {siteData} = useContext(SettingsContext) || {};
|
||||
const emailDomain = getEmailDomain(siteData!);
|
||||
|
||||
const parseEmailAddress = (value?: string) => {
|
||||
let emailAddress = value || 'noreply';
|
||||
// Adds default domain as site domain
|
||||
if (emailAddress.indexOf('@') < 0 && emailDomain) {
|
||||
emailAddress = `${emailAddress}@${emailDomain}`;
|
||||
}
|
||||
return emailAddress;
|
||||
};
|
||||
|
||||
const [value, setValue] = useState(parseEmailAddress(membersSupportAddress?.toString()));
|
||||
const [value, setValue] = useState(fullEmailAddress(membersSupportAddress?.toString() || '', siteData!));
|
||||
|
||||
const updateSupportAddress: FocusEventHandler<HTMLInputElement> = (e) => {
|
||||
let supportAddress = e.target.value;
|
||||
|
@ -31,7 +22,7 @@ const AccountPage: React.FC<{
|
|||
let settingValue = emailDomain && supportAddress === `noreply@${emailDomain}` ? 'noreply' : supportAddress;
|
||||
|
||||
updateSetting('members_support_address', settingValue);
|
||||
setValue(parseEmailAddress(settingValue));
|
||||
setValue(fullEmailAddress(settingValue, siteData!));
|
||||
};
|
||||
|
||||
return <Form marginTop>
|
||||
|
|
|
@ -110,7 +110,7 @@ const DesignModal: React.FC = () => {
|
|||
}
|
||||
|
||||
if (formState.settings.some(setting => setting.dirty)) {
|
||||
const newSettings = await saveSettings(formState.settings.filter(setting => setting.dirty));
|
||||
const {settings: newSettings} = await saveSettings(formState.settings.filter(setting => setting.dirty));
|
||||
updateForm(state => ({...state, settings: newSettings}));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {Config, CustomThemeSetting, InstalledTheme, Label, Offer, Post, Setting, SiteData, Theme, Tier, User, UserRole} from '../types/api';
|
||||
import {getGhostPaths} from './helpers';
|
||||
|
||||
interface Meta {
|
||||
export interface Meta {
|
||||
pagination: {
|
||||
page: number;
|
||||
limit: number;
|
||||
|
@ -12,8 +12,10 @@ interface Meta {
|
|||
}
|
||||
}
|
||||
|
||||
export type SettingsResponseMeta = Meta & { sent_email_verification?: boolean }
|
||||
|
||||
export interface SettingsResponseType {
|
||||
meta: Meta;
|
||||
meta?: SettingsResponseMeta;
|
||||
settings: Setting[];
|
||||
}
|
||||
|
||||
|
|
|
@ -108,6 +108,11 @@ export function getEmailDomain(siteData: SiteData): string {
|
|||
return domain;
|
||||
}
|
||||
|
||||
export function fullEmailAddress(value: 'noreply' | string, siteData: SiteData) {
|
||||
const emailDomain = getEmailDomain(siteData);
|
||||
return value === 'noreply' ? `noreply@${emailDomain}` : value;
|
||||
}
|
||||
|
||||
export function checkStripeEnabled(settings: Setting[], config: Config) {
|
||||
const hasSetting = (key: string) => settings.some(setting => setting.key === key && setting.value);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue