fix: several media lib ui issues

fix: using open prop does not clear any state and create a lot of bugs

fix: crop
This commit is contained in:
Alexandre Bodin 2024-06-20 12:21:02 +02:00
parent 5285f8db42
commit 3aee925501
19 changed files with 129 additions and 93 deletions

View File

@ -8,7 +8,7 @@ import { useIntl } from 'react-intl';
* ConfirmDialog * ConfirmDialog
* -----------------------------------------------------------------------------------------------*/ * -----------------------------------------------------------------------------------------------*/
interface ConfirmDialogProps extends Pick<ButtonProps, 'variant'>, Pick<Dialog.BodyProps, 'icon'> { interface ConfirmDialogProps extends Pick<ButtonProps, 'variant'>, Pick<Dialog.BodyProps, 'icon'> {
onConfirm?: () => Promise<void> | void; onConfirm?: (e?: React.MouseEvent<HTMLButtonElement>) => Promise<void> | void;
children?: React.ReactNode; children?: React.ReactNode;
endAction?: React.ReactNode; endAction?: React.ReactNode;
startAction?: React.ReactNode; startAction?: React.ReactNode;
@ -66,14 +66,14 @@ const ConfirmDialog = ({
defaultMessage: 'Are you sure?', defaultMessage: 'Are you sure?',
}); });
const handleConfirm = async () => { const handleConfirm = async (e: React.MouseEvent<HTMLButtonElement>) => {
if (!onConfirm) { if (!onConfirm) {
return; return;
} }
try { try {
setIsConfirming(true); setIsConfirming(true);
await onConfirm(); await onConfirm(e);
} finally { } finally {
setIsConfirming(false); setIsConfirming(false);
} }

View File

@ -309,7 +309,7 @@ const ListPage = () => {
<Td> <Td>
<Typography textColor="neutral800">{webhook.url}</Typography> <Typography textColor="neutral800">{webhook.url}</Typography>
</Td> </Td>
<Td> <Td onClick={(e) => e.stopPropagation()}>
<Flex> <Flex>
<Switch <Switch
onLabel={formatMessage({ onLabel={formatMessage({

View File

@ -298,7 +298,11 @@ export const BrowseStep = ({
onClick={() => handleClickFolderCard(folder.id, folder.path)} onClick={() => handleClickFolderCard(folder.id, folder.path)}
> >
<Flex tag="h2" direction="column" alignItems="start" maxWidth="100%"> <Flex tag="h2" direction="column" alignItems="start" maxWidth="100%">
<TypographyMaxWidth fontWeight="semiBold" ellipsis> <TypographyMaxWidth
fontWeight="semiBold"
ellipsis
textColor="neutral800"
>
{folder.name} {folder.name}
{/* VisuallyHidden dash here allows to separate folder title and count informations {/* VisuallyHidden dash here allows to separate folder title and count informations
for voice reading structure purpose */} for voice reading structure purpose */}

View File

@ -278,7 +278,7 @@ exports[`BrowseStep renders and match snapshot 1`] = `
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
font-weight: 500; font-weight: 500;
color: currentcolor; color: #32324d;
} }
.c56 { .c56 {

View File

@ -214,7 +214,7 @@ export const AssetContent = ({
</Modal.Title> </Modal.Title>
</Modal.Header> </Modal.Header>
<Tabs.Root variant="simple" defaultValue={selectedAssets.length > 0 ? 'selected' : 'browse'}> <TabsRoot variant="simple" defaultValue={selectedAssets.length > 0 ? 'selected' : 'browse'}>
<Flex paddingLeft={8} paddingRight={8} paddingTop={6} justifyContent="space-between"> <Flex paddingLeft={8} paddingRight={8} paddingTop={6} justifyContent="space-between">
<Tabs.List> <Tabs.List>
<Tabs.Trigger value="browse"> <Tabs.Trigger value="browse">
@ -283,7 +283,7 @@ export const AssetContent = ({
/> />
</Tabs.Content> </Tabs.Content>
</Modal.Body> </Modal.Body>
</Tabs.Root> </TabsRoot>
<DialogFooter onClose={onClose} onValidate={() => onValidate(selectedAssets)} /> <DialogFooter onClose={onClose} onValidate={() => onValidate(selectedAssets)} />
</> </>
); );
@ -342,3 +342,9 @@ AssetDialog.propTypes = {
onValidate: PropTypes.func.isRequired, onValidate: PropTypes.func.isRequired,
trackedLocation: PropTypes.string, trackedLocation: PropTypes.string,
}; };
const TabsRoot = styled(Tabs.Root)`
display: flex;
flex-direction: column;
overflow: hidden;
`;

View File

@ -4,7 +4,7 @@ import { Flex, FocusTrap, IconButton, Menu } from '@strapi/design-system';
import { Check, Cross } from '@strapi/icons'; import { Check, Cross } from '@strapi/icons';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
import { styled } from 'styled-components'; import { styled, useTheme } from 'styled-components';
import getTrad from '../../../utils/getTrad'; import getTrad from '../../../utils/getTrad';
@ -12,6 +12,7 @@ import { CroppingActionRow } from './components';
export const CroppingActions = ({ onCancel, onValidate, onDuplicate }) => { export const CroppingActions = ({ onCancel, onValidate, onDuplicate }) => {
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
const theme = useTheme();
return ( return (
<FocusTrap onEscape={onCancel}> <FocusTrap onEscape={onCancel}>
@ -45,7 +46,7 @@ export const CroppingActions = ({ onCancel, onValidate, onDuplicate }) => {
fill="#C0C0D0" fill="#C0C0D0"
/> />
</Trigger> </Trigger>
<Menu.Content zIndex={5}> <Menu.Content zIndex={theme.zIndices.dialog}>
<Menu.Item onSelect={onValidate}> <Menu.Item onSelect={onValidate}>
{formatMessage({ {formatMessage({
id: getTrad('checkControl.crop-original'), id: getTrad('checkControl.crop-original'),

View File

@ -7,7 +7,8 @@ export const RelativeBox = styled(Box)`
export const Wrapper = styled.div` export const Wrapper = styled.div`
position: relative; position: relative;
text-align: center; display: flex;
justify-content: center;
background: repeating-conic-gradient( background: repeating-conic-gradient(
${({ theme }) => theme.colors.neutral100} 0% 25%, ${({ theme }) => theme.colors.neutral100} 0% 25%,
transparent 0% 50% transparent 0% 50%

View File

@ -8,9 +8,12 @@ import { useRemoveAsset } from '../../hooks/useRemoveAsset';
export const RemoveAssetDialog = ({ open, onClose, asset }) => { export const RemoveAssetDialog = ({ open, onClose, asset }) => {
// `null` means asset is deleted // `null` means asset is deleted
const { removeAsset } = useRemoveAsset(() => onClose(null)); const { removeAsset } = useRemoveAsset(() => {
onClose(null);
});
const handleConfirm = async () => { const handleConfirm = async (event) => {
event.preventDefault();
await removeAsset(asset.id); await removeAsset(asset.id);
}; };

View File

@ -485,7 +485,8 @@ exports[`<EditAssetDialog /> renders and matches the snapshot 1`] = `
.c24 { .c24 {
position: relative; position: relative;
text-align: center; display: flex;
justify-content: center;
background: repeating-conic-gradient( #f6f6f9 0% 25%, transparent 0% 50% ) 50%/20px 20px; background: repeating-conic-gradient( #f6f6f9 0% 25%, transparent 0% 50% ) 50%/20px 20px;
} }

View File

@ -485,7 +485,8 @@ exports[`<EditAssetDialog /> renders and matches the snapshot 1`] = `
.c24 { .c24 {
position: relative; position: relative;
text-align: center; display: flex;
justify-content: center;
background: repeating-conic-gradient( #f6f6f9 0% 25%, transparent 0% 50% ) 50%/20px 20px; background: repeating-conic-gradient( #f6f6f9 0% 25%, transparent 0% 50% ) 50%/20px 20px;
} }

View File

@ -179,38 +179,44 @@ export const MediaLibraryInput = forwardRef(
trackedLocation="content-manager" trackedLocation="content-manager"
/> />
<AssetDialog {step === STEPS.AssetSelect && (
allowedTypes={fieldAllowedTypes} <AssetDialog
initiallySelectedAssets={initiallySelectedAssets} allowedTypes={fieldAllowedTypes}
folderId={folderId} initiallySelectedAssets={initiallySelectedAssets}
onClose={() => { folderId={folderId}
setStep(undefined); onClose={() => {
setFolderId(null); setStep(undefined);
}} setFolderId(null);
open={step === STEPS.AssetSelect} }}
onValidate={handleValidation} open={step === STEPS.AssetSelect}
multiple={multiple} onValidate={handleValidation}
onAddAsset={() => setStep(STEPS.AssetUpload)} multiple={multiple}
onAddFolder={() => setStep(STEPS.FolderCreate)} onAddAsset={() => setStep(STEPS.AssetUpload)}
onChangeFolder={(folder) => setFolderId(folder)} onAddFolder={() => setStep(STEPS.FolderCreate)}
trackedLocation="content-manager" onChangeFolder={(folder) => setFolderId(folder)}
/> trackedLocation="content-manager"
/>
)}
<UploadAssetDialog {step === STEPS.AssetUpload && (
open={step === STEPS.AssetUpload} <UploadAssetDialog
onClose={() => setStep(STEPS.AssetSelect)} open={step === STEPS.AssetUpload}
initialAssetsToAdd={droppedAssets} onClose={() => setStep(STEPS.AssetSelect)}
addUploadedFiles={handleFilesUploadSucceeded} initialAssetsToAdd={droppedAssets}
trackedLocation="content-manager" addUploadedFiles={handleFilesUploadSucceeded}
folderId={folderId} trackedLocation="content-manager"
validateAssetsTypes={validateAssetsTypes} folderId={folderId}
/> validateAssetsTypes={validateAssetsTypes}
/>
)}
<EditFolderDialog {step === STEPS.FolderCreate && (
open={step === STEPS.FolderCreate} <EditFolderDialog
onClose={() => setStep(STEPS.AssetSelect)} open={step === STEPS.FolderCreate}
parentFolderId={folderId} onClose={() => setStep(STEPS.AssetSelect)}
/> parentFolderId={folderId}
/>
)}
</> </>
); );
} }

View File

@ -199,6 +199,11 @@ const getSelectStyles = (theme, error) => {
color: theme.colors.neutral800, color: theme.colors.neutral800,
gridTemplateColumns: '0 100%', gridTemplateColumns: '0 100%',
}), }),
menuPortal: (base) => ({
...base,
zIndex: theme.zIndices.dialog,
pointerEvents: 'auto',
}),
menu(base) { menu(base) {
return { return {
...base, ...base,
@ -220,10 +225,6 @@ const getSelectStyles = (theme, error) => {
paddingRight: theme.spaces[1], paddingRight: theme.spaces[1],
paddingBottom: theme.spaces[1], paddingBottom: theme.spaces[1],
}), }),
menuPortal: (base) => ({
...base,
zIndex: 100,
}),
option(base, state) { option(base, state) {
let backgroundColor = base.backgroundColor; let backgroundColor = base.backgroundColor;

View File

@ -77,7 +77,7 @@ export const PendingAssetStep = ({
}; };
return ( return (
<form onSubmit={handleSubmit}> <>
<Modal.Header> <Modal.Header>
<Modal.Title> <Modal.Title>
{formatMessage({ {formatMessage({
@ -159,7 +159,7 @@ export const PendingAssetStep = ({
<Button onClick={onClose} variant="tertiary"> <Button onClick={onClose} variant="tertiary">
{formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'cancel' })} {formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'cancel' })}
</Button> </Button>
<Button type="submit" loading={uploadStatus === Status.Uploading}> <Button onClick={handleSubmit} loading={uploadStatus === Status.Uploading}>
{formatMessage( {formatMessage(
{ {
id: getTrad('modal.upload-list.footer.button'), id: getTrad('modal.upload-list.footer.button'),
@ -170,7 +170,7 @@ export const PendingAssetStep = ({
)} )}
</Button> </Button>
</Modal.Footer> </Modal.Footer>
</form> </>
); );
}; };

View File

@ -93,16 +93,18 @@ export const UploadAssetDialog = ({
return ( return (
<Modal.Root open={open} onOpenChange={handleClose}> <Modal.Root open={open} onOpenChange={handleClose}>
<Modal.Content> {step === Steps.AddAsset && (
{step === Steps.AddAsset && ( <Modal.Content>
<AddAssetStep <AddAssetStep
onClose={onClose} onClose={onClose}
onAddAsset={handleAddToPendingAssets} onAddAsset={handleAddToPendingAssets}
trackedLocation={trackedLocation} trackedLocation={trackedLocation}
/> />
)} </Modal.Content>
)}
{step === Steps.PendingAsset && ( {step === Steps.PendingAsset && (
<Modal.Content>
<PendingAssetStep <PendingAssetStep
onClose={handleClose} onClose={handleClose}
assets={assets} assets={assets}
@ -116,9 +118,11 @@ export const UploadAssetDialog = ({
folderId={folderId} folderId={folderId}
trackedLocation={trackedLocation} trackedLocation={trackedLocation}
/> />
)} </Modal.Content>
)}
{assetToEdit && ( {assetToEdit && (
<Modal.Content>
<EditAssetContent <EditAssetContent
onClose={handleAssetEditValidation} onClose={handleAssetEditValidation}
asset={assetToEdit} asset={assetToEdit}
@ -127,8 +131,8 @@ export const UploadAssetDialog = ({
canDownload={false} canDownload={false}
trackedLocation={trackedLocation} trackedLocation={trackedLocation}
/> />
)} </Modal.Content>
</Modal.Content> )}
</Modal.Root> </Modal.Root>
); );
}; };

View File

@ -44,7 +44,7 @@ const ConfigureTheView = ({ config }) => {
const handleConfirm = async () => { const handleConfirm = async () => {
trackUsage('willEditMediaLibraryConfig'); trackUsage('willEditMediaLibraryConfig');
await mutateConfig.mutateAsync(modifiedData); await mutateConfig.mutateAsync(modifiedData);
toggleWarningSubmit(); setWarningSubmit(false);
dispatch(setLoaded()); dispatch(setLoaded());
toggleNotification({ toggleNotification({
type: 'success', type: 'success',

View File

@ -6,7 +6,7 @@ import { ArrowLeft, Plus } from '@strapi/icons';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { stringify } from 'qs'; import { stringify } from 'qs';
import { useIntl } from 'react-intl'; import { useIntl } from 'react-intl';
import { useLocation } from 'react-router-dom'; import { useLocation, NavLink } from 'react-router-dom';
import { Breadcrumbs } from '../../../../components/Breadcrumbs'; import { Breadcrumbs } from '../../../../components/Breadcrumbs';
import { BreadcrumbsDefinition, FolderDefinition } from '../../../../constants'; import { BreadcrumbsDefinition, FolderDefinition } from '../../../../constants';
@ -51,6 +51,7 @@ export const Header = ({
navigationAction={ navigationAction={
folder && ( folder && (
<Link <Link
tag={NavLink}
startIcon={<ArrowLeft />} startIcon={<ArrowLeft />}
to={`${pathname}?${stringify(backQuery, { encode: false })}`} to={`${pathname}?${stringify(backQuery, { encode: false })}`}
> >

View File

@ -262,10 +262,11 @@ exports[`Header renders 1`] = `
class="c1" class="c1"
> >
<a <a
aria-current="page"
aria-disabled="false" aria-disabled="false"
class="c2 c3" class="c2 c3 active"
href="/?folder=2&folderPath=/1"
target="_self" target="_self"
to="/?folder=2&folderPath=/1"
> >
<svg <svg
fill="currentColor" fill="currentColor"

View File

@ -486,35 +486,41 @@ export const MediaLibrary = () => {
</Pagination.Root> </Pagination.Root>
</Layouts.Content> </Layouts.Content>
</Page.Main> </Page.Main>
<UploadAssetDialog {showUploadAssetDialog && (
open={showUploadAssetDialog} <UploadAssetDialog
onClose={toggleUploadAssetDialog} open={showUploadAssetDialog}
trackedLocation="upload" onClose={toggleUploadAssetDialog}
folderId={query?.folder} trackedLocation="upload"
/> folderId={query?.folder}
<EditFolderDialog />
open={showEditFolderDialog} )}
onClose={handleEditFolderClose} {showEditFolderDialog && (
folder={folderToEdit} <EditFolderDialog
parentFolderId={query?.folder} open={showEditFolderDialog}
location="upload" onClose={handleEditFolderClose}
/> folder={folderToEdit}
<EditAssetDialog parentFolderId={query?.folder}
onClose={(editedAsset) => { location="upload"
// The asset has been deleted />
if (editedAsset === null) { )}
handleAssetDeleted(1); {assetToEdit && (
} <EditAssetDialog
onClose={(editedAsset) => {
// The asset has been deleted
if (editedAsset === null) {
handleAssetDeleted(1);
}
setAssetToEdit(undefined); setAssetToEdit(undefined);
}} }}
open={!!assetToEdit} open={!!assetToEdit}
asset={assetToEdit} asset={assetToEdit}
canUpdate={canUpdate} canUpdate={canUpdate}
canCopyLink={canCopyLink} canCopyLink={canCopyLink}
canDownload={canDownload} canDownload={canDownload}
trackedLocation="upload" trackedLocation="upload"
/> />
)}
</Layouts.Root> </Layouts.Root>
); );
}; };