Skip to content

Commit

Permalink
Merge pull request #37 from openearth/feat/graph-generic-update-ux
Browse files Browse the repository at this point in the history
Update graph display and data loading to allow ux updates
  • Loading branch information
luisrodriguezgalvez authored Jan 28, 2025
2 parents 05ca520 + ca0e4fb commit 4983408
Show file tree
Hide file tree
Showing 11 changed files with 229 additions and 267 deletions.
4 changes: 2 additions & 2 deletions src/components/AppSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@
<v-card-title class="layer-card-title"> Data layers </v-card-title>
<v-list class="layer-list">
<v-list-item
v-for="dataset in datasetsInActiveTheme.filter(
(dataset) => dataset.id !== 'slp' && dataset.id !== 'cfhp'
v-for="dataset in this.datasetsInActiveTheme.filter(
({ id }) => id !== 'slp' && id !== 'cfhp'
)"
:key="dataset.id"
:title="dataset.title"
Expand Down
216 changes: 67 additions & 149 deletions src/components/ChartComponents/SeaLevelGraph.vue
Original file line number Diff line number Diff line change
@@ -1,163 +1,81 @@
<template>
<div ref="chartContainer" style="width: 100%; height: 100%"></div>
<v-chart :option="option" autoresize />
</template>

<script>
import { nextTick } from "vue";
import * as echarts from "echarts";
<script setup>
import { use } from "echarts/core";
import { CanvasRenderer } from "echarts/renderers";
import { BarChart } from "echarts/charts";
import {
LegendComponent,
TitleComponent,
TooltipComponent,
} from "echarts/components";
import { computed } from "vue";
import VChart from "vue-echarts";
export default {
props: {
graphData: {
type: Object,
required: true,
},
},
data: function () {
return {
colors: ["#000000", "#173c66", "#f79320", "#951b1e"], // Standard colors
};
use([
CanvasRenderer,
BarChart,
TitleComponent,
TooltipComponent,
LegendComponent,
]);
const props = defineProps({
graphData: {
type: Object,
required: true,
},
methods: {
generateSeries() {
const series = [];
// Loop through each scenario in the data and generate the series
this.graphData.scenarios.forEach((scenario, index) => {
const color = this.colors[index % this.colors.length]; // Use standard colors in a cycle
});
// Add low data as a transparent placeholder (baseline)
series.push({
name: `Low ${scenario.name}`,
type: "bar",
stack: scenario.name,
itemStyle: {
borderColor: "transparent",
color: "transparent",
},
emphasis: {
itemStyle: {
borderColor: "transparent",
color: "transparent",
},
},
data: scenario.msl_l.values,
animation: false,
silent: true,
barWidth: 3,
});
// Add medium sea level rise data
series.push({
name: `Medium ${scenario.name}`,
type: "bar",
stack: scenario.name,
color: color, // Use one of the standard colors
itemStyle: {
borderWidth: 0.2,
borderColor: "#000000",
},
data: scenario.msl_m.values,
animation: false,
silent: true,
barWidth: 3,
});
// Add high sea level rise data (top)
series.push({
name: `High ${scenario.name}`,
type: "bar",
stack: scenario.name,
color: color, // Use the same color as medium
itemStyle: {
borderWidth: 0.2,
borderColor: "#000000",
},
data: scenario.msl_h.values,
animation: false,
silent: true,
barWidth: 3,
});
const option = computed(() => ({
title: {
text: "Sea Level Rise",
left: "center",
},
xAxis: {
type: "category",
data: props.graphData.time, // Use time for x-axis
name: "Year",
nameLocation: "middle",
nameGap: 25,
},
yAxis: {
type: "value",
name: "Sea level rise [m]",
nameLocation: "middle",
nameGap: 30,
},
tooltip: {
trigger: "axis",
confine: false,
formatter: function (params) {
const formatValue = (value) => parseFloat(value).toFixed(2);
let tooltip = params[0].axisValue.bold() + "<br/>";
params.forEach((param) => {
tooltip += `${param.seriesName} : ${formatValue(param.value)} m<br/>`;
});
// Move the first three items to the end
// TODO: Etienne should provide them in the right order instead
const firstThreeItems = series.splice(0, 3);
series.push(...firstThreeItems);
return series;
return tooltip;
},
renderChart() {
const chartDom = this.$refs.chartContainer;
if (chartDom && chartDom.clientWidth && chartDom.clientHeight) {
const myChart = echarts.init(chartDom);
const option = {
title: {
text: "Sea Level Rise",
left: "center",
},
xAxis: {
type: "category",
data: this.graphData.time, // Use time for x-axis
name: "Year",
nameLocation: "middle",
nameGap: 25,
},
yAxis: {
type: "value",
name: "Sea level rise [m]",
nameLocation: "middle",
nameGap: 30,
},
tooltip: {
trigger: "axis",
confine: false,
formatter: function (params) {
const formatValue = (value) => parseFloat(value).toFixed(2);
let tooltip = params[0].axisValue.bold() + "<br/>";
params.forEach((param) => {
tooltip += `${param.seriesName} : ${formatValue(
param.value
)} m<br/>`;
});
return tooltip;
},
},
legend: {
data: this.graphData.scenarios.map(
(scenario) => `${scenario.name}`
),
selectedMode: false,
orient: "horizontal",
bottom: 0,
itemStyle: {
borderWidth: 0.5,
},
},
grid: {
top: "15%",
left: "5%",
right: "5%",
bottom: "15%",
containLabel: true,
},
series: this.generateSeries(),
};
myChart.setOption(option);
}
},
legend: {
data: props.graphData.scenarios,
selectedMode: false,
orient: "horizontal",
bottom: 0,
itemStyle: {
borderWidth: 0.5,
},
},
mounted() {
if (this.graphData && this.graphData.time) {
nextTick(() => {
this.renderChart();
});
window.addEventListener("resize", this.renderChart);
} else {
console.error("No valid sea level rise data provided.");
}
grid: {
top: "15%",
left: "5%",
right: "5%",
bottom: "15%",
containLabel: true,
},
};
series: props.graphData.values,
}));
</script>

<style></style>
13 changes: 9 additions & 4 deletions src/lib/geoserver_utils/get-feature-info.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,23 @@ export default async function getFeatureInfo({
bbox = [lng - radius, lat - radius, lng + radius, lat + radius].join(",");
}

const names = layers.flatMap(({ name }) => name);

const geoServerUrl = await buildGeoServerUrl({
url,
request: "GetFeatureInfo",
service: "WMS",
version: "1.1.1",
info_format: "application/json",
crs: "EPSG:4326",
layers: layers,
query_layers: layers,
layers: names,
query_layers: names,
width,
height,
x,
y,
bbox,
feature_count: 50,
feature_count: names.length,
});

return (
Expand All @@ -56,7 +58,10 @@ export default async function getFeatureInfo({
.then(({ features }) => features)
//map and send back only the greyIndex values
.then((features) =>
features.map((feature) => feature.properties.GRAY_INDEX)
layers.map((layer, index) => ({
...layer,
value: features[index].properties.GRAY_INDEX,
}))
)
.catch(() => undefined)
);
Expand Down
26 changes: 18 additions & 8 deletions src/lib/graphs.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import getGraphDataSlp from "@/lib/graphs/slp/get-graph-data-slp";
import { get, unzip } from "lodash-es";
import { openArray } from "zarr";
import { getSlpGraphData } from "@/lib/graphs/slp/get-graph-data-slp";

export const GRAPH_TYPES = {
FLOOD_EXTEND: "flood-extend-graph",
Expand Down Expand Up @@ -51,15 +51,20 @@ export const getGraphType = (id) =>
*/
export function getFeatureData(dataset, properties, values) {
switch (dataset) {
case "cba":
case "cba": {
return Object.entries(properties)
.filter(([key]) => key.includes(values.time))
.filter(
([key]) =>
key.toLowerCase().includes(values.time.toLowerCase()) &&
key.toLowerCase().includes(values.scenarios.toLowerCase())
)
.map(([name, value]) => {
return {
name,
name: name.split("\\")[0],
value,
};
});
}
case "cfhp": {
const scenarios =
values.scenarios !== "none"
Expand Down Expand Up @@ -103,17 +108,21 @@ export function getFeatureData(dataset, properties, values) {
/**
* Get data for a raster based dataset and location
* @param dataset
* @param lng
* @param lat
* @param coords
* @param props
* @returns {Promise<*|null>}
*/
export async function getRasterData(dataset, lng, lat) {
export async function getRasterData(dataset, coords, props) {
const { id } = dataset;

switch (id) {
case "slp":
try {
return await getGraphDataSlp(dataset, lng, lat);
return {
values: await getSlpGraphData(dataset, coords, props),
time: props.find(({ id }) => id === "time").values.sort(),
scenarios: props.find(({ id }) => id === "scenarios").values,
};
} catch (error) {
console.error("Error while fetching data from getGraphDataSlp:", error);
throw error;
Expand All @@ -128,6 +137,7 @@ export async function getRasterData(dataset, lng, lat) {
* Get data for a zarr based dataset
* @param dataset
* @param features
* @param props
* @returns {Promise<null>}
*/
export async function getZarrData(dataset, features, props) {
Expand Down
41 changes: 0 additions & 41 deletions src/lib/graphs/slp/create-series-structure-slp.js

This file was deleted.

Loading

0 comments on commit 4983408

Please sign in to comment.