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')}> <ConfirmModal
type="import"
trigger={(
<Button disabled={isEmpty(partialDiff)}>
{formatMessage({ id: 'config-sync.Buttons.Import' })} {formatMessage({ id: 'config-sync.Buttons.Import' })}
</Button> </Button>
<Button disabled={isEmpty(partialDiff)} onClick={() => openModal('export')}> )}
onSubmit={(force) => dispatch(importAllConfig(partialDiff, force, toggleNotification, formatMessage, post, get))}
/>
<ConfirmModal
type="export"
trigger={(
<Button disabled={isEmpty(partialDiff)}>
{formatMessage({ id: 'config-sync.Buttons.Export' })} {formatMessage({ id: 'config-sync.Buttons.Export' })}
</Button> </Button>
{!isEmpty(partialDiff) && (
<h4 style={{ display: 'inline' }}>{Object.keys(partialDiff).length} {Object.keys(partialDiff).length === 1 ? "config change" : "config changes"}</h4>
)} )}
<ConfirmModal onSubmit={(force) => dispatch(exportAllConfig(partialDiff, toggleNotification, formatMessage, post, get))}
isOpen={modalIsOpen}
onClose={closeModal}
type={actionType}
onSubmit={(force) => actionType === 'import' ? dispatch(importAllConfig(partialDiff, force, toggleNotification, formatMessage, post, get)) : 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,15 +8,15 @@ 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.Content>
<Modal.Header> <Modal.Header>
<Typography variant="omega" fontWeight="bold" textColor="neutral800"> <Typography variant="omega" fontWeight="bold" textColor="neutral800">
{formatMessage({ id: 'config-sync.ConfigDiff.Title' })} {configName} {formatMessage({ id: 'config-sync.ConfigDiff.Title' })} {configName}
@ -25,19 +25,22 @@ const ConfigDiff = ({ isOpen, onClose, oldValue, newValue, configName }) => {
<Modal.Body> <Modal.Body>
<Grid.Root paddingBottom={4} style={{ textAlign: 'center' }}> <Grid.Root paddingBottom={4} style={{ textAlign: 'center' }}>
<Grid.Item col={6}> <Grid.Item col={6}>
<Typography variant="delta">{formatMessage({ id: 'config-sync.ConfigDiff.SyncDirectory' })}</Typography> <Typography variant="delta" style={{ width: '100%' }}>{formatMessage({ id: 'config-sync.ConfigDiff.SyncDirectory' })}</Typography>
</Grid.Item> </Grid.Item>
<Grid.Item col={6}> <Grid.Item col={6}>
<Typography variant="delta">{formatMessage({ id: 'config-sync.ConfigDiff.Database' })}</Typography> <Typography variant="delta" style={{ width: '100%' }}>{formatMessage({ id: 'config-sync.ConfigDiff.Database' })}</Typography>
</Grid.Item> </Grid.Item>
</Grid.Root> </Grid.Root>
<Typography variant="pi">
<ReactDiffViewer <ReactDiffViewer
oldValue={JSON.stringify(oldValue, null, 2)} oldValue={JSON.stringify(oldValue, null, 2)}
newValue={JSON.stringify(newValue, null, 2)} newValue={JSON.stringify(newValue, null, 2)}
splitView splitView
compareMethod={DiffMethod.WORDS} compareMethod={DiffMethod.WORDS}
/> />
</Typography>
</Modal.Body> </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,8 +141,13 @@ const ConfigList = ({ diff, isLoading }) => {
</Thead> </Thead>
<Tbody> <Tbody>
{rows.map((row, index) => ( {rows.map((row, index) => (
<ConfigListRow <ConfigDiff
key={row.configName} key={row.configName}
oldValue={originalConfig}
newValue={newConfig}
configName={cName}
trigger={(
<ConfigListRow
row={row} row={row}
checked={checkedItems[index]} checked={checkedItems[index]}
updateValue={() => { updateValue={() => {
@ -157,6 +155,8 @@ const ConfigList = ({ diff, isLoading }) => {
setCheckedItems([...checkedItems]); setCheckedItems([...checkedItems]);
}} }}
/> />
)}
/>
))} ))}
</Tbody> </Tbody>
</Table> </Table>

View File

@ -10,23 +10,24 @@ 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>
<Dialog.Body>
<WarningCircle fill="danger600" width="32px" height="32px" />
<Flex size={2}> <Flex size={2}>
<Flex justifyContent="center"> <Flex justifyContent="center">
<Typography variant="omega" id="confirm-description" style={{ textAlign: 'center' }}> <Typography variant="omega" id="confirm-description" style={{ textAlign: 'center' }}>
@ -35,44 +36,43 @@ const ConfirmModal = ({ isOpen, onClose, onSubmit, type }) => {
</Typography> </Typography>
</Flex> </Flex>
</Flex> </Flex>
</Dialog.Body>
{(soft && type === 'import') && ( {(soft && type === 'import') && (
<React.Fragment> <Box width="100%">
<Divider /> <Divider marginTop={4} />
<Box padding={4}> <Box paddingTop={6}>
<Field.Root hint="Check this to ignore the soft setting.">
<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' })} {formatMessage({ id: 'config-sync.popUpWarning.force' })}
</Checkbox> </Checkbox>
<Field.Hint />
</Field.Root>
</Box>
</Box> </Box>
</React.Fragment>
)} )}
<Dialog.Footer </Dialog.Body>
startAction={( <Dialog.Footer>
<Button <Dialog.Cancel>
onClick={() => { <Button fullWidth variant="tertiary">
onClose();
}}
variant="tertiary"
>
{formatMessage({ id: 'config-sync.popUpWarning.button.cancel' })} {formatMessage({ id: 'config-sync.popUpWarning.button.cancel' })}
</Button> </Button>
)} </Dialog.Cancel>
endAction={( <Dialog.Action>
<Button <Button
fullWidth
variant="secondary" variant="secondary"
onClick={() => { onClick={() => {
onClose();
onSubmit(force); onSubmit(force);
}} }}
> >
{formatMessage({ id: `config-sync.popUpWarning.button.${type}` })} {formatMessage({ id: `config-sync.popUpWarning.button.${type}` })}
</Button> </Button>
)} /> </Dialog.Action>
</Dialog.Footer>
</Dialog.Content>
</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>