mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-01-20 22:42:53 -05:00
Added static user detail popup in AdminX Settings
refs. https://github.com/TryGhost/Team/issues/3150
This commit is contained in:
parent
f2277ded40
commit
9791b341be
15 changed files with 297 additions and 62 deletions
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
|
||||
export type ButtonColor = 'clear' | 'black' | 'green' | 'red';
|
||||
export type ButtonColor = 'clear' | 'grey' | 'black' | 'green' | 'red';
|
||||
|
||||
export interface IButton {
|
||||
label: string;
|
||||
|
@ -35,6 +35,9 @@ const Button: React.FC<IButton> = ({
|
|||
case 'black':
|
||||
styles += link ? ' text-black hover:text-grey-800' : ' bg-black text-white hover:bg-grey-900';
|
||||
break;
|
||||
case 'grey':
|
||||
styles += link ? ' text-black hover:text-grey-800' : ' bg-grey-100 text-black hover:!bg-grey-300';
|
||||
break;
|
||||
case 'green':
|
||||
styles += link ? ' text-green hover:text-green-400' : ' bg-green text-white hover:bg-green-400';
|
||||
break;
|
||||
|
|
|
@ -6,6 +6,7 @@ type THeadingLevels = 1 | 2 | 3 | 4 | 5 | 6;
|
|||
interface IHeading {
|
||||
level?: THeadingLevels;
|
||||
children?: React.ReactNode;
|
||||
styles?: string;
|
||||
|
||||
/**
|
||||
* Only available for Heading 6
|
||||
|
@ -19,13 +20,13 @@ interface IHeading {
|
|||
useLabelTag?: boolean;
|
||||
}
|
||||
|
||||
const Heading: React.FC<IHeading> = ({level, children, grey, separator, useLabelTag, ...props}) => {
|
||||
const Heading: React.FC<IHeading> = ({level, children, styles, grey, separator, useLabelTag, ...props}) => {
|
||||
if (!level) {
|
||||
level = 1;
|
||||
}
|
||||
|
||||
const newElement = `${useLabelTag ? 'label' : `h${level}`}`;
|
||||
let styles = (level === 6 || useLabelTag) ? (`block text-2xs font-semibold uppercase tracking-wide ${(grey && 'text-grey-700')}`) : '';
|
||||
styles += (level === 6 || useLabelTag) ? (` block text-2xs font-semibold uppercase tracking-wide ${(grey && 'text-grey-700')}`) : ' ';
|
||||
|
||||
const Element = React.createElement(newElement, {className: styles, ...props}, children);
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ const ListItem: React.FC<ListItemProps> = ({id, title, detail, action, hideActio
|
|||
{detail && <span className='text-xs text-grey-700'>{detail}</span>}
|
||||
</div>
|
||||
{action &&
|
||||
<div className={`px-3 ${separator ? 'py-3' : 'py-2'} ${hideActions ? 'invisible group-hover:visible' : ''}`}>
|
||||
<div className={`px-6 ${separator ? 'py-3' : 'py-2'} ${hideActions ? 'invisible group-hover:visible' : ''}`}>
|
||||
{action}
|
||||
</div>
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ export interface ModalProps {
|
|||
size?: ModalSize;
|
||||
title?: string;
|
||||
okLabel?: string;
|
||||
okColor?: string;
|
||||
cancelLabel?: string;
|
||||
leftButtonLabel?: string;
|
||||
customFooter?: React.ReactNode;
|
||||
|
@ -18,7 +19,7 @@ export interface ModalProps {
|
|||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
const Modal: React.FC<ModalProps> = ({size = 'md', title, okLabel, cancelLabel, customFooter, leftButtonLabel, onOk, onCancel, children}) => {
|
||||
const Modal: React.FC<ModalProps> = ({size = 'md', title, okLabel, cancelLabel, customFooter, leftButtonLabel, onOk, okColor, onCancel, children}) => {
|
||||
const modal = useModal();
|
||||
|
||||
let buttons: IButton[] = [];
|
||||
|
@ -35,40 +36,40 @@ const Modal: React.FC<ModalProps> = ({size = 'md', title, okLabel, cancelLabel,
|
|||
buttons.push({
|
||||
key: 'ok-modal',
|
||||
label: okLabel ? okLabel : 'OK',
|
||||
color: 'black',
|
||||
color: okColor ? okColor : 'black',
|
||||
styles: 'min-w-[80px]',
|
||||
onClick: onOk
|
||||
});
|
||||
}
|
||||
|
||||
let modalStyles = 'relative z-50 mx-auto flex flex-col justify-between bg-white p-8 shadow-xl w-full';
|
||||
let modalStyles = 'relative z-50 mx-auto flex flex-col justify-between bg-white shadow-xl w-full';
|
||||
let backdropStyles = 'fixed inset-0 h-[100vh] w-[100vw] overflow-y-scroll ';
|
||||
|
||||
switch (size) {
|
||||
case 'sm':
|
||||
modalStyles += ' max-w-[480px]';
|
||||
modalStyles += ' max-w-[480px] p-8';
|
||||
break;
|
||||
|
||||
case 'md':
|
||||
modalStyles += ' max-w-[720px]';
|
||||
modalStyles += ' max-w-[720px] p-8';
|
||||
break;
|
||||
|
||||
case 'lg':
|
||||
modalStyles += ' max-w-[940px]';
|
||||
modalStyles += ' max-w-[940px] p-10';
|
||||
break;
|
||||
|
||||
case 'xl':
|
||||
modalStyles += ' max-w-[1180px] ';
|
||||
modalStyles += ' max-w-[1180px] p-12';
|
||||
break;
|
||||
|
||||
case 'full':
|
||||
case 'bleed':
|
||||
modalStyles += ' h-full';
|
||||
modalStyles += ' h-full p-12';
|
||||
break;
|
||||
}
|
||||
|
||||
if (size !== 'bleed') {
|
||||
modalStyles += ' rounded';
|
||||
modalStyles += ' rounded-md overflow-hidden';
|
||||
}
|
||||
|
||||
if (size !== 'bleed' && size !== 'full') {
|
||||
|
@ -83,7 +84,7 @@ const Modal: React.FC<ModalProps> = ({size = 'md', title, okLabel, cancelLabel,
|
|||
|
||||
return (
|
||||
<div className={backdropStyles} id='modal-backdrop'>
|
||||
<div className='absolute inset-0 z-0 bg-[rgba(0,0,0,0.1)]' onClick={handleBackdropClick}></div>
|
||||
<div className='fixed inset-0 z-0 bg-[rgba(0,0,0,0.1)]' onClick={handleBackdropClick}></div>
|
||||
<section className={modalStyles}>
|
||||
<div>
|
||||
{title && <Heading level={4}>{title}</Heading>}
|
||||
|
|
|
@ -37,13 +37,13 @@ const Radio: React.FC<RadioProps> = ({id, title, options, onSelect, error, hint,
|
|||
|
||||
return (
|
||||
<div>
|
||||
<div className={`flex flex-col gap-1 ${separator && 'pb-2'}`}>
|
||||
{title && <Heading grey={true} level={6}>{title}</Heading>}
|
||||
<div className={`flex flex-col gap-2 ${separator && 'pb-2'}`}>
|
||||
{title && <Heading level={6}>{title}</Heading>}
|
||||
{options.map(option => (
|
||||
<label key={option.value} className={`flex cursor-pointer items-start ${title && '-mb-1 mt-1'}`} htmlFor={option.value}>
|
||||
<input
|
||||
checked={selectedOption === option.value}
|
||||
className="relative float-left mt-[3px] h-4 w-4 appearance-none rounded-full border-2 border-solid border-grey-300 after:absolute after:z-[1] after:block after:h-3 after:w-3 after:rounded-full after:content-[''] checked:border-green checked:after:absolute checked:after:left-1/2 checked:after:top-1/2 checked:after:h-[0.625rem] checked:after:w-[0.625rem] checked:after:rounded-full checked:after:border-green checked:after:bg-green checked:after:content-[''] checked:after:[transform:translate(-50%,-50%)] hover:cursor-pointer focus:shadow-none focus:outline-none focus:ring-0 checked:focus:border-green dark:border-grey-600 dark:checked:border-green dark:checked:after:border-green dark:checked:after:bg-green dark:checked:focus:border-green"
|
||||
className="relative float-left mt-[3px] h-4 w-4 min-w-[16px] appearance-none rounded-full border-2 border-solid border-grey-300 after:absolute after:z-[1] after:block after:h-3 after:w-3 after:rounded-full after:content-[''] checked:border-green checked:after:absolute checked:after:left-1/2 checked:after:top-1/2 checked:after:h-[0.625rem] checked:after:w-[0.625rem] checked:after:rounded-full checked:after:border-green checked:after:bg-green checked:after:content-[''] checked:after:[transform:translate(-50%,-50%)] hover:cursor-pointer focus:shadow-none focus:outline-none focus:ring-0 checked:focus:border-green dark:border-grey-600 dark:checked:border-green dark:checked:after:border-green dark:checked:after:bg-green dark:checked:focus:border-green"
|
||||
id={option.value}
|
||||
name={id}
|
||||
type='radio'
|
||||
|
|
|
@ -42,7 +42,7 @@ const Toggle: React.FC<ToggleProps> = ({id, size, direction, label, hint, separa
|
|||
<div>
|
||||
<div className={`flex items-start gap-2 ${direction === 'rtl' && 'justify-between'} ${separator && 'pb-2'}`}>
|
||||
<input checked={checked}
|
||||
className={`appearance-none rounded-full bg-grey-300 after:absolute after:z-[2] after:ml-0.5 after:mt-0.5 after:rounded-full after:border-none after:bg-white after:transition-[background-color_0.2s,transform_0.2s] after:content-[''] checked:bg-green checked:after:absolute checked:after:z-[2] checked:after:rounded-full checked:after:border-none checked:after:bg-white checked:after:transition-[background-color_0.2s,transform_0.2s] checked:after:content-[''] hover:cursor-pointer focus:outline-none focus:ring-0 focus:after:absolute focus:after:z-[1] focus:after:block focus:after:rounded-full focus:after:content-[''] checked:focus:border-green checked:focus:bg-green dark:bg-grey-600 dark:after:bg-grey-400 dark:checked:bg-green dark:checked:after:bg-green ${sizeStyles} ${direction === 'rtl' && ' order-2'}`}
|
||||
className={`appearance-none rounded-full bg-grey-300 after:absolute after:ml-0.5 after:mt-0.5 after:rounded-full after:border-none after:bg-white after:transition-[background-color_0.2s,transform_0.2s] after:content-[''] checked:bg-green checked:after:absolute checked:after:rounded-full checked:after:border-none checked:after:bg-white checked:after:transition-[background-color_0.2s,transform_0.2s] checked:after:content-[''] hover:cursor-pointer dark:bg-grey-600 dark:after:bg-grey-400 dark:checked:bg-green dark:checked:after:bg-green ${sizeStyles} ${direction === 'rtl' && ' order-2'}`}
|
||||
id={id}
|
||||
role="switch"
|
||||
type="checkbox"
|
||||
|
|
|
@ -77,4 +77,12 @@ export const CustomHeader: Story = {
|
|||
description: SingleColumn.args?.description,
|
||||
customHeader: customHeader
|
||||
}
|
||||
};
|
||||
|
||||
export const NoBorders: Story = {
|
||||
args: {
|
||||
title: SingleColumn.args?.title,
|
||||
description: SingleColumn.args?.description,
|
||||
children: twoColView
|
||||
}
|
||||
};
|
|
@ -13,6 +13,14 @@ interface SettingGroupProps {
|
|||
customHeader?: React.ReactNode;
|
||||
customButtons?: React.ReactNode;
|
||||
children?: React.ReactNode;
|
||||
hideEditButton?: boolean;
|
||||
alwaysShowSaveButton?: boolean;
|
||||
|
||||
/**
|
||||
* Remove borders and paddings
|
||||
*/
|
||||
border?: boolean;
|
||||
styles?: string;
|
||||
|
||||
/**
|
||||
* Default buttons only appear if onStateChange is implemented
|
||||
|
@ -30,6 +38,10 @@ const SettingGroup: React.FC<SettingGroupProps> = ({
|
|||
customHeader,
|
||||
customButtons,
|
||||
children,
|
||||
hideEditButton,
|
||||
alwaysShowSaveButton = true,
|
||||
border = true,
|
||||
styles,
|
||||
onStateChange,
|
||||
onSave,
|
||||
onCancel
|
||||
|
@ -50,30 +62,32 @@ const SettingGroup: React.FC<SettingGroupProps> = ({
|
|||
onStateChange?.('view');
|
||||
};
|
||||
|
||||
let styles = '';
|
||||
|
||||
switch (state) {
|
||||
case 'edit':
|
||||
styles = 'border-grey-300';
|
||||
styles += ' border-grey-300';
|
||||
break;
|
||||
|
||||
case 'unsaved':
|
||||
styles = 'border-green';
|
||||
styles += ' border-green';
|
||||
break;
|
||||
|
||||
default:
|
||||
styles = 'border-grey-200';
|
||||
styles += ' border-grey-200';
|
||||
break;
|
||||
}
|
||||
|
||||
const viewButtons = [
|
||||
{
|
||||
label: 'Edit',
|
||||
key: 'edit',
|
||||
color: 'green',
|
||||
onClick: handleEdit
|
||||
}
|
||||
];
|
||||
let viewButtons = [];
|
||||
|
||||
if (!hideEditButton) {
|
||||
viewButtons.push(
|
||||
{
|
||||
label: 'Edit',
|
||||
key: 'edit',
|
||||
color: 'green',
|
||||
onClick: handleEdit
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
let editButtons: IButton[] = [
|
||||
{
|
||||
|
@ -83,7 +97,7 @@ const SettingGroup: React.FC<SettingGroupProps> = ({
|
|||
}
|
||||
];
|
||||
|
||||
if (state === 'unsaved') {
|
||||
if (state === 'unsaved' || alwaysShowSaveButton) {
|
||||
editButtons.push(
|
||||
{
|
||||
label: 'Save',
|
||||
|
@ -95,7 +109,7 @@ const SettingGroup: React.FC<SettingGroupProps> = ({
|
|||
}
|
||||
|
||||
return (
|
||||
<div className={`flex flex-col gap-6 rounded border p-5 md:p-7 ${styles}`} id={navid && navid}>
|
||||
<div className={`flex flex-col gap-6 rounded ${border && 'border p-5 md:p-7'} ${styles}`} id={navid && navid}>
|
||||
{customHeader ? customHeader :
|
||||
<SettingGroupHeader description={description} title={title!}>
|
||||
{customButtons ? customButtons :
|
||||
|
|
|
@ -16,7 +16,7 @@ interface ISettingGroupContent {
|
|||
const SettingGroupContent: React.FC<ISettingGroupContent> = ({columns, values, children}) => {
|
||||
let styles = 'flex flex-col gap-x-6 gap-y-7';
|
||||
if (columns === 2) {
|
||||
styles = 'grid grid-cols-2 gap-6';
|
||||
styles = 'grid grid-cols-2 gap-x-8 gap-y-6';
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -13,7 +13,7 @@ const SettingValue: React.FC<ISettingValue> = ({heading, value, hint, ...props})
|
|||
return (
|
||||
<div className='flex flex-col' {...props}>
|
||||
{heading && <Heading grey={true} level={6}>{heading}</Heading>}
|
||||
<div className={`-mt-0.5 flex items-center ${heading && `min-h-[40px]`}`}>{value}</div>
|
||||
<div className={`-mt-0.5 flex items-center ${heading && `min-h-[36px]`}`}>{value}</div>
|
||||
{hint && <p className='mt-0.5 text-xs'>{hint}</p>}
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
import Modal from '../../admin-x-ds/global/Modal';
|
||||
import NiceModal from '@ebay/nice-modal-react';
|
||||
|
||||
const UserDetailModal = NiceModal.create(() => {
|
||||
return (
|
||||
<Modal
|
||||
size='lg'
|
||||
title='User details'
|
||||
onOk={() => {
|
||||
alert('Clicked OK');
|
||||
}}
|
||||
>
|
||||
<div className='py-4'>
|
||||
Some user details
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
});
|
||||
|
||||
export default UserDetailModal;
|
|
@ -1,12 +1,12 @@
|
|||
import Button from '../../../admin-x-ds/global/Button';
|
||||
import InviteUserModal from '../../modals/InviteUserModal';
|
||||
import InviteUserModal from './modals/InviteUserModal';
|
||||
import List from '../../../admin-x-ds/global/List';
|
||||
import ListItem from '../../../admin-x-ds/global/ListItem';
|
||||
import NiceModal from '@ebay/nice-modal-react';
|
||||
import React from 'react';
|
||||
import SettingGroup from '../../../admin-x-ds/settings/SettingGroup';
|
||||
import TabView from '../../../admin-x-ds/global/TabView';
|
||||
import UserDetailModal from '../../modals/UserDetailModal';
|
||||
import UserDetailModal from './modals/UserDetailModal';
|
||||
|
||||
const Users: React.FC = () => {
|
||||
const showInviteModal = () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Modal from '../../admin-x-ds/global/Modal';
|
||||
import Modal from '../../../../admin-x-ds/global/Modal';
|
||||
import NiceModal from '@ebay/nice-modal-react';
|
||||
|
||||
const InviteUserModal = NiceModal.create(() => {
|
|
@ -0,0 +1,227 @@
|
|||
import Button from '../../../../admin-x-ds/global/Button';
|
||||
import Heading from '../../../../admin-x-ds/global/Heading';
|
||||
import Modal from '../../../../admin-x-ds/global/Modal';
|
||||
import NiceModal from '@ebay/nice-modal-react';
|
||||
import Radio from '../../../../admin-x-ds/global/Radio';
|
||||
import React, {useState} 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 Toggle from '../../../../admin-x-ds/global/Toggle';
|
||||
|
||||
interface CustomHeadingProps {
|
||||
children?: string;
|
||||
}
|
||||
|
||||
const CustomHeader: React.FC<CustomHeadingProps> = ({children}) => {
|
||||
return (
|
||||
<Heading level={4} separator={true}>{children}</Heading>
|
||||
);
|
||||
};
|
||||
|
||||
const Basic: React.FC = () => {
|
||||
const inputs = (
|
||||
<SettingGroupContent>
|
||||
<TextField
|
||||
hint="Use real name so people can recognize you"
|
||||
title="Full name"
|
||||
value="Martin Culhane"
|
||||
/>
|
||||
<TextField
|
||||
title="Email"
|
||||
value="martin@culhane.com"
|
||||
/>
|
||||
<Radio
|
||||
defaultSelectedOption="administrator"
|
||||
id='role'
|
||||
options={[
|
||||
{
|
||||
hint: 'Can create and edit their own posts, but cannot publish. An Editor needs to approve and publish for them.',
|
||||
label: 'Contributor',
|
||||
value: 'contributor'
|
||||
},
|
||||
{
|
||||
hint: 'A trusted user who can create, edit and publish their own posts, but can’t modify others.',
|
||||
label: 'Author',
|
||||
value: 'author'
|
||||
},
|
||||
{
|
||||
hint: 'Can invite and manage other Authors and Contributors, as well as edit and publish any posts on the site.',
|
||||
label: 'Editor',
|
||||
value: 'editor'
|
||||
},
|
||||
{
|
||||
hint: 'Trusted staff user who should be able to manage all content and users, as well as site settings and options.',
|
||||
label: 'Administrator',
|
||||
value: 'administrator'
|
||||
}
|
||||
]}
|
||||
title="Role"
|
||||
onSelect={() => {}}
|
||||
/>
|
||||
</SettingGroupContent>
|
||||
);
|
||||
|
||||
return (
|
||||
<SettingGroup
|
||||
border={false}
|
||||
customHeader={<CustomHeader>Basic info</CustomHeader>}
|
||||
title='Basic'
|
||||
>
|
||||
{inputs}
|
||||
</SettingGroup>
|
||||
);
|
||||
};
|
||||
|
||||
const Details: React.FC = () => {
|
||||
const inputs = (
|
||||
<SettingGroupContent>
|
||||
<TextField
|
||||
hint="https://example.com/author"
|
||||
title="Slug"
|
||||
/>
|
||||
<TextField
|
||||
title="Location"
|
||||
/>
|
||||
<TextField
|
||||
title="Website"
|
||||
/>
|
||||
<TextField
|
||||
title="Facebook profile"
|
||||
/>
|
||||
<TextField
|
||||
title="Twitter profile"
|
||||
/>
|
||||
<TextField
|
||||
hint="Recommended: 200 characters."
|
||||
title="Bio"
|
||||
/>
|
||||
</SettingGroupContent>
|
||||
);
|
||||
|
||||
return (
|
||||
<SettingGroup
|
||||
border={false}
|
||||
customHeader={<CustomHeader>Details</CustomHeader>}
|
||||
title='Details'
|
||||
>
|
||||
{inputs}
|
||||
</SettingGroup>
|
||||
);
|
||||
};
|
||||
|
||||
const EmailNotifications: React.FC = () => {
|
||||
const inputs = (
|
||||
<SettingGroupContent>
|
||||
<Toggle
|
||||
direction='rtl'
|
||||
hint='Every time a member comments on one of your posts'
|
||||
id='comments'
|
||||
label='Comments'
|
||||
/>
|
||||
<Toggle
|
||||
direction='rtl'
|
||||
hint='Every time a new free member signs up'
|
||||
id='new-signups'
|
||||
label='New signups'
|
||||
/>
|
||||
<Toggle
|
||||
direction='rtl'
|
||||
hint='Every time a member starts a new paid subscription'
|
||||
id='new-paid-members'
|
||||
label='New paid members'
|
||||
/>
|
||||
<Toggle
|
||||
direction='rtl'
|
||||
hint='Every time a member cancels their paid subscription'
|
||||
id='paid-member-cancellations'
|
||||
label='Paid member cancellations'
|
||||
/>
|
||||
<Toggle
|
||||
direction='rtl'
|
||||
hint='Occasional summaries of your audience & revenue growth'
|
||||
id='milestones'
|
||||
label='Milestones'
|
||||
/>
|
||||
</SettingGroupContent>
|
||||
);
|
||||
|
||||
return (
|
||||
<SettingGroup
|
||||
border={false}
|
||||
customHeader={<CustomHeader>Email notifications</CustomHeader>}
|
||||
title='Email notifications'
|
||||
>
|
||||
{inputs}
|
||||
</SettingGroup>
|
||||
);
|
||||
};
|
||||
|
||||
const Password: React.FC = () => {
|
||||
const [editPassword, setEditPassword] = useState(false);
|
||||
|
||||
const showPasswordInputs = () => {
|
||||
setEditPassword(true);
|
||||
};
|
||||
|
||||
const view = (
|
||||
<Button
|
||||
color='grey'
|
||||
label='Change password'
|
||||
onClick={showPasswordInputs}
|
||||
/>
|
||||
);
|
||||
|
||||
const form = (
|
||||
<>
|
||||
<TextField
|
||||
title="New password"
|
||||
value=''
|
||||
/>
|
||||
<TextField
|
||||
title="Verify password"
|
||||
value=''
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
return (
|
||||
<SettingGroup
|
||||
border={false}
|
||||
customHeader={<CustomHeader>Password</CustomHeader>}
|
||||
title='Password'
|
||||
>
|
||||
{editPassword ? form : view}
|
||||
</SettingGroup>
|
||||
);
|
||||
};
|
||||
|
||||
const UserDetailModal = NiceModal.create(() => {
|
||||
return (
|
||||
<Modal
|
||||
okColor='green'
|
||||
okLabel='Save'
|
||||
size='xl'
|
||||
onOk={() => {
|
||||
alert('Clicked OK');
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<div className='-mx-12 -mt-12 bg-gradient-to-tr from-grey-900 to-black p-12 text-white'>
|
||||
<div className='mt-60'>
|
||||
<Heading styles='text-white'>Martin Culhane</Heading>
|
||||
<span className='text-md font-semibold'>Administrator</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className='mt-10 grid grid-cols-2 gap-x-12 gap-y-20 pb-10'>
|
||||
<Basic />
|
||||
<Details />
|
||||
<EmailNotifications />
|
||||
<Password />
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
});
|
||||
|
||||
export default UserDetailModal;
|
|
@ -26,8 +26,8 @@ const Analytics: React.FC = () => {
|
|||
const inputs = (
|
||||
<SettingGroupContent columns={2}>
|
||||
<Toggle
|
||||
// direction='rtl'
|
||||
checked={trackEmailOpens}
|
||||
direction='rtl'
|
||||
hint='Record when a member opens an email'
|
||||
id='newsletter-opens'
|
||||
label='Newsletter opens'
|
||||
|
@ -36,8 +36,8 @@ const Analytics: React.FC = () => {
|
|||
}}
|
||||
/>
|
||||
<Toggle
|
||||
// direction='rtl'
|
||||
checked={trackEmailClicks}
|
||||
direction='rtl'
|
||||
hint='Record when a member clicks on any link in an email'
|
||||
id='newsletter-clicks'
|
||||
label='Newsletter clicks'
|
||||
|
@ -46,8 +46,8 @@ const Analytics: React.FC = () => {
|
|||
}}
|
||||
/>
|
||||
<Toggle
|
||||
// direction='rtl'
|
||||
checked={trackMemberSources}
|
||||
direction='rtl'
|
||||
hint='Track the traffic sources and posts that drive the most member growth'
|
||||
id='member-sources'
|
||||
label='Member sources'
|
||||
|
@ -56,8 +56,8 @@ const Analytics: React.FC = () => {
|
|||
}}
|
||||
/>
|
||||
<Toggle
|
||||
// direction='rtl'
|
||||
checked={outboundLinkTagging}
|
||||
direction='rtl'
|
||||
hint='Make it easier for other sites to track the traffic you send them in their analytics'
|
||||
id='outbound-links'
|
||||
label='Outbound link tagging'
|
||||
|
@ -71,6 +71,7 @@ const Analytics: React.FC = () => {
|
|||
return (
|
||||
<SettingGroup
|
||||
description='Decide what data you collect from your members'
|
||||
hideEditButton={true}
|
||||
state={currentState}
|
||||
title='Analytics'
|
||||
onCancel={handleCancel}
|
||||
|
|
Loading…
Add table
Reference in a new issue