mirror of
https://github.com/ckaczor/HomeMonitor.git
synced 2026-02-16 10:58:32 -05:00
More new UI
This commit is contained in:
1
WebDisplay/components.d.ts
vendored
1
WebDisplay/components.d.ts
vendored
@@ -16,6 +16,7 @@ declare module 'vue' {
|
|||||||
Indoor: typeof import('./src/components/Indoor.vue')['default']
|
Indoor: typeof import('./src/components/Indoor.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
|
TimeRange: typeof import('./src/components/TimeRange.vue')['default']
|
||||||
ValueChart: typeof import('./src/components/ValueChart.vue')['default']
|
ValueChart: typeof import('./src/components/ValueChart.vue')['default']
|
||||||
WeatherSummary: typeof import('./src/components/WeatherSummary.vue')['default']
|
WeatherSummary: typeof import('./src/components/WeatherSummary.vue')['default']
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
"@mdi/font": "7.0.96",
|
"@mdi/font": "7.0.96",
|
||||||
"@microsoft/signalr": "^8.0.0",
|
"@microsoft/signalr": "^8.0.0",
|
||||||
"@types/suncalc": "^1.9.2",
|
"@types/suncalc": "^1.9.2",
|
||||||
|
"@vuepic/vue-datepicker": "^8.2.0",
|
||||||
"apexcharts": "^3.46.0",
|
"apexcharts": "^3.46.0",
|
||||||
"axios": "^1.6.7",
|
"axios": "^1.6.7",
|
||||||
"core-js": "^3.34.0",
|
"core-js": "^3.34.0",
|
||||||
|
|||||||
13
WebDisplay/pnpm-lock.yaml
generated
13
WebDisplay/pnpm-lock.yaml
generated
@@ -14,6 +14,9 @@ dependencies:
|
|||||||
'@types/suncalc':
|
'@types/suncalc':
|
||||||
specifier: ^1.9.2
|
specifier: ^1.9.2
|
||||||
version: 1.9.2
|
version: 1.9.2
|
||||||
|
'@vuepic/vue-datepicker':
|
||||||
|
specifier: ^8.2.0
|
||||||
|
version: 8.2.0(vue@3.4.21)
|
||||||
apexcharts:
|
apexcharts:
|
||||||
specifier: ^3.46.0
|
specifier: ^3.46.0
|
||||||
version: 3.46.0
|
version: 3.46.0
|
||||||
@@ -850,6 +853,16 @@ packages:
|
|||||||
/@vue/shared@3.4.21:
|
/@vue/shared@3.4.21:
|
||||||
resolution: {integrity: sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==}
|
resolution: {integrity: sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==}
|
||||||
|
|
||||||
|
/@vuepic/vue-datepicker@8.2.0(vue@3.4.21):
|
||||||
|
resolution: {integrity: sha512-H3X9/XRvF4/ttdgxgNhFCp9m9gt9UVsiuv8FXOfAPpfQvVlmlTHZ3yf3E5oAxzP/INVhBIJCGrkijhCl5+UAPg==}
|
||||||
|
engines: {node: '>=18.12.0'}
|
||||||
|
peerDependencies:
|
||||||
|
vue: '>=3.2.0'
|
||||||
|
dependencies:
|
||||||
|
date-fns: 3.3.1
|
||||||
|
vue: 3.4.21(typescript@5.3.3)
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@vuetify/loader-shared@2.0.2(vue@3.4.21)(vuetify@3.5.6):
|
/@vuetify/loader-shared@2.0.2(vue@3.4.21)(vuetify@3.5.6):
|
||||||
resolution: {integrity: sha512-91itRxkTRKUhEZhWR/ICfYml1WkVxC7/DIeJEyUzzzLQxRo9wpyk+rhFtwHUUJE2O8wL1VG9L6TkR5SIUswwKQ==}
|
resolution: {integrity: sha512-91itRxkTRKUhEZhWR/ICfYml1WkVxC7/DIeJEyUzzzLQxRo9wpyk+rhFtwHUUJE2O8wL1VG9L6TkR5SIUswwKQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|||||||
188
WebDisplay/src/components/TimeRange.vue
Normal file
188
WebDisplay/src/components/TimeRange.vue
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { PropType } from 'vue';
|
||||||
|
import { subHours, addDays, startOfDay, endOfDay, isSameDay } from 'date-fns';
|
||||||
|
import TimeSpan from '@/models/time-span';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
timeSpan: { type: Number as PropType<TimeSpan>, required: true },
|
||||||
|
start: { type: Date, required: true },
|
||||||
|
end: { type: Date, required: true }
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
change: [
|
||||||
|
{
|
||||||
|
timeSpan: TimeSpan;
|
||||||
|
start: Date;
|
||||||
|
end: Date;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
refresh: [];
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const timeSpanItems: { [value: number]: string } = {
|
||||||
|
[TimeSpan.Last24Hours]: 'Last 24 hours',
|
||||||
|
[TimeSpan.Day]: 'Day'
|
||||||
|
};
|
||||||
|
|
||||||
|
const addDay = (increment: number) => {
|
||||||
|
const start = addDays(props.start, increment);
|
||||||
|
const end = addDays(props.end, increment);
|
||||||
|
|
||||||
|
emit('change', {
|
||||||
|
timeSpan: props.timeSpan,
|
||||||
|
start: start,
|
||||||
|
end: end
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTimeSpanChange = (timeSpan: TimeSpan) => {
|
||||||
|
const date = new Date();
|
||||||
|
|
||||||
|
if (timeSpan == TimeSpan.Last24Hours) {
|
||||||
|
const end = date;
|
||||||
|
const start = subHours(end, 24);
|
||||||
|
|
||||||
|
emit('change', {
|
||||||
|
timeSpan: timeSpan,
|
||||||
|
start: start,
|
||||||
|
end: end
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const end = endOfDay(date);
|
||||||
|
const start = startOfDay(date);
|
||||||
|
|
||||||
|
emit('change', {
|
||||||
|
timeSpan: timeSpan,
|
||||||
|
start: start,
|
||||||
|
end: end
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const showDayBack = () => {
|
||||||
|
return props.timeSpan === TimeSpan.Day;
|
||||||
|
};
|
||||||
|
|
||||||
|
const showDayForward = () => {
|
||||||
|
return props.timeSpan === TimeSpan.Day && !isSameDay(props.start, new Date());
|
||||||
|
};
|
||||||
|
|
||||||
|
const refresh = () => {
|
||||||
|
const date = new Date();
|
||||||
|
|
||||||
|
if (props.timeSpan == TimeSpan.Last24Hours) {
|
||||||
|
const end = date;
|
||||||
|
const start = subHours(end, 24);
|
||||||
|
|
||||||
|
emit('change', {
|
||||||
|
timeSpan: props.timeSpan,
|
||||||
|
start: start,
|
||||||
|
end: end
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
emit('refresh');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const setToday = () => {
|
||||||
|
const date = new Date();
|
||||||
|
|
||||||
|
const end = endOfDay(date);
|
||||||
|
const start = startOfDay(date);
|
||||||
|
|
||||||
|
emit('change', {
|
||||||
|
timeSpan: props.timeSpan,
|
||||||
|
start: start,
|
||||||
|
end: end
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const setDate = (value: Date) => {
|
||||||
|
const end = endOfDay(value);
|
||||||
|
const start = startOfDay(value);
|
||||||
|
|
||||||
|
emit('change', {
|
||||||
|
timeSpan: props.timeSpan,
|
||||||
|
start: start,
|
||||||
|
end: end
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<v-app-bar
|
||||||
|
class="bar"
|
||||||
|
density="compact"
|
||||||
|
fixed
|
||||||
|
:elevation="0">
|
||||||
|
<v-toolbar-items>
|
||||||
|
<v-btn
|
||||||
|
icon
|
||||||
|
@click="refresh()">
|
||||||
|
<v-icon>mdi-refresh</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
<v-menu>
|
||||||
|
<template v-slot:activator="{ props }">
|
||||||
|
<v-btn
|
||||||
|
class="ml-2"
|
||||||
|
color="primary"
|
||||||
|
v-bind="props">
|
||||||
|
{{ timeSpanItems[timeSpan] }}
|
||||||
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
<v-list :value="props.timeSpan">
|
||||||
|
<v-list-item
|
||||||
|
v-for="(item, index) in timeSpanItems"
|
||||||
|
:key="index"
|
||||||
|
:value="index"
|
||||||
|
@click="handleTimeSpanChange(+index)">
|
||||||
|
<v-list-item-title>{{ item }}</v-list-item-title>
|
||||||
|
</v-list-item>
|
||||||
|
</v-list>
|
||||||
|
</v-menu>
|
||||||
|
<v-btn
|
||||||
|
class="ml-2"
|
||||||
|
icon
|
||||||
|
@click="addDay(-1)"
|
||||||
|
v-show="showDayBack()">
|
||||||
|
<v-icon>mdi-arrow-left</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
<VueDatePicker
|
||||||
|
class="date-picker"
|
||||||
|
v-show="showDayBack()"
|
||||||
|
auto-apply
|
||||||
|
:model-value="props.start"
|
||||||
|
@update:model-value="setDate"
|
||||||
|
:clearable="false"
|
||||||
|
:max-date="new Date()"
|
||||||
|
:teleport="true"
|
||||||
|
:enable-time-picker="false" />
|
||||||
|
<v-btn
|
||||||
|
icon
|
||||||
|
@click="addDay(1)"
|
||||||
|
v-show="showDayForward()">
|
||||||
|
<v-icon>mdi-arrow-right</v-icon>
|
||||||
|
</v-btn>
|
||||||
|
<v-btn
|
||||||
|
class="ml-2"
|
||||||
|
@click="setToday()"
|
||||||
|
v-show="showDayForward()">
|
||||||
|
Today
|
||||||
|
</v-btn>
|
||||||
|
</v-toolbar-items>
|
||||||
|
</v-app-bar>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.bar {
|
||||||
|
background-color: #eeeeee;
|
||||||
|
border-bottom: 1px solid lightgray;
|
||||||
|
}
|
||||||
|
|
||||||
|
.date-picker {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -11,7 +11,12 @@
|
|||||||
valueDecimalPoints: { type: Number, required: false, default: 2 },
|
valueDecimalPoints: { type: Number, required: false, default: 2 },
|
||||||
group: { type: String, required: false, default: undefined },
|
group: { type: String, required: false, default: undefined },
|
||||||
stepline: { type: Boolean, required: false, default: false },
|
stepline: { type: Boolean, required: false, default: false },
|
||||||
ready: { type: Boolean, required: true }
|
ready: { type: Boolean, required: true },
|
||||||
|
yAxisMinimum: { type: Number, required: false, default: undefined },
|
||||||
|
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 }
|
||||||
});
|
});
|
||||||
|
|
||||||
var chartOptions: ApexOptions = {
|
var chartOptions: ApexOptions = {
|
||||||
@@ -66,12 +71,18 @@
|
|||||||
formatter: (value) => {
|
formatter: (value) => {
|
||||||
return `${value.toFixed(props.yAxisDecimalPoints)}${props.unit}`;
|
return `${value.toFixed(props.yAxisDecimalPoints)}${props.unit}`;
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
tickAmount: props.tickAmount,
|
||||||
|
min: props.yAxisMinimum,
|
||||||
|
max: props.yAxisMaximum
|
||||||
},
|
},
|
||||||
stroke: {
|
stroke: {
|
||||||
width: 2,
|
width: props.lineSize,
|
||||||
curve: props.stepline ? 'stepline' : 'smooth'
|
curve: props.stepline ? 'stepline' : 'smooth'
|
||||||
},
|
},
|
||||||
|
markers: {
|
||||||
|
size: props.markerSize
|
||||||
|
},
|
||||||
dataLabels: {
|
dataLabels: {
|
||||||
enabled: false
|
enabled: false
|
||||||
}
|
}
|
||||||
@@ -96,7 +107,7 @@
|
|||||||
<apexchart
|
<apexchart
|
||||||
v-else
|
v-else
|
||||||
width="100%"
|
width="100%"
|
||||||
height="300"
|
height="250"
|
||||||
:type="props.type"
|
:type="props.type"
|
||||||
:options="chartOptions"
|
:options="chartOptions"
|
||||||
:series="chartSeries"></apexchart>
|
:series="chartSeries"></apexchart>
|
||||||
@@ -106,7 +117,7 @@
|
|||||||
<style scoped>
|
<style scoped>
|
||||||
.loading {
|
.loading {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
min-height: 300px;
|
min-height: 250px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chart {
|
.chart {
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ import { createPinia } from 'pinia';
|
|||||||
|
|
||||||
import VueApexCharts from 'vue3-apexcharts';
|
import VueApexCharts from 'vue3-apexcharts';
|
||||||
|
|
||||||
|
import VueDatePicker from '@vuepic/vue-datepicker';
|
||||||
|
import '@vuepic/vue-datepicker/dist/main.css';
|
||||||
|
|
||||||
const pinia = createPinia();
|
const pinia = createPinia();
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
|
||||||
@@ -14,4 +17,7 @@ registerPlugins(app);
|
|||||||
|
|
||||||
app.use(VueApexCharts);
|
app.use(VueApexCharts);
|
||||||
app.use(pinia);
|
app.use(pinia);
|
||||||
|
|
||||||
|
app.component('VueDatePicker', VueDatePicker);
|
||||||
|
|
||||||
app.mount('#app');
|
app.mount('#app');
|
||||||
|
|||||||
7
WebDisplay/src/models/time-span.ts
Normal file
7
WebDisplay/src/models/time-span.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
export enum TimeSpan {
|
||||||
|
Last24Hours,
|
||||||
|
Day,
|
||||||
|
Custom
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TimeSpan;
|
||||||
23
WebDisplay/src/models/weather/wind-direction-number.ts
Normal file
23
WebDisplay/src/models/weather/wind-direction-number.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
export enum WindDirectionNumber {
|
||||||
|
None,
|
||||||
|
North,
|
||||||
|
East,
|
||||||
|
South,
|
||||||
|
West,
|
||||||
|
NorthEast,
|
||||||
|
SouthEast,
|
||||||
|
SouthWest,
|
||||||
|
NorthWest,
|
||||||
|
NorthNorthEast,
|
||||||
|
EastNorthEast,
|
||||||
|
EastSouthEast,
|
||||||
|
SouthSouthEast,
|
||||||
|
SouthSouthWest,
|
||||||
|
WestSouthWest,
|
||||||
|
WestNorthWest,
|
||||||
|
NorthNorthWest,
|
||||||
|
Min = North,
|
||||||
|
Max = NorthNorthWest
|
||||||
|
}
|
||||||
|
|
||||||
|
export default WindDirectionNumber;
|
||||||
@@ -5,11 +5,17 @@
|
|||||||
import { ConvertCToF } from '@/temperatureConverter';
|
import { ConvertCToF } from '@/temperatureConverter';
|
||||||
import { ConvertMillibarToInchesOfMercury } from '@/pressureConverter';
|
import { ConvertMillibarToInchesOfMercury } from '@/pressureConverter';
|
||||||
import ValueChart from '../components/ValueChart.vue';
|
import ValueChart from '../components/ValueChart.vue';
|
||||||
|
import TimeRange from '@/components/TimeRange.vue';
|
||||||
|
import TimeSpan from '@/models/time-span';
|
||||||
|
|
||||||
const indoorStore = createIndoorStore('charts');
|
const indoorStore = createIndoorStore('charts');
|
||||||
|
|
||||||
const ready = ref(false);
|
const ready = ref(false);
|
||||||
|
|
||||||
|
const end = ref(new Date());
|
||||||
|
const start = ref(subHours(end.value, 24));
|
||||||
|
const timeSpan = ref(TimeSpan.Last24Hours);
|
||||||
|
|
||||||
const categories: number[] = [];
|
const categories: number[] = [];
|
||||||
|
|
||||||
const mainTemperatureSeries = { name: 'Upstairs', data: [] as number[] };
|
const mainTemperatureSeries = { name: 'Upstairs', data: [] as number[] };
|
||||||
@@ -21,10 +27,21 @@
|
|||||||
const mainPressureSeries = { name: 'Upstairs', data: [] as number[] };
|
const mainPressureSeries = { name: 'Upstairs', data: [] as number[] };
|
||||||
const basementPressureSeries = { name: 'Downstairs', data: [] as number[] };
|
const basementPressureSeries = { name: 'Downstairs', data: [] as number[] };
|
||||||
|
|
||||||
const end = new Date();
|
const load = () => {
|
||||||
const start = subHours(end, 24);
|
ready.value = false;
|
||||||
|
|
||||||
indoorStore.getReadingValueHistoryGrouped(start, end, 15).then((groupedReadingsList) => {
|
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) => {
|
||||||
groupedReadingsList.forEach((groupedReadings) => {
|
groupedReadingsList.forEach((groupedReadings) => {
|
||||||
if (groupedReadings.name === 'main') {
|
if (groupedReadings.name === 'main') {
|
||||||
categories.push(new Date(groupedReadings.bucket).getTime());
|
categories.push(new Date(groupedReadings.bucket).getTime());
|
||||||
@@ -41,12 +58,30 @@
|
|||||||
|
|
||||||
ready.value = true;
|
ready.value = true;
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
load();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-container
|
<v-container
|
||||||
fluid
|
fluid
|
||||||
class="container">
|
class="container">
|
||||||
|
<TimeRange
|
||||||
|
:time-span="timeSpan"
|
||||||
|
:start="start"
|
||||||
|
:end="end"
|
||||||
|
@change="
|
||||||
|
(value) => {
|
||||||
|
timeSpan = value.timeSpan;
|
||||||
|
start = value.start;
|
||||||
|
end = value.end;
|
||||||
|
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@refresh="load"></TimeRange>
|
||||||
|
<div class="content">
|
||||||
<v-row
|
<v-row
|
||||||
dense
|
dense
|
||||||
align="start">
|
align="start">
|
||||||
@@ -88,6 +123,7 @@
|
|||||||
:series="[mainPressureSeries, basementPressureSeries]"></ValueChart>
|
:series="[mainPressureSeries, basementPressureSeries]"></ValueChart>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
</div>
|
||||||
</v-container>
|
</v-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -95,5 +131,10 @@
|
|||||||
.container {
|
.container {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: #fafafa;
|
background-color: #fafafa;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -4,6 +4,9 @@
|
|||||||
import { useWeatherStore } from '@/stores/weatherStore';
|
import { useWeatherStore } from '@/stores/weatherStore';
|
||||||
import { ConvertPascalToInchesOfMercury } from '@/pressureConverter';
|
import { ConvertPascalToInchesOfMercury } from '@/pressureConverter';
|
||||||
import ValueChart from '../components/ValueChart.vue';
|
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';
|
||||||
|
|
||||||
const weatherStore = useWeatherStore();
|
const weatherStore = useWeatherStore();
|
||||||
|
|
||||||
@@ -22,11 +25,29 @@
|
|||||||
const windMinimumSeries = { name: 'Minimum', data: [] as number[] };
|
const windMinimumSeries = { name: 'Minimum', data: [] as number[] };
|
||||||
const windAverageSeries = { name: 'Average', data: [] as number[] };
|
const windAverageSeries = { name: 'Average', data: [] as number[] };
|
||||||
const windMaximumSeries = { name: 'Maximum', data: [] as number[] };
|
const windMaximumSeries = { name: 'Maximum', data: [] as number[] };
|
||||||
|
const windDirectionSeries = { name: 'Average Direction', data: [] as number[] };
|
||||||
|
|
||||||
const end = new Date();
|
const end = ref(new Date());
|
||||||
const start = subHours(end, 24);
|
const start = ref(subHours(end.value, 24));
|
||||||
|
const timeSpan = ref(TimeSpan.Last24Hours);
|
||||||
|
|
||||||
weatherStore.getReadingHistoryGrouped(start, end, 15).then((groupedReadingsList) => {
|
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) => {
|
groupedReadingsList.forEach((groupedReadings) => {
|
||||||
readingsCategories.push(new Date(groupedReadings.bucket).getTime());
|
readingsCategories.push(new Date(groupedReadings.bucket).getTime());
|
||||||
|
|
||||||
@@ -40,23 +61,43 @@
|
|||||||
readingsReady.value = true;
|
readingsReady.value = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
weatherStore.getWindHistoryGrouped(start, end, 15).then((groupedReadingsList) => {
|
weatherStore.getWindHistoryGrouped(start.value, end.value, 15).then((groupedReadingsList) => {
|
||||||
groupedReadingsList.forEach((groupedReadings) => {
|
groupedReadingsList.forEach((groupedReadings) => {
|
||||||
windCategories.push(new Date(groupedReadings.bucket).getTime());
|
windCategories.push(new Date(groupedReadings.bucket).getTime());
|
||||||
|
|
||||||
windMinimumSeries.data.push(groupedReadings.minimumSpeed);
|
windMinimumSeries.data.push(groupedReadings.minimumSpeed);
|
||||||
windAverageSeries.data.push(groupedReadings.averageSpeed);
|
windAverageSeries.data.push(groupedReadings.averageSpeed);
|
||||||
windMaximumSeries.data.push(groupedReadings.maximumSpeed);
|
windMaximumSeries.data.push(groupedReadings.maximumSpeed);
|
||||||
|
|
||||||
|
windDirectionSeries.data.push(groupedReadings.averageDirection);
|
||||||
});
|
});
|
||||||
|
|
||||||
windReady.value = true;
|
windReady.value = true;
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
load();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-container
|
<v-container
|
||||||
fluid
|
fluid
|
||||||
class="container">
|
class="container">
|
||||||
|
<TimeRange
|
||||||
|
:time-span="timeSpan"
|
||||||
|
:start="start"
|
||||||
|
:end="end"
|
||||||
|
@change="
|
||||||
|
(value) => {
|
||||||
|
timeSpan = value.timeSpan;
|
||||||
|
start = value.start;
|
||||||
|
end = value.end;
|
||||||
|
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@refresh="load"></TimeRange>
|
||||||
|
<div class="content">
|
||||||
<v-row
|
<v-row
|
||||||
dense
|
dense
|
||||||
align="start">
|
align="start">
|
||||||
@@ -128,7 +169,8 @@
|
|||||||
unit='"'
|
unit='"'
|
||||||
group="outdoor"
|
group="outdoor"
|
||||||
:stepline="true"
|
:stepline="true"
|
||||||
:y-axis-decimal-points="2"
|
:y-axis-decimal-points="3"
|
||||||
|
:value-decimal-points="2"
|
||||||
:categories="readingsCategories"
|
:categories="readingsCategories"
|
||||||
:series="[rainSeries]">
|
:series="[rainSeries]">
|
||||||
</ValueChart>
|
</ValueChart>
|
||||||
@@ -140,15 +182,35 @@
|
|||||||
<ValueChart
|
<ValueChart
|
||||||
:ready="windReady"
|
:ready="windReady"
|
||||||
type="line"
|
type="line"
|
||||||
title="Wind"
|
title="Wind Speed"
|
||||||
unit=" MPH"
|
unit=" MPH"
|
||||||
group="outdoor"
|
group="outdoor"
|
||||||
:y-axis-decimal-points="0"
|
:y-axis-decimal-points="0"
|
||||||
:categories="windCategories"
|
:categories="windCategories"
|
||||||
:series="[windMinimumSeries, windAverageSeries, windMaximumSeries]">
|
:series="[windMaximumSeries, windAverageSeries, windMinimumSeries]">
|
||||||
|
</ValueChart>
|
||||||
|
</v-col>
|
||||||
|
<v-col
|
||||||
|
sm="4"
|
||||||
|
xl="6"
|
||||||
|
cols="12">
|
||||||
|
<ValueChart
|
||||||
|
:ready="windReady"
|
||||||
|
type="line"
|
||||||
|
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"
|
||||||
|
:categories="windCategories"
|
||||||
|
:series="[windDirectionSeries]">
|
||||||
</ValueChart>
|
</ValueChart>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
</div>
|
||||||
</v-container>
|
</v-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -156,5 +218,10 @@
|
|||||||
.container {
|
.container {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: #fafafa;
|
background-color: #fafafa;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
import { usePowerStore } from '@/stores/powerStore';
|
import { usePowerStore } from '@/stores/powerStore';
|
||||||
import { useWeatherStore } from '@/stores/weatherStore';
|
import { useWeatherStore } from '@/stores/weatherStore';
|
||||||
import ValueChart from '../components/ValueChart.vue';
|
import ValueChart from '../components/ValueChart.vue';
|
||||||
|
import TimeRange from '@/components/TimeRange.vue';
|
||||||
import WeatherValueType from '@/models/weather/weather-value-type';
|
import WeatherValueType from '@/models/weather/weather-value-type';
|
||||||
|
import TimeSpan from '@/models/time-span';
|
||||||
|
|
||||||
const powerStore = usePowerStore();
|
const powerStore = usePowerStore();
|
||||||
const weatherStore = useWeatherStore();
|
const weatherStore = useWeatherStore();
|
||||||
@@ -20,10 +22,21 @@
|
|||||||
|
|
||||||
const lightSeries = { name: 'Average Light', data: [] as number[] };
|
const lightSeries = { name: 'Average Light', data: [] as number[] };
|
||||||
|
|
||||||
const end = new Date();
|
const end = ref(new Date());
|
||||||
const start = subHours(end, 24);
|
const start = ref(subHours(end.value, 24));
|
||||||
|
const timeSpan = ref(TimeSpan.Last24Hours);
|
||||||
|
|
||||||
powerStore.getReadingHistoryGrouped(start, end, 15).then((groupedReadingsList) => {
|
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) => {
|
groupedReadingsList.forEach((groupedReadings) => {
|
||||||
powerCategories.push(new Date(groupedReadings.bucket).getTime());
|
powerCategories.push(new Date(groupedReadings.bucket).getTime());
|
||||||
|
|
||||||
@@ -34,7 +47,7 @@
|
|||||||
powerReady.value = true;
|
powerReady.value = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
weatherStore.getReadingValueHistoryGrouped(WeatherValueType.Light, start, end, 15).then((groupedReadingsList) => {
|
weatherStore.getReadingValueHistoryGrouped(WeatherValueType.Light, start.value, end.value, 15).then((groupedReadingsList) => {
|
||||||
groupedReadingsList.forEach((groupedReadings) => {
|
groupedReadingsList.forEach((groupedReadings) => {
|
||||||
lightCategories.push(new Date(groupedReadings.bucket).getTime());
|
lightCategories.push(new Date(groupedReadings.bucket).getTime());
|
||||||
|
|
||||||
@@ -43,12 +56,30 @@
|
|||||||
|
|
||||||
lightReady.value = true;
|
lightReady.value = true;
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
load();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<v-container
|
<v-container
|
||||||
fluid
|
fluid
|
||||||
class="container">
|
class="container">
|
||||||
|
<TimeRange
|
||||||
|
:time-span="timeSpan"
|
||||||
|
:start="start"
|
||||||
|
:end="end"
|
||||||
|
@change="
|
||||||
|
(value) => {
|
||||||
|
timeSpan = value.timeSpan;
|
||||||
|
start = value.start;
|
||||||
|
end = value.end;
|
||||||
|
|
||||||
|
load();
|
||||||
|
}
|
||||||
|
"
|
||||||
|
@refresh="load"></TimeRange>
|
||||||
|
<div class="content">
|
||||||
<v-row
|
<v-row
|
||||||
dense
|
dense
|
||||||
align="start">
|
align="start">
|
||||||
@@ -80,6 +111,7 @@
|
|||||||
</ValueChart>
|
</ValueChart>
|
||||||
</v-col>
|
</v-col>
|
||||||
</v-row>
|
</v-row>
|
||||||
|
</div>
|
||||||
</v-container>
|
</v-container>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -87,5 +119,10 @@
|
|||||||
.container {
|
.container {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: #fafafa;
|
background-color: #fafafa;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content {
|
||||||
|
padding: 10px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user