mirror of
				https://github.com/strapi/strapi.git
				synced 2025-11-04 03:43:34 +00:00 
			
		
		
		
	Merge pull request #12428 from strapi/content-92/remove-assets-upload
UploadDialog: allow removing assets before uploading
This commit is contained in:
		
						commit
						55f07ec804
					
				@ -8,11 +8,33 @@ import { AssetType, AssetDefinition } from '../../constants';
 | 
				
			|||||||
import { createAssetUrl } from '../../utils/createAssetUrl';
 | 
					import { createAssetUrl } from '../../utils/createAssetUrl';
 | 
				
			||||||
import toSingularTypes from '../../utils/toSingularTypes';
 | 
					import toSingularTypes from '../../utils/toSingularTypes';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const AssetCard = ({ allowedTypes, asset, isSelected, onSelect, onEdit, size, local }) => {
 | 
					export const AssetCard = ({
 | 
				
			||||||
 | 
					  allowedTypes,
 | 
				
			||||||
 | 
					  asset,
 | 
				
			||||||
 | 
					  isSelected,
 | 
				
			||||||
 | 
					  onSelect,
 | 
				
			||||||
 | 
					  onEdit,
 | 
				
			||||||
 | 
					  onRemove,
 | 
				
			||||||
 | 
					  size,
 | 
				
			||||||
 | 
					  local,
 | 
				
			||||||
 | 
					}) => {
 | 
				
			||||||
  const singularTypes = toSingularTypes(allowedTypes);
 | 
					  const singularTypes = toSingularTypes(allowedTypes);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  let handleSelect = onSelect ? () => onSelect(asset) : undefined;
 | 
					  let handleSelect = onSelect ? () => onSelect(asset) : undefined;
 | 
				
			||||||
  const fileType = asset.mime.split('/')[0];
 | 
					  const fileType = asset.mime.split('/')[0];
 | 
				
			||||||
 | 
					  const commonAssetCardProps = {
 | 
				
			||||||
 | 
					    id: asset.id,
 | 
				
			||||||
 | 
					    extension: getFileExtension(asset.ext),
 | 
				
			||||||
 | 
					    key: asset.id,
 | 
				
			||||||
 | 
					    name: asset.name,
 | 
				
			||||||
 | 
					    url: local ? asset.url : createAssetUrl(asset, true),
 | 
				
			||||||
 | 
					    mime: asset.mime,
 | 
				
			||||||
 | 
					    onEdit: onEdit ? () => onEdit(asset) : undefined,
 | 
				
			||||||
 | 
					    onSelect: handleSelect,
 | 
				
			||||||
 | 
					    onRemove: onRemove ? () => onRemove(asset) : undefined,
 | 
				
			||||||
 | 
					    selected: isSelected,
 | 
				
			||||||
 | 
					    size,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (asset.mime.includes(AssetType.Video)) {
 | 
					  if (asset.mime.includes(AssetType.Video)) {
 | 
				
			||||||
    const canSelectAsset = singularTypes.includes(fileType);
 | 
					    const canSelectAsset = singularTypes.includes(fileType);
 | 
				
			||||||
@ -21,20 +43,7 @@ export const AssetCard = ({ allowedTypes, asset, isSelected, onSelect, onEdit, s
 | 
				
			|||||||
      handleSelect = undefined;
 | 
					      handleSelect = undefined;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return <VideoAssetCard {...commonAssetCardProps} />;
 | 
				
			||||||
      <VideoAssetCard
 | 
					 | 
				
			||||||
        id={asset.id}
 | 
					 | 
				
			||||||
        key={asset.id}
 | 
					 | 
				
			||||||
        name={asset.name}
 | 
					 | 
				
			||||||
        extension={getFileExtension(asset.ext)}
 | 
					 | 
				
			||||||
        url={local ? asset.url : createAssetUrl(asset, true)}
 | 
					 | 
				
			||||||
        mime={asset.mime}
 | 
					 | 
				
			||||||
        onEdit={onEdit ? () => onEdit(asset) : undefined}
 | 
					 | 
				
			||||||
        onSelect={handleSelect}
 | 
					 | 
				
			||||||
        selected={isSelected}
 | 
					 | 
				
			||||||
        size={size}
 | 
					 | 
				
			||||||
      />
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (asset.mime.includes(AssetType.Image)) {
 | 
					  if (asset.mime.includes(AssetType.Image)) {
 | 
				
			||||||
@ -46,18 +55,11 @@ export const AssetCard = ({ allowedTypes, asset, isSelected, onSelect, onEdit, s
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <ImageAssetCard
 | 
					      <ImageAssetCard
 | 
				
			||||||
        id={asset.id}
 | 
					        {...commonAssetCardProps}
 | 
				
			||||||
        key={asset.id}
 | 
					 | 
				
			||||||
        name={asset.name}
 | 
					 | 
				
			||||||
        alt={asset.alternativeText || asset.name}
 | 
					        alt={asset.alternativeText || asset.name}
 | 
				
			||||||
        extension={getFileExtension(asset.ext)}
 | 
					 | 
				
			||||||
        height={asset.height}
 | 
					        height={asset.height}
 | 
				
			||||||
        width={asset.width}
 | 
					 | 
				
			||||||
        thumbnail={prefixFileUrlWithBackendUrl(asset?.formats?.thumbnail?.url || asset.url)}
 | 
					        thumbnail={prefixFileUrlWithBackendUrl(asset?.formats?.thumbnail?.url || asset.url)}
 | 
				
			||||||
        onEdit={onEdit ? () => onEdit(asset) : undefined}
 | 
					        width={asset.width}
 | 
				
			||||||
        onSelect={handleSelect}
 | 
					 | 
				
			||||||
        selected={isSelected}
 | 
					 | 
				
			||||||
        size={size}
 | 
					 | 
				
			||||||
      />
 | 
					      />
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -68,18 +70,7 @@ export const AssetCard = ({ allowedTypes, asset, isSelected, onSelect, onEdit, s
 | 
				
			|||||||
    handleSelect = undefined;
 | 
					    handleSelect = undefined;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return <DocAssetCard {...commonAssetCardProps} />;
 | 
				
			||||||
    <DocAssetCard
 | 
					 | 
				
			||||||
      id={asset.id}
 | 
					 | 
				
			||||||
      key={asset.id}
 | 
					 | 
				
			||||||
      name={asset.name}
 | 
					 | 
				
			||||||
      extension={getFileExtension(asset.ext)}
 | 
					 | 
				
			||||||
      onEdit={onEdit ? () => onEdit(asset) : undefined}
 | 
					 | 
				
			||||||
      onSelect={handleSelect}
 | 
					 | 
				
			||||||
      selected={isSelected}
 | 
					 | 
				
			||||||
      size={size}
 | 
					 | 
				
			||||||
    />
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AssetCard.defaultProps = {
 | 
					AssetCard.defaultProps = {
 | 
				
			||||||
@ -89,6 +80,7 @@ AssetCard.defaultProps = {
 | 
				
			|||||||
  local: false,
 | 
					  local: false,
 | 
				
			||||||
  onSelect: undefined,
 | 
					  onSelect: undefined,
 | 
				
			||||||
  onEdit: undefined,
 | 
					  onEdit: undefined,
 | 
				
			||||||
 | 
					  onRemove: undefined,
 | 
				
			||||||
  size: 'M',
 | 
					  size: 'M',
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -98,6 +90,7 @@ AssetCard.propTypes = {
 | 
				
			|||||||
  local: PropTypes.bool,
 | 
					  local: PropTypes.bool,
 | 
				
			||||||
  onSelect: PropTypes.func,
 | 
					  onSelect: PropTypes.func,
 | 
				
			||||||
  onEdit: PropTypes.func,
 | 
					  onEdit: PropTypes.func,
 | 
				
			||||||
 | 
					  onRemove: PropTypes.func,
 | 
				
			||||||
  isSelected: PropTypes.bool,
 | 
					  isSelected: PropTypes.bool,
 | 
				
			||||||
  size: PropTypes.oneOf(['S', 'M']),
 | 
					  size: PropTypes.oneOf(['S', 'M']),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,7 @@ import {
 | 
				
			|||||||
} from '@strapi/design-system/Card';
 | 
					} from '@strapi/design-system/Card';
 | 
				
			||||||
import { IconButton } from '@strapi/design-system/IconButton';
 | 
					import { IconButton } from '@strapi/design-system/IconButton';
 | 
				
			||||||
import Pencil from '@strapi/icons/Pencil';
 | 
					import Pencil from '@strapi/icons/Pencil';
 | 
				
			||||||
 | 
					import Trash from '@strapi/icons/Trash';
 | 
				
			||||||
import { useIntl } from 'react-intl';
 | 
					import { useIntl } from 'react-intl';
 | 
				
			||||||
import { getTrad } from '../../utils';
 | 
					import { getTrad } from '../../utils';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -32,6 +33,7 @@ export const ImageAssetCard = ({
 | 
				
			|||||||
  selected,
 | 
					  selected,
 | 
				
			||||||
  onSelect,
 | 
					  onSelect,
 | 
				
			||||||
  onEdit,
 | 
					  onEdit,
 | 
				
			||||||
 | 
					  onRemove,
 | 
				
			||||||
  size,
 | 
					  size,
 | 
				
			||||||
  alt,
 | 
					  alt,
 | 
				
			||||||
}) => {
 | 
					}) => {
 | 
				
			||||||
@ -46,13 +48,26 @@ export const ImageAssetCard = ({
 | 
				
			|||||||
    <Card>
 | 
					    <Card>
 | 
				
			||||||
      <CardHeader>
 | 
					      <CardHeader>
 | 
				
			||||||
        {onSelect && <CardCheckbox value={selected} onValueChange={onSelect} />}
 | 
					        {onSelect && <CardCheckbox value={selected} onValueChange={onSelect} />}
 | 
				
			||||||
        {onEdit && (
 | 
					        {(onRemove || onEdit) && (
 | 
				
			||||||
          <CardAction position="end">
 | 
					          <CardAction position="end">
 | 
				
			||||||
 | 
					            {onRemove && (
 | 
				
			||||||
 | 
					              <IconButton
 | 
				
			||||||
 | 
					                label={formatMessage({
 | 
				
			||||||
 | 
					                  id: getTrad('control-card.remove-selection'),
 | 
				
			||||||
 | 
					                  defaultMessage: 'Remove from selection',
 | 
				
			||||||
 | 
					                })}
 | 
				
			||||||
 | 
					                icon={<Trash />}
 | 
				
			||||||
 | 
					                onClick={onRemove}
 | 
				
			||||||
 | 
					              />
 | 
				
			||||||
 | 
					            )}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            {onEdit && (
 | 
				
			||||||
              <IconButton
 | 
					              <IconButton
 | 
				
			||||||
                label={formatMessage({ id: getTrad('control-card.edit'), defaultMessage: 'Edit' })}
 | 
					                label={formatMessage({ id: getTrad('control-card.edit'), defaultMessage: 'Edit' })}
 | 
				
			||||||
                icon={<Pencil />}
 | 
					                icon={<Pencil />}
 | 
				
			||||||
                onClick={onEdit}
 | 
					                onClick={onEdit}
 | 
				
			||||||
              />
 | 
					              />
 | 
				
			||||||
 | 
					            )}
 | 
				
			||||||
          </CardAction>
 | 
					          </CardAction>
 | 
				
			||||||
        )}
 | 
					        )}
 | 
				
			||||||
        <CardAsset src={optimizedCachingThumbnail} size={size} alt={alt} />
 | 
					        <CardAsset src={optimizedCachingThumbnail} size={size} alt={alt} />
 | 
				
			||||||
@ -81,6 +96,7 @@ ImageAssetCard.defaultProps = {
 | 
				
			|||||||
  selected: false,
 | 
					  selected: false,
 | 
				
			||||||
  onEdit: undefined,
 | 
					  onEdit: undefined,
 | 
				
			||||||
  onSelect: undefined,
 | 
					  onSelect: undefined,
 | 
				
			||||||
 | 
					  onRemove: undefined,
 | 
				
			||||||
  size: 'M',
 | 
					  size: 'M',
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -91,6 +107,7 @@ ImageAssetCard.propTypes = {
 | 
				
			|||||||
  name: PropTypes.string.isRequired,
 | 
					  name: PropTypes.string.isRequired,
 | 
				
			||||||
  onEdit: PropTypes.func,
 | 
					  onEdit: PropTypes.func,
 | 
				
			||||||
  onSelect: PropTypes.func,
 | 
					  onSelect: PropTypes.func,
 | 
				
			||||||
 | 
					  onRemove: PropTypes.func,
 | 
				
			||||||
  width: PropTypes.number,
 | 
					  width: PropTypes.number,
 | 
				
			||||||
  thumbnail: PropTypes.string.isRequired,
 | 
					  thumbnail: PropTypes.string.isRequired,
 | 
				
			||||||
  selected: PropTypes.bool,
 | 
					  selected: PropTypes.bool,
 | 
				
			||||||
 | 
				
			|||||||
@ -23,6 +23,7 @@ export const PendingAssetStep = ({
 | 
				
			|||||||
  addUploadedFiles,
 | 
					  addUploadedFiles,
 | 
				
			||||||
  onClose,
 | 
					  onClose,
 | 
				
			||||||
  onEditAsset,
 | 
					  onEditAsset,
 | 
				
			||||||
 | 
					  onRemoveAsset,
 | 
				
			||||||
  assets,
 | 
					  assets,
 | 
				
			||||||
  onClickAddAsset,
 | 
					  onClickAddAsset,
 | 
				
			||||||
  onCancelUpload,
 | 
					  onCancelUpload,
 | 
				
			||||||
@ -126,6 +127,7 @@ export const PendingAssetStep = ({
 | 
				
			|||||||
                      local
 | 
					                      local
 | 
				
			||||||
                      alt={asset.name}
 | 
					                      alt={asset.name}
 | 
				
			||||||
                      onEdit={onEditAsset}
 | 
					                      onEdit={onEditAsset}
 | 
				
			||||||
 | 
					                      onRemove={onRemoveAsset}
 | 
				
			||||||
                    />
 | 
					                    />
 | 
				
			||||||
                  </GridItem>
 | 
					                  </GridItem>
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
@ -168,6 +170,7 @@ PendingAssetStep.propTypes = {
 | 
				
			|||||||
  assets: PropTypes.arrayOf(AssetDefinition).isRequired,
 | 
					  assets: PropTypes.arrayOf(AssetDefinition).isRequired,
 | 
				
			||||||
  onClose: PropTypes.func.isRequired,
 | 
					  onClose: PropTypes.func.isRequired,
 | 
				
			||||||
  onEditAsset: PropTypes.func.isRequired,
 | 
					  onEditAsset: PropTypes.func.isRequired,
 | 
				
			||||||
 | 
					  onRemoveAsset: PropTypes.func.isRequired,
 | 
				
			||||||
  onClickAddAsset: PropTypes.func.isRequired,
 | 
					  onClickAddAsset: PropTypes.func.isRequired,
 | 
				
			||||||
  onUploadSucceed: PropTypes.func.isRequired,
 | 
					  onUploadSucceed: PropTypes.func.isRequired,
 | 
				
			||||||
  onCancelUpload: PropTypes.func.isRequired,
 | 
					  onCancelUpload: PropTypes.func.isRequired,
 | 
				
			||||||
 | 
				
			|||||||
@ -78,6 +78,11 @@ export const UploadAssetDialog = ({
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const handleRemoveAsset = assetToRemove => {
 | 
				
			||||||
 | 
					    const nextAssets = assets.filter(asset => asset !== assetToRemove);
 | 
				
			||||||
 | 
					    setAssets(nextAssets);
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
    <ModalLayout onClose={handleClose} labelledBy="title">
 | 
					    <ModalLayout onClose={handleClose} labelledBy="title">
 | 
				
			||||||
      {step === Steps.AddAsset && (
 | 
					      {step === Steps.AddAsset && (
 | 
				
			||||||
@ -93,6 +98,7 @@ export const UploadAssetDialog = ({
 | 
				
			|||||||
          onClose={handleClose}
 | 
					          onClose={handleClose}
 | 
				
			||||||
          assets={assets}
 | 
					          assets={assets}
 | 
				
			||||||
          onEditAsset={setAssetToEdit}
 | 
					          onEditAsset={setAssetToEdit}
 | 
				
			||||||
 | 
					          onRemoveAsset={handleRemoveAsset}
 | 
				
			||||||
          onClickAddAsset={moveToAddAsset}
 | 
					          onClickAddAsset={moveToAddAsset}
 | 
				
			||||||
          onCancelUpload={handleCancelUpload}
 | 
					          onCancelUpload={handleCancelUpload}
 | 
				
			||||||
          onUploadSucceed={handleUploadSuccess}
 | 
					          onUploadSucceed={handleUploadSuccess}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user