More new UI

This commit is contained in:
2024-03-11 01:44:32 +00:00
parent 69379d761f
commit 21f5522950
11 changed files with 615 additions and 220 deletions

View File

@@ -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']
} }

View File

@@ -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",

View File

@@ -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:

View 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>

View File

@@ -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 {

View File

@@ -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');

View File

@@ -0,0 +1,7 @@
export enum TimeSpan {
Last24Hours,
Day,
Custom
}
export default TimeSpan;

View 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;

View File

@@ -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,73 +27,103 @@
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;
groupedReadingsList.forEach((groupedReadings) => {
if (groupedReadings.name === 'main') {
categories.push(new Date(groupedReadings.bucket).getTime());
mainTemperatureSeries.data.push(ConvertCToF(groupedReadings.averageTemperature)); mainTemperatureSeries.data.length = 0;
mainHumiditySeries.data.push(groupedReadings.averageHumidity); basementTemperatureSeries.data.length = 0;
mainPressureSeries.data.push(ConvertMillibarToInchesOfMercury(groupedReadings.averagePressure));
} else if (groupedReadings.name === 'basement') { mainHumiditySeries.data.length = 0;
basementTemperatureSeries.data.push(ConvertCToF(groupedReadings.averageTemperature)); basementHumiditySeries.data.length = 0;
basementHumiditySeries.data.push(groupedReadings.averageHumidity);
basementPressureSeries.data.push(ConvertMillibarToInchesOfMercury(groupedReadings.averagePressure)); mainPressureSeries.data.length = 0;
} basementPressureSeries.data.length = 0;
indoorStore.getReadingValueHistoryGrouped(start.value, end.value, 15).then((groupedReadingsList) => {
groupedReadingsList.forEach((groupedReadings) => {
if (groupedReadings.name === 'main') {
categories.push(new Date(groupedReadings.bucket).getTime());
mainTemperatureSeries.data.push(ConvertCToF(groupedReadings.averageTemperature));
mainHumiditySeries.data.push(groupedReadings.averageHumidity);
mainPressureSeries.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));
}
});
ready.value = true;
}); });
};
ready.value = true; load();
});
</script> </script>
<template> <template>
<v-container <v-container
fluid fluid
class="container"> class="container">
<v-row <TimeRange
dense :time-span="timeSpan"
align="start"> :start="start"
<v-col :end="end"
sm="6" @change="
cols="12"> (value) => {
<ValueChart timeSpan = value.timeSpan;
:ready="ready" start = value.start;
type="line" end = value.end;
title="Temperature"
unit="°F" load();
group="indoor" }
:categories="categories" "
:series="[mainTemperatureSeries, basementTemperatureSeries]"></ValueChart> @refresh="load"></TimeRange>
</v-col> <div class="content">
<v-col <v-row
sm="6" dense
cols="12"> align="start">
<ValueChart <v-col
:ready="ready" sm="6"
type="line" cols="12">
title="Humidity" <ValueChart
unit="%" :ready="ready"
group="indoor" type="line"
:categories="categories" title="Temperature"
:series="[mainHumiditySeries, basementHumiditySeries]"></ValueChart> unit="°F"
</v-col> group="indoor"
<v-col :categories="categories"
sm="6" :series="[mainTemperatureSeries, basementTemperatureSeries]"></ValueChart>
cols="12"> </v-col>
<ValueChart <v-col
:ready="ready" sm="6"
type="line" cols="12">
title="Pressure" <ValueChart
unit='"' :ready="ready"
group="indoor" type="line"
:y-axis-decimal-points="1" title="Humidity"
:categories="categories" unit="%"
:series="[mainPressureSeries, basementPressureSeries]"></ValueChart> group="indoor"
</v-col> :categories="categories"
</v-row> :series="[mainHumiditySeries, basementHumiditySeries]"></ValueChart>
</v-col>
<v-col
sm="6"
cols="12">
<ValueChart
:ready="ready"
type="line"
title="Pressure"
unit='"'
group="indoor"
:y-axis-decimal-points="1"
:categories="categories"
:series="[mainPressureSeries, basementPressureSeries]"></ValueChart>
</v-col>
</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>

View File

@@ -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,133 +25,192 @@
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 = () => {
groupedReadingsList.forEach((groupedReadings) => { readingsReady.value = false;
readingsCategories.push(new Date(groupedReadings.bucket).getTime()); readingsCategories.length = 0;
temperatureSeries.data.length = 0;
humiditySeries.data.length = 0;
pressureSeries.data.length = 0;
lightSeries.data.length = 0;
rainSeries.data.length = 0;
temperatureSeries.data.push(groupedReadings.averageTemperature); windReady.value = false;
humiditySeries.data.push(groupedReadings.averageHumidity); windCategories.length = 0;
pressureSeries.data.push(ConvertPascalToInchesOfMercury(groupedReadings.averagePressure)); windMinimumSeries.data.length = 0;
lightSeries.data.push(groupedReadings.averageLightLevel); windAverageSeries.data.length = 0;
rainSeries.data.push(groupedReadings.rainTotal); 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());
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);
});
readingsReady.value = true;
}); });
readingsReady.value = true; weatherStore.getWindHistoryGrouped(start.value, end.value, 15).then((groupedReadingsList) => {
}); groupedReadingsList.forEach((groupedReadings) => {
windCategories.push(new Date(groupedReadings.bucket).getTime());
weatherStore.getWindHistoryGrouped(start, end, 15).then((groupedReadingsList) => { windMinimumSeries.data.push(groupedReadings.minimumSpeed);
groupedReadingsList.forEach((groupedReadings) => { windAverageSeries.data.push(groupedReadings.averageSpeed);
windCategories.push(new Date(groupedReadings.bucket).getTime()); windMaximumSeries.data.push(groupedReadings.maximumSpeed);
windMinimumSeries.data.push(groupedReadings.minimumSpeed); windDirectionSeries.data.push(groupedReadings.averageDirection);
windAverageSeries.data.push(groupedReadings.averageSpeed); });
windMaximumSeries.data.push(groupedReadings.maximumSpeed);
windReady.value = true;
}); });
};
windReady.value = true; load();
});
</script> </script>
<template> <template>
<v-container <v-container
fluid fluid
class="container"> class="container">
<v-row <TimeRange
dense :time-span="timeSpan"
align="start"> :start="start"
<v-col :end="end"
sm="4" @change="
xl="6" (value) => {
cols="12"> timeSpan = value.timeSpan;
<ValueChart start = value.start;
:ready="readingsReady" end = value.end;
type="line"
title="Temperature" load();
unit="°F" }
group="outdoor" "
:categories="readingsCategories" @refresh="load"></TimeRange>
:series="[temperatureSeries]"> <div class="content">
</ValueChart> <v-row
</v-col> dense
<v-col align="start">
sm="4" <v-col
xl="6" sm="4"
cols="12"> xl="6"
<ValueChart cols="12">
:ready="readingsReady" <ValueChart
type="line" :ready="readingsReady"
title="Humidity" type="line"
unit="%" title="Temperature"
group="outdoor" unit="°F"
:categories="readingsCategories" group="outdoor"
:series="[humiditySeries]"> :categories="readingsCategories"
</ValueChart> :series="[temperatureSeries]">
</v-col> </ValueChart>
<v-col </v-col>
sm="4" <v-col
xl="6" sm="4"
cols="12"> xl="6"
<ValueChart cols="12">
:ready="readingsReady" <ValueChart
type="line" :ready="readingsReady"
title="Pressure" type="line"
unit='"' title="Humidity"
group="outdoor" unit="%"
:y-axis-decimal-points="1" group="outdoor"
:categories="readingsCategories" :categories="readingsCategories"
:series="[pressureSeries]"> :series="[humiditySeries]">
</ValueChart> </ValueChart>
</v-col> </v-col>
<v-col <v-col
sm="4" sm="4"
xl="6" xl="6"
cols="12"> cols="12">
<ValueChart <ValueChart
:ready="readingsReady" :ready="readingsReady"
type="line" type="line"
title="Light" title="Pressure"
unit=" lx" unit='"'
group="outdoor" group="outdoor"
:categories="readingsCategories" :y-axis-decimal-points="1"
:series="[lightSeries]"> :categories="readingsCategories"
</ValueChart> :series="[pressureSeries]">
</v-col> </ValueChart>
<v-col </v-col>
sm="4" <v-col
xl="6" sm="4"
cols="12"> xl="6"
<ValueChart cols="12">
:ready="readingsReady" <ValueChart
type="line" :ready="readingsReady"
title="Rain" type="line"
unit='"' title="Light"
group="outdoor" unit=" lx"
:stepline="true" group="outdoor"
:y-axis-decimal-points="2" :categories="readingsCategories"
:categories="readingsCategories" :series="[lightSeries]">
:series="[rainSeries]"> </ValueChart>
</ValueChart> </v-col>
</v-col> <v-col
<v-col sm="4"
sm="4" xl="6"
xl="6" cols="12">
cols="12"> <ValueChart
<ValueChart :ready="readingsReady"
:ready="windReady" type="line"
type="line" title="Rain"
title="Wind" unit='"'
unit=" MPH" group="outdoor"
group="outdoor" :stepline="true"
:y-axis-decimal-points="0" :y-axis-decimal-points="3"
:categories="windCategories" :value-decimal-points="2"
:series="[windMinimumSeries, windAverageSeries, windMaximumSeries]"> :categories="readingsCategories"
</ValueChart> :series="[rainSeries]">
</v-col> </ValueChart>
</v-row> </v-col>
<v-col
sm="4"
xl="6"
cols="12">
<ValueChart
:ready="windReady"
type="line"
title="Wind Speed"
unit=" MPH"
group="outdoor"
:y-axis-decimal-points="0"
:categories="windCategories"
: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>
</v-col>
</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>

View File

@@ -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,66 +22,96 @@
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 = () => {
groupedReadingsList.forEach((groupedReadings) => { powerReady.value = false;
powerCategories.push(new Date(groupedReadings.bucket).getTime()); powerCategories.length = 0;
generationSeries.data.length = 0;
consumptionSeries.data.length = 0;
generationSeries.data.push(groupedReadings.averageGeneration); lightReady.value = false;
consumptionSeries.data.push(groupedReadings.averageConsumption); 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());
generationSeries.data.push(groupedReadings.averageGeneration);
consumptionSeries.data.push(groupedReadings.averageConsumption);
});
powerReady.value = true;
}); });
powerReady.value = true; weatherStore.getReadingValueHistoryGrouped(WeatherValueType.Light, start.value, end.value, 15).then((groupedReadingsList) => {
}); groupedReadingsList.forEach((groupedReadings) => {
lightCategories.push(new Date(groupedReadings.bucket).getTime());
weatherStore.getReadingValueHistoryGrouped(WeatherValueType.Light, start, end, 15).then((groupedReadingsList) => { lightSeries.data.push(groupedReadings.averageValue);
groupedReadingsList.forEach((groupedReadings) => { });
lightCategories.push(new Date(groupedReadings.bucket).getTime());
lightSeries.data.push(groupedReadings.averageValue); lightReady.value = true;
}); });
};
lightReady.value = true; load();
});
</script> </script>
<template> <template>
<v-container <v-container
fluid fluid
class="container"> class="container">
<v-row <TimeRange
dense :time-span="timeSpan"
align="start"> :start="start"
<v-col :end="end"
sm="6" @change="
cols="12"> (value) => {
<ValueChart timeSpan = value.timeSpan;
:ready="powerReady" start = value.start;
type="line" end = value.end;
title="Power"
unit=" W" load();
group="power" }
:y-axis-decimal-points="0" "
:value-decimal-points="0" @refresh="load"></TimeRange>
:categories="powerCategories" <div class="content">
:series="[generationSeries, consumptionSeries]"></ValueChart> <v-row
</v-col> dense
<v-col align="start">
sm="6" <v-col
cols="12"> sm="6"
<ValueChart cols="12">
:ready="lightReady" <ValueChart
type="line" :ready="powerReady"
title="Light" type="line"
unit=" lx" title="Power"
group="power" unit=" W"
:categories="lightCategories" group="power"
:series="[lightSeries]"> :y-axis-decimal-points="0"
</ValueChart> :value-decimal-points="0"
</v-col> :categories="powerCategories"
</v-row> :series="[generationSeries, consumptionSeries]"></ValueChart>
</v-col>
<v-col
sm="6"
cols="12">
<ValueChart
:ready="lightReady"
type="line"
title="Light"
unit=" lx"
group="power"
:categories="lightCategories"
:series="[lightSeries]">
</ValueChart>
</v-col>
</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>