Skip to content

Commit

Permalink
Merge pull request #989 from Deltares/981-location-tooltips
Browse files Browse the repository at this point in the history
Add location information
  • Loading branch information
bogaardt authored Sep 24, 2024
2 parents 1a7e555 + a976cc4 commit 3e3b4c7
Show file tree
Hide file tree
Showing 10 changed files with 180 additions and 20 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
18 changes: 17 additions & 1 deletion src/components/spatialdisplay/SpatialDisplayComponent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@
/>
</MapComponent>
<div class="mapcomponent__controls-container">
<v-chip-group class="px-2">
<v-chip-group class="control-group">
<TooltipPanel v-if="tooltip" :content="tooltip" />
<BoundingBoxControl
v-model:active="workflowsStore.isDrawingBoundingBox"
v-model:boundingBox="workflowsStore.boundingBox"
Expand Down Expand Up @@ -152,6 +153,8 @@ import {
} from '@/lib/legend'
import { useWorkflowsStore } from '@/stores/workflows'
import { TimeSeriesData } from '@/lib/timeseries/types/SeriesData'
import { useLocationTooltip } from '@/services/useLocationTooltip'
import TooltipPanel from '@/components/wms/TooltipPanel.vue'
interface ElevationWithUnitSymbol {
units?: string
Expand Down Expand Up @@ -418,6 +421,15 @@ watch(currentTime, () => {
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 = {
Expand Down Expand Up @@ -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;
}
</style>
20 changes: 20 additions & 0 deletions src/components/spatialdisplay/SpatialTimeSeriesDisplay.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
:elevation-chart-config="elevationChartDisplayconfig"
:current-time="props.currentTime"
:displayType="displayType"
:information-content="tooltip"
>
</TimeSeriesComponent>
<TimeSeriesFileDownloadComponent
Expand Down Expand Up @@ -77,6 +78,8 @@ import { computed } from 'vue'
import TimeSeriesFileDownloadComponent from '@/components/download/TimeSeriesFileDownloadComponent.vue'
import { useUserSettingsStore } from '@/stores/userSettings.ts'
import { useSystemTimeStore } from '@/stores/systemTime'
import { useLocationTooltip } from '@/services/useLocationTooltip'
import { isFilterActionsFilter } from '@/lib/filters'
interface Props {
filter: filterActionsFilter | timeSeriesGridActionsFilter
elevationChartFilter?: timeSeriesGridActionsFilter
Expand Down Expand Up @@ -128,6 +131,15 @@ const { displayConfig: elevationChartDisplayconfig } = useDisplayConfigFilter(
() => systemTimeStore.endTime,
)
const { tooltip } = useLocationTooltip(baseUrl, () =>
isFilterActionsFilter(props.filter)
? {
filterId: props.filter.filterId,
locationId: props.filter.locationIds,
}
: undefined,
)
interface DisplayTypeItem {
icon: string
label: string
Expand Down Expand Up @@ -159,6 +171,14 @@ const displayTypeItems = computed<DisplayTypeItem[]>(() => {
})
}
if (tooltip.value) {
displayItems.push({
icon: 'mdi-information',
label: 'Information',
value: DisplayType.Information,
})
}
return displayItems
})
Expand Down
7 changes: 7 additions & 0 deletions src/components/timeseries/TimeSeriesComponent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@
</ElevationChart>
</KeepAlive>
</v-window-item>
<v-window-item :value="DisplayType.Information" class="h-100">
<!-- <div class="px-4 h-100"> -->
<!-- <iframe :srcdoc="informationContent" class="h-100 w-100 border-none" /> -->
<!-- </div> -->
<div v-html="informationContent" class="pa-4 h-100 w-100" />
</v-window-item>
</v-window>
<v-dialog v-model="confirmationDialog" persistent max-width="500">
<v-card prepend-icon="mdi-content-save" title="Unsaved Changes">
Expand Down Expand Up @@ -93,6 +99,7 @@ interface Props {
elevationChartConfig?: DisplayConfig
displayType: DisplayType
currentTime?: Date
informationContent?: string
}
const props = withDefaults(defineProps<Props>(), {
Expand Down
40 changes: 40 additions & 0 deletions src/components/wms/TooltipPanel.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<template>
<v-chip label class="tooltip-chip">
<v-icon>mdi-information</v-icon>
<v-menu
v-model="opened"
transition="slide-y-transition"
:close-on-content-click="false"
activator="parent"
persistent
no-click-animation
>
<div class="tooltip-chip px-3 py-2 my-2 elevation-1">
<div v-html="content" />
</div>
</v-menu>
</v-chip>
</template>

<script setup lang="ts">
import { ref } from 'vue'
interface Props {
content: string
}
defineProps<Props>()
const opened = ref(true)
</script>

<style scoped>
.tooltip-chip {
font-size: 0.825em;
z-index: 1000;
border-radius: 5px;
backdrop-filter: blur(5px);
background-color: rgba(var(--v-theme-surface), 0.8);
box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
}
</style>
1 change: 1 addition & 0 deletions src/lib/display/DisplayConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export enum DisplayType {
TimeSeriesChart = 'TimeSeriesChart',
TimeSeriesTable = 'TimeSeriesTable',
ElevationChart = 'ElevationChart',
Information = 'Information',
}

export interface DisplayConfig {
Expand Down
18 changes: 18 additions & 0 deletions src/lib/filters/index.ts
Original file line number Diff line number Diff line change
@@ -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
}
19 changes: 5 additions & 14 deletions src/services/useDisplayConfig/index.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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<DisplayConfig | undefined>
Expand All @@ -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.
Expand Down
67 changes: 67 additions & 0 deletions src/services/useLocationTooltip/index.ts
Original file line number Diff line number Diff line change
@@ -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<string | undefined>
tooltip: ShallowRef<string | undefined>
isReady: Ref<boolean>
isLoading: Ref<boolean>
}

export function useLocationTooltip(
baseUrl: string,
filter: MaybeRefOrGetter<LocationsTooltipFilter | undefined>,
): UseLocationTooltipReturn {
const tooltip = shallowRef<string>()
const isReady = ref(false)
const isLoading = ref(false)
const error = shallowRef<string>()

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 `<pre>${str}</pre>`
}

0 comments on commit 3e3b4c7

Please sign in to comment.