git commit -m "feat: Enhance DetailModal with auto-loading and improved UX
- Add automatic data loading every 2 seconds when no chart data available - Implement intelligent cursor-wait display for entire modal during loading - Auto-reset to 'Alle Messwerte' (DIA0) and clear date fields on modal open - Add Tailwind-based color system for chart lines (gray for min/max, littwin-blue for current/average) - Improve chart line layering with background/foreground organization - Add periodic UI updates to ensure responsive loading feedback - Maintain manual 'Daten laden' button control alongside auto-loading - Fix TypeScript dependencies and optimize useEffect performance"
This commit is contained in:
@@ -6,6 +6,6 @@ NEXT_PUBLIC_USE_MOCK_BACKEND_LOOP_START=false
|
|||||||
NEXT_PUBLIC_EXPORT_STATIC=false
|
NEXT_PUBLIC_EXPORT_STATIC=false
|
||||||
NEXT_PUBLIC_USE_CGI=false
|
NEXT_PUBLIC_USE_CGI=false
|
||||||
# App-Versionsnummer
|
# App-Versionsnummer
|
||||||
NEXT_PUBLIC_APP_VERSION=1.6.679
|
NEXT_PUBLIC_APP_VERSION=1.6.680
|
||||||
NEXT_PUBLIC_CPL_MODE=json # json (Entwicklungsumgebung) oder jsSimulatedProd (CPL ->CGI-Interface-Simulator) oder production (CPL-> CGI-Interface Platzhalter)
|
NEXT_PUBLIC_CPL_MODE=json # json (Entwicklungsumgebung) oder jsSimulatedProd (CPL ->CGI-Interface-Simulator) oder production (CPL-> CGI-Interface Platzhalter)
|
||||||
|
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ NEXT_PUBLIC_CPL_API_PATH=/CPL
|
|||||||
NEXT_PUBLIC_EXPORT_STATIC=true
|
NEXT_PUBLIC_EXPORT_STATIC=true
|
||||||
NEXT_PUBLIC_USE_CGI=true
|
NEXT_PUBLIC_USE_CGI=true
|
||||||
# App-Versionsnummer
|
# App-Versionsnummer
|
||||||
NEXT_PUBLIC_APP_VERSION=1.6.679
|
NEXT_PUBLIC_APP_VERSION=1.6.680
|
||||||
NEXT_PUBLIC_CPL_MODE=production
|
NEXT_PUBLIC_CPL_MODE=production
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
|
## [1.6.680] – 2025-08-01
|
||||||
|
|
||||||
|
- fix: System ->Detailansicht -> Modal
|
||||||
|
|
||||||
|
---
|
||||||
## [1.6.679] – 2025-08-01
|
## [1.6.679] – 2025-08-01
|
||||||
|
|
||||||
- fix: Chart System
|
- fix: Chart System
|
||||||
|
|||||||
@@ -148,6 +148,7 @@ export const DetailModal = ({
|
|||||||
});
|
});
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [shouldUpdateChart, setShouldUpdateChart] = useState(false);
|
const [shouldUpdateChart, setShouldUpdateChart] = useState(false);
|
||||||
|
const [forceUpdate, setForceUpdate] = useState(0); // Für periodische UI-Updates
|
||||||
|
|
||||||
const reduxData = useSelector((state: RootState) => {
|
const reduxData = useSelector((state: RootState) => {
|
||||||
switch (selectedKey) {
|
switch (selectedKey) {
|
||||||
@@ -173,46 +174,6 @@ export const DetailModal = ({
|
|||||||
);
|
);
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
// Reset Zeitraum auf DIA0 und Datumswerte wenn Modal geöffnet wird
|
|
||||||
useEffect(() => {
|
|
||||||
if (isOpen) {
|
|
||||||
setZeitraum("DIA0");
|
|
||||||
dispatch(setVonDatum(""));
|
|
||||||
dispatch(setBisDatum(""));
|
|
||||||
|
|
||||||
// Automatisch Daten laden nach dem Reset
|
|
||||||
setTimeout(() => {
|
|
||||||
handleFetchData();
|
|
||||||
}, 100); // Kurze Verzögerung damit setZeitraum wirksam wird
|
|
||||||
}
|
|
||||||
}, [isOpen, setZeitraum, dispatch]);
|
|
||||||
|
|
||||||
const toggleFullScreen = () => {
|
|
||||||
dispatch(setFullScreen(!isFullScreen));
|
|
||||||
setTimeout(() => {
|
|
||||||
chartRef.current?.resize();
|
|
||||||
}, 50);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleClose = () => {
|
|
||||||
dispatch(setFullScreen(false));
|
|
||||||
dispatch(setVonDatum(""));
|
|
||||||
dispatch(setBisDatum(""));
|
|
||||||
onClose();
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const loadZoomPlugin = async () => {
|
|
||||||
if (typeof window !== "undefined") {
|
|
||||||
const zoomPlugin = (await import("chartjs-plugin-zoom")).default;
|
|
||||||
if (!ChartJS.registry.plugins.get("zoom")) {
|
|
||||||
ChartJS.register(zoomPlugin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
loadZoomPlugin();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
// API-Request beim Klick auf "Daten laden" - memoized für useEffect dependency
|
// API-Request beim Klick auf "Daten laden" - memoized für useEffect dependency
|
||||||
const handleFetchData = useCallback(() => {
|
const handleFetchData = useCallback(() => {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
@@ -247,6 +208,67 @@ export const DetailModal = ({
|
|||||||
}
|
}
|
||||||
}, [selectedKey, zeitraum, dispatch]);
|
}, [selectedKey, zeitraum, dispatch]);
|
||||||
|
|
||||||
|
// Reset Zeitraum auf DIA0 und Datumswerte wenn Modal geöffnet wird
|
||||||
|
useEffect(() => {
|
||||||
|
if (isOpen) {
|
||||||
|
setZeitraum("DIA0");
|
||||||
|
dispatch(setVonDatum(""));
|
||||||
|
dispatch(setBisDatum(""));
|
||||||
|
|
||||||
|
// Chart-Daten zurücksetzen beim Öffnen
|
||||||
|
setChartData({ datasets: [] });
|
||||||
|
}
|
||||||
|
}, [isOpen, setZeitraum, dispatch]);
|
||||||
|
|
||||||
|
// Periodische UI-Updates alle 2 Sekunden während Wartezeit
|
||||||
|
useEffect(() => {
|
||||||
|
if (isOpen && (!chartData.datasets || chartData.datasets.length === 0)) {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
setForceUpdate((prev) => prev + 1); // Force re-render für cursor-wait Update
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}
|
||||||
|
}, [isOpen, chartData.datasets]);
|
||||||
|
|
||||||
|
// Automatisches "Daten laden" alle 2 Sekunden wenn keine Daten vorhanden
|
||||||
|
useEffect(() => {
|
||||||
|
if (isOpen && (!chartData.datasets || chartData.datasets.length === 0)) {
|
||||||
|
const interval = setInterval(() => {
|
||||||
|
console.log("Auto-clicking 'Daten laden' button...");
|
||||||
|
handleFetchData(); // Automatisch Daten laden
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
|
return () => clearInterval(interval);
|
||||||
|
}
|
||||||
|
}, [isOpen, chartData.datasets, handleFetchData]);
|
||||||
|
|
||||||
|
const toggleFullScreen = () => {
|
||||||
|
dispatch(setFullScreen(!isFullScreen));
|
||||||
|
setTimeout(() => {
|
||||||
|
chartRef.current?.resize();
|
||||||
|
}, 50);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
dispatch(setFullScreen(false));
|
||||||
|
dispatch(setVonDatum(""));
|
||||||
|
dispatch(setBisDatum(""));
|
||||||
|
onClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const loadZoomPlugin = async () => {
|
||||||
|
if (typeof window !== "undefined") {
|
||||||
|
const zoomPlugin = (await import("chartjs-plugin-zoom")).default;
|
||||||
|
if (!ChartJS.registry.plugins.get("zoom")) {
|
||||||
|
ChartJS.register(zoomPlugin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
loadZoomPlugin();
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (chartRef.current && selectedKey) {
|
if (chartRef.current && selectedKey) {
|
||||||
chartRef.current.options.plugins.title.text = `Verlauf ${selectedKey}`;
|
chartRef.current.options.plugins.title.text = `Verlauf ${selectedKey}`;
|
||||||
@@ -373,16 +395,19 @@ export const DetailModal = ({
|
|||||||
|
|
||||||
if (!isOpen || !selectedKey) return null;
|
if (!isOpen || !selectedKey) return null;
|
||||||
|
|
||||||
|
// Prüfen ob Chart Daten haben (für cursor-wait)
|
||||||
|
const hasChartData = chartData.datasets && chartData.datasets.length > 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={`fixed inset-0 bg-black bg-opacity-40 flex items-center justify-center z-50 ${
|
className={`fixed inset-0 bg-black bg-opacity-40 flex items-center justify-center z-50 ${
|
||||||
isLoading ? "cursor-wait" : ""
|
!hasChartData ? "cursor-wait" : ""
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={`bg-white p-6 rounded-xl overflow-auto shadow-2xl transition-all duration-300 ${
|
className={`bg-white p-6 rounded-xl overflow-auto shadow-2xl transition-all duration-300 ${
|
||||||
isFullScreen ? "w-[95vw] h-[90vh]" : "w-[50%] h-[60%]"
|
isFullScreen ? "w-[95vw] h-[90vh]" : "w-[50%] h-[60%]"
|
||||||
}`}
|
} ${!hasChartData ? "cursor-wait" : ""}`}
|
||||||
>
|
>
|
||||||
<div className="relative">
|
<div className="relative">
|
||||||
<h2 className="text-xl font-semibold">
|
<h2 className="text-xl font-semibold">
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "cpl-v4",
|
"name": "cpl-v4",
|
||||||
"version": "1.6.679",
|
"version": "1.6.680",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "cpl-v4",
|
"name": "cpl-v4",
|
||||||
"version": "1.6.679",
|
"version": "1.6.680",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource/roboto": "^5.1.0",
|
"@fontsource/roboto": "^5.1.0",
|
||||||
"@headlessui/react": "^2.2.4",
|
"@headlessui/react": "^2.2.4",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "cpl-v4",
|
"name": "cpl-v4",
|
||||||
"version": "1.6.679",
|
"version": "1.6.680",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
|
|||||||
Reference in New Issue
Block a user