mirror of
https://github.com/strapi/strapi.git
synced 2025-12-27 07:03:38 +00:00
refactor: use one AssetCardBase
This commit is contained in:
parent
2e44e15bc7
commit
102e4d1c84
@ -0,0 +1,122 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
import { Box } from '@strapi/design-system/Box';
|
||||
import {
|
||||
Card,
|
||||
CardAction,
|
||||
CardBadge,
|
||||
CardBody,
|
||||
CardCheckbox,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
CardSubtitle,
|
||||
} from '@strapi/design-system/Card';
|
||||
import { IconButton } from '@strapi/design-system/IconButton';
|
||||
import Pencil from '@strapi/icons/Pencil';
|
||||
import Trash from '@strapi/icons/Trash';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
import { getTrad } from '../../utils';
|
||||
|
||||
const Extension = styled.span`
|
||||
text-transform: uppercase;
|
||||
`;
|
||||
|
||||
const CardActionsContainer = styled(CardAction)``;
|
||||
|
||||
const CardContainer = styled(Card)`
|
||||
${CardActionsContainer} {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
${CardActionsContainer} {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const AssetCardBase = ({
|
||||
children,
|
||||
name,
|
||||
extension,
|
||||
selected,
|
||||
onSelect,
|
||||
onRemove,
|
||||
onEdit,
|
||||
subtitle,
|
||||
variant,
|
||||
}) => {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
return (
|
||||
<CardContainer height="100%">
|
||||
<CardHeader>
|
||||
{onSelect && <CardCheckbox value={selected} onValueChange={onSelect} />}
|
||||
{(onRemove || onEdit) && (
|
||||
<CardActionsContainer position="end">
|
||||
{onRemove && (
|
||||
<IconButton
|
||||
label={formatMessage({
|
||||
id: getTrad('control-card.remove-selection'),
|
||||
defaultMessage: 'Remove from selection',
|
||||
})}
|
||||
icon={<Trash />}
|
||||
onClick={onRemove}
|
||||
/>
|
||||
)}
|
||||
|
||||
{onEdit && (
|
||||
<IconButton
|
||||
label={formatMessage({ id: getTrad('control-card.edit'), defaultMessage: 'Edit' })}
|
||||
icon={<Pencil />}
|
||||
onClick={onEdit}
|
||||
/>
|
||||
)}
|
||||
</CardActionsContainer>
|
||||
)}
|
||||
{children}
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<CardContent>
|
||||
<Box paddingTop={1}>
|
||||
<CardTitle as="h2">{name}</CardTitle>
|
||||
</Box>
|
||||
<CardSubtitle>
|
||||
<Extension>{extension}</Extension>
|
||||
{subtitle}
|
||||
</CardSubtitle>
|
||||
</CardContent>
|
||||
<CardBadge>
|
||||
{formatMessage({
|
||||
id: getTrad(`settings.section.${variant.toLowerCase()}.label`),
|
||||
defaultMessage: variant,
|
||||
})}
|
||||
</CardBadge>
|
||||
</CardBody>
|
||||
</CardContainer>
|
||||
);
|
||||
};
|
||||
|
||||
AssetCardBase.defaultProps = {
|
||||
selected: false,
|
||||
onEdit: undefined,
|
||||
onSelect: undefined,
|
||||
onRemove: undefined,
|
||||
subtitle: '',
|
||||
variant: 'Image',
|
||||
};
|
||||
|
||||
AssetCardBase.propTypes = {
|
||||
children: PropTypes.node.isRequired,
|
||||
extension: PropTypes.string.isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
onEdit: PropTypes.func,
|
||||
onSelect: PropTypes.func,
|
||||
onRemove: PropTypes.func,
|
||||
selected: PropTypes.bool,
|
||||
subtitle: PropTypes.string,
|
||||
variant: PropTypes.oneOf(['Image', 'Video', 'Audio', 'Doc']),
|
||||
};
|
||||
@ -1,29 +1,11 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
import {
|
||||
Card,
|
||||
CardAction,
|
||||
CardAsset,
|
||||
CardBadge,
|
||||
CardBody,
|
||||
CardCheckbox,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
CardSubtitle,
|
||||
} from '@strapi/design-system/Card';
|
||||
import { IconButton } from '@strapi/design-system/IconButton';
|
||||
import Pencil from '@strapi/icons/Pencil';
|
||||
import Trash from '@strapi/icons/Trash';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { CardAsset } from '@strapi/design-system/Card';
|
||||
import { Box } from '@strapi/design-system/Box';
|
||||
import { AudioPreview } from './AudioPreview';
|
||||
import { getTrad } from '../../utils';
|
||||
|
||||
const Extension = styled.span`
|
||||
text-transform: uppercase;
|
||||
`;
|
||||
import { AudioPreview } from './AudioPreview';
|
||||
import { AssetCardBase } from './AssetCardBase';
|
||||
|
||||
const AudioPreviewWrapper = styled(Box)`
|
||||
canvas,
|
||||
@ -34,64 +16,15 @@ const AudioPreviewWrapper = styled(Box)`
|
||||
}
|
||||
`;
|
||||
|
||||
export const AudioAssetCard = ({
|
||||
name,
|
||||
extension,
|
||||
url,
|
||||
selected,
|
||||
onSelect,
|
||||
onEdit,
|
||||
onRemove,
|
||||
size,
|
||||
}) => {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
export const AudioAssetCard = ({ name, url, size, ...restProps }) => {
|
||||
return (
|
||||
<Card height="100%">
|
||||
<CardHeader>
|
||||
<CardAsset size={size}>
|
||||
<AudioPreviewWrapper size={size}>
|
||||
<AudioPreview url={url} alt={name} />
|
||||
</AudioPreviewWrapper>
|
||||
</CardAsset>
|
||||
{onSelect && <CardCheckbox value={selected} onValueChange={onSelect} />}
|
||||
{(onRemove || onEdit) && (
|
||||
<CardAction position="end">
|
||||
{onRemove && (
|
||||
<IconButton
|
||||
label={formatMessage({
|
||||
id: getTrad('control-card.remove-selection'),
|
||||
defaultMessage: 'Remove from selection',
|
||||
})}
|
||||
icon={<Trash />}
|
||||
onClick={onRemove}
|
||||
/>
|
||||
)}
|
||||
|
||||
{onEdit && (
|
||||
<IconButton
|
||||
label={formatMessage({ id: getTrad('control-card.edit'), defaultMessage: 'Edit' })}
|
||||
icon={<Pencil />}
|
||||
onClick={onEdit}
|
||||
/>
|
||||
)}
|
||||
</CardAction>
|
||||
)}
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<CardContent>
|
||||
<Box paddingTop={1}>
|
||||
<CardTitle as="h2">{name}</CardTitle>
|
||||
</Box>
|
||||
<CardSubtitle>
|
||||
<Extension>{extension}</Extension>
|
||||
</CardSubtitle>
|
||||
</CardContent>
|
||||
<CardBadge>
|
||||
{formatMessage({ id: getTrad('settings.section.audio.label'), defaultMessage: 'Audio' })}
|
||||
</CardBadge>
|
||||
</CardBody>
|
||||
</Card>
|
||||
<AssetCardBase name={name} {...restProps} variant="Audio">
|
||||
<CardAsset size={size}>
|
||||
<AudioPreviewWrapper size={size}>
|
||||
<AudioPreview url={url} alt={name} />
|
||||
</AudioPreviewWrapper>
|
||||
</CardAsset>
|
||||
</AssetCardBase>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -1,31 +1,12 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
import {
|
||||
Card,
|
||||
CardAction,
|
||||
CardBadge,
|
||||
CardBody,
|
||||
CardCheckbox,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
CardSubtitle,
|
||||
} from '@strapi/design-system/Card';
|
||||
import { Box } from '@strapi/design-system/Box';
|
||||
import { Flex } from '@strapi/design-system/Flex';
|
||||
import { IconButton } from '@strapi/design-system/IconButton';
|
||||
import Pencil from '@strapi/icons/Pencil';
|
||||
import FileIcon from '@strapi/icons/File';
|
||||
import FilePdfIcon from '@strapi/icons/FilePdf';
|
||||
import Trash from '@strapi/icons/Trash';
|
||||
import { pxToRem } from '@strapi/helper-plugin';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { getTrad } from '../../utils';
|
||||
|
||||
const Extension = styled.span`
|
||||
text-transform: uppercase;
|
||||
`;
|
||||
import { AssetCardBase } from './AssetCardBase';
|
||||
|
||||
const IconWrapper = styled.span`
|
||||
svg {
|
||||
@ -38,80 +19,28 @@ const CardAsset = styled(Flex)`
|
||||
background: linear-gradient(180deg, #ffffff 0%, #f6f6f9 121.48%);
|
||||
`;
|
||||
|
||||
export const DocAssetCard = ({ name, extension, selected, onSelect, onEdit, onRemove, size }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
export const DocAssetCard = ({ name, extension, size, ...restProps }) => {
|
||||
return (
|
||||
<Card height="100%">
|
||||
<CardHeader>
|
||||
{onSelect && <CardCheckbox value={selected} onValueChange={onSelect} />}
|
||||
{(onRemove || onEdit) && (
|
||||
<CardAction position="end">
|
||||
{onRemove && (
|
||||
<IconButton
|
||||
label={formatMessage({
|
||||
id: getTrad('control-card.remove-selection'),
|
||||
defaultMessage: 'Remove from selection',
|
||||
})}
|
||||
icon={<Trash />}
|
||||
onClick={onRemove}
|
||||
/>
|
||||
)}
|
||||
|
||||
{onEdit && (
|
||||
<IconButton
|
||||
label={formatMessage({ id: getTrad('control-card.edit'), defaultMessage: 'Edit' })}
|
||||
icon={<Pencil />}
|
||||
onClick={onEdit}
|
||||
/>
|
||||
)}
|
||||
</CardAction>
|
||||
)}
|
||||
<CardAsset
|
||||
width="100%"
|
||||
height={size === 'S' ? pxToRem(88) : pxToRem(164)}
|
||||
justifyContent="center"
|
||||
>
|
||||
<IconWrapper>
|
||||
{extension === 'pdf' ? (
|
||||
<FilePdfIcon aria-label={name} />
|
||||
) : (
|
||||
<FileIcon aria-label={name} />
|
||||
)}
|
||||
</IconWrapper>
|
||||
</CardAsset>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<CardContent>
|
||||
<Box paddingTop={1}>
|
||||
<CardTitle as="h2">{name}</CardTitle>
|
||||
</Box>
|
||||
<CardSubtitle>
|
||||
<Extension>{extension}</Extension>
|
||||
</CardSubtitle>
|
||||
</CardContent>
|
||||
<CardBadge>
|
||||
{formatMessage({ id: getTrad('settings.section.doc.label'), defaultMessage: 'Doc' })}
|
||||
</CardBadge>
|
||||
</CardBody>
|
||||
</Card>
|
||||
<AssetCardBase name={name} extension={extension} {...restProps} variant="Doc">
|
||||
<CardAsset
|
||||
width="100%"
|
||||
height={size === 'S' ? pxToRem(88) : pxToRem(164)}
|
||||
justifyContent="center"
|
||||
>
|
||||
<IconWrapper>
|
||||
{extension === 'pdf' ? <FilePdfIcon aria-label={name} /> : <FileIcon aria-label={name} />}
|
||||
</IconWrapper>
|
||||
</CardAsset>
|
||||
</AssetCardBase>
|
||||
);
|
||||
};
|
||||
|
||||
DocAssetCard.defaultProps = {
|
||||
selected: false,
|
||||
onEdit: undefined,
|
||||
onSelect: undefined,
|
||||
onRemove: undefined,
|
||||
size: 'M',
|
||||
};
|
||||
|
||||
DocAssetCard.propTypes = {
|
||||
extension: PropTypes.string.isRequired,
|
||||
...AssetCardBase.propTypes,
|
||||
name: PropTypes.string.isRequired,
|
||||
onEdit: PropTypes.func,
|
||||
onRemove: PropTypes.func,
|
||||
onSelect: PropTypes.func,
|
||||
selected: PropTypes.bool,
|
||||
size: PropTypes.oneOf(['S', 'M']),
|
||||
};
|
||||
|
||||
@ -1,92 +1,19 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
import { Box } from '@strapi/design-system/Box';
|
||||
import {
|
||||
Card,
|
||||
CardAction,
|
||||
CardAsset,
|
||||
CardBadge,
|
||||
CardBody,
|
||||
CardCheckbox,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
CardSubtitle,
|
||||
} from '@strapi/design-system/Card';
|
||||
import { IconButton } from '@strapi/design-system/IconButton';
|
||||
import Pencil from '@strapi/icons/Pencil';
|
||||
import Trash from '@strapi/icons/Trash';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { getTrad } from '../../utils';
|
||||
import { CardAsset } from '@strapi/design-system/Card';
|
||||
|
||||
const Extension = styled.span`
|
||||
text-transform: uppercase;
|
||||
`;
|
||||
|
||||
export const ImageAssetCard = ({
|
||||
name,
|
||||
extension,
|
||||
height,
|
||||
width,
|
||||
thumbnail,
|
||||
selected,
|
||||
onSelect,
|
||||
onEdit,
|
||||
onRemove,
|
||||
size,
|
||||
alt,
|
||||
}) => {
|
||||
const { formatMessage } = useIntl();
|
||||
import { AssetCardBase } from './AssetCardBase';
|
||||
|
||||
export const ImageAssetCard = ({ height, width, thumbnail, size, alt, ...props }) => {
|
||||
// Prevents the browser from caching the URL for all sizes and allow react-query to make a smooth update
|
||||
// instead of a full refresh
|
||||
const optimizedCachingThumbnail =
|
||||
width && height ? `${thumbnail}?width=${width}&height=${height}` : thumbnail;
|
||||
|
||||
return (
|
||||
<Card height="100%">
|
||||
<CardHeader>
|
||||
{onSelect && <CardCheckbox value={selected} onValueChange={onSelect} />}
|
||||
{(onRemove || onEdit) && (
|
||||
<CardAction position="end">
|
||||
{onRemove && (
|
||||
<IconButton
|
||||
label={formatMessage({
|
||||
id: getTrad('control-card.remove-selection'),
|
||||
defaultMessage: 'Remove from selection',
|
||||
})}
|
||||
icon={<Trash />}
|
||||
onClick={onRemove}
|
||||
/>
|
||||
)}
|
||||
|
||||
{onEdit && (
|
||||
<IconButton
|
||||
label={formatMessage({ id: getTrad('control-card.edit'), defaultMessage: 'Edit' })}
|
||||
icon={<Pencil />}
|
||||
onClick={onEdit}
|
||||
/>
|
||||
)}
|
||||
</CardAction>
|
||||
)}
|
||||
<CardAsset src={optimizedCachingThumbnail} size={size} alt={alt} />
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<CardContent>
|
||||
<Box paddingTop={1}>
|
||||
<CardTitle as="h2">{name}</CardTitle>
|
||||
</Box>
|
||||
<CardSubtitle>
|
||||
<Extension>{extension}</Extension>
|
||||
{height && width && ` - ${width}✕${height}`}
|
||||
</CardSubtitle>
|
||||
</CardContent>
|
||||
<CardBadge>
|
||||
{formatMessage({ id: getTrad('settings.section.image.label'), defaultMessage: 'Image' })}
|
||||
</CardBadge>
|
||||
</CardBody>
|
||||
</Card>
|
||||
<AssetCardBase {...props} subtitle={height && width && ` - ${width}✕${height}`} variant="Image">
|
||||
<CardAsset src={optimizedCachingThumbnail} size={size} alt={alt} />
|
||||
</AssetCardBase>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@ -1,30 +1,13 @@
|
||||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
import {
|
||||
Card,
|
||||
CardAction,
|
||||
CardAsset,
|
||||
CardBadge,
|
||||
CardBody,
|
||||
CardCheckbox,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
CardSubtitle,
|
||||
CardTimer,
|
||||
} from '@strapi/design-system/Card';
|
||||
import { IconButton } from '@strapi/design-system/IconButton';
|
||||
import Pencil from '@strapi/icons/Pencil';
|
||||
import Trash from '@strapi/icons/Trash';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { CardAsset, CardTimer } from '@strapi/design-system/Card';
|
||||
import { Box } from '@strapi/design-system/Box';
|
||||
import { VideoPreview } from './VideoPreview';
|
||||
import { getTrad, formatDuration } from '../../utils';
|
||||
|
||||
const Extension = styled.span`
|
||||
text-transform: uppercase;
|
||||
`;
|
||||
import { VideoPreview } from './VideoPreview';
|
||||
import { AssetCardBase } from './AssetCardBase';
|
||||
|
||||
import { formatDuration } from '../../utils';
|
||||
|
||||
const VideoPreviewWrapper = styled(Box)`
|
||||
canvas,
|
||||
@ -35,69 +18,20 @@ const VideoPreviewWrapper = styled(Box)`
|
||||
}
|
||||
`;
|
||||
|
||||
export const VideoAssetCard = ({
|
||||
name,
|
||||
extension,
|
||||
url,
|
||||
mime,
|
||||
selected,
|
||||
onSelect,
|
||||
onEdit,
|
||||
onRemove,
|
||||
size,
|
||||
}) => {
|
||||
const { formatMessage } = useIntl();
|
||||
export const VideoAssetCard = ({ name, url, mime, size, ...props }) => {
|
||||
const [duration, setDuration] = useState();
|
||||
|
||||
const formattedDuration = duration && formatDuration(duration);
|
||||
|
||||
return (
|
||||
<Card height="100%">
|
||||
<CardHeader>
|
||||
{onSelect && <CardCheckbox value={selected} onValueChange={onSelect} />}
|
||||
{(onRemove || onEdit) && (
|
||||
<CardAction position="end">
|
||||
{onRemove && (
|
||||
<IconButton
|
||||
label={formatMessage({
|
||||
id: getTrad('control-card.remove-selection'),
|
||||
defaultMessage: 'Remove from selection',
|
||||
})}
|
||||
icon={<Trash />}
|
||||
onClick={onRemove}
|
||||
/>
|
||||
)}
|
||||
|
||||
{onEdit && (
|
||||
<IconButton
|
||||
label={formatMessage({ id: getTrad('control-card.edit'), defaultMessage: 'Edit' })}
|
||||
icon={<Pencil />}
|
||||
onClick={onEdit}
|
||||
/>
|
||||
)}
|
||||
</CardAction>
|
||||
)}
|
||||
<CardAsset size={size}>
|
||||
<VideoPreviewWrapper size={size}>
|
||||
<VideoPreview url={url} mime={mime} onLoadDuration={setDuration} alt={name} />
|
||||
</VideoPreviewWrapper>
|
||||
</CardAsset>
|
||||
<CardTimer>{formattedDuration || '...'}</CardTimer>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
<CardContent>
|
||||
<Box paddingTop={1}>
|
||||
<CardTitle as="h2">{name}</CardTitle>
|
||||
</Box>
|
||||
<CardSubtitle>
|
||||
<Extension>{extension}</Extension>
|
||||
</CardSubtitle>
|
||||
</CardContent>
|
||||
<CardBadge>
|
||||
{formatMessage({ id: getTrad('settings.section.video.label'), defaultMessage: 'Video' })}
|
||||
</CardBadge>
|
||||
</CardBody>
|
||||
</Card>
|
||||
<AssetCardBase {...props} variant="Video">
|
||||
<CardAsset size={size}>
|
||||
<VideoPreviewWrapper size={size}>
|
||||
<VideoPreview url={url} mime={mime} onLoadDuration={setDuration} alt={name} />
|
||||
</VideoPreviewWrapper>
|
||||
</CardAsset>
|
||||
<CardTimer>{formattedDuration || '...'}</CardTimer>
|
||||
</AssetCardBase>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user