From 972fbd55710e66f37fe448c7c65a656ab383d523 Mon Sep 17 00:00:00 2001 From: Caio Cabral Date: Mon, 2 Dec 2024 21:27:42 -0500 Subject: [PATCH 1/7] fix: adding background disabled --- Client/src/Utils/Theme/globalTheme.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Client/src/Utils/Theme/globalTheme.js b/Client/src/Utils/Theme/globalTheme.js index 1df586dc4..654888767 100644 --- a/Client/src/Utils/Theme/globalTheme.js +++ b/Client/src/Utils/Theme/globalTheme.js @@ -93,6 +93,10 @@ const baseTheme = (palette) => ({ "&:hover": { boxShadow: "none", }, + "&.MuiLoadingButton-root:disabled": { + backgroundColor: theme.palette.secondary.main, + color: theme.palette.text.primary, + }, }), }, }, From 8946c98a6861160e2201bd42eaf68ecf353a9c6e Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Tue, 3 Dec 2024 11:35:43 +0800 Subject: [PATCH 2/7] update tests for hardware check module --- Docker/test/cerbot-compose.yaml | 19 ++++++ .../db/mongo/modules/hardwareCheckModule.js | 2 + Server/tests/db/hardwareCheckModule.test.js | 63 ++++++++++++++++++- 3 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 Docker/test/cerbot-compose.yaml diff --git a/Docker/test/cerbot-compose.yaml b/Docker/test/cerbot-compose.yaml new file mode 100644 index 000000000..9220d07a1 --- /dev/null +++ b/Docker/test/cerbot-compose.yaml @@ -0,0 +1,19 @@ +version: "3" + +services: + webserver: + image: nginx:latest + ports: + - 80:80 + - 443:443 + restart: always + volumes: + - ./nginx/conf.d/:/etc/nginx/conf.d/:ro + - ./certbot/www/:/var/www/certbot/:ro + certbot: + image: certbot/certbot:latest + volumes: + - ./certbot/www/:/var/www/certbot/:rw + - ./certbot/conf/:/etc/letsencrypt/:rw + depends_on: + - webserver diff --git a/Server/db/mongo/modules/hardwareCheckModule.js b/Server/db/mongo/modules/hardwareCheckModule.js index 00b2c1c07..3eab0dfb9 100644 --- a/Server/db/mongo/modules/hardwareCheckModule.js +++ b/Server/db/mongo/modules/hardwareCheckModule.js @@ -1,5 +1,6 @@ import HardwareCheck from "../../models/HardwareCheck.js"; import Monitor from "../../models/Monitor.js"; +import logger from "../../../utils/logger.js"; const SERVICE_NAME = "hardwareCheckModule"; const createHardwareCheck = async (hardwareCheckData) => { @@ -15,6 +16,7 @@ const createHardwareCheck = async (hardwareCheckData) => { method: "createHardwareCheck", details: `monitor ID: ${monitorId}`, }); + return null; } if (monitor.uptimePercentage === undefined) { diff --git a/Server/tests/db/hardwareCheckModule.test.js b/Server/tests/db/hardwareCheckModule.test.js index 530f5f4f8..df16441b2 100644 --- a/Server/tests/db/hardwareCheckModule.test.js +++ b/Server/tests/db/hardwareCheckModule.test.js @@ -1,6 +1,8 @@ import sinon from "sinon"; import HardwareCheck from "../../db/models/HardwareCheck.js"; import { createHardwareCheck } from "../../db/mongo/modules/hardwareCheckModule.js"; +import Monitor from "../../db/models/Monitor.js"; +import logger from "../../utils/logger.js"; const mockHardwareCheck = { data: { @@ -42,10 +44,23 @@ const mockHardwareCheck = { ], }; +const mockMonitor = { + _id: "123", + uptimePercentage: 1, + status: true, + save: () => this, +}; + describe("HardwareCheckModule", () => { - let hardwareCheckSaveStub; + let hardwareCheckSaveStub, + hardwareCheckCountDocumentsStub, + monitorFindByIdStub, + loggerStub; beforeEach(() => { + loggerStub = sinon.stub(logger, "error"); hardwareCheckSaveStub = sinon.stub(HardwareCheck.prototype, "save"); + monitorFindByIdStub = sinon.stub(Monitor, "findById"); + hardwareCheckCountDocumentsStub = sinon.stub(HardwareCheck, "countDocuments"); }); afterEach(() => { @@ -55,12 +70,23 @@ describe("HardwareCheckModule", () => { describe("createHardwareCheck", () => { it("should return a hardware check", async () => { hardwareCheckSaveStub.resolves(mockHardwareCheck); - const hardwareCheck = await createHardwareCheck({}); + monitorFindByIdStub.resolves(mockMonitor); + hardwareCheckCountDocumentsStub.resolves(1); + const hardwareCheck = await createHardwareCheck({ status: true }); + expect(hardwareCheck).to.exist; + expect(hardwareCheck).to.deep.equal(mockHardwareCheck); + }); + it("should return a hardware check for a check with status false", async () => { + hardwareCheckSaveStub.resolves(mockHardwareCheck); + monitorFindByIdStub.resolves(mockMonitor); + hardwareCheckCountDocumentsStub.resolves(1); + const hardwareCheck = await createHardwareCheck({ status: false }); expect(hardwareCheck).to.exist; expect(hardwareCheck).to.deep.equal(mockHardwareCheck); }); it("should handle an error", async () => { const err = new Error("test error"); + monitorFindByIdStub.resolves(mockMonitor); hardwareCheckSaveStub.rejects(err); try { await createHardwareCheck({}); @@ -69,5 +95,38 @@ describe("HardwareCheckModule", () => { expect(error).to.deep.equal(err); } }); + it("should log an error if a monitor is not found", async () => { + monitorFindByIdStub.resolves(null); + const res = await createHardwareCheck({}); + expect(loggerStub.calledOnce).to.be.true; + expect(res).to.be.null; + }); + it("should handle a monitor with undefined uptimePercentage", async () => { + monitorFindByIdStub.resolves({ ...mockMonitor, uptimePercentage: undefined }); + hardwareCheckSaveStub.resolves(mockHardwareCheck); + hardwareCheckCountDocumentsStub.resolves(1); + const res = await createHardwareCheck({}); + expect(res).to.exist; + }); + it("should handle a monitor with undefined uptimePercentage and true status", async () => { + monitorFindByIdStub.resolves({ + ...mockMonitor, + uptimePercentage: undefined, + }); + hardwareCheckSaveStub.resolves(mockHardwareCheck); + hardwareCheckCountDocumentsStub.resolves(1); + const res = await createHardwareCheck({ status: true }); + expect(res).to.exist; + }); + it("should handle a monitor with undefined uptimePercentage and false status", async () => { + monitorFindByIdStub.resolves({ + ...mockMonitor, + uptimePercentage: undefined, + }); + hardwareCheckSaveStub.resolves(mockHardwareCheck); + hardwareCheckCountDocumentsStub.resolves(1); + const res = await createHardwareCheck({ status: false }); + expect(res).to.exist; + }); }); }); From f9af6c8b1b62fd748891cbb930bd7f4ad45bbff0 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 3 Dec 2024 06:30:23 +0000 Subject: [PATCH 3/7] fix(deps): update dependency recharts to v2.14.1 --- Client/package-lock.json | 8 ++++---- Client/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Client/package-lock.json b/Client/package-lock.json index 1a48081ef..b4fa05ba1 100644 --- a/Client/package-lock.json +++ b/Client/package-lock.json @@ -28,7 +28,7 @@ "react-router": "^6.23.0", "react-router-dom": "^6.23.1", "react-toastify": "^10.0.5", - "recharts": "2.14.0", + "recharts": "2.14.1", "redux-persist": "6.0.0", "vite-plugin-svgr": "^4.2.0" }, @@ -5442,9 +5442,9 @@ } }, "node_modules/recharts": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.14.0.tgz", - "integrity": "sha512-kgDvDdNOh/gHQ4Q8hu7VrLNKs/bP/meG/XaRnsQG+Yp4PxugfPvaRFC0m4q7RWdlw0HxIkTSdcsGrsVQsg2qTA==", + "version": "2.14.1", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.14.1.tgz", + "integrity": "sha512-xtWulflkA+/xu4/QClBdtZYN30dbvTHjxjkh5XTMrH/CQ3WGDDPHHa/LLKCbgoqz0z3UaSH2/blV1i6VNMeh1g==", "license": "MIT", "dependencies": { "clsx": "^2.0.0", diff --git a/Client/package.json b/Client/package.json index 9e315b217..e5faa9bef 100644 --- a/Client/package.json +++ b/Client/package.json @@ -31,7 +31,7 @@ "react-router": "^6.23.0", "react-router-dom": "^6.23.1", "react-toastify": "^10.0.5", - "recharts": "2.14.0", + "recharts": "2.14.1", "redux-persist": "6.0.0", "vite-plugin-svgr": "^4.2.0" }, From ee9103d4a688755b2c0c3f3c4faffd5f4ad9bc93 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Tue, 3 Dec 2024 15:29:19 +0800 Subject: [PATCH 4/7] refactor create monitor --- .../Pages/Monitors/CreateMonitor/index.jsx | 372 +++++++----------- 1 file changed, 148 insertions(+), 224 deletions(-) diff --git a/Client/src/Pages/Monitors/CreateMonitor/index.jsx b/Client/src/Pages/Monitors/CreateMonitor/index.jsx index 6a794e464..b71562b69 100644 --- a/Client/src/Pages/Monitors/CreateMonitor/index.jsx +++ b/Client/src/Pages/Monitors/CreateMonitor/index.jsx @@ -1,61 +1,54 @@ -import { useState, useEffect } from "react"; -import { Box, Button, ButtonGroup, Stack, Typography } from "@mui/material"; -import LoadingButton from "@mui/lab/LoadingButton"; -import { useSelector, useDispatch } from "react-redux"; -import { monitorValidation } from "../../../Validation/validation"; -import { createUptimeMonitor } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice"; -import { checkEndpointResolution } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice"; -import { useNavigate, useParams } from "react-router-dom"; +// React, Redux, Router import { useTheme } from "@emotion/react"; -import { createToast } from "../../../Utils/toastUtils"; -import { logger } from "../../../Utils/Logger"; +import { useNavigate, useParams } from "react-router-dom"; +import { useEffect } from "react"; +import { useState } from "react"; +import { useSelector, useDispatch } from "react-redux"; + +// Utility and Network +import { checkEndpointResolution } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice"; +import { monitorValidation } from "../../../Validation/validation"; +import { getUptimeMonitorById } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice"; +import { createUptimeMonitor } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice"; + +// MUI +import { Box, Stack, Typography, Button, ButtonGroup } from "@mui/material"; +import LoadingButton from "@mui/lab/LoadingButton"; + +//Components +import Breadcrumbs from "../../../Components/Breadcrumbs"; import { ConfigBox } from "../styled"; -import Radio from "../../../Components/Inputs/Radio"; import TextInput from "../../../Components/Inputs/TextInput"; import { HttpAdornment } from "../../../Components/Inputs/TextInput/Adornments"; -import Select from "../../../Components/Inputs/Select"; +import { createToast } from "../../../Utils/toastUtils"; +import Radio from "../../../Components/Inputs/Radio"; import Checkbox from "../../../Components/Inputs/Checkbox"; -import Breadcrumbs from "../../../Components/Breadcrumbs"; -import { getUptimeMonitorById } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice"; -import "./index.css"; -import { parseDomainName } from "../../../Utils/monitorUtils"; +import Select from "../../../Components/Inputs/Select"; const CreateMonitor = () => { const MS_PER_MINUTE = 60000; + const SELECT_VALUES = [ + { _id: 1, name: "1 minute" }, + { _id: 2, name: "2 minutes" }, + { _id: 3, name: "3 minutes" }, + { _id: 4, name: "4 minutes" }, + { _id: 5, name: "5 minutes" }, + ]; + const { user, authToken } = useSelector((state) => state.auth); const { monitors, isLoading } = useSelector((state) => state.uptimeMonitors); const dispatch = useDispatch(); const navigate = useNavigate(); const theme = useTheme(); - - const idMap = { - "monitor-url": "url", - "monitor-name": "name", - "monitor-checks-http": "type", - "monitor-checks-ping": "type", - "monitor-checks-docker": "type", - "notify-email-default": "notification-email", - }; - - const monitorTypeMaps = { - http: { - label: "URL to monitor", - placeholder: "google.com", - namePlaceholder: "Google", - }, - ping: { - label: "IP address to monitor", - placeholder: "1.1.1.1", - namePlaceholder: "Google", - }, - docker: { - label: "Container ID", - placeholder: "abc123", - namePlaceholder: "My Container", - }, - }; - const { monitorId } = useParams(); + const crumbs = [ + { name: "monitors", path: "/monitors" }, + { name: "create", path: `/monitors/create` }, + ]; + + // State + const [errors, setErrors] = useState({}); + const [https, setHttps] = useState(true); const [monitor, setMonitor] = useState({ url: "", name: "", @@ -63,8 +56,105 @@ const CreateMonitor = () => { notifications: [], interval: 1, }); - const [https, setHttps] = useState(true); - const [errors, setErrors] = useState({}); + + const handleCreateMonitor = async (event) => { + event.preventDefault(); + let form = { + url: + //prepending protocol for url + monitor.type === "http" + ? `http${https ? "s" : ""}://` + monitor.url + : monitor.url, + name: monitor.name === "" ? monitor.url : monitor.name, + type: monitor.type, + interval: monitor.interval * MS_PER_MINUTE, + }; + + const { error } = monitorValidation.validate(form, { + abortEarly: false, + }); + + if (error) { + const newErrors = {}; + error.details.forEach((err) => { + newErrors[err.path[0]] = err.message; + }); + setErrors(newErrors); + createToast({ body: "Please check the form for errors." }); + return; + } + + if (monitor.type === "http") { + const checkEndpointAction = await dispatch( + checkEndpointResolution({ authToken, monitorURL: form.url }) + ); + if (checkEndpointAction.meta.requestStatus === "rejected") { + createToast({ + body: "The endpoint you entered doesn't resolve. Check the URL again.", + }); + setErrors({ url: "The entered URL is not reachable." }); + return; + } + } + + form = { + ...form, + description: form.name, + teamId: user.teamId, + userId: user._id, + notifications: monitor.notifications, + }; + const action = await dispatch(createUptimeMonitor({ authToken, monitor: form })); + if (action.meta.requestStatus === "fulfilled") { + createToast({ body: "Monitor created successfully!" }); + navigate("/monitors"); + } else { + createToast({ body: "Failed to create monitor." }); + } + }; + + const handleChange = (event, formName) => { + const { value } = event.target; + setMonitor({ + ...monitor, + [formName]: value, + }); + + const { error } = monitorValidation.validate( + { [formName]: value }, + { abortEarly: false } + ); + setErrors((prev) => ({ + ...prev, + ...(error ? { [formName]: error.details[0].message } : { [formName]: undefined }), + })); + }; + + const handleNotifications = (event, type) => { + const { value } = event.target; + let notifications = [...monitor.notifications]; + const notificationExists = notifications.some((notification) => { + if (notification.type === type && notification.address === value) { + return true; + } + return false; + }); + if (notificationExists) { + notifications = notifications.filter((notification) => { + if (notification.type === type && notification.address === value) { + return false; + } + return true; + }); + } else { + notifications.push({ type, address: value }); + } + + setMonitor((prev) => ({ + ...prev, + notifications, + })); + }; useEffect(() => { const fetchMonitor = async () => { @@ -94,143 +184,14 @@ const CreateMonitor = () => { fetchMonitor(); }, [monitorId, authToken, monitors, dispatch, navigate]); - const handleChange = (event, name) => { - const { value, id } = event.target; - if (!name) name = idMap[id]; - - if (name.includes("notification-")) { - name = name.replace("notification-", ""); - let hasNotif = monitor.notifications.some( - (notification) => notification.type === name - ); - setMonitor((prev) => { - const notifs = [...prev.notifications]; - if (hasNotif) { - return { - ...prev, - notifications: notifs.filter((notif) => notif.type !== name), - }; - } else { - return { - ...prev, - notifications: [ - ...notifs, - name === "email" - ? { type: name, address: value } - : // TODO - phone number - { type: name, phone: value }, - ], - }; - } - }); - } else { - setMonitor((prev) => ({ - ...prev, - [name]: value, - })); - - const { error } = monitorValidation.validate( - { [name]: value }, - { abortEarly: false } - ); - setErrors((prev) => { - const updatedErrors = { ...prev }; - if (error) updatedErrors[name] = error.details[0].message; - else delete updatedErrors[name]; - return updatedErrors; - }); - } - }; - - const onUrlBlur = (event) => { - const { value } = event.target; - setMonitor((prev) => ({ - ...prev, - name: parseDomainName(value), - })); - }; - - const handleCreateMonitor = async (event) => { - event.preventDefault(); - //obj to submit - let form = { - url: - //preprending protocol for url - monitor.type === "http" - ? `http${https ? "s" : ""}://` + monitor.url - : monitor.url, - name: monitor.name === "" ? monitor.url : monitor.name, - type: monitor.type, - interval: monitor.interval * MS_PER_MINUTE, - }; - - const { error } = monitorValidation.validate(form, { - abortEarly: false, - }); - - if (error) { - const newErrors = {}; - error.details.forEach((err) => { - newErrors[err.path[0]] = err.message; - }); - setErrors(newErrors); - createToast({ body: "Error validation data." }); - } else { - if (monitor.type === "http") { - const checkEndpointAction = await dispatch( - checkEndpointResolution({ authToken, monitorURL: form.url }) - ); - if (checkEndpointAction.meta.requestStatus === "rejected") { - createToast({ - body: "The endpoint you entered doesn't resolve. Check the URL again.", - }); - setErrors({ url: "The entered URL is not reachable." }); - return; - } - } - - form = { - ...form, - description: form.name, - teamId: user.teamId, - userId: user._id, - notifications: monitor.notifications, - }; - const action = await dispatch(createUptimeMonitor({ authToken, monitor: form })); - if (action.meta.requestStatus === "fulfilled") { - createToast({ body: "Monitor created successfully!" }); - navigate("/monitors"); - } else { - createToast({ body: "Failed to create monitor." }); - } - } - }; - - //select values - const frequencies = [ - { _id: 1, name: "1 minute" }, - { _id: 2, name: "2 minutes" }, - { _id: 3, name: "3 minutes" }, - { _id: 4, name: "4 minutes" }, - { _id: 5, name: "5 minutes" }, - ]; - return ( - + { monitor + General settings @@ -263,12 +225,8 @@ const CreateMonitor = () => { type={monitor.type === "http" ? "url" : "text"} id="monitor-url" startAdornment={} - label={monitorTypeMaps[monitor.type].label || "URL to monitor"} - https={https} - placeholder={monitorTypeMaps[monitor.type].placeholder || ""} value={monitor.url} - onChange={handleChange} - onBlur={onUrlBlur} + onChange={(event) => handleChange(event, "url")} error={errors["url"] ? true : false} helperText={errors["url"]} /> @@ -277,9 +235,8 @@ const CreateMonitor = () => { id="monitor-name" label="Display name" isOptional={true} - placeholder={monitorTypeMaps[monitor.type].namePlaceholder || ""} value={monitor.name} - onChange={handleChange} + onChange={(event) => handleChange(event, "name")} error={errors["name"] ? true : false} helperText={errors["name"]} /> @@ -301,7 +258,7 @@ const CreateMonitor = () => { size="small" value="http" checked={monitor.type === "http"} - onChange={(event) => handleChange(event)} + onChange={(event) => handleChange(event, "type")} /> {monitor.type === "http" ? ( @@ -331,7 +288,7 @@ const CreateMonitor = () => { size="small" value="ping" checked={monitor.type === "ping"} - onChange={(event) => handleChange(event)} + onChange={(event) => handleChange(event, "type")} /> { size="small" value="docker" checked={monitor.type === "docker"} - onChange={(event) => handleChange(event)} + onChange={(event) => handleChange(event, "type")} /> {errors["type"] ? ( @@ -366,14 +323,7 @@ const CreateMonitor = () => { When there is a new incident, - logger.warn("disabled")} - isDisabled={true} - /> + { (notification) => notification.type === "email" )} value={user?.email} - onChange={(event) => handleChange(event)} + onChange={(event) => handleNotifications(event, "email")} /> - logger.warn("disabled")} - isDisabled={true} - /> - {monitor.notifications.some( - (notification) => notification.type === "emails" - ) ? ( - - logger.warn("disabled")} - /> - - You can separate multiple emails with a comma - - - ) : ( - "" - )} @@ -421,7 +345,7 @@ const CreateMonitor = () => { label="Check frequency" value={monitor.interval || 1} onChange={(event) => handleChange(event, "interval")} - items={frequencies} + items={SELECT_VALUES} /> @@ -433,7 +357,7 @@ const CreateMonitor = () => { variant="contained" color="primary" onClick={handleCreateMonitor} - disabled={Object.keys(errors).length !== 0 && true} + disabled={!Object.values(errors).every((value) => value === undefined)} loading={isLoading} > Create monitor From 7ffead16ca45f0ad3a4b68baa7f92ccb240deb46 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 3 Dec 2024 20:09:23 +0000 Subject: [PATCH 5/7] fix(deps): update dependency dotenv to v16.4.7 --- Server/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Server/package-lock.json b/Server/package-lock.json index 2a0672929..72cfbe33d 100644 --- a/Server/package-lock.json +++ b/Server/package-lock.json @@ -2179,9 +2179,9 @@ } }, "node_modules/dotenv": { - "version": "16.4.6", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.6.tgz", - "integrity": "sha512-JhcR/+KIjkkjiU8yEpaB/USlzVi3i5whwOjpIRNGi9svKEXZSe+Qp6IWAjFjv+2GViAoDRCUv/QLNziQxsLqDg==", + "version": "16.4.7", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", + "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", "license": "BSD-2-Clause", "engines": { "node": ">=12" From 941761cb15c025ec01cc085345389e8a0b0a49db Mon Sep 17 00:00:00 2001 From: Caio Cabral Date: Tue, 3 Dec 2024 19:12:51 -0500 Subject: [PATCH 6/7] fix: adding color transparent to button when loading --- Client/src/Utils/Theme/globalTheme.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Client/src/Utils/Theme/globalTheme.js b/Client/src/Utils/Theme/globalTheme.js index 654888767..2effdb1f8 100644 --- a/Client/src/Utils/Theme/globalTheme.js +++ b/Client/src/Utils/Theme/globalTheme.js @@ -93,9 +93,19 @@ const baseTheme = (palette) => ({ "&:hover": { boxShadow: "none", }, - "&.MuiLoadingButton-root:disabled": { - backgroundColor: theme.palette.secondary.main, - color: theme.palette.text.primary, + "&.MuiLoadingButton-root": { + "&:disabled": { + backgroundColor: theme.palette.secondary.main, + color: theme.palette.text.primary, + }, + }, + "&.MuiLoadingButton-loading": { + "& .MuiLoadingButton-label": { + color: "transparent", + }, + "& .MuiLoadingButton-loadingIndicator": { + color: "inherit", + }, }, }), }, From 903ae220ddbbef6c511553f2344ce47dd6981eb8 Mon Sep 17 00:00:00 2001 From: Caio Cabral Date: Tue, 3 Dec 2024 19:31:00 -0500 Subject: [PATCH 7/7] fix: disabled input --- Client/src/Utils/Theme/globalTheme.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Client/src/Utils/Theme/globalTheme.js b/Client/src/Utils/Theme/globalTheme.js index 1df586dc4..f79bc5768 100644 --- a/Client/src/Utils/Theme/globalTheme.js +++ b/Client/src/Utils/Theme/globalTheme.js @@ -218,6 +218,10 @@ const baseTheme = (palette) => ({ fontSize: "var(--env-var-font-size-medium)", fontWeight: 400, color: palette.text.secondary, + "&.Mui-disabled": { + opacity: 0.25, + "-webkit-text-fill-color": "unset", + }, }, "& .MuiInputBase-input.MuiOutlinedInput-input": { padding: "0 var(--env-var-spacing-1-minus) !important",