mirror of
https://github.com/strapi/strapi.git
synced 2025-09-02 21:32:43 +00:00
Remove old components
Signed-off-by: soupette <cyril@strapi.io>
This commit is contained in:
parent
b31c6e3e7d
commit
0bbc99a331
@ -12,7 +12,6 @@ const FileWrapper = styled(Row)`
|
||||
border-radius: 50%;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
// TODO
|
||||
background: ${({ theme }) => theme.colors.neutral100};
|
||||
`;
|
||||
|
||||
|
@ -1,171 +0,0 @@
|
||||
import styled, { css } from 'styled-components';
|
||||
|
||||
const sizes = {
|
||||
small: '35px',
|
||||
big: '127px',
|
||||
margin: '20px',
|
||||
};
|
||||
const max = 4;
|
||||
|
||||
const StyledMediaPreviewList = styled.div`
|
||||
position: relative;
|
||||
height: ${sizes.small};
|
||||
> div {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
${createCSS()};
|
||||
}
|
||||
`;
|
||||
|
||||
function createCSS() {
|
||||
let styles = '';
|
||||
|
||||
for (let i = 0; i <= max; i += 1) {
|
||||
styles += `
|
||||
&:nth-of-type(${i}) {
|
||||
left: calc( ${sizes.margin} * ${i - 1});
|
||||
z-index: ${i};
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
return css`
|
||||
${styles}
|
||||
`;
|
||||
}
|
||||
|
||||
const MediaPreviewItem = styled.div`
|
||||
width: ${sizes.small};
|
||||
height: ${sizes.small};
|
||||
div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
border-radius: calc(${sizes.small} / 2);
|
||||
background-color: #f3f3f4;
|
||||
border: 1px solid #f3f3f4;
|
||||
}
|
||||
&.hoverable {
|
||||
:hover {
|
||||
z-index: ${max + 1};
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const MediaPreviewFile = styled(MediaPreviewItem)`
|
||||
span {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
div {
|
||||
position: relative;
|
||||
background-color: #f3f3f4;
|
||||
color: #333740;
|
||||
text-align: center;
|
||||
line-height: ${sizes.small};
|
||||
border: 1px solid white;
|
||||
span {
|
||||
display: block;
|
||||
padding: 0 3px;
|
||||
text-transform: uppercase;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
}
|
||||
i,
|
||||
svg {
|
||||
position: absolute;
|
||||
left: 1px;
|
||||
top: -1px;
|
||||
font-size: 15px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
&:before {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 10px;
|
||||
line-height: 35px;
|
||||
background: #f3f3f4;
|
||||
}
|
||||
}
|
||||
}
|
||||
div + span {
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: 120%;
|
||||
bottom: -10px;
|
||||
max-width: 150px;
|
||||
color: #333740;
|
||||
}
|
||||
&.hoverable {
|
||||
:hover {
|
||||
div + span {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const MediaPreviewText = styled(MediaPreviewItem)`
|
||||
div {
|
||||
font-size: 13px;
|
||||
color: #333740;
|
||||
text-align: center;
|
||||
line-height: ${sizes.small};
|
||||
font-weight: 600;
|
||||
}
|
||||
`;
|
||||
|
||||
const MediaPreviewImage = styled(MediaPreviewItem)`
|
||||
img {
|
||||
display: block;
|
||||
object-fit: cover;
|
||||
background-color: #fafafb;
|
||||
}
|
||||
div {
|
||||
position: relative;
|
||||
&::before {
|
||||
content: '-';
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: white;
|
||||
color: transparent;
|
||||
opacity: 0;
|
||||
}
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
div + img {
|
||||
display: none;
|
||||
width: ${sizes.big};
|
||||
height: ${sizes.big};
|
||||
border-radius: calc(${sizes.big} / 2);
|
||||
margin-top: calc(${`-${sizes.big}`} - ${sizes.small} - 5px);
|
||||
margin-left: calc((${sizes.small} - ${sizes.big}) / 2);
|
||||
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
&.hoverable {
|
||||
:hover {
|
||||
div {
|
||||
&::before {
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
div + img {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export {
|
||||
MediaPreviewFile,
|
||||
MediaPreviewImage,
|
||||
MediaPreviewItem,
|
||||
MediaPreviewText,
|
||||
StyledMediaPreviewList,
|
||||
};
|
@ -1,110 +0,0 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { get, isArray, includes, isEmpty } from 'lodash';
|
||||
import { getFileExtension, prefixFileUrlWithBackendUrl } from '@strapi/helper-plugin';
|
||||
import DefaultIcon from '../../icons/Na';
|
||||
import {
|
||||
StyledMediaPreviewList,
|
||||
MediaPreviewFile,
|
||||
MediaPreviewImage,
|
||||
MediaPreviewItem,
|
||||
MediaPreviewText,
|
||||
} from './StyledMediaPreviewList';
|
||||
|
||||
const IMAGE_PREVIEW_COUNT = 3;
|
||||
|
||||
function MediaPreviewList({ hoverable, files }) {
|
||||
const renderImage = image => {
|
||||
const { name, size, url } = image;
|
||||
const thumbnail = get(image, ['formats', 'thumbnail', 'url'], null);
|
||||
const fileUrl = thumbnail || url;
|
||||
|
||||
if (!thumbnail && size > 20000) {
|
||||
return renderFile(image);
|
||||
}
|
||||
|
||||
return (
|
||||
<MediaPreviewImage className={hoverable ? 'hoverable' : ''}>
|
||||
<div>
|
||||
<img src={prefixFileUrlWithBackendUrl(fileUrl)} alt={`${name}`} />
|
||||
</div>
|
||||
<img src={prefixFileUrlWithBackendUrl(fileUrl)} alt={`${name}`} />
|
||||
</MediaPreviewImage>
|
||||
);
|
||||
};
|
||||
|
||||
const renderFile = file => {
|
||||
const { ext, name } = file;
|
||||
const fileExtension = getFileExtension(ext);
|
||||
|
||||
return (
|
||||
<MediaPreviewFile className={hoverable ? 'hoverable' : ''}>
|
||||
{fileExtension ? (
|
||||
<div>
|
||||
<span>{fileExtension}</span>
|
||||
</div>
|
||||
) : (
|
||||
<MediaPreviewItem>
|
||||
<DefaultIcon />
|
||||
</MediaPreviewItem>
|
||||
)}
|
||||
|
||||
<span>{name}</span>
|
||||
</MediaPreviewFile>
|
||||
);
|
||||
};
|
||||
|
||||
const renderItem = file => {
|
||||
const { mime } = file;
|
||||
|
||||
return (
|
||||
<React.Fragment key={JSON.stringify(file)}>
|
||||
{includes(mime, 'image') ? renderImage(file) : renderFile(file)}
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const renderText = count => {
|
||||
return (
|
||||
<MediaPreviewText>
|
||||
<div>
|
||||
<span>+{count}</span>
|
||||
</div>
|
||||
</MediaPreviewText>
|
||||
);
|
||||
};
|
||||
|
||||
const renderMultipleItems = files => {
|
||||
return files.map((file, index) => {
|
||||
return (
|
||||
<React.Fragment key={JSON.stringify(file)}>
|
||||
{index === IMAGE_PREVIEW_COUNT && files.length > IMAGE_PREVIEW_COUNT + 1
|
||||
? renderText(files.length - IMAGE_PREVIEW_COUNT)
|
||||
: renderItem(file)}
|
||||
</React.Fragment>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
return !!files && !isEmpty(files) ? (
|
||||
<StyledMediaPreviewList>
|
||||
{!isArray(files) ? renderItem(files) : renderMultipleItems(files)}
|
||||
</StyledMediaPreviewList>
|
||||
) : (
|
||||
<MediaPreviewItem>
|
||||
<DefaultIcon />
|
||||
</MediaPreviewItem>
|
||||
);
|
||||
}
|
||||
|
||||
MediaPreviewList.defaultProps = {
|
||||
hoverable: true,
|
||||
files: null,
|
||||
};
|
||||
|
||||
MediaPreviewList.propTypes = {
|
||||
hoverable: PropTypes.bool,
|
||||
files: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
||||
};
|
||||
|
||||
export default MediaPreviewList;
|
@ -1,7 +0,0 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const CountWrapper = styled.div`
|
||||
padding-top: 0.3rem;
|
||||
`;
|
||||
|
||||
export default CountWrapper;
|
@ -1,123 +0,0 @@
|
||||
import React, { useState, useEffect, useCallback, useRef, useLayoutEffect } from 'react';
|
||||
import { Text, Padded } from '@buffetjs/core';
|
||||
import { LoadingIndicator, Tooltip } from '@buffetjs/styles';
|
||||
import PropTypes from 'prop-types';
|
||||
import axios from 'axios';
|
||||
import { axiosInstance } from '../../../core/utils';
|
||||
import { getDisplayedValue, getRequestUrl } from '../../utils';
|
||||
|
||||
const RelationPreviewTooltip = ({
|
||||
tooltipId,
|
||||
rowId,
|
||||
mainField,
|
||||
name,
|
||||
queryInfos: { endPoint },
|
||||
size,
|
||||
}) => {
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [relationData, setRelationData] = useState([]);
|
||||
const tooltipRef = useRef();
|
||||
|
||||
const fetchRelationData = useCallback(
|
||||
async source => {
|
||||
const requestURL = getRequestUrl(`${endPoint}/${rowId}/${name}`);
|
||||
|
||||
try {
|
||||
const {
|
||||
data: { results },
|
||||
} = await axiosInstance.get(requestURL, { cancelToken: source.token });
|
||||
|
||||
setRelationData(results);
|
||||
setIsLoading(false);
|
||||
} catch (err) {
|
||||
if (axios.isCancel(err)) {
|
||||
return;
|
||||
}
|
||||
|
||||
console.error({ err });
|
||||
setIsLoading(false);
|
||||
}
|
||||
},
|
||||
[endPoint, name, rowId]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const CancelToken = axios.CancelToken;
|
||||
const source = CancelToken.source();
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
fetchRelationData(source);
|
||||
}, 500);
|
||||
|
||||
return () => {
|
||||
clearTimeout(timeout);
|
||||
|
||||
source.cancel('Operation canceled by the user.');
|
||||
};
|
||||
}, [fetchRelationData]);
|
||||
|
||||
const getValueToDisplay = useCallback(
|
||||
item => {
|
||||
return getDisplayedValue(mainField.schema.type, item[mainField.name], mainField.name);
|
||||
},
|
||||
[mainField]
|
||||
);
|
||||
|
||||
// Used to update the position after the loader
|
||||
useLayoutEffect(() => {
|
||||
if (!isLoading && tooltipRef.current) {
|
||||
// A react-tooltip uncaught error is triggered when updatePosition is called in firefox.
|
||||
// https://github.com/wwayne/react-tooltip/issues/619
|
||||
try {
|
||||
tooltipRef.current.updatePosition();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
}, [isLoading]);
|
||||
|
||||
return (
|
||||
<Tooltip ref={tooltipRef} id={tooltipId}>
|
||||
<div>
|
||||
{isLoading ? (
|
||||
<Padded left right size="sm">
|
||||
<LoadingIndicator borderWidth="3px" size="2rem" />
|
||||
</Padded>
|
||||
) : (
|
||||
<>
|
||||
{relationData.map(item => (
|
||||
<Padded key={item.id} top bottom size="xs">
|
||||
<Text ellipsis color="white">
|
||||
{getValueToDisplay(item)}
|
||||
</Text>
|
||||
</Padded>
|
||||
))}
|
||||
{size > 10 && (
|
||||
<Padded top size="xs">
|
||||
<Text color="white">[...]</Text>
|
||||
</Padded>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
RelationPreviewTooltip.propTypes = {
|
||||
tooltipId: PropTypes.string.isRequired,
|
||||
mainField: PropTypes.exact({
|
||||
name: PropTypes.string.isRequired,
|
||||
schema: PropTypes.shape({
|
||||
type: PropTypes.string.isRequired,
|
||||
}).isRequired,
|
||||
}).isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
size: PropTypes.number.isRequired,
|
||||
rowId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
||||
queryInfos: PropTypes.shape({
|
||||
endPoint: PropTypes.string.isRequired,
|
||||
}).isRequired,
|
||||
};
|
||||
|
||||
export default RelationPreviewTooltip;
|
@ -1,111 +0,0 @@
|
||||
import React, { memo, useState, useMemo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Flex, Padded, Count } from '@buffetjs/core';
|
||||
import { Tooltip } from '@buffetjs/styles';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
import { getTrad } from '../../utils';
|
||||
import Truncate from '../Truncate';
|
||||
import Truncated from '../Truncated';
|
||||
import CountWrapper from './CountWrapper';
|
||||
import RelationPreviewTooltip from './RelationPreviewTooltip';
|
||||
|
||||
const RelationPreviewList = ({
|
||||
options: {
|
||||
metadatas: { mainField },
|
||||
relationType,
|
||||
value,
|
||||
rowId,
|
||||
cellId,
|
||||
name,
|
||||
queryInfos,
|
||||
},
|
||||
}) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const [tooltipIsDisplayed, setDisplayTooltip] = useState(false);
|
||||
const isSingle = ['oneWay', 'oneToOne', 'manyToOne'].includes(relationType);
|
||||
const tooltipId = useMemo(() => `${rowId}-${cellId}`, [rowId, cellId]);
|
||||
const valueToDisplay = value ? value[mainField.name] : '-';
|
||||
|
||||
if (value === undefined) {
|
||||
return (
|
||||
<Truncate>
|
||||
<Truncated>-</Truncated>
|
||||
</Truncate>
|
||||
);
|
||||
}
|
||||
|
||||
if (isSingle) {
|
||||
return (
|
||||
<Truncate>
|
||||
<Truncated>
|
||||
<span data-for={tooltipId} data-tip={valueToDisplay}>
|
||||
{valueToDisplay}
|
||||
</span>
|
||||
</Truncated>
|
||||
<Tooltip id={tooltipId} />
|
||||
</Truncate>
|
||||
);
|
||||
}
|
||||
|
||||
const size = value ? value.count : 0;
|
||||
|
||||
const handleTooltipToggle = () => {
|
||||
setDisplayTooltip(prev => !prev);
|
||||
};
|
||||
|
||||
return (
|
||||
<Truncate style={{ maxWidth: 'fit-content' }}>
|
||||
<Flex
|
||||
// This is useful to avoid the render of every tooltips of the list at the same time.
|
||||
// https://github.com/wwayne/react-tooltip/issues/524
|
||||
onMouseEnter={handleTooltipToggle}
|
||||
onMouseLeave={handleTooltipToggle}
|
||||
data-for={tooltipId}
|
||||
data-tip={JSON.stringify(value)}
|
||||
>
|
||||
<CountWrapper>
|
||||
<Count count={size} />
|
||||
</CountWrapper>
|
||||
<Padded left size="xs" />
|
||||
<Truncated>
|
||||
{formatMessage({
|
||||
id: getTrad(
|
||||
size > 1 ? 'containers.ListPage.items.plural' : 'containers.ListPage.items.singular'
|
||||
),
|
||||
})}
|
||||
</Truncated>
|
||||
</Flex>
|
||||
{size > 0 && tooltipIsDisplayed && (
|
||||
<RelationPreviewTooltip
|
||||
name={name}
|
||||
rowId={rowId}
|
||||
tooltipId={tooltipId}
|
||||
value={value}
|
||||
mainField={mainField}
|
||||
queryInfos={queryInfos}
|
||||
size={size}
|
||||
/>
|
||||
)}
|
||||
</Truncate>
|
||||
);
|
||||
};
|
||||
|
||||
RelationPreviewList.propTypes = {
|
||||
options: PropTypes.shape({
|
||||
cellId: PropTypes.string.isRequired,
|
||||
metadatas: PropTypes.shape({
|
||||
mainField: PropTypes.object.isRequired,
|
||||
}).isRequired,
|
||||
name: PropTypes.string.isRequired,
|
||||
relationType: PropTypes.string,
|
||||
rowId: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
|
||||
type: PropTypes.string,
|
||||
queryInfos: PropTypes.shape({
|
||||
endPoint: PropTypes.string.isRequired,
|
||||
}).isRequired,
|
||||
value: PropTypes.any,
|
||||
}).isRequired,
|
||||
};
|
||||
|
||||
export default memo(RelationPreviewList);
|
@ -1,5 +0,0 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const Truncate = styled.div``;
|
||||
|
||||
export default Truncate;
|
@ -1,10 +0,0 @@
|
||||
import styled from 'styled-components';
|
||||
|
||||
const Truncated = styled.p`
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin-bottom: 0;
|
||||
`;
|
||||
|
||||
export default Truncated;
|
Loading…
x
Reference in New Issue
Block a user