From e7b29bb00b2da2ab96e61cd7dbe1881ece13c5b2 Mon Sep 17 00:00:00 2001 From: Anne Haley Date: Wed, 14 Aug 2024 16:58:17 +0000 Subject: [PATCH 01/40] feat: Add basic ProjectConfig component --- web/src/App.vue | 3 + web/src/api/rest.ts | 25 ++++ web/src/components/ProjectConfig.vue | 213 +++++++++++++++++++++++++++ web/src/storeFunctions.ts | 11 ++ 4 files changed, 252 insertions(+) create mode 100644 web/src/components/ProjectConfig.vue diff --git a/web/src/App.vue b/web/src/App.vue index 2dd46d92..9e5853b3 100644 --- a/web/src/App.vue +++ b/web/src/App.vue @@ -16,6 +16,7 @@ import MainDrawerContents from "./components/MainDrawerContents.vue"; import OptionsDrawerContents from "./components/OptionsDrawerContents.vue"; import ChartJS from "./components/ChartJS.vue"; import SimulationsPanel from "./components/SimulationsPanel.vue"; +import ProjectConfig from "./components/ProjectConfig.vue"; export default defineComponent({ components: { @@ -24,6 +25,7 @@ export default defineComponent({ OptionsDrawerContents, ChartJS, SimulationsPanel, + ProjectConfig, }, setup() { const drawer = ref(false); @@ -103,6 +105,7 @@ export default defineComponent({ /> UVDAT + { return (await apiClient.get("projects")).data.results; } +export async function createProject( + name: string, + default_map_center: number[], + default_map_zoom: number +): Promise { + return ( + await apiClient.post("projects/", { + name, + default_map_center, + default_map_zoom, + }) + ).data; +} + +export async function patchProject( + projectId: number, + data: object +): Promise { + return await apiClient.patch(`projects/${projectId}/`, data); +} + +export async function deleteProject(projectId: number): Promise { + return await apiClient.delete(`projects/${projectId}/`).data; +} + export async function getProjectDatasets( projectId: number ): Promise { diff --git a/web/src/components/ProjectConfig.vue b/web/src/components/ProjectConfig.vue new file mode 100644 index 00000000..107f24e7 --- /dev/null +++ b/web/src/components/ProjectConfig.vue @@ -0,0 +1,213 @@ + + + + + diff --git a/web/src/storeFunctions.ts b/web/src/storeFunctions.ts index 231d025f..460d0775 100644 --- a/web/src/storeFunctions.ts +++ b/web/src/storeFunctions.ts @@ -104,6 +104,17 @@ export function setMapCenter() { map.jumpTo({ center, zoom }); } +export function getCurrentMapPosition() { + const map = getMap(); + let center = [0, 0]; + let zoom = map.getZoom(); + const centerLngLat = map.getCenter(); + if (centerLngLat) center = [centerLngLat.lat, centerLngLat.lng]; + if (zoom) zoom = Math.floor(zoom); + else zoom = 1; + return { center, zoom }; +} + export function loadDatasets() { if (!currentProject.value) return; availableDatasets.value = undefined; From 13f00ead7791a53c42140276f11d984af9fc8ab5 Mon Sep 17 00:00:00 2001 From: Anne Haley Date: Mon, 16 Sep 2024 18:51:42 +0000 Subject: [PATCH 02/40] ui: Redesign main drawer contents --- web/src/App.vue | 34 +- web/src/components/DatasetList.vue | 296 +++++++++++++++++ web/src/components/MainDrawerContents.vue | 369 ++++++---------------- web/src/components/ProjectContents.vue | 127 ++++++++ web/src/types.ts | 7 + 5 files changed, 527 insertions(+), 306 deletions(-) create mode 100644 web/src/components/DatasetList.vue create mode 100644 web/src/components/ProjectContents.vue diff --git a/web/src/App.vue b/web/src/App.vue index 9e5853b3..15c01dec 100644 --- a/web/src/App.vue +++ b/web/src/App.vue @@ -16,7 +16,6 @@ import MainDrawerContents from "./components/MainDrawerContents.vue"; import OptionsDrawerContents from "./components/OptionsDrawerContents.vue"; import ChartJS from "./components/ChartJS.vue"; import SimulationsPanel from "./components/SimulationsPanel.vue"; -import ProjectConfig from "./components/ProjectConfig.vue"; export default defineComponent({ components: { @@ -25,10 +24,9 @@ export default defineComponent({ OptionsDrawerContents, ChartJS, SimulationsPanel, - ProjectConfig, }, setup() { - const drawer = ref(false); + const drawer = ref(true); const showError = computed(() => currentError.value !== undefined); function onReady() { @@ -43,9 +41,6 @@ export default defineComponent({ onMounted(onReady); watch(currentUser, onReady); - watch(currentProject, () => { - drawer.value = currentProject.value !== undefined; - }); return { login, @@ -99,23 +94,9 @@ export default defineComponent({ - + UVDAT - - -
{{ currentUser.first_name }} @@ -133,10 +114,9 @@ export default defineComponent({
@@ -177,12 +157,12 @@ export default defineComponent({ left: 250px; } .shifted-1 { - left: 300px; - width: calc(100% - 300px); + left: 350px; + width: calc(100% - 350px); } .shifted-2 { - left: 300px; + left: 350px; right: 300px; - width: calc(100% - 600px); + width: calc(100% - 650px); } diff --git a/web/src/components/DatasetList.vue b/web/src/components/DatasetList.vue new file mode 100644 index 00000000..9b785016 --- /dev/null +++ b/web/src/components/DatasetList.vue @@ -0,0 +1,296 @@ + + + + + diff --git a/web/src/components/MainDrawerContents.vue b/web/src/components/MainDrawerContents.vue index 987230ac..cc9de39c 100644 --- a/web/src/components/MainDrawerContents.vue +++ b/web/src/components/MainDrawerContents.vue @@ -1,305 +1,116 @@ diff --git a/web/src/types.ts b/web/src/types.ts index 282215e0..e18cbc87 100644 --- a/web/src/types.ts +++ b/web/src/types.ts @@ -38,6 +38,7 @@ export interface SourceRegion { export interface DerivedRegion { id: number; name: string; + description: string; project: number; metadata: object; boundary: object; @@ -62,6 +63,12 @@ export interface Project { owner: User; collaborators: User[]; followers: User[]; + item_counts: { + datasets: number; + regions: number; + charts: number; + simulations: number; + }; } export interface Feature { From 7afef9be6ecca1db97135dddca7fa3bf223770e2 Mon Sep 17 00:00:00 2001 From: Anne Haley Date: Mon, 16 Sep 2024 22:36:31 +0000 Subject: [PATCH 03/40] refactor: populate store vars when fetching for Project contents --- web/src/components/ProjectContents.vue | 39 +++++++++++++++++++++---- web/src/storeFunctions.ts | 40 +------------------------- 2 files changed, 34 insertions(+), 45 deletions(-) diff --git a/web/src/components/ProjectContents.vue b/web/src/components/ProjectContents.vue index 732420fa..7bc2b046 100644 --- a/web/src/components/ProjectContents.vue +++ b/web/src/components/ProjectContents.vue @@ -14,7 +14,15 @@ import { getProjectSimulationTypes, } from "@/api/rest"; import DatasetList from "./DatasetList.vue"; -import { currentChart, currentSimulationType } from "@/store"; +import { + availableCharts, + availableDatasets, + availableDerivedRegions, + availableSimulationTypes, + currentChart, + currentSimulationType, +} from "@/store"; +import { getDatasetLayerForDataObject, toggleDatasetLayer } from "@/layers"; export default { components: { DatasetList }, @@ -27,10 +35,26 @@ export default { // eslint-disable-next-line @typescript-eslint/no-explicit-any setup(props: any) { const panels = [ - { label: "Datasets", loadFunction: getProjectDatasets }, - { label: "Regions", loadFunction: getProjectDerivedRegions }, - { label: "Charts", loadFunction: getProjectCharts }, - { label: "Simulations", loadFunction: getProjectSimulationTypes }, + { + label: "Datasets", + loadFunction: getProjectDatasets, + storeVar: availableDatasets, + }, + { + label: "Regions", + loadFunction: getProjectDerivedRegions, + storeVar: availableDerivedRegions, + }, + { + label: "Charts", + loadFunction: getProjectCharts, + storeVar: availableCharts, + }, + { + label: "Simulations", + loadFunction: getProjectSimulationTypes, + storeVar: availableSimulationTypes, + }, ]; const openPanels: Ref = ref([]); @@ -43,7 +67,9 @@ export default { item: Dataset | DerivedRegion | Chart | SimulationType ) { if (panelLabel == "Regions") { - // TODO: select region + getDatasetLayerForDataObject(item as DerivedRegion).then((layer) => { + toggleDatasetLayer(layer); + }); } else if (panelLabel == "Charts") { currentChart.value = item as Chart; } else if (panelLabel == "Simulations") { @@ -57,6 +83,7 @@ export default { if (openPanels.value.includes(panel.label)) { panel.loadFunction(props.project.id).then((data) => { projectContents.value[panel.label] = data; + panel.storeVar.value = data; }); } }); diff --git a/web/src/storeFunctions.ts b/web/src/storeFunctions.ts index 460d0775..e64f9803 100644 --- a/web/src/storeFunctions.ts +++ b/web/src/storeFunctions.ts @@ -31,15 +31,7 @@ import { tooltipOverlay, clickedFeatureCandidates, } from "./store"; -import { Dataset } from "./types"; -import { - getProjectDatasets, - getProjects, - getDataset, - getProjectCharts, - getProjectSimulationTypes, - getProjectDerivedRegions, -} from "@/api/rest"; +import { getProjects, getDataset, getProjectDerivedRegions } from "@/api/rest"; import { datasetLayerFromMapLayerID, styleNetworkVectorTileLayer, @@ -115,32 +107,6 @@ export function getCurrentMapPosition() { return { center, zoom }; } -export function loadDatasets() { - if (!currentProject.value) return; - availableDatasets.value = undefined; - getProjectDatasets(currentProject.value.id).then((data: Dataset[]) => { - availableDatasets.value = data; - }); -} - -export function loadCharts() { - if (!currentProject.value) return; - availableCharts.value = undefined; - currentChart.value = undefined; - getProjectCharts(currentProject.value.id).then((charts) => { - availableCharts.value = charts; - }); -} - -export function loadSimulationTypes() { - if (!currentProject.value) return; - availableSimulationTypes.value = undefined; - currentSimulationType.value = undefined; - getProjectSimulationTypes(currentProject.value.id).then((sims) => { - availableSimulationTypes.value = sims; - }); -} - export async function loadDerivedRegions() { if (!currentProject.value) { return; @@ -199,10 +165,6 @@ export function clearCurrentNetwork() { watch(currentProject, () => { clearState(); setMapCenter(); - loadDatasets(); - loadCharts(); - loadSimulationTypes(); - loadDerivedRegions(); }); watch(currentDataset, () => { rasterTooltipEnabled.value = false; From b84303d806776500b20a29191ee2ad8c814da193 Mon Sep 17 00:00:00 2001 From: Anne Haley Date: Mon, 16 Sep 2024 22:40:39 +0000 Subject: [PATCH 04/40] feat: Toggle dataset layers with maplibre --- web/src/components/DatasetList.vue | 36 +++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/web/src/components/DatasetList.vue b/web/src/components/DatasetList.vue index 9b785016..cc17e700 100644 --- a/web/src/components/DatasetList.vue +++ b/web/src/components/DatasetList.vue @@ -2,8 +2,13 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { onMounted, ref, Ref, computed } from "vue"; import { Dataset } from "@/types"; -import { selectedDatasets } from "../store"; +import { + availableDatasetLayers, + currentDataset, + selectedDatasets, +} from "../store"; import { getDatasetLayers } from "@/api/rest"; +import { toggleDatasetLayer } from "@/layers"; export default { props: { @@ -79,17 +84,36 @@ export default { } function toggleDatasets(show: unknown, datasets: Dataset[]) { - datasets.forEach((dataset) => { + datasets.forEach(async (dataset) => { + // Ensure layer index is set + dataset.current_layer_index = dataset.current_layer_index || 0; + if (dataset.map_layers === undefined) { + dataset.map_layers = await getDatasetLayers(dataset.id); + availableDatasetLayers.value = [ + ...availableDatasetLayers.value, + ...dataset.map_layers, + ]; + } + let layer = undefined; + if ( + dataset.map_layers !== undefined && + dataset.current_layer_index !== undefined + ) { + layer = dataset.map_layers[dataset.current_layer_index]; + } if (show && !selectedIds.value.includes(dataset.id)) { selectedDatasets.value.push(dataset); - } else if (!show) { + if (layer) toggleDatasetLayer(layer); + } else if (!show && selectedIds.value.includes(dataset.id)) { + if (currentDataset.value?.id === dataset.id) { + currentDataset.value = undefined; + } selectedDatasets.value = selectedDatasets.value.filter((d) => { d.id != dataset.id; }); + if (layer) toggleDatasetLayer(layer); } }); - // TODO: Pair program with Jake - // Update map layers with selected datasets } onMounted(fetchAllLayers); @@ -238,7 +262,7 @@ export default { Date: Mon, 16 Sep 2024 22:41:01 +0000 Subject: [PATCH 05/40] fix: Add matplotlib to requirements for raster colormaps --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 5d7bd986..0062c0b2 100644 --- a/setup.py +++ b/setup.py @@ -47,6 +47,7 @@ 'djangorestframework==3.15.2', 'django-large-image==0.10.0', 'drf-yasg==1.21.7', + 'matplotlib==3.9.2', # for raster colormaps 'osmnx==1.9.4', 'geopandas==0.14.4', 'networkx==3.3', From 407eccf53eb68b6d3b60579c6cc35baf0d07eac1 Mon Sep 17 00:00:00 2001 From: Anne Haley Date: Tue, 17 Sep 2024 13:18:26 +0000 Subject: [PATCH 06/40] fix: change loading behavior of Project contents panels --- web/src/components/ProjectContents.vue | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/web/src/components/ProjectContents.vue b/web/src/components/ProjectContents.vue index 7bc2b046..5d897572 100644 --- a/web/src/components/ProjectContents.vue +++ b/web/src/components/ProjectContents.vue @@ -78,9 +78,11 @@ export default { } watch(openPanels, () => { - projectContents.value = {}; panels.forEach((panel) => { - if (openPanels.value.includes(panel.label)) { + if ( + openPanels.value.includes(panel.label) && + !projectContents.value[panel.label]?.length + ) { panel.loadFunction(props.project.id).then((data) => { projectContents.value[panel.label] = data; panel.storeVar.value = data; From 58f59a4b0cae192aba5a091e8288cac80e84115b Mon Sep 17 00:00:00 2001 From: Anne Haley Date: Wed, 18 Sep 2024 13:27:27 +0000 Subject: [PATCH 07/40] fix: adjust map state watchers --- web/src/storeFunctions.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/web/src/storeFunctions.ts b/web/src/storeFunctions.ts index e64f9803..5761aca6 100644 --- a/web/src/storeFunctions.ts +++ b/web/src/storeFunctions.ts @@ -33,6 +33,7 @@ import { } from "./store"; import { getProjects, getDataset, getProjectDerivedRegions } from "@/api/rest"; import { + clearMapLayers, datasetLayerFromMapLayerID, styleNetworkVectorTileLayer, updateBaseLayer, @@ -165,6 +166,7 @@ export function clearCurrentNetwork() { watch(currentProject, () => { clearState(); setMapCenter(); + clearMapLayers(); }); watch(currentDataset, () => { rasterTooltipEnabled.value = false; From e7e0e3ce16fc15b0cda5b0aadc0daf699c8335c0 Mon Sep 17 00:00:00 2001 From: Anne Haley Date: Wed, 18 Sep 2024 14:37:01 +0000 Subject: [PATCH 08/40] ui: Set primary color to blue --- web/src/main.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/web/src/main.ts b/web/src/main.ts index 54d6a980..3fc860d7 100644 --- a/web/src/main.ts +++ b/web/src/main.ts @@ -2,6 +2,7 @@ import { createApp } from "vue"; import App from "./App.vue"; // Vuetify import "vuetify/styles"; +import colors from "vuetify/lib/util/colors"; import { createVuetify } from "vuetify"; import * as components from "vuetify/components"; import * as directives from "vuetify/directives"; @@ -12,6 +13,15 @@ import "@mdi/font/css/materialdesignicons.css"; const vuetify = createVuetify({ components, directives, + theme: { + themes: { + light: { + colors: { + primary: colors.blue.darken3, + }, + }, + }, + }, }); restoreLogin().then(createApp(App).use(vuetify).mount("#app")); From 8977ada2e19a2e543c13f38a63c12e1ff39004b3 Mon Sep 17 00:00:00 2001 From: Anne Haley Date: Wed, 18 Sep 2024 14:56:26 +0000 Subject: [PATCH 09/40] deps: Upgrade vuetify --- web/package-lock.json | 507 ++++++++++++++++++++---------------------- web/package.json | 4 +- 2 files changed, 249 insertions(+), 262 deletions(-) diff --git a/web/package-lock.json b/web/package-lock.json index 23a60466..d4e64a89 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -21,7 +21,7 @@ "vue": "^3.2.13", "vue-chartjs": "^5.2.0", "vuedraggable": "^4.1.0", - "vuetify": "^3.3.16" + "vuetify": "^3.7.2" }, "devDependencies": { "@types/lodash": "^4.17.7", @@ -416,19 +416,17 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", - "dev": true, + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true, + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", "engines": { "node": ">=6.9.0" } @@ -486,9 +484,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "dependencies": { + "@babel/types": "^7.25.6" + }, "bin": { "parser": "bin/babel-parser.js" }, @@ -1717,13 +1718,12 @@ } }, "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" }, "engines": { @@ -1913,10 +1913,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.18", @@ -5469,49 +5468,60 @@ "dev": true }, "node_modules/@vue/compiler-core": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.47.tgz", - "integrity": "sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.6.tgz", + "integrity": "sha512-r+gNu6K4lrvaQLQGmf+1gc41p3FO2OUJyWmNqaIITaJU6YFiV5PtQSFZt8jfztYyARwqhoCayjprC7KMvT3nRA==", "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/shared": "3.2.47", + "@babel/parser": "^7.25.3", + "@vue/shared": "3.5.6", + "entities": "^4.5.0", "estree-walker": "^2.0.2", - "source-map": "^0.6.1" + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-core/node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, "node_modules/@vue/compiler-dom": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.47.tgz", - "integrity": "sha512-dBBnEHEPoftUiS03a4ggEig74J2YBZ2UIeyfpcRM2tavgMWo4bsEfgCGsu+uJIL/vax9S+JztH8NmQerUo7shQ==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.6.tgz", + "integrity": "sha512-xRXqxDrIqK8v8sSScpistyYH0qYqxakpsIvqMD2e5sV/PXQ1mTwtXp4k42yHK06KXxKSmitop9e45Ui/3BrTEw==", "dependencies": { - "@vue/compiler-core": "3.2.47", - "@vue/shared": "3.2.47" + "@vue/compiler-core": "3.5.6", + "@vue/shared": "3.5.6" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.47.tgz", - "integrity": "sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ==", - "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.47", - "@vue/compiler-dom": "3.2.47", - "@vue/compiler-ssr": "3.2.47", - "@vue/reactivity-transform": "3.2.47", - "@vue/shared": "3.2.47", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.6.tgz", + "integrity": "sha512-pjWJ8Kj9TDHlbF5LywjVso+BIxCY5wVOLhkEXRhuCHDxPFIeX1zaFefKs8RYoHvkSMqRWt93a0f2gNJVJixHwg==", + "dependencies": { + "@babel/parser": "^7.25.3", + "@vue/compiler-core": "3.5.6", + "@vue/compiler-dom": "3.5.6", + "@vue/compiler-ssr": "3.5.6", + "@vue/shared": "3.5.6", "estree-walker": "^2.0.2", - "magic-string": "^0.25.7", - "postcss": "^8.1.10", - "source-map": "^0.6.1" + "magic-string": "^0.30.11", + "postcss": "^8.4.47", + "source-map-js": "^1.2.0" } }, "node_modules/@vue/compiler-ssr": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.47.tgz", - "integrity": "sha512-wVXC+gszhulcMD8wpxMsqSOpvDZ6xKXSVWkf50Guf/S+28hTAXPDYRTbLQ3EDkOP5Xz/+SY37YiwDquKbJOgZw==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.6.tgz", + "integrity": "sha512-VpWbaZrEOCqnmqjE83xdwegtr5qO/2OPUC6veWgvNqTJ3bYysz6vY3VqMuOijubuUYPRpG3OOKIh9TD0Stxb9A==", "dependencies": { - "@vue/compiler-dom": "3.2.47", - "@vue/shared": "3.2.47" + "@vue/compiler-dom": "3.5.6", + "@vue/shared": "3.5.6" } }, "node_modules/@vue/component-compiler-utils": { @@ -5597,60 +5607,49 @@ } }, "node_modules/@vue/reactivity": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.47.tgz", - "integrity": "sha512-7khqQ/75oyyg+N/e+iwV6lpy1f5wq759NdlS1fpAhFXa8VeAIKGgk2E/C4VF59lx5b+Ezs5fpp/5WsRYXQiKxQ==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.6.tgz", + "integrity": "sha512-shZ+KtBoHna5GyUxWfoFVBCVd7k56m6lGhk5e+J9AKjheHF6yob5eukssHRI+rzvHBiU1sWs/1ZhNbLExc5oYQ==", "dependencies": { - "@vue/shared": "3.2.47" - } - }, - "node_modules/@vue/reactivity-transform": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.47.tgz", - "integrity": "sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==", - "dependencies": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.47", - "@vue/shared": "3.2.47", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7" + "@vue/shared": "3.5.6" } }, "node_modules/@vue/runtime-core": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.47.tgz", - "integrity": "sha512-RZxbLQIRB/K0ev0K9FXhNbBzT32H9iRtYbaXb0ZIz2usLms/D55dJR2t6cIEUn6vyhS3ALNvNthI+Q95C+NOpA==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.6.tgz", + "integrity": "sha512-FpFULR6+c2lI+m1fIGONLDqPQO34jxV8g6A4wBOgne8eSRHP6PQL27+kWFIx5wNhhjkO7B4rgtsHAmWv7qKvbg==", "dependencies": { - "@vue/reactivity": "3.2.47", - "@vue/shared": "3.2.47" + "@vue/reactivity": "3.5.6", + "@vue/shared": "3.5.6" } }, "node_modules/@vue/runtime-dom": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.47.tgz", - "integrity": "sha512-ArXrFTjS6TsDei4qwNvgrdmHtD930KgSKGhS5M+j8QxXrDJYLqYw4RRcDy1bz1m1wMmb6j+zGLifdVHtkXA7gA==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.6.tgz", + "integrity": "sha512-SDPseWre45G38ENH2zXRAHL1dw/rr5qp91lS4lt/nHvMr0MhsbCbihGAWLXNB/6VfFOJe2O+RBRkXU+CJF7/sw==", "dependencies": { - "@vue/runtime-core": "3.2.47", - "@vue/shared": "3.2.47", - "csstype": "^2.6.8" + "@vue/reactivity": "3.5.6", + "@vue/runtime-core": "3.5.6", + "@vue/shared": "3.5.6", + "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.47.tgz", - "integrity": "sha512-dN9gc1i8EvmP9RCzvneONXsKfBRgqFeFZLurmHOveL7oH6HiFXJw5OGu294n1nHc/HMgTy6LulU/tv5/A7f/LA==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.6.tgz", + "integrity": "sha512-zivnxQnOnwEXVaT9CstJ64rZFXMS5ZkKxCjDQKiMSvUhXRzFLWZVbaBiNF4HGDqGNNsTgmjcCSmU6TB/0OOxLA==", "dependencies": { - "@vue/compiler-ssr": "3.2.47", - "@vue/shared": "3.2.47" + "@vue/compiler-ssr": "3.5.6", + "@vue/shared": "3.5.6" }, "peerDependencies": { - "vue": "3.2.47" + "vue": "3.5.6" } }, "node_modules/@vue/shared": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.47.tgz", - "integrity": "sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==" + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.6.tgz", + "integrity": "sha512-eidH0HInnL39z6wAt6SFIwBrvGOpDWsDxlw3rCgo1B+CQ1781WzQUSU3YjxgdkcJo9Q8S6LmXTkvI+cLHGkQfA==" }, "node_modules/@vue/vue-loader-v15": { "name": "vue-loader", @@ -7455,9 +7454,9 @@ } }, "node_modules/csstype": { - "version": "2.6.21", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", - "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "node_modules/d3-array": { "version": "1.2.4", @@ -10608,11 +10607,11 @@ } }, "node_modules/magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "version": "0.30.11", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", "dependencies": { - "sourcemap-codec": "^1.4.8" + "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/make-dir": { @@ -11000,9 +10999,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "funding": [ { "type": "github", @@ -11607,9 +11606,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" }, "node_modules/picomatch": { "version": "2.3.1", @@ -11683,9 +11682,9 @@ } }, "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "funding": [ { "type": "opencollective", @@ -11701,9 +11700,9 @@ } ], "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" @@ -13226,14 +13225,15 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, "engines": { "node": ">=0.10.0" } }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", "engines": { "node": ">=0.10.0" } @@ -13248,12 +13248,6 @@ "source-map": "^0.6.0" } }, - "node_modules/sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "deprecated": "Please use @jridgewell/sourcemap-codec instead" - }, "node_modules/spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", @@ -13727,7 +13721,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true, "engines": { "node": ">=4" } @@ -14182,15 +14175,23 @@ } }, "node_modules/vue": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.47.tgz", - "integrity": "sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.6.tgz", + "integrity": "sha512-zv+20E2VIYbcJOzJPUWp03NOGFhMmpCKOfSxVTmCYyYFFko48H9tmuQFzYj7tu4qX1AeXlp9DmhIP89/sSxxhw==", "dependencies": { - "@vue/compiler-dom": "3.2.47", - "@vue/compiler-sfc": "3.2.47", - "@vue/runtime-dom": "3.2.47", - "@vue/server-renderer": "3.2.47", - "@vue/shared": "3.2.47" + "@vue/compiler-dom": "3.5.6", + "@vue/compiler-sfc": "3.5.6", + "@vue/runtime-dom": "3.5.6", + "@vue/server-renderer": "3.5.6", + "@vue/shared": "3.5.6" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/vue-chartjs": { @@ -14447,9 +14448,9 @@ "integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w==" }, "node_modules/vuetify": { - "version": "3.3.16", - "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.3.16.tgz", - "integrity": "sha512-vVfUroT5lSU+yOZAf7JlGm2j3dCR4BQml8Al27+/Uh0YW+97/CyUqOzo6IzMCt/bXLvnRerJ5fCAJtQYWnwfLA==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.7.2.tgz", + "integrity": "sha512-q0WTcRG977+a9Dqhb8TOaPm+Xmvj0oVhnBJhAdHWFSov3HhHTTxlH2nXP/GBTXZuuMHDbBeIWFuUR2/1Fx0PPw==", "engines": { "node": "^12.20 || >=14.13" }, @@ -14459,10 +14460,9 @@ }, "peerDependencies": { "typescript": ">=4.7", - "vite-plugin-vuetify": "^1.0.0-alpha.12", - "vue": "^3.2.0", - "vue-i18n": "^9.0.0", - "webpack-plugin-vuetify": "^2.0.0-alpha.11" + "vite-plugin-vuetify": ">=1.0.0", + "vue": "^3.3.0", + "webpack-plugin-vuetify": ">=2.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -14471,9 +14471,6 @@ "vite-plugin-vuetify": { "optional": true }, - "vue-i18n": { - "optional": true - }, "webpack-plugin-vuetify": { "optional": true } @@ -15505,16 +15502,14 @@ } }, "@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", - "dev": true + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==" }, "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==" }, "@babel/helper-validator-option": { "version": "7.21.0", @@ -15557,9 +15552,12 @@ } }, "@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==" + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", + "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", + "requires": { + "@babel/types": "^7.25.6" + } }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.18.6", @@ -16386,13 +16384,12 @@ } }, "@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", - "dev": true, + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", + "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", "requires": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-string-parser": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" } }, @@ -16529,10 +16526,9 @@ } }, "@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, "@jridgewell/trace-mapping": { "version": "0.3.18", @@ -19360,49 +19356,56 @@ } }, "@vue/compiler-core": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.47.tgz", - "integrity": "sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.6.tgz", + "integrity": "sha512-r+gNu6K4lrvaQLQGmf+1gc41p3FO2OUJyWmNqaIITaJU6YFiV5PtQSFZt8jfztYyARwqhoCayjprC7KMvT3nRA==", "requires": { - "@babel/parser": "^7.16.4", - "@vue/shared": "3.2.47", + "@babel/parser": "^7.25.3", + "@vue/shared": "3.5.6", + "entities": "^4.5.0", "estree-walker": "^2.0.2", - "source-map": "^0.6.1" + "source-map-js": "^1.2.0" + }, + "dependencies": { + "entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==" + } } }, "@vue/compiler-dom": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.47.tgz", - "integrity": "sha512-dBBnEHEPoftUiS03a4ggEig74J2YBZ2UIeyfpcRM2tavgMWo4bsEfgCGsu+uJIL/vax9S+JztH8NmQerUo7shQ==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.6.tgz", + "integrity": "sha512-xRXqxDrIqK8v8sSScpistyYH0qYqxakpsIvqMD2e5sV/PXQ1mTwtXp4k42yHK06KXxKSmitop9e45Ui/3BrTEw==", "requires": { - "@vue/compiler-core": "3.2.47", - "@vue/shared": "3.2.47" + "@vue/compiler-core": "3.5.6", + "@vue/shared": "3.5.6" } }, "@vue/compiler-sfc": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.47.tgz", - "integrity": "sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ==", - "requires": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.47", - "@vue/compiler-dom": "3.2.47", - "@vue/compiler-ssr": "3.2.47", - "@vue/reactivity-transform": "3.2.47", - "@vue/shared": "3.2.47", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.6.tgz", + "integrity": "sha512-pjWJ8Kj9TDHlbF5LywjVso+BIxCY5wVOLhkEXRhuCHDxPFIeX1zaFefKs8RYoHvkSMqRWt93a0f2gNJVJixHwg==", + "requires": { + "@babel/parser": "^7.25.3", + "@vue/compiler-core": "3.5.6", + "@vue/compiler-dom": "3.5.6", + "@vue/compiler-ssr": "3.5.6", + "@vue/shared": "3.5.6", "estree-walker": "^2.0.2", - "magic-string": "^0.25.7", - "postcss": "^8.1.10", - "source-map": "^0.6.1" + "magic-string": "^0.30.11", + "postcss": "^8.4.47", + "source-map-js": "^1.2.0" } }, "@vue/compiler-ssr": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.47.tgz", - "integrity": "sha512-wVXC+gszhulcMD8wpxMsqSOpvDZ6xKXSVWkf50Guf/S+28hTAXPDYRTbLQ3EDkOP5Xz/+SY37YiwDquKbJOgZw==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.6.tgz", + "integrity": "sha512-VpWbaZrEOCqnmqjE83xdwegtr5qO/2OPUC6veWgvNqTJ3bYysz6vY3VqMuOijubuUYPRpG3OOKIh9TD0Stxb9A==", "requires": { - "@vue/compiler-dom": "3.2.47", - "@vue/shared": "3.2.47" + "@vue/compiler-dom": "3.5.6", + "@vue/shared": "3.5.6" } }, "@vue/component-compiler-utils": { @@ -19472,57 +19475,46 @@ } }, "@vue/reactivity": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.47.tgz", - "integrity": "sha512-7khqQ/75oyyg+N/e+iwV6lpy1f5wq759NdlS1fpAhFXa8VeAIKGgk2E/C4VF59lx5b+Ezs5fpp/5WsRYXQiKxQ==", - "requires": { - "@vue/shared": "3.2.47" - } - }, - "@vue/reactivity-transform": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.47.tgz", - "integrity": "sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.6.tgz", + "integrity": "sha512-shZ+KtBoHna5GyUxWfoFVBCVd7k56m6lGhk5e+J9AKjheHF6yob5eukssHRI+rzvHBiU1sWs/1ZhNbLExc5oYQ==", "requires": { - "@babel/parser": "^7.16.4", - "@vue/compiler-core": "3.2.47", - "@vue/shared": "3.2.47", - "estree-walker": "^2.0.2", - "magic-string": "^0.25.7" + "@vue/shared": "3.5.6" } }, "@vue/runtime-core": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.47.tgz", - "integrity": "sha512-RZxbLQIRB/K0ev0K9FXhNbBzT32H9iRtYbaXb0ZIz2usLms/D55dJR2t6cIEUn6vyhS3ALNvNthI+Q95C+NOpA==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.6.tgz", + "integrity": "sha512-FpFULR6+c2lI+m1fIGONLDqPQO34jxV8g6A4wBOgne8eSRHP6PQL27+kWFIx5wNhhjkO7B4rgtsHAmWv7qKvbg==", "requires": { - "@vue/reactivity": "3.2.47", - "@vue/shared": "3.2.47" + "@vue/reactivity": "3.5.6", + "@vue/shared": "3.5.6" } }, "@vue/runtime-dom": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.47.tgz", - "integrity": "sha512-ArXrFTjS6TsDei4qwNvgrdmHtD930KgSKGhS5M+j8QxXrDJYLqYw4RRcDy1bz1m1wMmb6j+zGLifdVHtkXA7gA==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.6.tgz", + "integrity": "sha512-SDPseWre45G38ENH2zXRAHL1dw/rr5qp91lS4lt/nHvMr0MhsbCbihGAWLXNB/6VfFOJe2O+RBRkXU+CJF7/sw==", "requires": { - "@vue/runtime-core": "3.2.47", - "@vue/shared": "3.2.47", - "csstype": "^2.6.8" + "@vue/reactivity": "3.5.6", + "@vue/runtime-core": "3.5.6", + "@vue/shared": "3.5.6", + "csstype": "^3.1.3" } }, "@vue/server-renderer": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.47.tgz", - "integrity": "sha512-dN9gc1i8EvmP9RCzvneONXsKfBRgqFeFZLurmHOveL7oH6HiFXJw5OGu294n1nHc/HMgTy6LulU/tv5/A7f/LA==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.6.tgz", + "integrity": "sha512-zivnxQnOnwEXVaT9CstJ64rZFXMS5ZkKxCjDQKiMSvUhXRzFLWZVbaBiNF4HGDqGNNsTgmjcCSmU6TB/0OOxLA==", "requires": { - "@vue/compiler-ssr": "3.2.47", - "@vue/shared": "3.2.47" + "@vue/compiler-ssr": "3.5.6", + "@vue/shared": "3.5.6" } }, "@vue/shared": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.47.tgz", - "integrity": "sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==" + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.6.tgz", + "integrity": "sha512-eidH0HInnL39z6wAt6SFIwBrvGOpDWsDxlw3rCgo1B+CQ1781WzQUSU3YjxgdkcJo9Q8S6LmXTkvI+cLHGkQfA==" }, "@vue/vue-loader-v15": { "version": "npm:vue-loader@15.11.1", @@ -20869,9 +20861,9 @@ } }, "csstype": { - "version": "2.6.21", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", - "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, "d3-array": { "version": "1.2.4", @@ -23237,11 +23229,11 @@ } }, "magic-string": { - "version": "0.25.9", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", - "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "version": "0.30.11", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.11.tgz", + "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==", "requires": { - "sourcemap-codec": "^1.4.8" + "@jridgewell/sourcemap-codec": "^1.5.0" } }, "make-dir": { @@ -23547,9 +23539,9 @@ } }, "nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==" + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==" }, "natural-compare": { "version": "1.4.0", @@ -23999,9 +23991,9 @@ } }, "picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" }, "picomatch": { "version": "2.3.1", @@ -24067,13 +24059,13 @@ } }, "postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "requires": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" } }, "postcss-calc": { @@ -25161,12 +25153,13 @@ "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true }, "source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==" }, "source-map-support": { "version": "0.5.21", @@ -25178,11 +25171,6 @@ "source-map": "^0.6.0" } }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" - }, "spdx-correct": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", @@ -25544,8 +25532,7 @@ "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", - "dev": true + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" }, "to-regex-range": { "version": "5.0.1", @@ -25870,15 +25857,15 @@ } }, "vue": { - "version": "3.2.47", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.47.tgz", - "integrity": "sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ==", + "version": "3.5.6", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.6.tgz", + "integrity": "sha512-zv+20E2VIYbcJOzJPUWp03NOGFhMmpCKOfSxVTmCYyYFFko48H9tmuQFzYj7tu4qX1AeXlp9DmhIP89/sSxxhw==", "requires": { - "@vue/compiler-dom": "3.2.47", - "@vue/compiler-sfc": "3.2.47", - "@vue/runtime-dom": "3.2.47", - "@vue/server-renderer": "3.2.47", - "@vue/shared": "3.2.47" + "@vue/compiler-dom": "3.5.6", + "@vue/compiler-sfc": "3.5.6", + "@vue/runtime-dom": "3.5.6", + "@vue/server-renderer": "3.5.6", + "@vue/shared": "3.5.6" } }, "vue-chartjs": { @@ -26072,9 +26059,9 @@ } }, "vuetify": { - "version": "3.3.16", - "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.3.16.tgz", - "integrity": "sha512-vVfUroT5lSU+yOZAf7JlGm2j3dCR4BQml8Al27+/Uh0YW+97/CyUqOzo6IzMCt/bXLvnRerJ5fCAJtQYWnwfLA==", + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.7.2.tgz", + "integrity": "sha512-q0WTcRG977+a9Dqhb8TOaPm+Xmvj0oVhnBJhAdHWFSov3HhHTTxlH2nXP/GBTXZuuMHDbBeIWFuUR2/1Fx0PPw==", "requires": {} }, "watchpack": { diff --git a/web/package.json b/web/package.json index 2aae0298..c6595f07 100644 --- a/web/package.json +++ b/web/package.json @@ -10,8 +10,8 @@ }, "dependencies": { "@mdi/font": "^7.2.96", - "@turf/turf": "^7.1.0", "@resonant/oauth-client": "^0.9.0", + "@turf/turf": "^7.1.0", "axios": "^1.4.0", "buffer": "^6.0.3", "core-js": "^3.8.3", @@ -22,7 +22,7 @@ "vue": "^3.2.13", "vue-chartjs": "^5.2.0", "vuedraggable": "^4.1.0", - "vuetify": "^3.3.16" + "vuetify": "^3.7.2" }, "devDependencies": { "@types/lodash": "^4.17.7", From bb2185903fba8ee4189c415206ed8a24250233fb Mon Sep 17 00:00:00 2001 From: Anne Haley Date: Thu, 19 Sep 2024 15:14:24 +0000 Subject: [PATCH 10/40] feat: Add Dataset selection panel to Project Config page --- uvdat/core/rest/project.py | 20 +- web/src/App.vue | 70 ++-- web/src/api/rest.ts | 20 + web/src/components/DatasetList.vue | 216 +++++----- web/src/components/MainDrawerContents.vue | 24 +- web/src/components/ProjectConfig.vue | 485 ++++++++++++++-------- web/src/components/ProjectContents.vue | 56 ++- web/src/store.ts | 1 + 8 files changed, 557 insertions(+), 335 deletions(-) diff --git a/uvdat/core/rest/project.py b/uvdat/core/rest/project.py index 448f943c..96de476b 100644 --- a/uvdat/core/rest/project.py +++ b/uvdat/core/rest/project.py @@ -2,10 +2,11 @@ from django.http import HttpResponse from rest_framework.decorators import action from rest_framework.viewsets import ModelViewSet +from rest_framework.response import Response -from uvdat.core.models import Project +from uvdat.core.models import Dataset, Project from uvdat.core.rest.access_control import GuardianFilter, GuardianPermission -from uvdat.core.rest.serializers import ProjectSerializer +from uvdat.core.rest.serializers import DatasetSerializer, ProjectSerializer from uvdat.core.tasks.osmnx import load_roads @@ -21,6 +22,21 @@ def perform_create(self, serializer): user: User = self.request.user project.set_permissions(owner=user) + def partial_update(self, request, id): + project = self.get_object() + project.datasets.set( + Dataset.objects.filter( + id__in=request.data.get('dataset_ids') + ) + ) + project.save() + response = ProjectSerializer(project).data + response.update(datasets=[ + DatasetSerializer(dataset).data + for dataset in project.datasets.all() + ]) + return Response(response, status=200) + @action(detail=True, methods=['get']) def regions(self, request, **kwargs): project = self.get_object() diff --git a/web/src/App.vue b/web/src/App.vue index 15c01dec..75a93fc2 100644 --- a/web/src/App.vue +++ b/web/src/App.vue @@ -8,6 +8,7 @@ import { availableProjects, currentChart, currentSimulationType, + projectConfigMode, } from "./store"; import { oauthClient, logout } from "./api/auth"; import { loadProjects } from "./storeFunctions"; @@ -16,6 +17,7 @@ import MainDrawerContents from "./components/MainDrawerContents.vue"; import OptionsDrawerContents from "./components/OptionsDrawerContents.vue"; import ChartJS from "./components/ChartJS.vue"; import SimulationsPanel from "./components/SimulationsPanel.vue"; +import ProjectConfig from "./components/ProjectConfig.vue"; export default defineComponent({ components: { @@ -24,6 +26,7 @@ export default defineComponent({ OptionsDrawerContents, ChartJS, SimulationsPanel, + ProjectConfig, }, setup() { const drawer = ref(true); @@ -54,6 +57,7 @@ export default defineComponent({ showError, currentChart, currentSimulationType, + projectConfigMode, }; }, }); @@ -94,7 +98,10 @@ export default defineComponent({ - + UVDAT
@@ -113,35 +120,38 @@ export default defineComponent({
- - - - - - -
- - - + +
+ + + + + + +
+ + + +
diff --git a/web/src/api/rest.ts b/web/src/api/rest.ts index 36a6becd..f7c7fb5a 100644 --- a/web/src/api/rest.ts +++ b/web/src/api/rest.ts @@ -1,5 +1,6 @@ import { apiClient } from "./auth"; import { + User, Project, Dataset, NetworkNode, @@ -12,6 +13,10 @@ import { Network, } from "@/types"; +export async function getUsers(): Promise { + return (await apiClient.get(`users`)).data.results; +} + export async function getProjects(): Promise { return (await apiClient.get("projects")).data.results; } @@ -47,6 +52,17 @@ export async function getProjectDatasets( return (await apiClient.get(`datasets?project=${projectId}`)).data.results; } +export async function setProjectDatasets( + projectId: number, + datasetIds: number[] +): Promise { + return ( + await apiClient.patch(`projects/${projectId}/`, { + dataset_ids: datasetIds, + }) + ).data; +} + export async function getProjectCharts(projectId: number): Promise { return (await apiClient.get(`charts?project=${projectId}`)).data.results; } @@ -65,6 +81,10 @@ export async function getProjectSimulationTypes( .data; } +export async function getDatasets(): Promise { + return (await apiClient.get(`datasets`)).data.results; +} + export async function getDataset(datasetId: number): Promise { return (await apiClient.get(`datasets/${datasetId}`)).data; } diff --git a/web/src/components/DatasetList.vue b/web/src/components/DatasetList.vue index cc17e700..b2d783dc 100644 --- a/web/src/components/DatasetList.vue +++ b/web/src/components/DatasetList.vue @@ -1,14 +1,8 @@ diff --git a/web/src/components/MainDrawerContents.vue b/web/src/components/MainDrawerContents.vue index cc9de39c..0c270439 100644 --- a/web/src/components/MainDrawerContents.vue +++ b/web/src/components/MainDrawerContents.vue @@ -1,6 +1,6 @@ diff --git a/web/src/components/ProjectContents.vue b/web/src/components/ProjectContents.vue index 5d897572..5f4f2f4b 100644 --- a/web/src/components/ProjectContents.vue +++ b/web/src/components/ProjectContents.vue @@ -1,5 +1,5 @@ + + + + diff --git a/web/src/components/DatasetList.vue b/web/src/components/DatasetList.vue index 38a8f5b8..fdd24cfa 100644 --- a/web/src/components/DatasetList.vue +++ b/web/src/components/DatasetList.vue @@ -1,6 +1,6 @@