Skip to content

Commit

Permalink
Add "fancy table" display
Browse files Browse the repository at this point in the history
This is currently only accessible by manually specifying the URL.
Furthermore, independent of the selected location, it will use the same
hard-coded configuration.
  • Loading branch information
ceesvoesenek committed Jun 27, 2024
1 parent d9f6eb6 commit d9db225
Show file tree
Hide file tree
Showing 4 changed files with 223 additions and 5 deletions.
84 changes: 84 additions & 0 deletions src/assets/example-table-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
{
"results": [
{
"type": "PI",
"requests": [
{
"key": "44fcec",
"request": "rest/fewspiservice/v1/timeseries?timeSeriesSetIndex=168&locationIds=uMhlanga_Main_Beach_wave&endForecastTime=2024-06-12T13%3A09%3A47Z&startTime=2024-06-05T13%3A09%3A47Z&endTime=2024-06-17T13%3A09%3A47Z&useDisplayUnits=true&matchAsQualifierSet=true&convertDatum=false&documentFormat=PI_JSON"
},
{
"key": "44fced",
"request": "rest/fewspiservice/v1/timeseries?timeSeriesSetIndex=162&locationIds=uMhlanga_Main_Beach_wave&endForecastTime=2024-06-18T07%3A54%3A46Z&startTime=2024-06-11T07%3A54%3A46Z&endTime=2024-06-23T07%3A54%3A46Z&useDisplayUnits=true&matchAsQualifierSet=true&convertDatum=false&documentFormat=PI_JSON"
}
],
"config": {
"timeSeriesDisplay": {},
"tableDisplay": {
"rows": [
{
"type": "value",
"label": "Wave height",
"request": "44fcec"
},
{
"type": "colored-value",
"label": "Wave height coloured",
"request": "44fcec",
"colorMap": [
{
"lowerValue": 0.0,
"color": "#070268"
},
{
"lowerValue": 2.5,
"color": "#00ff40"
},
{
"lowerValue": 5.0,
"color": "#800000"
}
]
},
{
"type": "colored-value",
"label": "Wave direction",
"request": "44fced",
"colorMap": [
{
"lowerValue": 0.0,
"color": "#070268"
},
{
"lowerValue": 180,
"color": "#00ff40"
},
{
"lowerValue": 360,
"color": "#800000"
}
],
"fontColor": "#fff"
},
{
"type": "direction",
"label": "Wave direction",
"directionType": "wave",
"request": "44fced"
},
{
"type": "graph",
"label": "Wave height graph",
"request": "44fcec",
"relativeHeight": 2,
"showValues": true,
"alignValues": "bottom",
"fill": "#f48fb1",
"stroke": "#fce4ec"
}
]
}
}
}
]
}
37 changes: 32 additions & 5 deletions src/components/spatialdisplay/SpatialDisplay.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
<template>
<div class="container">
<div class="child-container" :class="{ 'd-none': hideMap }">
<div
class="container"
:class="{ 'vertical-split': route.meta.useVerticalSplit }"
>
<div
class="child-container map-container"
:class="{
'd-none': hideMap,
'vertical-split': route.meta.useVerticalSplit,
}"
>
<SpatialDisplayComponent
:layer-name="props.layerName"
:location-id="props.locationId"
Expand All @@ -16,7 +25,11 @@
@coordinate-click="onCoordinateClick"
></SpatialDisplayComponent>
</div>
<div v-if="filter" class="child-container">
<div
v-if="filter"
class="child-container window-container"
:class="{ 'vertical-split': route.meta.useVerticalSplit }"
>
<router-view
@close="closeTimeSeriesDisplay"
:filter="filter"
Expand Down Expand Up @@ -275,17 +288,31 @@ watch(
height: 100%;
}
.container.vertical-split {
flex-direction: column;
}
.child-container {
position: relative;
display: flex;
flex-direction: column;
width: 50%;
max-width: 100%;
flex: 1 1 0px;
}
.child-container.mobile {
height: 100%;
width: 100%;
}
.child-container:not(.vertical-split) {
width: 50%;
max-width: 100%;
}
.map-container.vertical-split {
flex: 1 1 0;
}
.window-container.vertical-split {
flex: 0 1 0;
}
</style>
98 changes: 98 additions & 0 deletions src/components/spatialdisplay/SpatialTableDisplay.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<template>
<div class="table-container" ref="container"></div>
</template>

<script setup lang="ts">
import { onMounted, ref, watch } from 'vue'
import { useTheme } from 'vuetify'
import {
type ActionsResponse,
type TableConfig,
FancyTable,
} from '@/lib/fancy-table'
import { configManager } from '@/services/application-config'
import { UseTimeSeriesOptions, useTimeSeries } from '@/services/useTimeSeries'
import actionResponseRaw from '@/assets/example-table-config.json'
const theme = useTheme()
interface Props {
nodeId: string
locationId: string
}
defineProps<Props>()
const actionResponse = actionResponseRaw as ActionsResponse
const requests = actionResponse.results[0].requests
const tableConfig = actionResponse.results[0].config
?.tableDisplay as TableConfig
// TODO: Default period, how to set period?
const now = new Date()
const numDaysBackward = 10
const numDaysForward = 10
const start = new Date(now.getTime() - numDaysBackward * 24 * 60 * 60 * 1000)
const end = new Date(now.getTime() + numDaysForward * 24 * 60 * 60 * 1000)
const baseUrl = configManager.get('VITE_FEWS_WEBSERVICES_URL')
const lastUpdated = ref<Date>()
const options: UseTimeSeriesOptions = {
startTime: start,
endTime: end,
}
const { series } = useTimeSeries(baseUrl, requests, lastUpdated, options)
const container = ref<HTMLDivElement | null>(null)
let table: FancyTable | null = null
// Create the table when the component is mounted.
onMounted(initialise)
function initialise(): void {
if (!container.value) throw new Error('Container has not been mounted.')
// Scroll horizontally with the wheel.
container.value.addEventListener('wheel', (event: WheelEvent) => {
if (!container.value) return
event.preventDefault()
container.value.scrollLeft += event.deltaY
})
table = createNewTable()
// Watch for series being updated, then update the data.
// TODO: debounced?
watch(
() => Object.values(series.value).map((entry) => entry.lastUpdated),
() => table?.setData(series.value),
)
}
// Recreate the table when we switch themes.
watch(theme.current, () => {
table = createNewTable()
// Force an update with data that is probably already available.
table.setData(series.value)
})
function createNewTable(): FancyTable {
if (!container.value) throw new Error('Container has not been mounted.')
const isDark = theme.current.value.dark
const newTable = new FancyTable(container.value, tableConfig, isDark)
newTable.node().style.flexShrink = '0'
return newTable
}
</script>

<style scoped>
.table-container {
width: 100%;
height: fit-content;
display: flex;
overflow-x: scroll;
}
</style>
9 changes: 9 additions & 0 deletions src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ const SpatialDisplay = () =>
import('../components/spatialdisplay/SpatialDisplay.vue')
const SpatialTimeSeriesDisplay = () =>
import('../components/spatialdisplay/SpatialTimeSeriesDisplay.vue')
const SpatialTableDisplay = () =>
import('../components/spatialdisplay/SpatialTableDisplay.vue')
const TimeSeriesDisplayView = () => import('../views/TimeSeriesDisplayView.vue')
const TopologyDisplayView = () => import('../views/TopologyDisplayView.vue')
const DataDownloadDisplayView = () =>
Expand Down Expand Up @@ -192,6 +194,13 @@ export const dynamicRoutes: Readonly<RouteRecordRaw[]> = [
props: true,
meta: { sidebar: true },
},
{
path: '/topology/node/:nodeId*/map/:layerName/table/:locationId',
name: 'SpatialTableDisplay',
component: SpatialTableDisplay,
props: true,
meta: { sidebar: true, useVerticalSplit: true },
},
],
},
],
Expand Down

0 comments on commit d9db225

Please sign in to comment.