From 7edc2a71d83c84ba11164552de0ac0898ffc42f4 Mon Sep 17 00:00:00 2001 From: Adevixxx Date: Fri, 28 Nov 2025 10:12:10 +0100 Subject: [PATCH] =?UTF-8?q?Ajout=20de=20l'interface=20pour=20selectionner?= =?UTF-8?q?=20des=20disques=20et=20modifications=20du=20cot=C3=A9=20serveu?= =?UTF-8?q?r=20pour=20la=20sauvegarde?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Create/Components/DiskSelection.jsx | 92 +++++++++++++++++++ .../hooks/useInfrastructureMonitorForm.jsx | 3 + .../Pages/v1/Infrastructure/Create/index.jsx | 41 +++++++++ client/src/locales/en.json | 9 +- client/vite.config.ts | 3 + server/src/db/v1/models/Monitor.js | 4 + server/src/validation/joi.js | 2 + 7 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 client/src/Pages/v1/Infrastructure/Create/Components/DiskSelection.jsx diff --git a/client/src/Pages/v1/Infrastructure/Create/Components/DiskSelection.jsx b/client/src/Pages/v1/Infrastructure/Create/Components/DiskSelection.jsx new file mode 100644 index 000000000..7bf1538c5 --- /dev/null +++ b/client/src/Pages/v1/Infrastructure/Create/Components/DiskSelection.jsx @@ -0,0 +1,92 @@ +import React from "react"; +import ConfigBox from "@/Components/v1/ConfigBox/index.jsx"; +import { Box, Stack, Typography } from "@mui/material"; +import Checkbox from "@/Components/v1/Inputs/Checkbox/index.jsx"; +import { useTheme } from "@emotion/react"; +import { useTranslation } from "react-i18next"; +import PropTypes from "prop-types"; + +const DiskSelection = ({ availableDisks, selectedDisks, onChange }) => { + const theme = useTheme(); + const { t } = useTranslation(); + + const handleDiskChange = (event, mountpoint) => { + // Le composant Checkbox personnalisé renvoie l'event natif + const isChecked = event.target.checked; + let newSelectedDisks = []; + + if (isChecked) { + newSelectedDisks = [...selectedDisks, mountpoint]; + } else { + newSelectedDisks = selectedDisks.filter((disk) => disk !== mountpoint); + } + + onChange(newSelectedDisks); + }; + + return ( + + + + {t("v1.infrastructure.disk_selection_title")} + + + {t("v1.infrastructure.disk_selection_description")} + + + + + {(!availableDisks || availableDisks.length === 0) ? ( + + {t("v1.infrastructure.disk_selection_info")} + + ) : ( + availableDisks.map((disk) => ( + /* Reproduction exacte de la structure de CustomThreshold + pour garantir l'alignement parfait avec la section Alertes + */ + + + handleDiskChange(e, disk.mountpoint)} + /> + + {/* Pas de deuxième Stack ici car nous n'avons pas besoin + du champ TextInput pour la sélection simple + */} + + )) + )} + + + ); +}; + +DiskSelection.propTypes = { + availableDisks: PropTypes.arrayOf( + PropTypes.shape({ + mountpoint: PropTypes.string.isRequired, + }) + ), + selectedDisks: PropTypes.arrayOf(PropTypes.string).isRequired, + onChange: PropTypes.func.isRequired, +}; + +export default DiskSelection; \ No newline at end of file diff --git a/client/src/Pages/v1/Infrastructure/Create/hooks/useInfrastructureMonitorForm.jsx b/client/src/Pages/v1/Infrastructure/Create/hooks/useInfrastructureMonitorForm.jsx index f0a701517..a38ac9fc6 100644 --- a/client/src/Pages/v1/Infrastructure/Create/hooks/useInfrastructureMonitorForm.jsx +++ b/client/src/Pages/v1/Infrastructure/Create/hooks/useInfrastructureMonitorForm.jsx @@ -17,6 +17,7 @@ const useInfrastructureMonitorForm = () => { temperature: false, usage_temperature: "", secret: "", + selectedDisks: [], }); const onChangeForm = (name, value) => { @@ -48,6 +49,7 @@ const useInfrastructureMonitorForm = () => { temperature: gt.temperature !== undefined, usage_temperature: gt.temperature !== undefined ? gt.temperature.toString() : "", secret: "", + selectedDisks: [], })); }, []); @@ -81,6 +83,7 @@ const useInfrastructureMonitorForm = () => { ? (thresholds.usage_temperature * 100).toString() : "", secret: monitor.secret || "", + selectedDisks: monitor.selectedDisks || [], })); }, []); return { diff --git a/client/src/Pages/v1/Infrastructure/Create/index.jsx b/client/src/Pages/v1/Infrastructure/Create/index.jsx index d4fd859ec..bcc644363 100644 --- a/client/src/Pages/v1/Infrastructure/Create/index.jsx +++ b/client/src/Pages/v1/Infrastructure/Create/index.jsx @@ -10,9 +10,11 @@ import { HttpAdornment } from "@/Components/v1/Inputs/TextInput/Adornments/index import MonitorStatusHeader from "./Components/MonitorStatusHeader.jsx"; import MonitorActionButtons from "./Components/MonitorActionButtons.jsx"; import CustomAlertsSection from "./Components/CustomAlertsSection.jsx"; +import DiskSelection from "./Components/DiskSelection.jsx"; // Utils import NotificationsConfig from "@/Components/v1/NotificationConfig/index.jsx"; import { useGetNotificationsByTeamId } from "../../../../Hooks/v1/useNotifications.js"; +import NetworkService from "../../../../Utils/NetworkService"; import { useParams } from "react-router-dom"; import { useState, useEffect } from "react"; import { useTheme } from "@emotion/react"; @@ -37,6 +39,7 @@ const CreateInfrastructureMonitor = () => { // State const [https, setHttps] = useState(false); const [updateTrigger, setUpdateTrigger] = useState(false); + const [availableDisks, setAvailableDisks] = useState([]); // Fetch monitor details if editing const [monitor, isLoading] = useFetchHardwareMonitorById({ @@ -85,6 +88,24 @@ const CreateInfrastructureMonitor = () => { } else if (monitor) { setHttps(monitor.url.startsWith("https")); initializeInfrastructureMonitorForUpdate(monitor); + const fetchLastCheck = async () => { + try { + const params = { + dateRange: "recent", + limit: 1, + sortOrder: "desc", + }; + // On utilise NetworkService directement + const response = await NetworkService.get(`/api/v1/checks/${monitorId}`, { params }); + const disks = response?.data?.checks?.[0]?.payload?.disks || []; + setAvailableDisks(disks); + } catch (error) { + console.error("Erreur pendant la récupération des disques:", error); + setAvailableDisks([]); // En cas d'erreur, on met un tableau vide + } + }; + + fetchLastCheck(); } }, [ isCreate, @@ -133,6 +154,15 @@ const CreateInfrastructureMonitor = () => { isPausing || notificationsAreLoading; + // --- AJOUT TEMPORAIRE : Fausses données --- + const MOCK_DISKS = [ + { mountpoint: "C:" }, + { mountpoint: "D:" }, + { mountpoint: "/mnt/data" }, + { mountpoint: "/var/lib/docker" } + ]; + // ----------------------------------------- + return ( @@ -327,6 +357,17 @@ const CreateInfrastructureMonitor = () => { infrastructureMonitor={infrastructureMonitor} handleCheckboxChange={handleCheckboxChange} /> + + {monitorId && ( + + onChangeForm("selectedDisks", newSelectedDisks) + } + /> + )} + { return { base: "/", plugins: [svgr(), react()], + server: { + host: true, + }, resolve: { alias: { "@": path.resolve(__dirname, "src"), diff --git a/server/src/db/v1/models/Monitor.js b/server/src/db/v1/models/Monitor.js index e6e1a0024..901dc39d1 100755 --- a/server/src/db/v1/models/Monitor.js +++ b/server/src/db/v1/models/Monitor.js @@ -125,6 +125,10 @@ const MonitorSchema = mongoose.Schema( return this.alertThreshold; }, }, + selectedDisks: { + type: [String], + default: [], + }, gameId: { type: String, }, diff --git a/server/src/validation/joi.js b/server/src/validation/joi.js index bc88d4567..b3342de83 100755 --- a/server/src/validation/joi.js +++ b/server/src/validation/joi.js @@ -174,6 +174,7 @@ const createMonitorBodyValidation = joi.object({ expectedValue: joi.string().allow(""), matchMethod: joi.string(), gameId: joi.string().allow(""), + selectedDisks: joi.array().items(joi.string()).optional(), group: joi.string().max(50).trim().allow(null, "").optional(), }); @@ -204,6 +205,7 @@ const editMonitorBodyValidation = joi.object({ usage_temperature: joi.number(), }), gameId: joi.string(), + selectedDisks: joi.array().items(joi.string()).optional(), group: joi.string().max(50).trim().allow(null, "").optional(), });