@churchapps/apphelper
Version:
Library of helper functions for React and NextJS ChurchApps
100 lines • 7.51 kB
JavaScript
"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) => {
console.log('handleImageUpdated called with dataUrl:', dataUrl ? 'Data URL received' : 'Empty 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 };
console.log('Attempting to upload image with params:', params);
const presigned = await ApiHelper.post("/gallery/requestUpload", params, "ContentApi");
const doUpload = presigned.key !== undefined;
if (doUpload) {
console.log('Upload successful, uploading to presigned URL');
await FileHelper.postPresignedFile(presigned, file, () => { });
console.log('Image uploaded successfully');
}
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]); //eslint-disable-line
const getImages = () => {
let result = [];
images.forEach((img) => {
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" }) }) }) })] }) }));
});
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