diff --git a/package-lock.json b/package-lock.json
index 35ad4d9fc..c4e010aa8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,7 +8,7 @@
"name": "fews-weboc",
"version": "1.1.0",
"dependencies": {
- "@deltares/fews-pi-requests": "^1.2.6",
+ "@deltares/fews-pi-requests": "^1.2.7",
"@deltares/fews-ssd-requests": "^1.0.1",
"@deltares/fews-ssd-webcomponent": "^1.0.1",
"@deltares/fews-web-oc-charts": "^3.0.3-beta.6",
@@ -122,9 +122,9 @@
}
},
"node_modules/@deltares/fews-pi-requests": {
- "version": "1.2.6",
- "resolved": "https://registry.npmjs.org/@deltares/fews-pi-requests/-/fews-pi-requests-1.2.6.tgz",
- "integrity": "sha512-fQRQb7KItCsK6BGzeQ29z9LzqcgtRvj9zyTpSb9gNz0pOg3IOay0ISAyRtohz8jsfOLobNQa2iSrXFflBzFeyQ==",
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@deltares/fews-pi-requests/-/fews-pi-requests-1.2.7.tgz",
+ "integrity": "sha512-H7irlul2mnn85R0RSkDBvKM9qMFpfRzZuLQFz82Q7aeNOZ3IuDOhhe5hVknLAdg3w2Z5iaDq6MLZ4D5ju9PMtQ==",
"license": "MIT",
"dependencies": {
"@deltares/fews-web-oc-utils": "^1.0.0"
diff --git a/package.json b/package.json
index 01e59a9a5..f08a7ae45 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,7 @@
"test-ct": "playwright test -c playwright-ct.config.ts"
},
"dependencies": {
- "@deltares/fews-pi-requests": "^1.2.6",
+ "@deltares/fews-pi-requests": "^1.2.7",
"@deltares/fews-ssd-requests": "^1.0.1",
"@deltares/fews-ssd-webcomponent": "^1.0.1",
"@deltares/fews-web-oc-charts": "^3.0.3-beta.6",
diff --git a/src/components/spatialdisplay/SpatialDisplayComponent.vue b/src/components/spatialdisplay/SpatialDisplayComponent.vue
index ac3591762..c7100aef2 100644
--- a/src/components/spatialdisplay/SpatialDisplayComponent.vue
+++ b/src/components/spatialdisplay/SpatialDisplayComponent.vue
@@ -39,7 +39,8 @@
/>
-
+
+
{
emit('update:currentTime', currentTime.value)
})
+const { tooltip } = useLocationTooltip(baseUrl, () =>
+ props.filterIds.length && props.locationId
+ ? {
+ filterId: props.filterIds[0],
+ locationId: props.locationId,
+ }
+ : undefined,
+)
+
function setLayerOptions(): void {
if (props.layerName) {
layerOptions.value = {
@@ -489,4 +501,8 @@ function onCoordinateMoved(lat: number, lng: number): void {
.maplibregl-ctrl-bottom-left {
bottom: v-bind('offsetBottomControls') !important;
}
+
+.control-group :deep(.v-slide-group__content) {
+ padding: 0 8px;
+}
diff --git a/src/components/spatialdisplay/SpatialTimeSeriesDisplay.vue b/src/components/spatialdisplay/SpatialTimeSeriesDisplay.vue
index cfb9ce817..bad4309fb 100644
--- a/src/components/spatialdisplay/SpatialTimeSeriesDisplay.vue
+++ b/src/components/spatialdisplay/SpatialTimeSeriesDisplay.vue
@@ -45,6 +45,7 @@
:elevation-chart-config="elevationChartDisplayconfig"
:current-time="props.currentTime"
:displayType="displayType"
+ :information-content="tooltip"
>
systemTimeStore.endTime,
)
+const { tooltip } = useLocationTooltip(baseUrl, () =>
+ isFilterActionsFilter(props.filter)
+ ? {
+ filterId: props.filter.filterId,
+ locationId: props.filter.locationIds,
+ }
+ : undefined,
+)
+
interface DisplayTypeItem {
icon: string
label: string
@@ -159,6 +171,14 @@ const displayTypeItems = computed(() => {
})
}
+ if (tooltip.value) {
+ displayItems.push({
+ icon: 'mdi-information',
+ label: 'Information',
+ value: DisplayType.Information,
+ })
+ }
+
return displayItems
})
diff --git a/src/components/timeseries/TimeSeriesComponent.vue b/src/components/timeseries/TimeSeriesComponent.vue
index 30ae3a114..2c88a750f 100644
--- a/src/components/timeseries/TimeSeriesComponent.vue
+++ b/src/components/timeseries/TimeSeriesComponent.vue
@@ -48,6 +48,12 @@
+
+
+
+
+
+
@@ -93,6 +99,7 @@ interface Props {
elevationChartConfig?: DisplayConfig
displayType: DisplayType
currentTime?: Date
+ informationContent?: string
}
const props = withDefaults(defineProps(), {
diff --git a/src/components/wms/TooltipPanel.vue b/src/components/wms/TooltipPanel.vue
new file mode 100644
index 000000000..9481a47fa
--- /dev/null
+++ b/src/components/wms/TooltipPanel.vue
@@ -0,0 +1,40 @@
+
+
+ mdi-information
+
+
+
+
+
+
+
+
+
diff --git a/src/lib/display/DisplayConfig.ts b/src/lib/display/DisplayConfig.ts
index 7c3b5ef61..5129e9878 100644
--- a/src/lib/display/DisplayConfig.ts
+++ b/src/lib/display/DisplayConfig.ts
@@ -5,6 +5,7 @@ export enum DisplayType {
TimeSeriesChart = 'TimeSeriesChart',
TimeSeriesTable = 'TimeSeriesTable',
ElevationChart = 'ElevationChart',
+ Information = 'Information',
}
export interface DisplayConfig {
diff --git a/src/lib/filters/index.ts b/src/lib/filters/index.ts
new file mode 100644
index 000000000..abd1ffa88
--- /dev/null
+++ b/src/lib/filters/index.ts
@@ -0,0 +1,18 @@
+import {
+ type filterActionsFilter,
+ type timeSeriesGridActionsFilter,
+} from '@deltares/fews-pi-requests'
+
+export type Filter = timeSeriesGridActionsFilter | filterActionsFilter
+
+export function isFilterActionsFilter(
+ filter: Filter,
+): filter is filterActionsFilter {
+ return (filter as filterActionsFilter).filterId !== undefined
+}
+
+export function isTimeSeriesGridActionsFilter(
+ filter: Filter,
+): filter is timeSeriesGridActionsFilter {
+ return (filter as timeSeriesGridActionsFilter).x !== undefined
+}
diff --git a/src/services/useDisplayConfig/index.ts b/src/services/useDisplayConfig/index.ts
index 89a623f1d..a5334b337 100644
--- a/src/services/useDisplayConfig/index.ts
+++ b/src/services/useDisplayConfig/index.ts
@@ -1,8 +1,6 @@
import {
PiWebserviceProvider,
- type filterActionsFilter,
type ActionsResponse,
- type timeSeriesGridActionsFilter,
} from '@deltares/fews-pi-requests'
import { ref, toValue, watchEffect } from 'vue'
import type { MaybeRefOrGetter, Ref } from 'vue'
@@ -11,6 +9,11 @@ import { timeSeriesDisplayToChartConfig } from '../../lib/charts/timeSeriesDispl
import { createTransformRequestFn } from '@/lib/requests/transformRequest.js'
import { MD5 } from 'crypto-js'
import { convertFewsPiDateTimeToJsDate } from '@/lib/date'
+import {
+ type Filter,
+ isFilterActionsFilter,
+ isTimeSeriesGridActionsFilter,
+} from '@/lib/filters'
export interface UseDisplayConfigReturn {
displayConfig: Ref
@@ -22,18 +25,6 @@ export interface UseDisplayConfigOptions {
useDisplayUnits?: boolean
}
-type Filter = timeSeriesGridActionsFilter | filterActionsFilter
-// Guard functions, needed because it is not possible to use instanceof/typeof on interfaces
-function isFilterActionsFilter(filter: Filter): filter is filterActionsFilter {
- return (filter as filterActionsFilter).filterId !== undefined
-}
-
-function isTimeSeriesGridActionsFilter(
- filter: Filter,
-): filter is timeSeriesGridActionsFilter {
- return (filter as timeSeriesGridActionsFilter).x !== undefined
-}
-
/**
* Converts the actions response to an array of display configurations.
* @param actionsResponse The actions response object.
diff --git a/src/services/useLocationTooltip/index.ts b/src/services/useLocationTooltip/index.ts
new file mode 100644
index 000000000..b076d88c0
--- /dev/null
+++ b/src/services/useLocationTooltip/index.ts
@@ -0,0 +1,67 @@
+import { createTransformRequestFn } from '@/lib/requests/transformRequest'
+import {
+ LocationsTooltipFilter,
+ PiWebserviceProvider,
+} from '@deltares/fews-pi-requests'
+import type { MaybeRefOrGetter, Ref, ShallowRef } from 'vue'
+import { ref, shallowRef, toValue, watchEffect } from 'vue'
+
+export interface UseLocationTooltipReturn {
+ error: Ref
+ tooltip: ShallowRef
+ isReady: Ref
+ isLoading: Ref
+}
+
+export function useLocationTooltip(
+ baseUrl: string,
+ filter: MaybeRefOrGetter,
+): UseLocationTooltipReturn {
+ const tooltip = shallowRef()
+ const isReady = ref(false)
+ const isLoading = ref(false)
+ const error = shallowRef()
+
+ async function loadLocationTooltip() {
+ isLoading.value = true
+ isReady.value = false
+
+ try {
+ const _filter = toValue(filter)
+ if (!_filter) throw new Error('Tooltip filter is undefined')
+
+ const provider = new PiWebserviceProvider(baseUrl, {
+ transformRequestFn: createTransformRequestFn(),
+ })
+ const response = await provider.getLocationsTooltip(_filter)
+ if (!response) throw new Error('Tooltip response is undefined')
+
+ tooltip.value = isHTML(response) ? response : formatAsHTML(response)
+ } catch {
+ error.value = 'Error loading location tooltip'
+ tooltip.value = undefined
+ } finally {
+ isLoading.value = false
+ isReady.value = true
+ }
+ }
+
+ watchEffect(loadLocationTooltip)
+
+ return {
+ tooltip,
+ isReady,
+ isLoading,
+ error,
+ }
+}
+
+function isHTML(str: string) {
+ const parser = new DOMParser()
+ const doc = parser.parseFromString(str, 'text/html')
+ return Array.from(doc.body.childNodes).some((node) => node.nodeType === 1)
+}
+
+function formatAsHTML(str: string) {
+ return `${str}
`
+}