Skip to content

Commit

Permalink
Enable window selection for charts
Browse files Browse the repository at this point in the history
  • Loading branch information
bnord01 committed Jan 16, 2024
1 parent 26134be commit 1eeb9e8
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 22 deletions.
40 changes: 27 additions & 13 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,24 @@ import SidePanel from "./components/SidePanel";
import { useBoolean } from "@fluentui/react-hooks";
import MoistureMarkers from "./components/MoistureMarkers";
import { Info, Imprint } from "./components/Markdown";
import { useEffect, useState } from "react";
import { createContext, useEffect, useState } from "react";

export enum HistoryWindow {
daily = "1d",
weekly = "1w",
monthly = "4w",
}
export const HistoryWindowContext = createContext<{
historyWindow: HistoryWindow;
setHistoryWindow: React.Dispatch<React.SetStateAction<HistoryWindow>>;
}>({ historyWindow: HistoryWindow.daily, setHistoryWindow: () => {} });

function App() {
const position: [number, number] = [52.01, 8.542732];
const zoom = 13;

const [historyWindow, setHistoryWindow] = useState(HistoryWindow.daily);

const [imprintOpen, { setTrue: openImprint, setFalse: dismissImprint }] = useBoolean(false);
const [infoOpen, { setTrue: openInfo, setFalse: dismissInfo }] = useBoolean(false);

Expand All @@ -24,18 +36,20 @@ function App() {
});

return (
<div className="App">
<SidePanel isOpen={infoOpen} dismissPanel={() => dismissInfo()} children={<Info />} />
<SidePanel isOpen={imprintOpen} dismissPanel={() => dismissImprint()} children={<Imprint />} />
<MapContainer zoomControl={false} center={position} zoom={zoom} style={{ height: height }}>
<MoistureMarkers />
<TileLayer
attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<AppCommandBar openImprint={openImprint} openInfo={openInfo} />
</MapContainer>
</div>
<HistoryWindowContext.Provider value={{ historyWindow, setHistoryWindow }}>
<div className="App">
<SidePanel isOpen={infoOpen} dismissPanel={() => dismissInfo()} children={<Info />} />
<SidePanel isOpen={imprintOpen} dismissPanel={() => dismissImprint()} children={<Imprint />} />
<MapContainer zoomControl={false} center={position} zoom={zoom} style={{ height: height }}>
<MoistureMarkers />
<TileLayer
attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
/>
<AppCommandBar openImprint={openImprint} openInfo={openInfo} />
</MapContainer>
</div>
</HistoryWindowContext.Provider>
);
}

Expand Down
15 changes: 11 additions & 4 deletions src/components/SensorChart/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import { Chart } from "react-chartjs-2";
import { SensorDetails, SensorInfo } from "../../model/models";
import useSensorDetails from "../../hooks/useSensorDetails";
import { mergeStyleSets } from "@fluentui/react";

// ChartJS setup
ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, BarElement, Tooltip, Legend, LineController);
Expand Down Expand Up @@ -92,10 +93,16 @@ function extractRecentDaysDataset(details: SensorDetails): ChartData<"bar" | "li
};
}

const style = mergeStyleSets({
message: {
textAlign: "center",
width: "100%",
},
});

export default function SensorChart({ sensorInfo }: { sensorInfo: SensorInfo }) {
const { details, loading, error } = useSensorDetails(sensorInfo);
const { details, loading } = useSensorDetails(sensorInfo);
if (details) return <Chart type="line" options={recentDaysChartOptions} data={extractRecentDaysDataset(details)} />;
else if (loading) return "Loading";
else if (error) return "Error";
return "No chart";
else if (loading) return <div className={style.message}>lade Verlauf</div>;
return <div className={style.message}>Fehler beim Laden :(</div>;
}
39 changes: 35 additions & 4 deletions src/components/SensorTooltip/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { FontWeights, getTheme, mergeStyleSets, Text } from "@fluentui/react";
import { Dropdown, FontWeights, getTheme, Label, mergeStyleSets, Text } from "@fluentui/react";
import { SensorInfo } from "../../model/models";
import SensorChart from "../SensorChart";
import { useContext } from "react";
import { HistoryWindow, HistoryWindowContext } from "../../App";

// Styles
const theme = getTheme();
Expand All @@ -19,8 +21,19 @@ const styles = mergeStyleSets({
height: "100%",
padding: "0 18px 15px",
},
history: {
marginTop: "1em",
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
},
dropdown: {
minWidth: "11em",
},
chart: {
minHeight: "200px",
display: "flex",
alignItems: "center",
},
subtext: [
theme.fonts.small,
Expand All @@ -45,6 +58,7 @@ const styles = mergeStyleSets({

const SensorTooltip = ({ record }: { record: SensorInfo }) => {
const format = (n: number) => new Intl.NumberFormat("de-DE", { maximumFractionDigits: 2 }).format(Number(n));
const { historyWindow, setHistoryWindow } = useContext(HistoryWindowContext);
return (
<>
<div className={styles.inner}>
Expand Down Expand Up @@ -85,14 +99,31 @@ const SensorTooltip = ({ record }: { record: SensorInfo }) => {
)}
</tbody>
</table>
<div className={styles.history}>
<Label>Verlauf</Label>
<Dropdown
className={styles.dropdown}
options={[
{ key: "1d", text: "täglich" },
{ key: "1w", text: "wöchentlich" },
{ key: "4w", text: "monatlich" },
]}
defaultSelectedKey={historyWindow}
onChange={(event, option) => {
if (Object.values(HistoryWindow).includes(option?.key as any)) {
setHistoryWindow(option?.key as any);
}
}}
/>
</div>
<div className={styles.chart}>
<SensorChart sensorInfo={record} />
</div>
<div className={styles.footer}>
<Text className={styles.subtext}>
Letzte Aktualisierung: {record.last_updated.toLocaleString()}
</Text>
</div>
<div className={styles.chart}>
<SensorChart sensorInfo={record} />
</div>
</div>
</>
);
Expand Down
5 changes: 4 additions & 1 deletion src/hooks/useSensorDetails.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import useFetch from "use-http";
import { SensorDetails, SensorInfo } from "../model/models";
import { useContext } from "react";
import { HistoryWindowContext } from "../App";

const BACKEND_URL = import.meta.env.VITE_BACKEND_URL;

Expand Down Expand Up @@ -57,7 +59,8 @@ interface SensorDetailsState {
}

export default function useSensorDetails(sensorInfo: SensorInfo): SensorDetailsState {
const url = `${BACKEND_URL}/sensorData/${sensorInfo.device}?records=7&resolution=1d`;
const { historyWindow } = useContext(HistoryWindowContext);
const url = `${BACKEND_URL}/sensorData/${sensorInfo.device}?records=7&resolution=${historyWindow}`;

const fetchResult = useFetch<SensorDetailsDto>(url, [sensorInfo]);
const { loading, error, data: dto } = fetchResult;
Expand Down

0 comments on commit 1eeb9e8

Please sign in to comment.