UNPKG

@churchapps/apphelper

Version:

Library of helper functions for React and NextJS ChurchApps

96 lines 7.18 kB
"use client"; import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { FileHelper } from "../../helpers/FileHelper"; import { ApiHelper } from "../../helpers"; import { Locale } from "../../helpers"; import { CommonEnvironmentHelper } from "@churchapps/helpers"; import { Box, Button, Dialog, DialogActions, DialogContent, DialogTitle, FormControl, Grid, IconButton, InputLabel, MenuItem, Select, Tab, Tabs, Tooltip, Icon } from "@mui/material"; import React, { useState } from "react"; import { ImageEditor } from "../ImageEditor"; import { TabPanel } from "../TabPanel"; import { StockPhotos } from "./StockPhotos"; export const GalleryModal = (props) => { const [images, setImages] = useState([]); const [tabIndex, setTabIndex] = React.useState(0); const [aspectRatio, setAspectRatio] = React.useState(Math.round(props.aspectRatio * 100) / 100); const [editorPhotoUrl, setEditorPhotoUrl] = React.useState(""); const contentRoot = CommonEnvironmentHelper.ContentRoot; const handleTabChange = (el, newValue) => { setTabIndex(newValue); }; const loadData = () => { ApiHelper.get("/gallery/" + aspectRatio.toString(), "ContentApi").then((data) => setImages(data.images)); }; const handleImageUpdated = async (dataUrl) => { if (!dataUrl) { console.warn("No dataUrl provided to handleImageUpdated"); return; } try { const fileName = Math.floor(Date.now() / 1000).toString() + ".jpg"; const blob = FileHelper.dataURLtoBlob(dataUrl); const file = new File([blob], "file_name"); const params = { folder: aspectRatio.toString(), fileName }; const presigned = await ApiHelper.post("/gallery/requestUpload", params, "ContentApi"); const doUpload = presigned.key !== undefined; if (doUpload) { await FileHelper.postPresignedFile(presigned, file, () => { }); } else { console.warn("Upload failed - no presigned key received"); } setTabIndex(0); loadData(); } catch (error) { console.error("Error in handleImageUpdated:", error); // In case of API failure, still provide feedback to user alert("Image processing completed, but upload failed. API may not be available in this environment."); } }; const handleDelete = (folder, image) => { if (window.confirm(Locale.label("gallery.confirmDelete"))) { ApiHelper.delete("/gallery/" + folder + "/" + image, "ContentApi").then(() => { loadData(); }); } }; React.useEffect(() => { if (aspectRatio !== props.aspectRatio) setAspectRatio(Math.round(props.aspectRatio * 100) / 100); }, [props.aspectRatio]); //eslint-disable-line React.useEffect(loadData, [aspectRatio]); const getImages = () => { const result = []; images.forEach((img, index) => { const parts = img.split("/"); result.push(_jsx(Grid, { size: { xs: 12, md: 4 }, children: _jsxs(Box, { sx: { position: "relative", ":hover #deleteIcon": { visibility: "visible" } }, children: [_jsx("a", { href: "about:blank", onClick: (e) => { e.preventDefault(); props.onSelect(contentRoot + "/" + img); }, "aria-label": "Select image", "data-testid": "select-image", children: _jsx(Box, { component: "img", src: contentRoot + "/" + img, alt: "custom", sx: { width: "100%", height: "auto", maxWidth: "100%", display: "block" } }) }), _jsx(Box, { id: "deleteIcon", sx: { position: "absolute", top: 3, right: 3, visibility: "hidden", backgroundColor: "whitesmoke", borderRadius: 5 }, children: _jsx(Tooltip, { title: "Delete", children: _jsx(IconButton, { size: "small", color: "error", onClick: () => handleDelete(parts[2], parts[3]), "aria-label": "Delete image", "data-testid": "delete-image", children: _jsx(Icon, { sx: { fontSize: "17px !important" }, children: "delete_outline" }) }) }) })] }) }, img || index)); }); return result; }; const handleStockSelect = (url) => { setEditorPhotoUrl(url); setTabIndex(1); }; const getDisplayAspect = () => { let result = aspectRatio.toString(); if (aspectRatio === 0) result = "Free Form"; else if (aspectRatio === 1) result = "1:1"; else if (aspectRatio === 2) result = "2:1"; else if (aspectRatio === 3) result = "3:1"; else if (aspectRatio === 4) result = "4:1"; else if (aspectRatio === 1.33) result = "4:3"; else if (aspectRatio === 1.78) result = "16:9"; else if (aspectRatio === 0.5) result = "1:2"; else if (aspectRatio === 0.5625) result = "9:16"; return result; }; return (_jsx(_Fragment, { children: _jsxs(Dialog, { open: true, onClose: props.onClose, children: [_jsx(DialogTitle, { children: "Select a Photo" }), _jsxs(DialogContent, { style: { overflowX: "hidden" }, children: [(props.aspectRatio === 0) && (_jsxs(FormControl, { fullWidth: true, children: [_jsx(InputLabel, { children: Locale.label("gallery.aspectRatio") }), _jsxs(Select, { size: "small", label: Locale.label("gallery.aspectRatio"), name: "aspectRatio", value: aspectRatio, onChange: (e) => setAspectRatio(parseFloat(e.target.value.toString())), children: [_jsx(MenuItem, { value: "0", children: Locale.label("gallery.freeForm") }), _jsx(MenuItem, { value: "1", children: "1:1" }), _jsx(MenuItem, { value: "2", children: "2:1" }), _jsx(MenuItem, { value: "3", children: "3:1" }), _jsx(MenuItem, { value: "4", children: "4:1" }), _jsx(MenuItem, { value: "1.33", children: "4:3" }), _jsx(MenuItem, { value: "1.78", children: "16:9" }), _jsx(MenuItem, { value: "0.5", children: "1:2" }), _jsx(MenuItem, { value: "0.5625", children: "9:16" })] })] })), _jsxs(Tabs, { variant: "fullWidth", value: tabIndex, onChange: handleTabChange, children: [_jsx(Tab, { label: "Gallery" }), _jsx(Tab, { label: "Upload" }), _jsx(Tab, { label: "Stock Photos" })] }), _jsx(TabPanel, { value: tabIndex, index: 0, children: _jsx(Grid, { container: true, spacing: 3, alignItems: "center", children: getImages() }) }), _jsxs(TabPanel, { value: tabIndex, index: 1, children: [_jsxs("div", { children: [Locale.label("gallery.aspectRatio"), ": ", getDisplayAspect()] }), _jsx(ImageEditor, { onUpdate: handleImageUpdated, photoUrl: editorPhotoUrl, aspectRatio: aspectRatio, outputWidth: 1280, outputHeight: 768, hideDelete: true })] }), _jsx(TabPanel, { value: tabIndex, index: 2, children: _jsx(StockPhotos, { aspectRatio: aspectRatio, onSelect: props.onSelect, onStockSelect: handleStockSelect }) })] }), _jsx(DialogActions, { sx: { paddingX: "16px", paddingBottom: "12px" }, children: _jsx(Button, { variant: "outlined", onClick: props.onClose, children: "Close" }) })] }) })); }; //# sourceMappingURL=GalleryModal.js.map