2020-04-21 05:04:34 +05:00
|
|
|
import React, { useCallback } from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
2022-06-22 16:59:54 +02:00
|
|
|
import classNames from 'classnames';
|
2020-04-29 23:55:16 +05:00
|
|
|
import { useTranslation } from 'react-i18next';
|
2022-06-20 18:27:39 +02:00
|
|
|
import { Gallery, Item as GalleryItem } from 'react-photoswipe-gallery';
|
2022-06-22 16:59:54 +02:00
|
|
|
import { Button } from 'semantic-ui-react';
|
2020-04-29 23:55:16 +05:00
|
|
|
import { useToggle } from '../../../lib/hooks';
|
2020-04-21 05:04:34 +05:00
|
|
|
|
|
|
|
import Item from './Item';
|
|
|
|
|
2020-05-29 19:31:19 +05:00
|
|
|
import styles from './Attachments.module.scss';
|
2020-04-29 23:55:16 +05:00
|
|
|
|
2022-06-20 18:27:39 +02:00
|
|
|
const INITIALLY_VISIBLE = 4;
|
|
|
|
|
|
|
|
const Attachments = React.memo(
|
|
|
|
({ items, onUpdate, onDelete, onCoverUpdate, onGalleryOpen, onGalleryClose }) => {
|
|
|
|
const [t] = useTranslation();
|
|
|
|
const [isAllVisible, toggleAllVisible] = useToggle();
|
|
|
|
|
|
|
|
const handleCoverSelect = useCallback(
|
|
|
|
(id) => {
|
|
|
|
onCoverUpdate(id);
|
|
|
|
},
|
|
|
|
[onCoverUpdate],
|
|
|
|
);
|
|
|
|
|
|
|
|
const handleCoverDeselect = useCallback(() => {
|
|
|
|
onCoverUpdate(null);
|
|
|
|
}, [onCoverUpdate]);
|
|
|
|
|
|
|
|
const handleUpdate = useCallback(
|
|
|
|
(id, data) => {
|
|
|
|
onUpdate(id, data);
|
|
|
|
},
|
|
|
|
[onUpdate],
|
|
|
|
);
|
|
|
|
|
|
|
|
const handleDelete = useCallback(
|
|
|
|
(id) => {
|
|
|
|
onDelete(id);
|
|
|
|
},
|
|
|
|
[onDelete],
|
|
|
|
);
|
|
|
|
|
|
|
|
const handleBeforeGalleryOpen = useCallback(
|
|
|
|
(gallery) => {
|
|
|
|
onGalleryOpen();
|
|
|
|
|
|
|
|
gallery.on('destroy', () => {
|
|
|
|
onGalleryClose();
|
|
|
|
});
|
|
|
|
},
|
|
|
|
[onGalleryOpen, onGalleryClose],
|
|
|
|
);
|
|
|
|
|
|
|
|
const handleToggleAllVisibleClick = useCallback(() => {
|
|
|
|
toggleAllVisible();
|
|
|
|
}, [toggleAllVisible]);
|
|
|
|
|
|
|
|
const galleryItemsNode = items.map((item, index) => {
|
2022-06-22 16:59:54 +02:00
|
|
|
const isPdf = item.url.endsWith('.pdf');
|
|
|
|
|
|
|
|
let props;
|
|
|
|
if (item.image) {
|
|
|
|
props = item.image;
|
|
|
|
} else {
|
|
|
|
props = {
|
|
|
|
content: isPdf ? (
|
|
|
|
// eslint-disable-next-line jsx-a11y/alt-text
|
|
|
|
<object
|
|
|
|
data={item.url}
|
|
|
|
type="application/pdf"
|
|
|
|
className={classNames(styles.content, styles.contentPdf)}
|
|
|
|
/>
|
|
|
|
) : (
|
|
|
|
<span className={classNames(styles.content, styles.contentError)}>
|
|
|
|
{t('common.thereIsNoPreviewAvailableForThisAttachment')}
|
|
|
|
</span>
|
|
|
|
),
|
|
|
|
};
|
|
|
|
}
|
2022-06-20 18:27:39 +02:00
|
|
|
|
|
|
|
const isVisible = isAllVisible || index < INITIALLY_VISIBLE;
|
|
|
|
|
|
|
|
return (
|
|
|
|
<GalleryItem
|
|
|
|
{...props} // eslint-disable-line react/jsx-props-no-spreading
|
2020-04-21 05:04:34 +05:00
|
|
|
key={item.id}
|
2022-06-20 18:27:39 +02:00
|
|
|
original={item.url}
|
|
|
|
caption={item.name}
|
|
|
|
>
|
|
|
|
{({ ref, open }) =>
|
|
|
|
isVisible ? (
|
|
|
|
<Item
|
|
|
|
ref={ref}
|
|
|
|
name={item.name}
|
|
|
|
url={item.url}
|
|
|
|
coverUrl={item.coverUrl}
|
|
|
|
createdAt={item.createdAt}
|
|
|
|
isCover={item.isCover}
|
|
|
|
isPersisted={item.isPersisted}
|
2022-06-22 16:59:54 +02:00
|
|
|
onClick={item.image || isPdf ? open : undefined}
|
2022-06-20 18:27:39 +02:00
|
|
|
onCoverSelect={() => handleCoverSelect(item.id)}
|
|
|
|
onCoverDeselect={handleCoverDeselect}
|
|
|
|
onUpdate={(data) => handleUpdate(item.id, data)}
|
|
|
|
onDelete={() => handleDelete(item.id)}
|
|
|
|
/>
|
|
|
|
) : (
|
|
|
|
<span ref={ref} />
|
|
|
|
)
|
2020-04-29 23:55:16 +05:00
|
|
|
}
|
2022-06-20 18:27:39 +02:00
|
|
|
</GalleryItem>
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<Gallery
|
|
|
|
withCaption
|
|
|
|
withDownloadButton
|
|
|
|
options={{
|
|
|
|
showHideAnimationType: 'none',
|
|
|
|
closeTitle: '',
|
|
|
|
zoomTitle: '',
|
|
|
|
arrowPrevTitle: '',
|
|
|
|
arrowNextTitle: '',
|
|
|
|
errorMsg: '',
|
|
|
|
}}
|
|
|
|
onBeforeOpen={handleBeforeGalleryOpen}
|
|
|
|
>
|
|
|
|
{galleryItemsNode}
|
|
|
|
</Gallery>
|
|
|
|
{items.length > INITIALLY_VISIBLE && (
|
|
|
|
<Button
|
|
|
|
fluid
|
|
|
|
content={
|
|
|
|
isAllVisible
|
|
|
|
? t('action.showFewerAttachments')
|
|
|
|
: t('action.showAllAttachments', {
|
|
|
|
hidden: items.length - INITIALLY_VISIBLE,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
className={styles.toggleButton}
|
|
|
|
onClick={handleToggleAllVisibleClick}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</>
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
2020-04-21 05:04:34 +05:00
|
|
|
|
|
|
|
Attachments.propTypes = {
|
|
|
|
items: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types
|
|
|
|
onUpdate: PropTypes.func.isRequired,
|
|
|
|
onDelete: PropTypes.func.isRequired,
|
2020-04-23 03:02:53 +05:00
|
|
|
onCoverUpdate: PropTypes.func.isRequired,
|
2022-06-20 18:27:39 +02:00
|
|
|
onGalleryOpen: PropTypes.func.isRequired,
|
|
|
|
onGalleryClose: PropTypes.func.isRequired,
|
2020-04-21 05:04:34 +05:00
|
|
|
};
|
|
|
|
|
|
|
|
export default Attachments;
|