// import dependencies import copy from 'copy-to-clipboard'; import QRCode from 'qrcode.react'; import { Alert } from '@mui/material'; import React, { useRef, useState } from 'react'; import { Icon, View, Modal, DialogActions, FormControlLabel, FormGroup, Switch, DialogContentText, Box, TextField, Dialog, DialogTitle, Stack, Button, DialogContent, MenuItem, Divider, Tooltip, IconButton, LoadingButton, InputAdornment } from '../'; // let context let loading = false; let DashupContext = null; // debounce let timeout; const debounce = (fn, to = 500) => { clearTimeout(timeout); timeout = setTimeout(fn, to); }; // create menu component const DashupUIPageShare = (props = {}) => { // use state const [share, setSharing] = useState(null); const [shares, setShares] = useState([]); const [saving, setSaving] = useState(false); const [prevent, setPrevent] = useState(false); const [copying, setCopying] = useState(null); const [removing, setRemoving] = useState(null); // set ref const structRef = useRef(null); // get type const getType = (struct, page) => { // map return ['Link', 'Embed', 'Marketplace'].filter((item) => { // check item if (item === 'Marketplace' && (!struct?.data?.share || page.get('link'))) return false; // return true return true; }).map((label) => { // set value const value = label.toLowerCase(); // return value return { label, value, selected : (share?.type || 'link') === value, }; }); }; // on copy const onCopy = (share) => { // set copying setCopying(share.id); // timeout setTimeout(() => setCopying(null), 2000); // copy copy(`https://${eden.get('config.domain')}/share/${share.slug}`); }; // on share const onSubmit = async (page, dashup, revert = true) => { // loading setSaving(true); // get result const result = await eden.router.post(`/app/${dashup.get('_id')}/share/${page.get('_id')}/${share.id ? `${share.id}/update` : 'create'}`, share); // push result if (result.success) { // set id if (!share.id) { shares.push(share); } // set to found Object.keys(result.data).forEach((key) => { // update values share[key] = result.data[key]; }); } // loading setShares([...shares]); setSaving(false); if (revert) { setSharing(null); } else { setSharing({ ...share }); } }; // on remove const onRemove = async (page, dashup) => { // loading setSaving(true); // filter const newShares = shares.filter((s) => s.id !== removing.id); // get result await eden.router.post(`/app/${dashup.get('_id')}/share/${page.get('_id')}/${removing.id}/remove`); // loading setShares([...newShares]); setSaving(false); setSharing(null); setRemoving(null); }; // set share const setShare = (key, value, page, dashup) => { // set value share[key] = value; // set share setSharing({ ...share }); // debounce debounce(() => onSubmit(page, dashup, false)); }; // get shares const getShares = (dashup, page, share) => { // accum return Object.keys(share).reduce((accum, item) => { // check array let ids = page.get(item); if (!Array.isArray(ids)) ids = [ids].filter((i) => i); // find page ids.forEach((id) => { // check id if (!dashup.page(id)) return; if (!accum.find((p) => p.get('_id') === id)) accum.push(dashup.page(id)); }); // return accum return accum; }, []); }; // load shares const loadShares = (page, dashup) => { // check loading if (loading) return; // loading true loading = true; // load shares eden.router.get(`/app/${dashup.get('_id')}/share/${page.get('_id')}/list`).then(({ data, }) => { // shares setShares(data); // loading done loading = false; }); } // check is share const isShare = !!(typeof eden === 'undefined' ? {} : eden).state?.share; // check share if (isShare) return null; // return JSX return ( { ({ page, guest, dashup, getPageStruct }) => { // load shares if (!shares && props.show) loadShares(page, dashup); // shares page const shareP = guest && guest.page('shares'); const sForm = shareP && Array.from(guest.get('pages').values()).find((p) => p.get('type') === 'form' && p.get('data.model') === shareP.get('_id')); const sFields = sForm && sForm.get('data.fields'); const categories = sFields && (sFields || []).find((f) => f.name === 'categories'); // get struct const struct = page.get('type') && getPageStruct(page.get('type')); // add to ref structRef.current = struct; // return jsx return ( <> { share ? ( { !!struct?.data?.share?.pages && ( <> The following pages will also be shared. { getShares(dashup, page, struct.data.share.pages).map((sPage) => { // get color const color = sPage.get('color'); // return jsx return ( ), } } /> ); }) } ) } setShare('type', e.target?.value, page, dashup) } fullWidth > { getType(struct, page).map((option) => ( { option.label } ))} setShare('name', e.target?.value, page, dashup) } fullWidth /> setShare('description', e.target?.value, page, dashup) } fullWidth /> { share.type === 'marketplace' && ( <> Adding this page to the marketplace will make it available for anyone to see once approved. setShare('image', val, page, dashup) } setPrevent={ setPrevent } /> { !!categories && ( setShare('categories', val, page, dashup) } /> ) } { /* setShare('price', val) } /> */ } ) } { !!['embed', 'link'].includes(share.type) && ( <> { !!share.slug && ( <> ) } setShare('disableMenu', !!e.target.checked, page, dashup) } /> ) } label="Disable Menu" /> setShare('disableFilter', !!e.target.checked, page, dashup) } /> ) } label="Disable Filter" /> setShare('disablePadding', !!e.target.checked, page, dashup) } /> ) } label="Disable Padding" /> ) } ) : ( { (shares || []).length ? (shares || []).map((share, i) => { // return jsx return ( onCopy(share) }> { copying === share.id ? ( ) : ( share.type === 'link' ? ( ) : ( ) ) } ), endAdornment : ( <> setRemoving(share) }> setSharing(share) }> ) } } /> ); }) : ( This page has no shares, click below to create one. ) } ) } { !!share && ( setRemoving(true) }> ) } { !!share && ( ) } { share ? ( onSubmit(page, dashup) }> { saving ? 'Submitting...' : 'Submit' } ) : ( setSharing({ type : 'link' }) }> New Share ) } setRemoving(false) } > Confirm Remove Are you sure you want to remove this share? onRemove(page, dashup) } loading={ saving }> { saving ? 'Removing...' : 'Remove' } ); } } ); }; // export default page menu export default (ctx) => { // use context DashupContext = ctx; // return actual component return DashupUIPageShare; };