UNPKG

@paroicms/front-media-gallery

Version:

Basic media gallery react component for Paroi CMS.

83 lines (81 loc) 3.77 kB
import { useAppLog, useWrapAsync } from "@paroicms/front-app-log"; import { showToast } from "@paroicms/internal-front-lib"; import { classNames } from "primereact/utils"; import { useEffect, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { FileDrop } from "./FileDrop"; import GalleryItem from "./GalleryItem/GalleryItem"; import { ImagePicker } from "./ImagePicker/ImagePicker"; import UploadPlaceholder from "./UploadPlaceholder/UploadPlaceholder"; let uploadIdSeq = 0; export function SingleMedia({ mediaHandle, getMedia, getMediaByUid, httpUploadMedia, deleteMedia, accept, acceptFilter, label, remainingMediaPlaces, updateMediaCount, isMobile, updateMediaAttachedData, contentLanguage, }) { const wrapAsync = useWrapAsync(); const appLog = useAppLog(); const { t } = useTranslation(); const [initialized, setInitialized] = useState(false); const [media, setMedia] = useState(); const [uploadingFile, setUploadingFile] = useState(); const imagePickerRef = useRef(); useEffect(wrapAsync(async () => { setInitialized(false); await loadMedias(); setInitialized(true); }), [mediaHandle]); const updateMediaCaption = async (mediaUid, caption) => { await updateMediaAttachedData(mediaUid, { caption }); await loadMedias(); }; async function loadMedias() { const medias = await getMedia(mediaHandle); setMedia(medias); updateMediaCount?.({ handle: mediaHandle, count: medias ? 1 : 0 }); } const uploadSelectedFile = (selectedFiles) => { const files = acceptFilter ? selectedFiles.filter(acceptFilter) : selectedFiles; if (files.length === 0) return; const file = files[0]; const handler = httpUploadMedia({ file, handle: mediaHandle }); const newFile = { uploadId: ++uploadIdSeq, file, handler, }; handler.promise .catch(async () => { showToast(t("TextDocumentEditScreen.uploadError", { fileName: file.name }), { severity: "error", }); }) .then(async () => { setUploadingFile(undefined); await loadMedias(); }) .catch((error) => appLog.error("[single-media]", error)); setUploadingFile(newFile); }; const handleReplace = () => { imagePickerRef.current?.open(); }; const handleDeleteMedia = async () => { if (!media || !deleteMedia) return; await deleteMedia(mediaHandle); setMedia(undefined); updateMediaCount?.({ handle: mediaHandle, count: 0 }); }; function onDropFiles(files) { if (remainingMediaPlaces === 0) { showToast(t("frontMediaGallery.mediaLimitReached"), { severity: "warn" }); return; } uploadSelectedFile([...files]); } return (<FileDrop onDropFiles={onDropFiles}> <div className="SingleMedia w-8rem"> <ImagePicker className={classNames("single", { hidden: (initialized && media) || uploadingFile })} ref={imagePickerRef} label={label ?? t("frontMediaGallery.chooseAFile")} accept={accept} multiple={false} onFilesSelect={uploadSelectedFile} disabled={remainingMediaPlaces === 0}/> {uploadingFile && (<UploadPlaceholder localMedia={uploadingFile.file} handler={uploadingFile.handler}/>)} {!uploadingFile && media && (<GalleryItem key={media.uid} media={media} attachedData={media.attachedData} onReplace={handleReplace} onDelete={handleDeleteMedia} isMobile={isMobile} getMediaProperties={getMediaByUid} updateCaption={updateMediaCaption} contentLanguage={contentLanguage}/>)} </div> </FileDrop>); }