diff --git a/package-lock.json b/package-lock.json
index 1c9c3910..a7df5eae 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -25,6 +25,7 @@
"d3": "^7.8.5",
"dayjs": "^1.11.11",
"dotenv": "^16.4.5",
+ "html-to-image": "^1.11.11",
"leaflet": "^1.9.4",
"mapbox-gl": "^3.1.2",
"prop-types": "^15.8.1",
@@ -34,6 +35,7 @@
"react-leaflet": "^4.2.1",
"react-map-gl": "^7.1.7",
"react-query": "^3.39.3",
+ "react-router-dom": "^6.23.1",
"react-timeago": "^7.2.0",
"recharts": "^2.12.6"
},
@@ -5033,6 +5035,15 @@
"react-dom": "^18.0.0"
}
},
+ "node_modules/@remix-run/router": {
+ "version": "1.16.1",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.16.1.tgz",
+ "integrity": "sha512-es2g3dq6Nb07iFxGk5GuHN20RwBZOsuDQN7izWIisUcv9r+d2C5jQxqmgkdebXgReWfiyUabcki6Fg77mSNrig==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/@sinclair/typebox": {
"version": "0.27.8",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
@@ -7207,6 +7218,7 @@
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"fill-range": "^7.1.1"
},
@@ -10143,6 +10155,7 @@
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
},
@@ -11039,6 +11052,12 @@
"node": ">= 12"
}
},
+ "node_modules/html-to-image": {
+ "version": "1.11.11",
+ "resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.11.11.tgz",
+ "integrity": "sha512-9gux8QhvjRO/erSnDPv28noDZcPZmYE7e1vFsBLKLlRlKDSqNJYebj6Qz1TGd5lsRV+X+xYyjCKjuZdABinWjA==",
+ "license": "MIT"
+ },
"node_modules/html-webpack-plugin": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.0.tgz",
@@ -11712,6 +11731,7 @@
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.12.0"
}
@@ -16425,6 +16445,38 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-router": {
+ "version": "6.23.1",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.23.1.tgz",
+ "integrity": "sha512-fzcOaRF69uvqbbM7OhvQyBTFDVrrGlsFdS3AL+1KfIBtGETibHzi3FkoTRyiDJnWNc2VxrfvR+657ROHjaNjqQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/router": "1.16.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.23.1",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.23.1.tgz",
+ "integrity": "sha512-utP+K+aSTtEdbWpC+4gxhdlPFwuEfDKq8ZrPFU65bbRJY+l706qjR7yaidBpo3MSeA/fzwbXWbKBI6ftOnP3OQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/router": "1.16.1",
+ "react-router": "6.23.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
"node_modules/react-smooth": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.1.tgz",
@@ -18111,6 +18163,7 @@
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
},
diff --git a/package.json b/package.json
index edf6d89e..a3566b44 100644
--- a/package.json
+++ b/package.json
@@ -64,6 +64,7 @@
"d3": "^7.8.5",
"dayjs": "^1.11.11",
"dotenv": "^16.4.5",
+ "html-to-image": "^1.11.11",
"leaflet": "^1.9.4",
"mapbox-gl": "^3.1.2",
"prop-types": "^15.8.1",
@@ -73,6 +74,7 @@
"react-leaflet": "^4.2.1",
"react-map-gl": "^7.1.7",
"react-query": "^3.39.3",
+ "react-router-dom": "^6.23.1",
"react-timeago": "^7.2.0",
"recharts": "^2.12.6"
},
diff --git a/src/app.js b/src/app.js
index eae1e6ff..b101fb59 100644
--- a/src/app.js
+++ b/src/app.js
@@ -1,30 +1,57 @@
import React, { Fragment } from 'react';
+import { BrowserRouter, Route, Routes } from "react-router-dom";
import { Map } from '@components/map';
import { ObservationDialog } from "@components/dialog/observation-dialog";
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';
-export const App = () => {
+/**
+ * renders the main content
+ *
+ * @returns {JSX.Element}
+ * @constructor
+ */
+const Content = () => {
// install the selected observation list from the layer context
- const {
- selectedObservations
- } = useLayers();
+ const { selectedObservations } = useLayers();
+ // render all the application content
return (
- {
- // for each observation selected
- selectedObservations.map (function (obs) {
- // render the observation
- return ;
- })
- }
+ {
+ // for each observation selected
+ selectedObservations.map (function (obs) {
+ // render the observation
+ return ;
+ })
+ }
+
+
+ );
+};
+
+/**
+ * renders the application
+ *
+ * @returns {JSX.Element}
+ * @constructor
+ */
+export const App = () => {
+ // render the application
+ return (
+
+
+
+ } />
+
+
);
};
diff --git a/src/components/control-panel/control-panel.js b/src/components/control-panel/control-panel.js
index b7df62f2..ae6d7cf2 100644
--- a/src/components/control-panel/control-panel.js
+++ b/src/components/control-panel/control-panel.js
@@ -277,7 +277,7 @@ export const ControlPanel = () => {
'&:hover': { filter: 'opacity(1.0)' },
height: 'auto',
width: '300px',
- zIndex: 999,
+ zIndex: 401,
borderRadius: 'sm',
}}
>
diff --git a/src/components/dialog/base-floating-dialog.js b/src/components/dialog/base-floating-dialog.js
index 33343893..54660c60 100644
--- a/src/components/dialog/base-floating-dialog.js
+++ b/src/components/dialog/base-floating-dialog.js
@@ -63,13 +63,18 @@ export default function BaseFloatingDialog({ title, dialogObject, dataKey, dataL
disableEnforceFocus
style={{ pointerEvents: 'none' }}
PaperProps={{ sx: { width: 750, height: 485, pointerEvents: 'auto'} }}
- sx={{ width: 750, height: 485, '.MuiBackdrop-root': { backgroundColor: 'transparent' }}}
+ sx={{ zIndex: 402, width: 750, height: 485, '.MuiBackdrop-root': { backgroundColor: 'transparent' }}}
>
- { title }
+ { title }
- { dialogObject }
+ { dialogObject }
-
+
+
);
diff --git a/src/components/legend/legend.js b/src/components/legend/legend.js
index ee579130..86341efc 100644
--- a/src/components/legend/legend.js
+++ b/src/components/legend/legend.js
@@ -64,7 +64,7 @@ export const MapLegend = () => {
height: 'auto',
width: '100px',
padding: '10px',
- zIndex: 999,
+ zIndex: 401,
borderRadius: 'sm',
visibility: legendVisibilty,
}}
diff --git a/src/components/map/default-layers.js b/src/components/map/default-layers.js
index 546fcce4..0a4f7b12 100644
--- a/src/components/map/default-layers.js
+++ b/src/components/map/default-layers.js
@@ -5,6 +5,7 @@ import { useLayers } from '@context';
import { useQuery } from '@tanstack/react-query';
import axios from 'axios';
import { markClicked } from '@utils/map-utils';
+import { useLocation } from "react-router-dom";
const newLayerDefaultState = (layer) => {
const { product_type } = layer.properties;
@@ -23,10 +24,19 @@ const newLayerDefaultState = (layer) => {
};
export const DefaultLayers = () => {
-
const [obsData, setObsData] = useState("");
const map = useMap();
+ // get the hash location (if any)
+ const { hash } = useLocation();
+
+ let share_run = '';
+
+ if (hash !== '') {
+ share_run = '&run_id=' + hash.split('=')[1];
+ share_run = share_run.split(',')[0];
+ }
+
const {
defaultModelLayers,
setDefaultModelLayers,
@@ -88,7 +98,7 @@ export const DefaultLayers = () => {
};
// create the URLs to the data endpoints
- const data_url = `${process.env.REACT_APP_UI_DATA_URL}get_ui_data_secure?limit=1&use_new_wb=true&use_v3_sp=true`;
+ const data_url = `${process.env.REACT_APP_UI_DATA_URL}get_ui_data_secure?limit=1&use_new_wb=true&use_v3_sp=true` + share_run;
const gs_wms_url = `${process.env.REACT_APP_GS_DATA_URL}wms`;
const gs_wfs_url = `${process.env.REACT_APP_GS_DATA_URL}`;
diff --git a/src/components/share/buildlink.js b/src/components/share/buildlink.js
new file mode 100644
index 00000000..06cfb121
--- /dev/null
+++ b/src/components/share/buildlink.js
@@ -0,0 +1,64 @@
+import React, { Fragment } from 'react';
+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 in state
+ const { defaultModelLayers } = useLayers();
+
+ /**
+ * create the query string that can be used to share the current view
+ */
+ const createLink = () => {
+ // get the list of selected layers
+ const groups = 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']
+ ))
+ // generate a query string
+ .join(',');
+
+ // check to see if there was one or more groups selected
+ if (groups !== '') {
+ // copy the link to the cut/paste buffer
+ copyTextToClipboard(window.location.origin + '/#share=' + groups).then();
+
+ // tell the user what just happened
+ alert('The share link has been copied to the clipboard.');
+ }
+ // no layers were selected on the map
+ else
+ alert('There were no layers selected.');
+ };
+
+ /**
+ * 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);
+ }
+
+ // render the button
+ return (
+
+ Share
+
+
+
+ );
+};
diff --git a/src/components/share/index.js b/src/components/share/index.js
new file mode 100644
index 00000000..63e68594
--- /dev/null
+++ b/src/components/share/index.js
@@ -0,0 +1,3 @@
+export * from './share';
+export * from './buildlink';
+export * from './screenshot';
diff --git a/src/components/share/screenshot.js b/src/components/share/screenshot.js
new file mode 100644
index 00000000..04f8da96
--- /dev/null
+++ b/src/components/share/screenshot.js
@@ -0,0 +1,78 @@
+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
new file mode 100644
index 00000000..79438539
--- /dev/null
+++ b/src/components/share/share.js
@@ -0,0 +1,44 @@
+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 (
+
+
+
+
+ {/**/}
+
+
+
+ );
+};
diff --git a/src/components/sidebar/sidebar.js b/src/components/sidebar/sidebar.js
index 851b4dcd..182a72bf 100644
--- a/src/components/sidebar/sidebar.js
+++ b/src/components/sidebar/sidebar.js
@@ -28,7 +28,7 @@ export const Sidebar = () => {
position: 'absolute',
top: 0, left: 0,
height: '100vh',
- zIndex: 999,
+ zIndex: 401,
maxWidth: '68px',
overflow: 'hidden',
p: 0,
diff --git a/src/components/sidebar/tray.js b/src/components/sidebar/tray.js
index 9053b382..2f43f896 100644
--- a/src/components/sidebar/tray.js
+++ b/src/components/sidebar/tray.js
@@ -17,7 +17,7 @@ export const Tray = ({ active, Contents, title, closeHandler }) => {
transition: 'transform 250ms',
height: '100vh',
width: TRAY_WIDTH,
- zIndex: 998,
+ zIndex: 401,
filter: 'drop-shadow(0 0 8px rgba(0, 0, 0, 0.2))',
overflowX: 'hidden',
overflowY: 'auto',
diff --git a/src/components/trays/help_about/helpAboutTray.js b/src/components/trays/help-about/helpAboutTray.js
similarity index 54%
rename from src/components/trays/help_about/helpAboutTray.js
rename to src/components/trays/help-about/helpAboutTray.js
index 4a5327e9..02023bcf 100644
--- a/src/components/trays/help_about/helpAboutTray.js
+++ b/src/components/trays/help-about/helpAboutTray.js
@@ -9,10 +9,10 @@ import { AccordionGroup, Accordion, AccordionSummary, AccordionDetails, Stack, T
export const HelpAboutTray = () => {
// used to collapse other open accordions
const [index, setIndex] = React.useState(0);
+ const [subIndex, setSubIndex] = React.useState(-1);
// render the form
return (
-
@@ -41,46 +41,103 @@ export const HelpAboutTray = () => {
{ setIndex(expanded ? 4 : null); }}>
+ How do I capture a screenshot ?
+
+
+ { setSubIndex(expanded ? 0 : null); }}>
+ Edge
+
+
+ - Right click the browser surface.
+ - Select `Screenshot` from the context menu that appears.
+ - At the top of the browser you can select to capture a portion of the browser or the entire browser surface.
+ - A dialog of the screenshot will appear where you can save it to the Downloads folder or the cut/paste buffer.
+
+
+
+
+ { setSubIndex(expanded ? 1 : null); }}>
+ Firefox
+
+
+ - Right click the browser surface
+ - Select `Take screenshot` from the context menu that appears
+ - At the top of the browser you can select to capture the visible portion of the browser or the entire browser surface.
+ - A dialog of the screenshot will appear where you can save it to the Downloads folder or the cut/paste buffer.
+
+
+
+
+ { setSubIndex(expanded ? 2 : null); }}>
+ Chrome
+
+
+ - Install and activate the Chrome Full Page Screen Capture browser extension.
+ - A small camera icon will appear in the top right corner of the browser.
+ - Click the camera icon.
+ - Click the “download image” icon and the image will be saved to the Downloads folder.
+
+
+
+
+ { setSubIndex(expanded ? 3 : null); }}>
+ Safari
+
+
+ - Install and activate Awesome Screenshot
+ - Navigate to the target page in Safari
+ - Click the Awesome Screenshot icon (looks like a tiny camera lens) to the left of the Safari address bar
+ - Click “Capture entire page.” An image opens in a new tab.
+ - Click the “Done” button.
+ - Follow the directions to save the file.
+
+
+
+
+
+
+
+ { setIndex(expanded ? 5 : null); }}>
What are some features of this application?
Add some content here...
- { setIndex(expanded ? 5 : null); }}>
+ { setIndex(expanded ? 6 : null); }}>
How do I add/remove Layers on the map?
Add some content here...
- { setIndex(expanded ? 6 : null); }}>
+ { setIndex(expanded ? 7 : null); }}>
How do I move through synoptic cycles?
Add some content here...
- { setIndex(expanded ? 7 : null); }}>
+ { setIndex(expanded ? 8 : null); }}>
What do the icons on the left mean?
Add some content here...
- { setIndex(expanded ? 8 : null); }}>
+ { setIndex(expanded ? 9 : null); }}>
What are some user settings?
Add some content here...
- { setIndex(expanded ? 9 : null); }}>
+ { setIndex(expanded ? 10 : null); }}>
How do I change the base map?
Add some content here...
- { setIndex(expanded ? 10 : null); }}>
+ { setIndex(expanded ? 11 : null); }}>
How do I view observation data?
Add some content here...
- { setIndex(expanded ? 11 : null); }}>
+ { setIndex(expanded ? 12 : null); }}>
How do I show/hide layers?
Add some content here...
- { setIndex(expanded ? 12 : null); }}>
+ { setIndex(expanded ? 13 : null); }}>
How do I reorder layers on the map?
Add some content here...
diff --git a/src/components/trays/help_about/help_about.js b/src/components/trays/help-about/help_about.js
similarity index 100%
rename from src/components/trays/help_about/help_about.js
rename to src/components/trays/help-about/help_about.js
diff --git a/src/components/trays/help_about/index.js b/src/components/trays/help-about/index.js
similarity index 92%
rename from src/components/trays/help_about/index.js
rename to src/components/trays/help-about/index.js
index 111ae270..84955d56 100644
--- a/src/components/trays/help_about/index.js
+++ b/src/components/trays/help-about/index.js
@@ -9,7 +9,7 @@ import { HelpAbout } from "./help_about.js";
export const icon = ;
// create a title for this tray element
-export const title = 'ADCIRC Help/About';
+export const title = 'APSViz Help/About';
/**
* render the removal component
diff --git a/src/components/trays/hurricanes.js b/src/components/trays/hurricanes.js
deleted file mode 100644
index c946bfda..00000000
--- a/src/components/trays/hurricanes.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import React from 'react';
-import { Storm as HurricaneIcon } from '@mui/icons-material';
-
-export const icon = ;
-export const title = 'Hurricanes';
-export const trayContents = () => Coming soon!
;
diff --git a/src/components/trays/index.js b/src/components/trays/index.js
index 6f72e87d..9f886710 100644
--- a/src/components/trays/index.js
+++ b/src/components/trays/index.js
@@ -3,7 +3,8 @@ 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 help_about from './help_about';
+import * as help_about from './help-about';
+//import * as screen_shot from './screenshot';
export default {
layers,
@@ -12,6 +13,7 @@ export default {
remove_items,
settings,
help_about
+// ,screen_shot
};
/*
diff --git a/src/components/trays/model-selection/catalogItems.js b/src/components/trays/model-selection/catalogItems.js
index 7f0fc571..98434ff7 100644
--- a/src/components/trays/model-selection/catalogItems.js
+++ b/src/components/trays/model-selection/catalogItems.js
@@ -76,6 +76,7 @@ export default function CatalogItems(data) {
// reload the default layers less the layer group that was unselected
setDefaultModelLayers(newLayers);
}
+ // else add these layers to state
else if (!defaultModelLayers.find(layer => layer.group === layerGroup) && checked) {
// loop through the select layers in the group and add the default layer state
selectedLayers.forEach((layer) => {
@@ -92,9 +93,6 @@ export default function CatalogItems(data) {
// save the items to state so they can be rendered
setDefaultModelLayers([...newLayers, ...defaultModelLayers]);
}
- else
- // TODO: the checkbox checked value should follow what is in the defaultModelLayers state
- console.warn(`Layer group ${layerGroup} already exists.`);
};
/**
diff --git a/src/components/trays/settings/basemap.js b/src/components/trays/settings/basemap.js
index cf03b8ed..938ce7b9 100644
--- a/src/components/trays/settings/basemap.js
+++ b/src/components/trays/settings/basemap.js
@@ -94,7 +94,7 @@ export function BaseMaps() {
[`& .${radioClasses.radio}`]: {
display: 'contents',
'& > svg': {
- zIndex: 2,
+ zIndex: 1,
position: 'absolute',
top: '-8px',
right: '-8px',
diff --git a/src/index.js b/src/index.js
index e32dcd18..7a546546 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { Fragment } from 'react';
import { createRoot } from 'react-dom/client';
import { App } from './app';
import { LayersProvider, SettingsProvider } from '@context';
@@ -29,19 +29,22 @@ const materialTheme = materialExtendTheme();
// render the app specifying the material and joy providers
const ProvisionedApp = () => {
+ // render the app
return (
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
);
};
diff --git a/webpack.config.js b/webpack.config.js
index 0eb0257d..24145787 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -99,12 +99,13 @@ module.exports = {
'@components': path.resolve(__dirname, 'src/components/'),
'@content': path.resolve(__dirname, 'src/content/'),
'@context': path.resolve(__dirname, 'src/context/'),
- '@dialog': path.resolve(__dirname, 'src/components/dialog'),
+ '@dialog': path.resolve(__dirname, 'src/components/dialog/'),
'@help-about': path.resolve(__dirname, 'src/components/trays/help-about/'),
'@hooks': path.resolve(__dirname, 'src/hooks/'),
'@images': path.resolve(__dirname, 'src/images/'),
- '@model-selection': path.resolve(__dirname, 'src/components/trays/model-selection'),
- '@utils': path.resolve(__dirname, 'src/utils/'),
+ '@model-selection': path.resolve(__dirname, 'src/components/trays/model-selection/'),
+ '@share': path.resolve(__dirname, 'src/components/share/'),
+ '@utils': path.resolve(__dirname, 'src/utils/')
}
},