@selfcommunity/react-ui
Version:
React UI Components to integrate a Community created with SelfCommunity Platform.
122 lines (121 loc) • 8.1 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
import { asUploadButton } from '@rpldy/upload-button';
import React, { forwardRef, useContext, useState } from 'react';
import { Alert, AlertTitle, Box, CardContent, CardHeader, Fade, IconButton, ImageListItemBar, List, ListItem, Typography } from '@mui/material';
import Icon from '@mui/material/Icon';
import ChunkedUploady from '@rpldy/chunked-uploady';
import { SCMessageFileType } from '@selfcommunity/types';
import { Endpoints } from '@selfcommunity/api-services';
import { SCContext } from '@selfcommunity/react-core';
import { styled } from '@mui/material/styles';
import Widget from '../../Widget';
import MessageChunkUploader from '../../../shared/MessageChunkUploader';
import UploadDropZone from '@rpldy/upload-drop-zone';
import { FormattedMessage } from 'react-intl';
import { documentPlaceholder, pdfImagePlaceholder } from '../../../utils/thumbnailCoverter';
import classNames from 'classnames';
import { bytesToSize } from '../../../utils/sizeCoverter';
import { PREFIX } from '../constants';
const MAX_FILE_SIZE = 10485760;
const UploadButton = asUploadButton(forwardRef((props, ref) => (_jsx(IconButton, Object.assign({}, props, { ref: ref, color: "inherit" }, { children: _jsx(Icon, { children: "upload" }) })))));
const classes = {
root: `${PREFIX}-message-media-uploader-root`,
uploadSection: `${PREFIX}-upload-section`,
uploadButton: `${PREFIX}-upload-button`,
closeButton: `${PREFIX}-close-button`,
previewContent: `${PREFIX}-preview-content`,
previewItem: `${PREFIX}-preview-item`,
previewActions: `${PREFIX}-preview-actions`,
progress: `${PREFIX}-progress`,
previewInfo: `${PREFIX}-preview-info`
};
const Root = styled(Widget, {
name: PREFIX,
slot: 'MessageMediaUploader'
})(() => ({}));
export default function MessageMediaUploader(props) {
//PROPS
const { className, forwardMessageFile, onClose, isUploading, action } = props;
// STATE
const [files, setFiles] = useState([]);
const [uploading, setUploading] = useState({});
const [previews, setPreviews] = useState([]);
const [errors, setErrors] = useState({});
const [isHovered, setIsHovered] = useState({});
// CONTEXT
const scContext = useContext(SCContext);
// HANDLERS
const update = (list, itemId) => {
return list.filter((i) => i.file_uuid != itemId);
};
const handleClear = (itemId) => {
if (itemId) {
setPreviews((prev) => update(prev, itemId));
setFiles((prev) => update(prev, itemId));
forwardMessageFile(update(files, itemId));
}
else {
setFiles([]);
setPreviews([]);
forwardMessageFile([]);
}
setUploading({});
};
const handleSuccess = (media) => {
setFiles((prev) => [...prev, media]);
};
const forwardFiles = () => {
forwardMessageFile(files);
};
const handleProgress = (chunks) => {
setUploading(Object.assign({}, chunks));
setPreviews([...files, ...Object.values(chunks)]);
isUploading(Object.keys(chunks).length !== 0);
Object.keys(chunks).length === 0 && Object.keys(uploading).length !== 0 && forwardFiles();
};
const handleError = (chunk, error) => {
setErrors(Object.assign(Object.assign({}, errors), { [chunk.id]: Object.assign(Object.assign({}, chunk), { error }) }));
};
const handleRemoveErrors = (id) => {
return () => {
delete errors[id];
setErrors(Object.assign({}, errors));
};
};
const handleMouseEnter = (index) => {
setIsHovered((prevState) => {
return Object.assign(Object.assign({}, prevState), { [index]: true });
});
};
const handleMouseLeave = (index) => {
setIsHovered((prevState) => {
return Object.assign(Object.assign({}, prevState), { [index]: false });
});
};
const getMouseEvents = (mouseEnter, mouseLeave) => ({
onMouseEnter: mouseEnter,
onMouseLeave: mouseLeave,
onTouchStart: mouseEnter,
onTouchMove: mouseLeave
});
const filterBySizeAndType = (file) => {
return file.size < MAX_FILE_SIZE;
};
/**
* Renders root object
*/
return (_jsxs(Root, Object.assign({ className: classNames(classes.root, className) }, { children: [_jsx(CardHeader, { action: _jsx(Icon, Object.assign({ onClick: onClose, className: classes.closeButton }, { children: "close" })) }), Object.keys(errors).map((id) => (_jsx(Fade, Object.assign({ in: true }, { children: _jsxs(Alert, Object.assign({ severity: "error", onClose: handleRemoveErrors(id) }, { children: [_jsx(AlertTitle, { children: errors[id].name }), errors[id].error] })) }), id))), _jsx(CardContent, { children: _jsxs(ChunkedUploady, Object.assign({ destination: {
url: `${scContext.settings.portal}${Endpoints.PrivateMessageUploadMediaInChunks.url()}`,
headers: { Authorization: `Bearer ${scContext.settings.session.authToken.accessToken}` },
method: Endpoints.PrivateMessageUploadMediaInChunks.method
}, chunkSize: 204800, multiple: true, chunked: true, maxConcurrent: 2, fileFilter: filterBySizeAndType }, { children: [_jsx(MessageChunkUploader, { onSuccess: handleSuccess, onProgress: handleProgress, onError: handleError }), !files.length && Object.keys(uploading).length === 0 && Object.keys(errors).length === 0 && (_jsxs(UploadDropZone, Object.assign({ className: classes.uploadSection }, { children: [_jsx(UploadButton, { inputFieldName: "file", className: classes.uploadButton }), _jsx(Typography, Object.assign({ textAlign: 'center', fontWeight: 'medium' }, { children: _jsx(FormattedMessage, { id: "ui.privateMessage.editor.media.uploader.msg", defaultMessage: "ui.privateMessage.editor.media.uploader.msg" }) }))] }))), _jsxs(List, Object.assign({ className: classes.previewContent }, { children: [previews.length !== 0 &&
previews.map((item, index) => {
var _a;
return (_jsx(React.Fragment, { children: 'file' in item && (_jsxs(ListItem, Object.assign({ className: classes.previewItem }, getMouseEvents(() => handleMouseEnter(item.file_uuid), () => handleMouseLeave(item.file_uuid)), { children: ['video_url' in item ? (_jsx("video", { src: item.video_url })) : (_jsx("img", { src: item.file.type.startsWith(SCMessageFileType.PDF) && !item.file_url
? pdfImagePlaceholder
: !item.file_url
? documentPlaceholder
: item.file_url })), _jsx(ImageListItemBar, { className: classNames(classes.previewActions, { [classes.progress]: item.completed }), title: typeof item.completed !== 'undefined' &&
item.completed !== 0 && _jsx(Typography, Object.assign({ textAlign: "center" }, { children: `${Math.round(item.completed)}%` })), actionIcon: _jsx(_Fragment, { children: isHovered[item.file_uuid] && Object.keys(uploading).length === 0 && (_jsx(IconButton, Object.assign({ onClick: () => handleClear(item.file_uuid), size: "small" }, { children: _jsx(Icon, { children: "delete" }) }))) }) }), isHovered[item.file_uuid] && (_jsxs(Box, Object.assign({ component: 'span', className: classes.previewInfo }, { children: [_jsx(Typography, Object.assign({ noWrap: true, textAlign: 'center' }, { children: item.file.name })), _jsx(Typography, Object.assign({ textAlign: 'center', fontWeight: 'light' }, { children: bytesToSize(item.file.size) }))] })))] }), (_a = item.id) !== null && _a !== void 0 ? _a : item.file_uuid)) }, index));
}), previews.length !== 0 && action] }))] })) })] })));
}