feat(web-app): consistant inter-component communication

- All data are managed from the TimeSeriesManager.
- All other props of componenets were deleted
This commit is contained in:
fastium
2025-05-20 09:46:36 +02:00
parent a83257eb49
commit 71f8883f16
4 changed files with 75 additions and 116 deletions

View File

@@ -9,24 +9,12 @@
<div class="main-content"> <div class="main-content">
<!-- Left Sidebar with Controls --> <!-- Left Sidebar with Controls -->
<div class="sidebar"> <div class="sidebar">
<ControlPanel <ControlPanel :manager="manager" />
:show-temperature.sync="showTemperature"
:show-humidity.sync="showHumidity"
@add-temperature="addTemperature"
@refresh="refreshData"
:manager="manager"
/>
</div> </div>
<!-- Right Side Chart Area --> <!-- Right Side Chart Area -->
<div class="chart-area"> <div class="chart-area">
<ChartComponent <ChartComponent :manager="manager" />
:series="series"
:show-temperature="showTemperature"
:show-humidity="showHumidity"
:loading="loading"
:error="error"
/>
</div> </div>
</div> </div>
</div> </div>
@@ -38,7 +26,7 @@ import ChartComponent from "./components/ChartComponent.vue";
import ControlPanel from "./components/ControlPanel.vue"; import ControlPanel from "./components/ControlPanel.vue";
import { HttpClient } from "./Services/HttpClient"; import { HttpClient } from "./Services/HttpClient";
import { TimeSeriesManager } from "./Measures/TimeSeriesManager"; import { TimeSeriesManager } from "./Measures/TimeSeriesManager";
import { URL, USERNAME, PASSWORD, USER, ROOM, DEVICE, APP_NAME } from "./const"; import { URL, USERNAME, PASSWORD, APP_NAME } from "./const";
import { Serie } from "./Measures/Serie"; import { Serie } from "./Measures/Serie";
let httpClient = new HttpClient(URL, USERNAME, PASSWORD); let httpClient = new HttpClient(URL, USERNAME, PASSWORD);
@@ -53,53 +41,8 @@ export default defineComponent({
data() { data() {
return { return {
manager, manager,
series: [] as any[],
loading: true,
error: undefined as string | undefined,
showTemperature: true,
showHumidity: true,
}; };
}, },
methods: {
addTemperature() {
// Implement your functionality here
console.log("Add temperature clicked");
manager
.getNewValue(USER, ROOM, DEVICE)
.then((result) => {})
.catch((error) => {
console.error("Error asking data:", error);
this.error = "Failed to load data. Please try again later.";
this.loading = false;
});
},
refreshData() {
console.log("Refreshing data...");
this.fetchData();
},
fetchData() {
this.loading = true;
this.error = undefined;
manager
.getTimeSeriesData(USER, ROOM, DEVICE)
.then((result) => {
this.series = result;
this.loading = false;
})
.catch((error) => {
console.error("Error fetching data:", error);
this.error = "Failed to load data. Please try again later.";
this.loading = false;
});
},
},
mounted() {
// Fetch data when component is mounted
this.fetchData();
},
}); });
</script> </script>

View File

@@ -57,16 +57,17 @@ export class TimeSeriesManager {
}, },
]; ];
error = ref(false);
loading = ref("");
series = ref<Serie[]>([]);
constructor(client: HttpClient) { constructor(client: HttpClient) {
this.client = client; this.client = client;
} }
async getTimeSeriesData( async getTimeSeriesData() {
user: string, this.client
room: string,
device: string
): Promise<Serie[]> {
return this.client
.getValues( .getValues(
this.selected_user.tag, this.selected_user.tag,
this.selected_room.tag, this.selected_room.tag,
@@ -112,20 +113,20 @@ export class TimeSeriesManager {
const temperatureSerie = new Serie( const temperatureSerie = new Serie(
TEMPERATURE, TEMPERATURE,
temperatureRecordsProcessed, temperatureRecordsProcessed,
user, this.selected_user.user,
room, this.selected_room.room,
device this.selected_device.device
); );
const humiditySerie = new Serie( const humiditySerie = new Serie(
HUMIDITY, HUMIDITY,
humidityRecordProcessed, humidityRecordProcessed,
user, this.selected_user.user,
room, this.selected_room.room,
device this.selected_device.device
); );
return [temperatureSerie, humiditySerie]; this.series.value = [temperatureSerie, humiditySerie];
}) })
.catch((error) => { .catch((error) => {
console.error("Error fetching time series data:", error); console.error("Error fetching time series data:", error);
@@ -133,10 +134,16 @@ export class TimeSeriesManager {
}); });
} }
async getNewValue(user: string, room: string, device: string) { async getNewValue() {
this.client.newValue(user, room, device).catch((error) => { this.client
console.error("Error asking new values:", error); .newValue(
throw error; this.selected_user.user,
}); this.selected_room.room,
this.selected_device.device
)
.catch((error) => {
console.error("Error asking new values:", this.selected_device.device);
throw error;
});
} }
} }

View File

@@ -1,8 +1,8 @@
<!-- src/components/ChartComponent.vue --> <!-- src/components/ChartComponent.vue -->
<template> <template>
<div class="chart-wrapper"> <div class="chart-wrapper">
<div v-if="loading" class="loading-state">Loading data...</div> <div v-if="manager.loading" class="loading-state">Loading data...</div>
<div v-else-if="error" class="error-state">{{ error }}</div> <div v-else-if="manager.error" class="error-state">{{ manager.error }}</div>
<div v-else class="chart-container"> <div v-else class="chart-container">
<Scatter <Scatter
v-if="chartData.datasets.length > 0" v-if="chartData.datasets.length > 0"
@@ -26,6 +26,7 @@ import {
} from "chart.js"; } from "chart.js";
import { Scatter } from "vue-chartjs"; import { Scatter } from "vue-chartjs";
import { Serie } from "../Measures/Serie"; import { Serie } from "../Measures/Serie";
import { TimeSeriesManager } from "../Measures/TimeSeriesManager";
// Register Chart.js components // Register Chart.js components
ChartJS.register(LinearScale, PointElement, LineElement, Tooltip, Legend); ChartJS.register(LinearScale, PointElement, LineElement, Tooltip, Legend);
@@ -40,32 +41,31 @@ export default defineComponent({
type: Array as PropType<Serie[]>, // Use PropType to specify array of Serie type: Array as PropType<Serie[]>, // Use PropType to specify array of Serie
default: () => [], default: () => [],
}, },
showTemperature: { manager: {
type: Boolean, type: Object as PropType<TimeSeriesManager>,
default: true, required: true,
},
showHumidity: {
type: Boolean,
default: true,
},
loading: {
type: Boolean,
default: false,
},
error: {
type: String as PropType<string | undefined>,
default: null,
}, },
}, },
setup(props) { setup(props) {
const chartData = computed(() => { const chartData = computed(() => {
let series_prepared = props.series.map((s: Serie) => { if (
return s.getSerie(); props.manager ||
}); ((props.manager as TimeSeriesManager).series.value as Serie[])
) {
let series_prepared = (props.manager.series.value as Serie[]).map(
(s: Serie) => {
return s.getSerie();
}
);
return { return {
datasets: series_prepared, datasets: series_prepared,
}; };
} else {
return {
datasets: [],
};
}
}); });
const chartOptions = { const chartOptions = {

View File

@@ -1,10 +1,10 @@
<template> <template>
<div class="control-panel"> <div class="control-panel">
<button @click="$emit('add-temperature')" class="action-button"> <button @click="addTemperature" class="action-button">
Add Temperature Add Temperature
</button> </button>
<button @click="$emit('refresh')" class="refresh-button"> <button @click="fetchData" class="refresh-button">
<span class="button-icon"></span> Refresh Data <span class="button-icon"></span> Refresh Data
</button> </button>
</div> </div>
@@ -57,8 +57,6 @@ import "vue-multiselect/dist/vue-multiselect.css"; // Add
import { ref } from "vue"; import { ref } from "vue";
import { TimeSeriesManager } from "@/Measures/TimeSeriesManager"; import { TimeSeriesManager } from "@/Measures/TimeSeriesManager";
let options = [{ code: "CA", country: "Canada" }];
export default defineComponent({ export default defineComponent({
name: "ControlPanel", name: "ControlPanel",
@@ -74,23 +72,34 @@ export default defineComponent({
manager: { manager: {
type: TimeSeriesManager, type: TimeSeriesManager,
required: true, required: true,
} },
}, },
emits: [
"add-temperature",
"update:showTemperature",
"update:showHumidity",
"refresh",
"simulate-data",
],
components: { components: {
Multiselect, Multiselect,
}, },
methods: { methods: {
setSelected(value: any) { addTemperature() {
// trigger a mutation, or dispatch an action // Implement your functionality here
console.log("Add temperature clicked");
this.manager
.getNewValue()
.then((result) => {})
.catch((error) => {
console.error("Error asking data:", error);
});
}, },
fetchData() {
console.log("Fetch data");
this.manager
.getTimeSeriesData()
.then((result) => {})
.catch((error) => {
console.error("Error fetching data:", error);
});
},
},
mounted() {
this.fetchData();
}, },
}); });
</script> </script>