From 5739e5a37a017722344a9ef0ad3fa46d0b54636b Mon Sep 17 00:00:00 2001 From: Phil Owen <19691521+PhillipsOwen@users.noreply.github.com> Date: Wed, 31 Jul 2024 14:04:07 -0400 Subject: [PATCH 1/5] removing the share comment from here. --- src/components/trays/layers/tray-contents.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/components/trays/layers/tray-contents.js b/src/components/trays/layers/tray-contents.js index 6f7596fd..b3f3eeb0 100644 --- a/src/components/trays/layers/tray-contents.js +++ b/src/components/trays/layers/tray-contents.js @@ -6,7 +6,6 @@ import { } from '@mui/icons-material'; import { LayersList } from './list'; import { AddLayerForm } from './form'; -import { ShareComment } from '@share/share-comment'; const FORM = 'FORM'; const LIST = 'LIST'; @@ -54,8 +53,6 @@ export const TrayContents = () => { }}> { state === LIST && } - - { state === FORM && } From 2fc6fd5060dbf9ee5d595fde9298ed342d6e615b Mon Sep 17 00:00:00 2001 From: Phil Owen <19691521+PhillipsOwen@users.noreply.github.com> Date: Wed, 31 Jul 2024 14:04:38 -0400 Subject: [PATCH 2/5] tidying up --- src/components/trays/model-selection/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/trays/model-selection/index.js b/src/components/trays/model-selection/index.js index 6d1f09b7..ca0e2df9 100644 --- a/src/components/trays/model-selection/index.js +++ b/src/components/trays/model-selection/index.js @@ -18,6 +18,6 @@ export const title = 'ADCIRC Model selection'; */ export const trayContents = () => ( - + ); From e36f584de82d8891c5f1c47a33882471017171a3 Mon Sep 17 00:00:00 2001 From: Phil Owen <19691521+PhillipsOwen@users.noreply.github.com> Date: Wed, 31 Jul 2024 14:15:23 -0400 Subject: [PATCH 3/5] moving the share view code to a tray --- src/app.js | 2 - src/components/trays/index.js | 5 +- src/components/trays/share/index.js | 25 ++++ .../{ => trays}/share/share-comment.js | 0 src/components/trays/share/shareViewTray.js | 110 ++++++++++++++++++ src/components/trays/share/share_view.js | 17 +++ 6 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 src/components/trays/share/index.js rename src/components/{ => trays}/share/share-comment.js (100%) create mode 100644 src/components/trays/share/shareViewTray.js create mode 100644 src/components/trays/share/share_view.js diff --git a/src/app.js b/src/app.js index 74371385..a8194fc5 100644 --- a/src/app.js +++ b/src/app.js @@ -6,7 +6,6 @@ import { useLayers } from '@context'; import { Sidebar } from '@components/sidebar'; import { ControlPanel } from '@components/control-panel'; import { MapLegend } from '@components/legend'; -import { Share } from '@share/share'; /** * renders the main content @@ -35,7 +34,6 @@ const Content = () => { - ); }; diff --git a/src/components/trays/index.js b/src/components/trays/index.js index 9f886710..5fb40b7d 100644 --- a/src/components/trays/index.js +++ b/src/components/trays/index.js @@ -3,8 +3,9 @@ import * as layers from './layers'; import * as model_selection from './model-selection'; import * as remove_items from './remove'; import * as settings from './settings'; +import * as share_view from './share'; import * as help_about from './help-about'; -//import * as screen_shot from './screenshot'; + export default { layers, @@ -12,8 +13,8 @@ export default { model_selection, remove_items, settings, + share_view, help_about -// ,screen_shot }; /* diff --git a/src/components/trays/share/index.js b/src/components/trays/share/index.js new file mode 100644 index 00000000..96898e4c --- /dev/null +++ b/src/components/trays/share/index.js @@ -0,0 +1,25 @@ +export * from './share_view'; + +import React from 'react'; +import { Stack } from '@mui/joy'; +import { Share as ShareViewIcon} from '@mui/icons-material'; + +// import the component that will allow the user to make model selections +import { ShareView } from "./share_view.js"; + +// get an icon for the tray +export const icon = ; + +// create a title for this tray element +export const title = 'Share your view'; + +/** + * render the removal component + * + * @returns {JSX.Element} + */ +export const trayContents = () => ( + + + + ); diff --git a/src/components/share/share-comment.js b/src/components/trays/share/share-comment.js similarity index 100% rename from src/components/share/share-comment.js rename to src/components/trays/share/share-comment.js diff --git a/src/components/trays/share/shareViewTray.js b/src/components/trays/share/shareViewTray.js new file mode 100644 index 00000000..17dc5372 --- /dev/null +++ b/src/components/trays/share/shareViewTray.js @@ -0,0 +1,110 @@ +import React, { Fragment, useState } from 'react'; +import { Button, TextField, Typography, Link } from '@mui/material'; +import { useLayers } from "@context/map-context"; +import { ShareComment } from "@share/share-comment"; + +/** + * renders the shared content on the app as defined in the query string + * + * @returns {JSX.Element} + * @constructor + */ +export const ShareViewTray = () => { + // get the layers from state + const { defaultModelLayers, selectedObservations } = useLayers(); + + // store the result message of the share link building + const [ buildLinkMessage, setBuildLinkMessage ] = useState(''); + + // storage for the share link + const [shareLink, setShareLink] = useState(''); + + // create the query string that can be used to share the current view + const formShareViewHandler = (event) => { + // avoid doing the usual submit operations + event.preventDefault(); + + // get the list of selected layers from state + // this forces the group at the top to be the reproduced in the share line + const run_id = defaultModelLayers + // get all the distinct groups + .filter((val, idx, self) => + ( idx === self.findIndex((t)=> ( t['group'] === val['group'] )))) + // return the group name + .map((mbr) => ( + mbr['group'] + )).join(',').split(',')[0]; + + // capture the selected observations from state + const observations = selectedObservations.map( + (x) => ( + JSON.stringify({'id': x.id, 'lat': x.lat, 'lng': x.lon, 'location_name': x.location_name, 'station_name': x.station_name, 'csvurl': x.csvurl}) + ) + ).join(','); + + // check to see if there was one or more groups selected + if (run_id !== '') { + // create the link + const theLink = encodeURI(window.location.origin + '/#share=run_id:' + run_id + "~comment=" + event.target.elements.comment.value + '~obs=[' + observations + ']'); + + // copy the link to the cut/paste buffer + copyTextToClipboard(theLink).then(); + + // set the user feedback + setBuildLinkMessage(`Your share link is now in your clipboard.`); + setShareLink(theLink); + } + // no layers were selected on the map + else { + // set the error message + setBuildLinkMessage('There are no layers selected. Please try again.'); + setShareLink(''); + } + }; + + /** + * async function to copy the share link to the clipboard + * + * @param text + * @returns {Promise} + */ + async function copyTextToClipboard(text) { + // wait for the copy to complete + return await navigator.clipboard.writeText(text); + } + + /** + * resets the form + */ + function resetForm() { + // reset the form controls + setBuildLinkMessage(''); + setShareLink(''); + } + + /** + * return the rendered component + */ + return ( + +
+ + Please enter a comment below that describes the view you are sharing.

When ready, select the "Create" button + and your share URL will be copied into your clipboard. You can then send it to your colleagues. +
+ + {/* output the result of the link building/saving */} + {(buildLinkMessage.length) ?
{buildLinkMessage}
: ''} + + {/* output the link */} + {(shareLink.length) ? Test it! : ''} + + + + + + + +
+ ); +}; diff --git a/src/components/trays/share/share_view.js b/src/components/trays/share/share_view.js new file mode 100644 index 00000000..b5fcd9f4 --- /dev/null +++ b/src/components/trays/share/share_view.js @@ -0,0 +1,17 @@ +import React, { Fragment } from 'react'; +import { ShareViewTray } from "@share/shareViewTray.js"; + +/** + * component that handles the filtered selections of layers for the map. + * + * @returns {JSX.Element} + * @constructor + */ +export const ShareView = () => { + // render the layer selection component + return ( + + + + ); +}; From 96c011b14025c4719a6caf9070f7de17d39db450 Mon Sep 17 00:00:00 2001 From: Phil Owen <19691521+PhillipsOwen@users.noreply.github.com> Date: Wed, 31 Jul 2024 14:15:45 -0400 Subject: [PATCH 4/5] removing --- src/components/share/buildlink.js | 132 ----------------------------- src/components/share/index.js | 3 - src/components/share/screenshot.js | 78 ----------------- src/components/share/share.js | 44 ---------- 4 files changed, 257 deletions(-) delete mode 100644 src/components/share/buildlink.js delete mode 100644 src/components/share/index.js delete mode 100644 src/components/share/screenshot.js delete mode 100644 src/components/share/share.js diff --git a/src/components/share/buildlink.js b/src/components/share/buildlink.js deleted file mode 100644 index 48347e8b..00000000 --- a/src/components/share/buildlink.js +++ /dev/null @@ -1,132 +0,0 @@ -import React, { Fragment, useState } from 'react'; -import { Button, TextField, Dialog, DialogActions, - DialogContent, DialogContentText, DialogTitle, - Typography, Link } from '@mui/material'; -import { IconButton } from '@mui/joy'; -import ShareRoundedIcon from '@mui/icons-material/ShareRounded'; -import { useLayers } from "@context/map-context"; - -/** - * renders the link builder to recreate the current view elsewhere - * - * @returns {JSX.Element} - * @constructor - */ -export const BuildLink = () => { - // get the layers from state - const { defaultModelLayers, selectedObservations } = useLayers(); - - // store the result message of the share link building - const [ buildLinkMessage, setBuildLinkMessage ] = useState(''); - - // used to set the dialog view state - const [open, setOpen] = useState(false); - - // storage for the share link - const [shareLink, setShareLink] = useState(''); - - // create the query string that can be used to share the current view - const createLink = (comment) => { - // get the list of selected layers from state - // this forces the group at the top to be the reproduced in the share line - const run_id = defaultModelLayers - // get all the distinct groups - .filter((val, idx, self) => - ( idx === self.findIndex((t)=> ( t['group'] === val['group'] )))) - // return the group name - .map((mbr) => ( - mbr['group'] - )).join(',').split(',')[0]; - - // capture the selected observations from state - const observations = selectedObservations.map( - (x) => ( - JSON.stringify({'id': x.id, 'lat': x.lat, 'lng': x.lon, 'location_name': x.location_name, 'station_name': x.station_name, 'csvurl': x.csvurl}) - ) - ).join(','); - - // check to see if there was one or more groups selected - if (run_id !== '') { - // create the link - const theLink = encodeURI(window.location.origin + '/#share=run_id:' + run_id + "~comment=" + comment + '~obs=[' + observations + ']'); - - // copy the link to the cut/paste buffer - copyTextToClipboard(theLink).then(); - - // set the user feedback - setBuildLinkMessage(`The Share link is now in your clipboard.`); - setShareLink(theLink); - } - // no layers were selected on the map - else { - // set the error message - setBuildLinkMessage('There are no layers selected. Please try again.'); - setShareLink(''); - } - }; - - /** - * async function to copy the share link to the clipboard - * - * @param text - * @returns {Promise} - */ - async function copyTextToClipboard(text) { - // wait for the copy to complete - return await navigator.clipboard.writeText(text); - } - - // handles the dialog open event - const handleClickOpen = () => { - setOpen(true); - }; - - // handles the dialog close event - const handleClose = () => { - setBuildLinkMessage(''); - setShareLink(''); - setOpen(false); - }; - - return ( - - - - - { - event.preventDefault(); - const formData = new FormData(event.currentTarget); - const formJson = Object.fromEntries(formData.entries()); - const comment = formJson.comment; - createLink(comment); - }}}> - Share this view - - - - Please enter a comment below that describes what you are sharing. When ready, select the "Create" button - and you will have the share link copied into your cut/paste buffer. - - - {/* output the result of the link building/saving */} - { ( buildLinkMessage.length ) ? { buildLinkMessage } : '' } - - {/* output the link */} - { ( shareLink.length ) ? Test it! : '' } - - - - - - - - - - - ); -}; diff --git a/src/components/share/index.js b/src/components/share/index.js deleted file mode 100644 index 63e68594..00000000 --- a/src/components/share/index.js +++ /dev/null @@ -1,3 +0,0 @@ -export * from './share'; -export * from './buildlink'; -export * from './screenshot'; diff --git a/src/components/share/screenshot.js b/src/components/share/screenshot.js deleted file mode 100644 index 04f8da96..00000000 --- a/src/components/share/screenshot.js +++ /dev/null @@ -1,78 +0,0 @@ -import React, { Fragment } from 'react'; -import { IconButton } from '@mui/joy'; -import AddAPhotoRoundedIcon from '@mui/icons-material/AddAPhotoRounded'; -import { toJpeg } from 'html-to-image'; // toPng, toBlob, toPixelData, toSvg - -/** - * creates a screenshot of the app surface. this method expects a - * reference to the parent view that will be turned into an image. - * usage: - * - * import { Screenshot } from "@screen-shot/screenshot"; - * - * - * @returns {JSX.Element} - * @constructor - */ -export const Screenshot = () => { - /** - * Creates a filename for the download target - * - * @param extension - * @param names - * @returns {string} - */ - const createFileName = (extension = "", ...names) => { - // no file extension will result in no file name returned - if (!extension) { - return ""; - } - - // return the filename - return `${names.join("")}.${extension}`; - }; - - /** - * initiates the screenshot - * - * @param node - * @returns {Promise<*>} - */ - const takeScreenShot = async (node) => { - // return the rendering - return await toJpeg(node); - }; - - /** - * create the imaginary link to download the image - * - * @param image - * @param name - * @param extension - */ - const download = (image, { name = "screencap-" + new Date().toISOString(), extension = "jpg" } = {}) => { - // create a target element - const a = document.createElement("a"); - - // specify the image - a.href = image; - - // create a file name - a.download = createFileName(extension, name); - - // execute the link - a.click(); - }; - - // click handler to initiate the image download - const downloadScreenshot = () => takeScreenShot(document.body).then(download); - - // render the button to download the image - return ( - - - - - - ); -}; \ No newline at end of file diff --git a/src/components/share/share.js b/src/components/share/share.js deleted file mode 100644 index 174d56e2..00000000 --- a/src/components/share/share.js +++ /dev/null @@ -1,44 +0,0 @@ -import React, { Fragment } from 'react'; -import { Card, Stack } from '@mui/joy'; -import { BuildLink } from './buildlink'; -// import { Screenshot } from './screenshot'; - -/** - * renders the shared content on the app as defined in the query string - * - * @returns {JSX.Element} - * @constructor - */ -export const Share = () => { - return ( - - - - - {/**/} - - - - ); -}; From 0e5ffd08bb001d2d1c616c00f67ab4bb14a34004 Mon Sep 17 00:00:00 2001 From: Phil Owen <19691521+PhillipsOwen@users.noreply.github.com> Date: Wed, 31 Jul 2024 14:16:18 -0400 Subject: [PATCH 5/5] updating the share shortcut location --- webpack.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webpack.config.js b/webpack.config.js index 24145787..28ac53f1 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -104,7 +104,7 @@ module.exports = { '@hooks': path.resolve(__dirname, 'src/hooks/'), '@images': path.resolve(__dirname, 'src/images/'), '@model-selection': path.resolve(__dirname, 'src/components/trays/model-selection/'), - '@share': path.resolve(__dirname, 'src/components/share/'), + '@share': path.resolve(__dirname, 'src/components/trays/share/'), '@utils': path.resolve(__dirname, 'src/utils/') } },