fix: modal, dialog & typography styling

pull/147/head
Boaz Poolman 2024-10-12 18:46:42 +02:00
parent 11662c8421
commit 00da5012d8
6 changed files with 137 additions and 135 deletions

View File

@ -1,8 +1,8 @@
import React, { useState } from 'react'; import React from 'react';
import styled from 'styled-components'; import styled from 'styled-components';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch, useSelector } from 'react-redux';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import { Button } from '@strapi/design-system'; import { Button, Typography } from '@strapi/design-system';
import { Map } from 'immutable'; import { Map } from 'immutable';
import { getFetchClient, useNotification } from '@strapi/strapi/admin'; import { getFetchClient, useNotification } from '@strapi/strapi/admin';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
@ -14,38 +14,32 @@ const ActionButtons = () => {
const { post, get } = getFetchClient(); const { post, get } = getFetchClient();
const dispatch = useDispatch(); const dispatch = useDispatch();
const { toggleNotification } = useNotification(); const { toggleNotification } = useNotification();
const [modalIsOpen, setModalIsOpen] = useState(false);
const [actionType, setActionType] = useState('');
const partialDiff = useSelector((state) => state.getIn(['config', 'partialDiff'], Map({}))).toJS(); const partialDiff = useSelector((state) => state.getIn(['config', 'partialDiff'], Map({}))).toJS();
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
const closeModal = () => {
setActionType('');
setModalIsOpen(false);
};
const openModal = (type) => {
setActionType(type);
setModalIsOpen(true);
};
return ( return (
<ActionButtonsStyling> <ActionButtonsStyling>
<Button disabled={isEmpty(partialDiff)} onClick={() => openModal('import')}>
{formatMessage({ id: 'config-sync.Buttons.Import' })}
</Button>
<Button disabled={isEmpty(partialDiff)} onClick={() => openModal('export')}>
{formatMessage({ id: 'config-sync.Buttons.Export' })}
</Button>
{!isEmpty(partialDiff) && (
<h4 style={{ display: 'inline' }}>{Object.keys(partialDiff).length} {Object.keys(partialDiff).length === 1 ? "config change" : "config changes"}</h4>
)}
<ConfirmModal <ConfirmModal
isOpen={modalIsOpen} type="import"
onClose={closeModal} trigger={(
type={actionType} <Button disabled={isEmpty(partialDiff)}>
onSubmit={(force) => actionType === 'import' ? dispatch(importAllConfig(partialDiff, force, toggleNotification, formatMessage, post, get)) : dispatch(exportAllConfig(partialDiff, toggleNotification, formatMessage, post, get))} {formatMessage({ id: 'config-sync.Buttons.Import' })}
</Button>
)}
onSubmit={(force) => dispatch(importAllConfig(partialDiff, force, toggleNotification, formatMessage, post, get))}
/> />
<ConfirmModal
type="export"
trigger={(
<Button disabled={isEmpty(partialDiff)}>
{formatMessage({ id: 'config-sync.Buttons.Export' })}
</Button>
)}
onSubmit={(force) => dispatch(exportAllConfig(partialDiff, toggleNotification, formatMessage, post, get))}
/>
{!isEmpty(partialDiff) && (
<Typography variant="epsilon">{Object.keys(partialDiff).length} {Object.keys(partialDiff).length === 1 ? "config change" : "config changes"}</Typography>
)}
</ActionButtonsStyling> </ActionButtonsStyling>
); );
}; };

View File

@ -8,36 +8,39 @@ import {
Typography, Typography,
} from '@strapi/design-system'; } from '@strapi/design-system';
const ConfigDiff = ({ isOpen, onClose, oldValue, newValue, configName }) => { const ConfigDiff = ({ oldValue, newValue, configName, trigger }) => {
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
if (!isOpen) return null;
return ( return (
<Modal.Root <Modal.Root>
onClose={onClose} <Modal.Trigger>
labelledBy="title" {trigger}
> </Modal.Trigger>
<Modal.Header> <Modal.Content>
<Typography variant="omega" fontWeight="bold" textColor="neutral800"> <Modal.Header>
{formatMessage({ id: 'config-sync.ConfigDiff.Title' })} {configName} <Typography variant="omega" fontWeight="bold" textColor="neutral800">
</Typography> {formatMessage({ id: 'config-sync.ConfigDiff.Title' })} {configName}
</Modal.Header> </Typography>
<Modal.Body> </Modal.Header>
<Grid.Root paddingBottom={4} style={{ textAlign: 'center' }}> <Modal.Body>
<Grid.Item col={6}> <Grid.Root paddingBottom={4} style={{ textAlign: 'center' }}>
<Typography variant="delta">{formatMessage({ id: 'config-sync.ConfigDiff.SyncDirectory' })}</Typography> <Grid.Item col={6}>
</Grid.Item> <Typography variant="delta" style={{ width: '100%' }}>{formatMessage({ id: 'config-sync.ConfigDiff.SyncDirectory' })}</Typography>
<Grid.Item col={6}> </Grid.Item>
<Typography variant="delta">{formatMessage({ id: 'config-sync.ConfigDiff.Database' })}</Typography> <Grid.Item col={6}>
</Grid.Item> <Typography variant="delta" style={{ width: '100%' }}>{formatMessage({ id: 'config-sync.ConfigDiff.Database' })}</Typography>
</Grid.Root> </Grid.Item>
<ReactDiffViewer </Grid.Root>
oldValue={JSON.stringify(oldValue, null, 2)} <Typography variant="pi">
newValue={JSON.stringify(newValue, null, 2)} <ReactDiffViewer
splitView oldValue={JSON.stringify(oldValue, null, 2)}
compareMethod={DiffMethod.WORDS} newValue={JSON.stringify(newValue, null, 2)}
/> splitView
</Modal.Body> compareMethod={DiffMethod.WORDS}
/>
</Typography>
</Modal.Body>
</Modal.Content>
</Modal.Root> </Modal.Root>
); );
}; };

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
import { Tr, Td, Checkbox } from '@strapi/design-system'; import { Tr, Td, Checkbox, Typography } from '@strapi/design-system';
const CustomRow = ({ row, checked, updateValue }) => { const CustomRow = ({ row, checked, updateValue, ...props }) => {
const { configName, configType, state, onClick } = row; const { configName, configType, state, onClick } = row;
const stateStyle = (stateStr) => { const stateStyle = (stateStr) => {
@ -34,10 +34,14 @@ const CustomRow = ({ row, checked, updateValue }) => {
return ( return (
<Tr <Tr
{...props}
onClick={(e) => { onClick={(e) => {
if (e.target.type !== 'checkbox') { if (e.target.type !== 'checkbox') {
onClick(configType, configName); onClick(configType, configName);
} }
if (props.onClick) {
props.onClick(e);
}
}} }}
style={{ cursor: 'pointer' }} style={{ cursor: 'pointer' }}
> >
@ -49,13 +53,13 @@ const CustomRow = ({ row, checked, updateValue }) => {
/> />
</Td> </Td>
<Td> <Td>
<p>{configName}</p> <Typography variant="omega">{configName}</Typography>
</Td> </Td>
<Td> <Td>
<p>{configType}</p> <Typography variant="omega">{configType}</Typography>
</Td> </Td>
<Td> <Td>
<p style={stateStyle(state)}>{state}</p> <Typography variant="omega" style={stateStyle(state)}>{state}</Typography>
</Td> </Td>
</Tr> </Tr>
); );

View File

@ -117,13 +117,6 @@ const ConfigList = ({ diff, isLoading }) => {
return ( return (
<div> <div>
<ConfigDiff
isOpen={openModal}
oldValue={originalConfig}
newValue={newConfig}
onClose={closeModal}
configName={cName}
/>
<Table colCount={4} rowCount={rows.length + 1}> <Table colCount={4} rowCount={rows.length + 1}>
<Thead> <Thead>
<Tr> <Tr>
@ -148,14 +141,21 @@ const ConfigList = ({ diff, isLoading }) => {
</Thead> </Thead>
<Tbody> <Tbody>
{rows.map((row, index) => ( {rows.map((row, index) => (
<ConfigListRow <ConfigDiff
key={row.configName} key={row.configName}
row={row} oldValue={originalConfig}
checked={checkedItems[index]} newValue={newConfig}
updateValue={() => { configName={cName}
checkedItems[index] = !checkedItems[index]; trigger={(
setCheckedItems([...checkedItems]); <ConfigListRow
}} row={row}
checked={checkedItems[index]}
updateValue={() => {
checkedItems[index] = !checkedItems[index];
setCheckedItems([...checkedItems]);
}}
/>
)}
/> />
))} ))}
</Tbody> </Tbody>

View File

@ -10,69 +10,69 @@ import {
Checkbox, Checkbox,
Divider, Divider,
Box, Box,
Field,
} from '@strapi/design-system'; } from '@strapi/design-system';
import { WarningCircle } from '@strapi/icons'; import { WarningCircle } from '@strapi/icons';
const ConfirmModal = ({ isOpen, onClose, onSubmit, type }) => { const ConfirmModal = ({ onClose, onSubmit, type, trigger }) => {
const soft = useSelector((state) => state.getIn(['config', 'appEnv', 'config', 'soft'], false)); const soft = useSelector((state) => state.getIn(['config', 'appEnv', 'config', 'soft'], false));
const [force, setForce] = useState(false); const [force, setForce] = useState(false);
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
if (!isOpen) return null;
return ( return (
<Dialog.Root <Dialog.Root>
onClose={onClose} <Dialog.Trigger>
title={formatMessage({ id: "config-sync.popUpWarning.Confirmation" })} {trigger}
isOpen={isOpen} </Dialog.Trigger>
> <Dialog.Content>
<Dialog.Body icon={<WarningCircle />}> <Dialog.Header>{formatMessage({ id: "config-sync.popUpWarning.Confirmation" })}</Dialog.Header>
<Flex size={2}> <Dialog.Body>
<Flex justifyContent="center"> <WarningCircle fill="danger600" width="32px" height="32px" />
<Typography variant="omega" id="confirm-description" style={{ textAlign: 'center' }}> <Flex size={2}>
{formatMessage({ id: `config-sync.popUpWarning.warning.${type}_1` })}<br /> <Flex justifyContent="center">
{formatMessage({ id: `config-sync.popUpWarning.warning.${type}_2` })} <Typography variant="omega" id="confirm-description" style={{ textAlign: 'center' }}>
</Typography> {formatMessage({ id: `config-sync.popUpWarning.warning.${type}_1` })}<br />
{formatMessage({ id: `config-sync.popUpWarning.warning.${type}_2` })}
</Typography>
</Flex>
</Flex> </Flex>
</Flex> {(soft && type === 'import') && (
</Dialog.Body> <Box width="100%">
{(soft && type === 'import') && ( <Divider marginTop={4} />
<React.Fragment> <Box paddingTop={6}>
<Divider /> <Field.Root hint="Check this to ignore the soft setting.">
<Box padding={4}> <Checkbox
<Checkbox onValueChange={(value) => setForce(value)}
onValueChange={(value) => setForce(value)} value={force}
value={force} name="force"
name="force" >
hint="Check this to ignore the soft setting." {formatMessage({ id: 'config-sync.popUpWarning.force' })}
</Checkbox>
<Field.Hint />
</Field.Root>
</Box>
</Box>
)}
</Dialog.Body>
<Dialog.Footer>
<Dialog.Cancel>
<Button fullWidth variant="tertiary">
{formatMessage({ id: 'config-sync.popUpWarning.button.cancel' })}
</Button>
</Dialog.Cancel>
<Dialog.Action>
<Button
fullWidth
variant="secondary"
onClick={() => {
onSubmit(force);
}}
> >
{formatMessage({ id: 'config-sync.popUpWarning.force' })} {formatMessage({ id: `config-sync.popUpWarning.button.${type}` })}
</Checkbox> </Button>
</Box> </Dialog.Action>
</React.Fragment> </Dialog.Footer>
)} </Dialog.Content>
<Dialog.Footer
startAction={(
<Button
onClick={() => {
onClose();
}}
variant="tertiary"
>
{formatMessage({ id: 'config-sync.popUpWarning.button.cancel' })}
</Button>
)}
endAction={(
<Button
variant="secondary"
onClick={() => {
onClose();
onSubmit(force);
}}
>
{formatMessage({ id: `config-sync.popUpWarning.button.${type}` })}
</Button>
)} />
</Dialog.Root> </Dialog.Root>
); );
}; };

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react'; import React from 'react';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { getFetchClient, useNotification } from '@strapi/strapi/admin'; import { getFetchClient, useNotification } from '@strapi/strapi/admin';
@ -13,20 +13,21 @@ const FirstExport = () => {
const { post, get } = getFetchClient(); const { post, get } = getFetchClient();
const { toggleNotification } = useNotification(); const { toggleNotification } = useNotification();
const dispatch = useDispatch(); const dispatch = useDispatch();
const [modalIsOpen, setModalIsOpen] = useState(false);
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
return ( return (
<div> <div>
<ConfirmModal
isOpen={modalIsOpen}
onClose={() => setModalIsOpen(false)}
type="export"
onSubmit={() => dispatch(exportAllConfig([], toggleNotification, formatMessage, post, get))}
/>
<EmptyStateLayout <EmptyStateLayout
content={formatMessage({ id: 'config-sync.FirstExport.Message' })} content={formatMessage({ id: 'config-sync.FirstExport.Message' })}
action={<Button onClick={() => setModalIsOpen(true)}>{formatMessage({ id: 'config-sync.FirstExport.Button' })}</Button>} action={(
<ConfirmModal
type="export"
onSubmit={() => dispatch(exportAllConfig([], toggleNotification, formatMessage, post, get))}
trigger={(
<Button>{formatMessage({ id: 'config-sync.FirstExport.Button' })}</Button>
)}
/>
)}
icon={<EmptyDocuments width={160} />} icon={<EmptyDocuments width={160} />}
/> />
</div> </div>