@proca/widget
Version:
Proca is an open-source campaign toolkit designed to empower activists and organisations in their digital advocacy efforts. It provides a flexible and customisable platform for creating and managing online petitions, email campaigns, and other forms of di
251 lines (233 loc) • 7.36 kB
JavaScript
import React, { useState, useRef } from "react";
import { scrollTo } from "@lib/scroll";
import Camera from "./Camera";
import { useUpload } from "@components/field/image/Publish";
import Hidden from "./Hidden";
import UploadPicture from "./image/Upload";
import SelectPicture from "./image/Select";
import ImageIcon from "@material-ui/icons/Image";
import PhotoCameraIcon from "@material-ui/icons/PhotoCamera";
import PhotoLibraryIcon from "@material-ui/icons/PhotoLibrary";
import { useCampaignConfig } from "@hooks/useConfig";
import { useTranslation } from "react-i18next";
import {
Grid,
Accordion,
AccordionSummary,
AccordionDetails,
Button,
ButtonGroup,
Collapse,
DialogActions,
} from "@material-ui/core";
import { Alert, AlertTitle } from "@material-ui/lab";
import ExpandMoreIcon from "@material-ui/icons/ExpandMore";
import Dialog from "@components/Dialog";
import { makeStyles } from "@material-ui/core/styles";
const useStyles = makeStyles(theme => ({
accordion: {
display: "block!important",
},
buttonGroup: {
marginRight: theme.spacing(1),
},
dialog: {
minWidth: theme.breakpoints.values.sm,
},
}));
export default function Picture(props) {
const config = useCampaignConfig();
const [draw, setDraw] = useState(false);
const [image, setImage] = useState(undefined);
const [canvas, setCanvas] = useState(undefined);
// const data = props.form?.getValues();
const handleClose = () => {
setDraw(false);
scrollTo({ delay: 300, selector: "#proca-image" });
};
const uploadedCanvas = canvas => {
setCanvas(canvas);
};
const DialogAction = () => (
<DialogActions>
<PublishPicture
{...props}
canvas={canvas}
setImage={setImage}
setDraw={setDraw}
/>
</DialogActions>
);
return (
<div>
<Hidden name="hash" form={props.form} />
<Hidden name="dimension" form={props.form} />
<ImageOption image={image} setImage={setImage} setDraw={setDraw} />
<Dialog
name={config.campaign.title}
maxWidth="lg"
dialog={draw !== false}
close={handleClose}
hideBackdrop
Action={DialogAction}
>
{config.component.picture?.upload !== false && (
<PictureAccordion uploadedCanvas={uploadedCanvas} form={props.form} />
)}
{config.component.picture?.upload === false && (
<SelectPicture setCanvas={uploadedCanvas} form={props.form} />
)}
</Dialog>
{image && (
<img
alt="to send to the recipients"
style={{ maxWidth: "100%" }}
src={image}
/>
)}
</div>
);
}
const PictureAccordion = ({ uploadedCanvas, form }) => {
const config = useCampaignConfig();
const { t } = useTranslation();
const classes = useStyles();
const [expanded, setExpanded] = useState(false);
const handleChange = panel => (_event, isExpanded) => {
setExpanded(isExpanded ? panel : false);
};
return (
<>
{t("image.options", "Would you like to")}
<Accordion
TransitionProps={{ unmountOnExit: true }}
expanded={expanded === "upload"}
onChange={handleChange("upload")}
>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<ImageIcon color="primary" />
{t("image.upload", "Upload a picture")}
</AccordionSummary>
<AccordionDetails classes={{ root: classes.accordion }}>
<UploadPicture setCanvas={uploadedCanvas} />
</AccordionDetails>
</Accordion>
<Accordion
TransitionProps={{ unmountOnExit: true }}
expanded={expanded === "webcam"}
onChange={handleChange("webcam")}
>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<PhotoCameraIcon color="primary" />
{t("image.takeTitle", "Take a picture with your phone")}
</AccordionSummary>
<AccordionDetails classes={{ root: classes.accordion }}>
<Camera setCanvas={uploadedCanvas} form={form} />
</AccordionDetails>
</Accordion>
{config.component.picture?.library !== false && (
<Accordion
TransitionProps={{ unmountOnExit: true }}
expanded={expanded === "select"}
onChange={handleChange("select")}
>
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
<PhotoLibraryIcon color="primary" />
{t("image.select")}
</AccordionSummary>
<AccordionDetails classes={{ root: classes.accordion }}>
<SelectPicture setCanvas={uploadedCanvas} />
</AccordionDetails>
</Accordion>
)}
</>
);
};
const ImageOption = props => {
const config = useCampaignConfig();
const { image, setImage, setDraw } = props;
const { t } = useTranslation();
const classes = useStyles();
const confirmOptOut = !(config.component?.consent?.benefit === false); // !(config.component.consent?.confirm === false); // by default we ask for confirmation, same as for Consent
return (
<Grid container spacing={1} justifyContent="space-between" id="proca-image">
<Grid item>{t("image.wanttoadd")}</Grid>
<Grid item>
<ButtonGroup
variant="contained"
color="primary"
className={classes.buttonGroup}
>
<Button
disableElevation={!!image}
color={image === false ? "default" : "primary"}
onClick={() => {
setImage(undefined);
setDraw(true);
}}
>
{t("yes")}
</Button>
<Button
variant="contained"
onClick={() => setImage(false)}
color={image ? "default" : "primary"}
>
{t("no")}
</Button>
</ButtonGroup>
</Grid>
{confirmOptOut && (
<Collapse in={image === false}>
<Alert severity="info" icon={<ImageIcon />}>
<AlertTitle>{t("confirm", "Are you sure?")}</AlertTitle>
<span>{t("image.benefit")}</span>
</Alert>
</Collapse>
)}
</Grid>
);
};
const PublishPicture = props => {
const { t } = useTranslation();
const config = useCampaignConfig();
const { setValue } = props.form;
const canvasRef = useRef(props.canvas);
const data = props.form?.getValues();
const upload = useUpload(canvasRef, data);
const handleSave = async close => {
if (!close) close = true;
const r = await upload();
console.log("uploaded", r);
// r.hash;
setValue("hash", r.hash);
setValue("dimension", "[" + r.width + "," + r.height + "]");
props.setImage(props.canvas.toDataURL("image/jpeg", 0.8));
// console.log(canvasRef.current.toDataUrl("jpeg",81));
props.setDraw(!close);
};
return (
<div>
<Button
variant="contained"
color="primary"
onClick={handleSave}
disabled={!props.canvas}
size="large"
>
{t("image.publish", "Looks good, publish!")}
</Button>
{config.test && (
<Button
variant="contained"
color="secondary"
disabled={!props.canvas}
onClick={() => handleSave(false)}
size="large"
>
Publish (debug)
</Button>
)}
</div>
);
};