diff --git a/WebDisplay/Dockerfile b/WebDisplay/Dockerfile
new file mode 100644
index 0000000..9e13381
--- /dev/null
+++ b/WebDisplay/Dockerfile
@@ -0,0 +1,14 @@
+# build stage
+FROM node:lts-alpine as build-stage
+RUN corepack enable && corepack prepare pnpm@latest --activate
+WORKDIR /app
+COPY package*.json ./
+RUN pnpm install
+COPY . .
+RUN pnpm run build
+
+# production stage
+FROM nginx:stable-alpine as production-stage
+COPY --from=build-stage /app/dist /usr/share/nginx/html
+EXPOSE 80
+CMD ["nginx", "-g", "daemon off;"]
\ No newline at end of file
diff --git a/WebDisplay/components.d.ts b/WebDisplay/components.d.ts
index 7f11273..dc572b9 100644
--- a/WebDisplay/components.d.ts
+++ b/WebDisplay/components.d.ts
@@ -12,7 +12,6 @@ declare module 'vue' {
CurrentPower: typeof import('./src/components/CurrentPower.vue')['default']
CurrentWeather: typeof import('./src/components/CurrentWeather.vue')['default']
DashboardItem: typeof import('./src/components/DashboardItem.vue')['default']
- HelloWorld: typeof import('./src/components/HelloWorld.vue')['default']
Indoor: typeof import('./src/components/Indoor.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
diff --git a/WebDisplay/deploy/azure-pipelines.yml b/WebDisplay/deploy/azure-pipelines.yml
new file mode 100644
index 0000000..a4a9022
--- /dev/null
+++ b/WebDisplay/deploy/azure-pipelines.yml
@@ -0,0 +1,68 @@
+name: $(Rev:r)
+
+pr: none
+
+trigger:
+ batch: 'true'
+ branches:
+ include:
+ - master
+ paths:
+ include:
+ - WebDisplay
+
+stages:
+- stage: Build
+ jobs:
+ - job: Build
+ pool:
+ vmImage: 'ubuntu-latest'
+ steps:
+ - task: Docker@0
+ displayName: 'Build an image'
+ inputs:
+ containerregistrytype: 'Container Registry'
+ dockerRegistryConnection: 'Docker Hub'
+ dockerFile: 'WebDisplay/Dockerfile'
+ imageName: 'ckaczor/home-monitor-web-display:$(Build.BuildNumber)'
+ includeLatestTag: true
+ - task: Docker@0
+ displayName: 'Push an image'
+ inputs:
+ containerregistrytype: 'Container Registry'
+ dockerRegistryConnection: 'Docker Hub'
+ action: 'Push an image'
+ imageName: 'ckaczor/home-monitor-web-display:$(Build.BuildNumber)'
+ includeLatestTag: true
+ - task: Bash@3
+ inputs:
+ targetType: 'inline'
+ script: 'sed -i s/#BUILD_BUILDNUMBER#/$BUILD_BUILDNUMBER/ WebDisplay/deploy/manifest.yaml'
+ - task: PublishBuildArtifacts@1
+ inputs:
+ PathtoPublish: 'WebDisplay/deploy/manifest.yaml'
+ ArtifactName: 'Manifest'
+ publishLocation: 'Container'
+
+- stage: Deploy
+ jobs:
+ - job: Deploy
+ pool:
+ vmImage: 'ubuntu-latest'
+ steps:
+ - task: DownloadBuildArtifacts@0
+ inputs:
+ artifactName: 'Manifest'
+ buildType: 'current'
+ downloadType: 'single'
+ downloadPath: '$(System.ArtifactsDirectory)'
+ - task: Kubernetes@1
+ inputs:
+ connectionType: 'Kubernetes Service Connection'
+ kubernetesServiceEndpoint: 'Kubernetes'
+ namespace: 'home-monitor'
+ command: 'apply'
+ useConfigurationFile: true
+ configuration: '$(System.ArtifactsDirectory)/Manifest/manifest.yaml'
+ secretType: 'dockerRegistry'
+ containerRegistryType: 'Container Registry'
diff --git a/WebDisplay/deploy/manifest.yaml b/WebDisplay/deploy/manifest.yaml
new file mode 100644
index 0000000..abcd807
--- /dev/null
+++ b/WebDisplay/deploy/manifest.yaml
@@ -0,0 +1,76 @@
+---
+kind: Deployment
+apiVersion: apps/v1
+metadata:
+ name: display
+ namespace: home-monitor
+ labels:
+ app: display
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: display
+ template:
+ metadata:
+ labels:
+ app: display
+ spec:
+ containers:
+ - name: display
+ image: ckaczor/home-monitor-web-display:#BUILD_BUILDNUMBER#
+ terminationMessagePath: "/dev/termination-log"
+ terminationMessagePolicy: File
+ imagePullPolicy: Always
+ securityContext:
+ privileged: true
+ restartPolicy: Always
+ terminationGracePeriodSeconds: 30
+ dnsPolicy: ClusterFirst
+ nodeSelector:
+ kubernetes.io/hostname: kubernetes
+ schedulerName: default-scheduler
+---
+kind: Service
+apiVersion: v1
+metadata:
+ name: display
+spec:
+ ports:
+ - name: client
+ port: 80
+ selector:
+ app: display
+ type: ClusterIP
+---
+apiVersion: traefik.containo.us/v1alpha1
+kind: IngressRoute
+metadata:
+ annotations:
+ kubernetes.io/ingress.class: traefik
+ creationTimestamp: null
+ name: display
+ namespace: home-monitor
+spec:
+ routes:
+ - kind: Rule
+ match: PathPrefix(`/`)
+ middlewares:
+ - name: display
+ namespace: home-monitor
+ services:
+ - kind: Service
+ name: display
+ namespace: home-monitor
+ port: 80
+---
+apiVersion: traefik.containo.us/v1alpha1
+kind: Middleware
+metadata:
+ creationTimestamp: null
+ name: display
+ namespace: home-monitor
+spec:
+ stripPrefix:
+ prefixes:
+ - /
diff --git a/WebDisplay/package.json b/WebDisplay/package.json
index 687f5e2..2fe49cd 100644
--- a/WebDisplay/package.json
+++ b/WebDisplay/package.json
@@ -1,6 +1,6 @@
{
- "name": "WebDisplay",
- "version": "0.0.0",
+ "name": "web-display",
+ "version": "1.0.0",
"scripts": {
"dev": "cross-env NODE_OPTIONS='--no-warnings' vite",
"build": "vue-tsc --noEmit && vite build",
diff --git a/WebDisplay/src/components/CurrentWeather.vue b/WebDisplay/src/components/CurrentWeather.vue
index 58d832f..920d4e9 100644
--- a/WebDisplay/src/components/CurrentWeather.vue
+++ b/WebDisplay/src/components/CurrentWeather.vue
@@ -45,7 +45,7 @@
+ className="weather-current-header ml-8">
Feels like
|
diff --git a/WebDisplay/src/components/DashboardItem.vue b/WebDisplay/src/components/DashboardItem.vue
index d52505a..7de58f2 100644
--- a/WebDisplay/src/components/DashboardItem.vue
+++ b/WebDisplay/src/components/DashboardItem.vue
@@ -14,15 +14,9 @@
diff --git a/WebDisplay/src/components/ValueChart.vue b/WebDisplay/src/components/ValueChart.vue
index 6cd8f9d..6ebb434 100644
--- a/WebDisplay/src/components/ValueChart.vue
+++ b/WebDisplay/src/components/ValueChart.vue
@@ -16,7 +16,9 @@
yAxisMaximum: { type: Number, required: false, default: undefined },
tickAmount: { type: Number, required: false, default: undefined },
lineSize: { type: Number, required: false, default: 2 },
- markerSize: { type: Number, required: false, default: 0 }
+ markerSize: { type: Number, required: false, default: 0 },
+ yAxisLabelFormatter: { type: Function, required: false, default: undefined },
+ yAxisValueFormatter: { type: Function, required: false, default: undefined }
});
var chartOptions: ApexOptions = {
@@ -48,6 +50,10 @@
},
y: {
formatter: (value) => {
+ if (props.yAxisValueFormatter) {
+ return props.yAxisValueFormatter(value);
+ }
+
return `${value.toFixed(props.valueDecimalPoints)}${props.unit}`;
}
}
@@ -69,6 +75,10 @@
yaxis: {
labels: {
formatter: (value) => {
+ if (props.yAxisLabelFormatter) {
+ return props.yAxisLabelFormatter(value);
+ }
+
return `${value.toFixed(props.yAxisDecimalPoints)}${props.unit}`;
}
},
@@ -94,7 +104,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -36,4 +40,66 @@
height: 100%;
background-color: #fafafa;
}
+
+ @media (min-width: 700px) {
+ .container {
+ display: grid;
+ grid-template-columns: repeat(5, max-content);
+ grid-template-rows: repeat(5, max-content);
+ gap: 15px 15px;
+ grid-auto-flow: row;
+ grid-template-areas:
+ 'current-weather current-weather almanac almanac current-power'
+ 'current-weather current-weather almanac almanac current-laundry-status'
+ 'weather-summary weather-summary weather-summary upstairs downstairs'
+ 'weather-summary weather-summary weather-summary . .'
+ '. . . . .';
+ }
+ }
+
+ @media (max-width: 700px) {
+ .container {
+ padding: 7px;
+ display: grid;
+ grid-template-columns: repeat(1, max-content);
+ grid-template-rows: repeat(7, max-content);
+ gap: 10px 0px;
+ grid-template-areas:
+ 'current-weather'
+ 'almanac'
+ 'current-power'
+ 'current-laundry-status'
+ 'weather-summary'
+ 'upstairs'
+ 'downstairs';
+ }
+ }
+
+ .current-weather {
+ grid-area: current-weather;
+ }
+
+ .almanac {
+ grid-area: almanac;
+ }
+
+ .current-power {
+ grid-area: current-power;
+ }
+
+ .current-laundry-status {
+ grid-area: current-laundry-status;
+ }
+
+ .weather-summary {
+ grid-area: weather-summary;
+ }
+
+ .upstairs {
+ grid-area: upstairs;
+ }
+
+ .downstairs {
+ grid-area: downstairs;
+ }
diff --git a/WebDisplay/src/pages/indoor.vue b/WebDisplay/src/pages/indoor.vue
index b69fafa..b4eb811 100644
--- a/WebDisplay/src/pages/indoor.vue
+++ b/WebDisplay/src/pages/indoor.vue
@@ -16,43 +16,43 @@
const start = ref(subHours(end.value, 24));
const timeSpan = ref(TimeSpan.Last24Hours);
- const categories: number[] = [];
+ const categories = ref([]);
- const mainTemperatureSeries = { name: 'Upstairs', data: [] as number[] };
- const basementTemperatureSeries = { name: 'Downstairs', data: [] as number[] };
+ const mainTemperatureSeries = ref({ name: 'Upstairs', data: [] as number[] });
+ const basementTemperatureSeries = ref({ name: 'Downstairs', data: [] as number[] });
- const mainHumiditySeries = { name: 'Upstairs', data: [] as number[] };
- const basementHumiditySeries = { name: 'Downstairs', data: [] as number[] };
+ const mainHumiditySeries = ref({ name: 'Upstairs', data: [] as number[] });
+ const basementHumiditySeries = ref({ name: 'Downstairs', data: [] as number[] });
- const mainPressureSeries = { name: 'Upstairs', data: [] as number[] };
- const basementPressureSeries = { name: 'Downstairs', data: [] as number[] };
+ const mainPressureSeries = ref({ name: 'Upstairs', data: [] as number[] });
+ const basementPressureSeries = ref({ name: 'Downstairs', data: [] as number[] });
const load = () => {
ready.value = false;
- categories.length = 0;
-
- mainTemperatureSeries.data.length = 0;
- basementTemperatureSeries.data.length = 0;
-
- mainHumiditySeries.data.length = 0;
- basementHumiditySeries.data.length = 0;
-
- mainPressureSeries.data.length = 0;
- basementPressureSeries.data.length = 0;
-
indoorStore.getReadingValueHistoryGrouped(start.value, end.value, 15).then((groupedReadingsList) => {
+ categories.value.length = 0;
+
+ mainTemperatureSeries.value.data.length = 0;
+ basementTemperatureSeries.value.data.length = 0;
+
+ mainHumiditySeries.value.data.length = 0;
+ basementHumiditySeries.value.data.length = 0;
+
+ mainPressureSeries.value.data.length = 0;
+ basementPressureSeries.value.data.length = 0;
+
groupedReadingsList.forEach((groupedReadings) => {
if (groupedReadings.name === 'main') {
- categories.push(new Date(groupedReadings.bucket).getTime());
+ categories.value.push(new Date(groupedReadings.bucket).getTime());
- mainTemperatureSeries.data.push(ConvertCToF(groupedReadings.averageTemperature));
- mainHumiditySeries.data.push(groupedReadings.averageHumidity);
- mainPressureSeries.data.push(ConvertMillibarToInchesOfMercury(groupedReadings.averagePressure));
+ mainTemperatureSeries.value.data.push(ConvertCToF(groupedReadings.averageTemperature));
+ mainHumiditySeries.value.data.push(groupedReadings.averageHumidity);
+ mainPressureSeries.value.data.push(ConvertMillibarToInchesOfMercury(groupedReadings.averagePressure));
} else if (groupedReadings.name === 'basement') {
- basementTemperatureSeries.data.push(ConvertCToF(groupedReadings.averageTemperature));
- basementHumiditySeries.data.push(groupedReadings.averageHumidity);
- basementPressureSeries.data.push(ConvertMillibarToInchesOfMercury(groupedReadings.averagePressure));
+ basementTemperatureSeries.value.data.push(ConvertCToF(groupedReadings.averageTemperature));
+ basementHumiditySeries.value.data.push(groupedReadings.averageHumidity);
+ basementPressureSeries.value.data.push(ConvertMillibarToInchesOfMercury(groupedReadings.averagePressure));
}
});
diff --git a/WebDisplay/src/pages/outdoor.vue b/WebDisplay/src/pages/outdoor.vue
index fd4ad7e..5eac876 100644
--- a/WebDisplay/src/pages/outdoor.vue
+++ b/WebDisplay/src/pages/outdoor.vue
@@ -4,28 +4,28 @@
import { useWeatherStore } from '@/stores/weatherStore';
import { ConvertPascalToInchesOfMercury } from '@/pressureConverter';
import ValueChart from '../components/ValueChart.vue';
- import WindDirectionNumber from '@/models/weather/wind-direction-number';
import TimeRange from '@/components/TimeRange.vue';
import TimeSpan from '@/models/time-span';
+ import { ConvertDegreesToShortLabel, ConvertWindDirectionToDegrees } from '@/windConverter';
const weatherStore = useWeatherStore();
const readingsReady = ref(false);
const windReady = ref(false);
- const readingsCategories: number[] = [];
- const windCategories: number[] = [];
+ const readingsCategories = ref([]);
+ const windCategories = ref([]);
- const temperatureSeries = { name: 'Average Temperature', data: [] as number[] };
- const humiditySeries = { name: 'Average Humidity', data: [] as number[] };
- const pressureSeries = { name: 'Average Pressure', data: [] as number[] };
- const lightSeries = { name: 'Average Light', data: [] as number[] };
- const rainSeries = { name: 'Total Rain', data: [] as number[] };
+ const temperatureSeries = ref({ name: 'Average Temperature', data: [] as number[] });
+ const humiditySeries = ref({ name: 'Average Humidity', data: [] as number[] });
+ const pressureSeries = ref({ name: 'Average Pressure', data: [] as number[] });
+ const lightSeries = ref({ name: 'Average Light', data: [] as number[] });
+ const rainSeries = ref({ name: 'Total Rain', data: [] as number[] });
- const windMinimumSeries = { name: 'Minimum', data: [] as number[] };
- const windAverageSeries = { name: 'Average', data: [] as number[] };
- const windMaximumSeries = { name: 'Maximum', data: [] as number[] };
- const windDirectionSeries = { name: 'Average Direction', data: [] as number[] };
+ const windMinimumSeries = ref({ name: 'Minimum', data: [] as number[] });
+ const windAverageSeries = ref({ name: 'Average', data: [] as number[] });
+ const windMaximumSeries = ref({ name: 'Maximum', data: [] as number[] });
+ const windDirectionSeries = ref({ name: 'Average Direction', data: [] as number[] });
const end = ref(new Date());
const start = ref(subHours(end.value, 24));
@@ -33,43 +33,44 @@
const load = () => {
readingsReady.value = false;
- readingsCategories.length = 0;
- temperatureSeries.data.length = 0;
- humiditySeries.data.length = 0;
- pressureSeries.data.length = 0;
- lightSeries.data.length = 0;
- rainSeries.data.length = 0;
-
windReady.value = false;
- windCategories.length = 0;
- windMinimumSeries.data.length = 0;
- windAverageSeries.data.length = 0;
- windMaximumSeries.data.length = 0;
- windDirectionSeries.data.length = 0;
weatherStore.getReadingHistoryGrouped(start.value, end.value, 15).then((groupedReadingsList) => {
- groupedReadingsList.forEach((groupedReadings) => {
- readingsCategories.push(new Date(groupedReadings.bucket).getTime());
+ readingsCategories.value.length = 0;
+ temperatureSeries.value.data.length = 0;
+ humiditySeries.value.data.length = 0;
+ pressureSeries.value.data.length = 0;
+ lightSeries.value.data.length = 0;
+ rainSeries.value.data.length = 0;
- temperatureSeries.data.push(groupedReadings.averageTemperature);
- humiditySeries.data.push(groupedReadings.averageHumidity);
- pressureSeries.data.push(ConvertPascalToInchesOfMercury(groupedReadings.averagePressure));
- lightSeries.data.push(groupedReadings.averageLightLevel);
- rainSeries.data.push(groupedReadings.rainTotal);
+ groupedReadingsList.forEach((groupedReadings) => {
+ readingsCategories.value.push(new Date(groupedReadings.bucket).getTime());
+
+ temperatureSeries.value.data.push(groupedReadings.averageTemperature);
+ humiditySeries.value.data.push(groupedReadings.averageHumidity);
+ pressureSeries.value.data.push(ConvertPascalToInchesOfMercury(groupedReadings.averagePressure));
+ lightSeries.value.data.push(groupedReadings.averageLightLevel);
+ rainSeries.value.data.push(groupedReadings.rainTotal);
});
readingsReady.value = true;
});
weatherStore.getWindHistoryGrouped(start.value, end.value, 15).then((groupedReadingsList) => {
+ windCategories.value.length = 0;
+ windMinimumSeries.value.data.length = 0;
+ windAverageSeries.value.data.length = 0;
+ windMaximumSeries.value.data.length = 0;
+ windDirectionSeries.value.data.length = 0;
+
groupedReadingsList.forEach((groupedReadings) => {
- windCategories.push(new Date(groupedReadings.bucket).getTime());
+ windCategories.value.push(new Date(groupedReadings.bucket).getTime());
- windMinimumSeries.data.push(groupedReadings.minimumSpeed);
- windAverageSeries.data.push(groupedReadings.averageSpeed);
- windMaximumSeries.data.push(groupedReadings.maximumSpeed);
+ windMinimumSeries.value.data.push(groupedReadings.minimumSpeed);
+ windAverageSeries.value.data.push(groupedReadings.averageSpeed);
+ windMaximumSeries.value.data.push(groupedReadings.maximumSpeed);
- windDirectionSeries.data.push(groupedReadings.averageDirection);
+ windDirectionSeries.value.data.push(ConvertWindDirectionToDegrees(groupedReadings.averageDirection));
});
windReady.value = true;
@@ -200,11 +201,11 @@
title="Wind Direction"
unit=""
group="outdoor"
- :tick-amount="3"
- :marker-size="3"
- :line-size="0"
- :y-axis-minimum="WindDirectionNumber.Min"
- :y-axis-maximum="WindDirectionNumber.Max"
+ :tick-amount="4"
+ :y-axis-minimum="0"
+ :y-axis-maximum="360"
+ :y-axis-label-formatter="ConvertDegreesToShortLabel"
+ :y-axis-value-formatter="ConvertDegreesToShortLabel"
:categories="windCategories"
:series="[windDirectionSeries]">
diff --git a/WebDisplay/src/pages/power.vue b/WebDisplay/src/pages/power.vue
index 614d750..5cb05f4 100644
--- a/WebDisplay/src/pages/power.vue
+++ b/WebDisplay/src/pages/power.vue
@@ -14,13 +14,13 @@
const powerReady = ref(false);
const lightReady = ref(false);
- const powerCategories: number[] = [];
- const lightCategories: number[] = [];
+ const powerCategories = ref([]);
+ const lightCategories = ref([]);
- const generationSeries = { name: 'Generation', data: [] as number[] };
- const consumptionSeries = { name: 'Consumption', data: [] as number[] };
+ const generationSeries = ref({ name: 'Generation', data: [] as number[] });
+ const consumptionSeries = ref({ name: 'Consumption', data: [] as number[] });
- const lightSeries = { name: 'Average Light', data: [] as number[] };
+ const lightSeries = ref({ name: 'Average Light', data: [] as number[] });
const end = ref(new Date());
const start = ref(subHours(end.value, 24));
@@ -28,30 +28,31 @@
const load = () => {
powerReady.value = false;
- powerCategories.length = 0;
- generationSeries.data.length = 0;
- consumptionSeries.data.length = 0;
-
lightReady.value = false;
- lightCategories.length = 0;
- lightSeries.data.length = 0;
powerStore.getReadingHistoryGrouped(start.value, end.value, 15).then((groupedReadingsList) => {
- groupedReadingsList.forEach((groupedReadings) => {
- powerCategories.push(new Date(groupedReadings.bucket).getTime());
+ powerCategories.value.length = 0;
+ generationSeries.value.data.length = 0;
+ consumptionSeries.value.data.length = 0;
- generationSeries.data.push(groupedReadings.averageGeneration);
- consumptionSeries.data.push(groupedReadings.averageConsumption);
+ groupedReadingsList.forEach((groupedReadings) => {
+ powerCategories.value.push(new Date(groupedReadings.bucket).getTime());
+
+ generationSeries.value.data.push(groupedReadings.averageGeneration);
+ consumptionSeries.value.data.push(groupedReadings.averageConsumption);
});
powerReady.value = true;
});
weatherStore.getReadingValueHistoryGrouped(WeatherValueType.Light, start.value, end.value, 15).then((groupedReadingsList) => {
- groupedReadingsList.forEach((groupedReadings) => {
- lightCategories.push(new Date(groupedReadings.bucket).getTime());
+ lightCategories.value.length = 0;
+ lightSeries.value.data.length = 0;
- lightSeries.data.push(groupedReadings.averageValue);
+ groupedReadingsList.forEach((groupedReadings) => {
+ lightCategories.value.push(new Date(groupedReadings.bucket).getTime());
+
+ lightSeries.value.data.push(groupedReadings.averageValue);
});
lightReady.value = true;
diff --git a/WebDisplay/src/windConverter.ts b/WebDisplay/src/windConverter.ts
new file mode 100644
index 0000000..8c4804b
--- /dev/null
+++ b/WebDisplay/src/windConverter.ts
@@ -0,0 +1,81 @@
+import WindDirectionNumber from './models/weather/wind-direction-number';
+
+export function ConvertWindDirectionToDegrees(windDirection: WindDirectionNumber): number {
+ switch (windDirection) {
+ case WindDirectionNumber.None:
+ return -1;
+ case WindDirectionNumber.North:
+ return 0;
+ case WindDirectionNumber.East:
+ return 90;
+ case WindDirectionNumber.South:
+ return 180;
+ case WindDirectionNumber.West:
+ return 270;
+ case WindDirectionNumber.NorthEast:
+ return 45;
+ case WindDirectionNumber.SouthEast:
+ return 135;
+ case WindDirectionNumber.SouthWest:
+ return 225;
+ case WindDirectionNumber.NorthWest:
+ return 315;
+ case WindDirectionNumber.NorthNorthEast:
+ return 22.5;
+ case WindDirectionNumber.EastNorthEast:
+ return 67.5;
+ case WindDirectionNumber.EastSouthEast:
+ return 112.5;
+ case WindDirectionNumber.SouthSouthEast:
+ return 157.5;
+ case WindDirectionNumber.SouthSouthWest:
+ return 202.5;
+ case WindDirectionNumber.WestSouthWest:
+ return 247.5;
+ case WindDirectionNumber.WestNorthWest:
+ return 292.5;
+ case WindDirectionNumber.NorthNorthWest:
+ return 337.5;
+ }
+ return -1;
+}
+
+export function ConvertDegreesToShortLabel(degrees: number): string {
+ switch (degrees) {
+ case 0:
+ case 360:
+ return 'N';
+ case 90:
+ return 'E';
+ case 180:
+ return 'S';
+ case 270:
+ return 'W';
+ case 45:
+ return 'NE';
+ case 135:
+ return 'SE';
+ case 225:
+ return 'SW';
+ case 315:
+ return 'NW';
+ case 22.5:
+ return 'NNE';
+ case 67.5:
+ return 'ENE';
+ case 112.5:
+ return 'ESE';
+ case 157.5:
+ return 'SSE';
+ case 202.5:
+ return 'SSW';
+ case 247.5:
+ return 'WSW';
+ case 292.5:
+ return 'WNW';
+ case 337.5:
+ return 'NNW';
+ }
+
+ return '';
+}
diff --git a/WebDisplay/tsconfig.json b/WebDisplay/tsconfig.json
index 8c57d50..88f7352 100644
--- a/WebDisplay/tsconfig.json
+++ b/WebDisplay/tsconfig.json
@@ -17,7 +17,7 @@
"@/*": ["src/*"]
}
},
- "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
+ "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "typed-router.d.ts"],
"references": [{ "path": "./tsconfig.node.json" }],
"exclude": ["node_modules"]
}