From e8d636dcfdfaaafc2ac3e48343c797d6544e1884 Mon Sep 17 00:00:00 2001 From: Asim Ahmed Siddiqui Date: Fri, 23 May 2025 12:40:47 +0530 Subject: [PATCH] Fix: Optionally show IP/URL of the monitor in status page --- client/src/Components/Host/index.jsx | 5 ++- client/src/Features/UI/uiSlice.js | 5 +++ client/src/Pages/Settings/SettingsURL.jsx | 43 +++++++++++++++++++ client/src/Pages/Settings/index.jsx | 15 ++++++- .../Status/Components/MonitorsList/index.jsx | 8 ++++ client/src/Pages/StatusPage/Status/index.jsx | 1 + client/src/Validation/validation.js | 1 + client/src/locales/gb.json | 3 ++ client/src/locales/ru.json | 8 +++- client/src/locales/tr.json | 10 +++-- server/validation/joi.js | 1 + 11 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 client/src/Pages/Settings/SettingsURL.jsx diff --git a/client/src/Components/Host/index.jsx b/client/src/Components/Host/index.jsx index 051e60331..d1cf382b2 100644 --- a/client/src/Components/Host/index.jsx +++ b/client/src/Components/Host/index.jsx @@ -14,7 +14,7 @@ import Dot from "../Dot"; * @param {number} params.percentage - The percentage to display. * @returns {React.ElementType} Returns a div element with the host details. */ -const Host = ({ url, title, percentageColor, percentage }) => { +const Host = ({ url, title, percentageColor, percentage, showURL }) => { const theme = useTheme(); return ( @@ -40,7 +40,7 @@ const Host = ({ url, title, percentageColor, percentage }) => { )} - {url} + {showURL && {url}} ); }; @@ -50,6 +50,7 @@ Host.propTypes = { percentageColor: PropTypes.string, percentage: PropTypes.string, url: PropTypes.string, + showURL: PropTypes.bool, }; export default Host; diff --git a/client/src/Features/UI/uiSlice.js b/client/src/Features/UI/uiSlice.js index f20115b92..00d94d735 100644 --- a/client/src/Features/UI/uiSlice.js +++ b/client/src/Features/UI/uiSlice.js @@ -20,6 +20,7 @@ const initialState = { collapsed: false, }, mode: initialMode, + statusURL: "disabled", greeting: { index: 0, lastUpdate: null }, timezone: "America/Toronto", distributedUptimeEnabled: false, @@ -46,6 +47,9 @@ const uiSlice = createSlice({ setMode: (state, action) => { state.mode = action.payload; }, + setStatusURL: (state, action) => { + state.statusURL = action.payload; + }, setGreeting(state, action) { state.greeting.index = action.payload.index; state.greeting.lastUpdate = action.payload.lastUpdate; @@ -67,6 +71,7 @@ export const { setRowsPerPage, toggleSidebar, setMode, + setStatusURL, setGreeting, setTimezone, setDistributedUptimeEnabled, diff --git a/client/src/Pages/Settings/SettingsURL.jsx b/client/src/Pages/Settings/SettingsURL.jsx new file mode 100644 index 000000000..ddcc271b4 --- /dev/null +++ b/client/src/Pages/Settings/SettingsURL.jsx @@ -0,0 +1,43 @@ +import Box from "@mui/material/Box"; +import Stack from "@mui/material/Stack"; +import Typography from "@mui/material/Typography"; +import ConfigBox from "../../Components/ConfigBox"; +import Select from "../../Components/Inputs/Select"; + +// Utils +import { useTheme } from "@emotion/react"; +import { PropTypes } from "prop-types"; +import { useTranslation } from "react-i18next"; + +const SettingsURL = ({ HEADING_SX, handleChange, statusURL }) => { + const { t } = useTranslation(); + const theme = useTheme(); + return ( + + + {t("settingsURLTitle")} + {t("settingsURLDescription")} + + + + + + ); +}; + +SettingsURL.propTypes = { + HEADING_SX: PropTypes.object, + handleChange: PropTypes.func, + statusURL: PropTypes.string, +}; + +export default SettingsURL; diff --git a/client/src/Pages/Settings/index.jsx b/client/src/Pages/Settings/index.jsx index 66662dc58..b4d890984 100644 --- a/client/src/Pages/Settings/index.jsx +++ b/client/src/Pages/Settings/index.jsx @@ -3,6 +3,7 @@ import Typography from "@mui/material/Typography"; import Breadcrumbs from "../../Components/Breadcrumbs"; import SettingsTimeZone from "./SettingsTimeZone"; import SettingsUI from "./SettingsUI"; +import SettingsURL from "./SettingsURL"; import SettingsPagespeed from "./SettingsPagespeed"; import SettingsDemoMonitors from "./SettingsDemoMonitors"; import SettingsAbout from "./SettingsAbout"; @@ -15,7 +16,7 @@ import { useState } from "react"; import { useTheme } from "@emotion/react"; import { useTranslation } from "react-i18next"; import { useSelector, useDispatch } from "react-redux"; -import { setTimezone, setMode, setLanguage } from "../../Features/UI/uiSlice"; +import { setTimezone, setMode, setLanguage, setStatusURL } from "../../Features/UI/uiSlice"; import SettingsStats from "./SettingsStats"; import { deleteMonitorChecksByTeamId, @@ -31,7 +32,7 @@ const BREADCRUMBS = [{ name: `Settings`, path: "/settings" }]; const Settings = () => { // Redux state - const { mode, language, timezone } = useSelector((state) => state.ui); + const { mode, language, timezone, statusURL } = useSelector((state) => state.ui); const { user } = useSelector((state) => state.auth); // Local state @@ -67,6 +68,7 @@ const Settings = () => { const { error } = settingsValidation.validate(newSettingsData.settings, { abortEarly: false, }); + console.log(error) if (!error || error.details.length === 0) { setErrors({}); } else { @@ -85,6 +87,10 @@ const Settings = () => { dispatch(setMode(value)); } + if (name === "statusURL") { + dispatch(setStatusURL(value)); + } + if (name === "language") { dispatch(setLanguage(value)); i18n.changeLanguage(value); @@ -164,6 +170,11 @@ const Settings = () => { setSettingsData={setSettingsData} isApiKeySet={settingsData?.pagespeedKeySet ?? false} /> + { const theme = useTheme(); const { determineState } = useUtils(); + + const { statusURL } = useSelector((state) => state.ui); + const showURL = statusURL === "enabled"; + return ( <> {monitors?.map((monitor) => { @@ -27,6 +34,7 @@ const MonitorsList = ({ isLoading = false, shouldRender = true, monitors = [] }) title={monitor.name} percentageColor={monitor.percentageColor} percentage={monitor.percentage} + showURL={showURL} /> { const { url } = useParams(); diff --git a/client/src/Validation/validation.js b/client/src/Validation/validation.js index b83c35763..bbf1227ec 100644 --- a/client/src/Validation/validation.js +++ b/client/src/Validation/validation.js @@ -277,6 +277,7 @@ const settingsValidation = joi.object({ }), pagespeedApiKey: joi.string().allow("").optional(), language: joi.string().required(), + statusURL: joi.string().required(), systemEmailHost: joi.string().allow(""), systemEmailPort: joi.number().allow(null, ""), systemEmailAddress: joi.string().allow(""), diff --git a/client/src/locales/gb.json b/client/src/locales/gb.json index e15968a80..716f45ca3 100644 --- a/client/src/locales/gb.json +++ b/client/src/locales/gb.json @@ -75,6 +75,9 @@ "settingsThemeModeLight": "Light", "settingsThemeModeDark": "Dark", "settingsLanguage": "Language", + "settingsURLTitle": "Monitor IP/URL on Status Page", + "settingsURLDescription": "Display the IP address or URL of monitor on the public Status page. If it's disabled, only the monitor name will be shown to protect sensitive information.", + "settingsURLSelectTitle": "Display IP/URL on status page", "settingsDistributedUptime": "Distributed uptime", "settingsDistributedUptimeDescription": "Enable/disable distributed uptime monitoring.", "settingsEnabled": "Enabled", diff --git a/client/src/locales/ru.json b/client/src/locales/ru.json index df1e5a5a7..2240cf314 100644 --- a/client/src/locales/ru.json +++ b/client/src/locales/ru.json @@ -89,6 +89,9 @@ "settingsThemeModeLight": "Светлая", "settingsThemeModeDark": "Тёмная", "settingsLanguage": "Язык", + "settingsURLTitle": "Отображать IP/URL на странице статуса", + "settingsURLDescription": "Отображать IP-адрес или URL-адрес монитора на общедоступной странице статуса. Если отключено, будет отображаться только имя монитора для защиты конфиденциальной информации.", + "settingsURLSelectTitle": "Показать IP/URL на странице статуса", "settingsDistributedUptime": "Distributed uptime", "settingsDistributedUptimeDescription": "Включить/выключить distributed uptime monitoring.", "settingsEnabled": "Включено", @@ -152,7 +155,6 @@ "http": "HTTP", "monitor": "монитор", "aboutus": "О Нас", - "now": "Сейчас", "delete": "Удалить", "configure": "Настроить", @@ -409,6 +411,10 @@ "pageSpeedWarning": "Предупреждение: Вы не добавили ключ API Google PageSpeed. Без него монитор PageSpeed не будет работать.", "pageSpeedLearnMoreLink": "Нажмите здесь, чтобы узнать", "pageSpeedAddApiKey": "как добавить ваш ключ API.", + "pageSpeedApiKeyFieldTitle": "Ключ Google PageSpeed API", + "pageSpeedApiKeyFieldLabel": "Ключ PageSpeed API", + "pageSpeedApiKeyFieldDescription": "Введите свой ключ Google PageSpeed API, чтобы включить мониторинг скорости страниц. Нажмите «Сбросить», чтобы обновить ключ.", + "pageSpeedApiKeyFieldResetLabel": "Ключ API установлен. Нажмите «Сбросить», чтобы изменить его.", "createNew": "Создать новый", "greeting": { "prepend": "Привет", diff --git a/client/src/locales/tr.json b/client/src/locales/tr.json index 5aee7cf51..69db239dd 100644 --- a/client/src/locales/tr.json +++ b/client/src/locales/tr.json @@ -73,6 +73,9 @@ "settingsThemeModeLight": "Açık", "settingsThemeModeDark": "Koyu", "settingsLanguage": "Dil", + "settingsURLTitle": "Durum Sayfasında IP/URL'yi Göster", + "settingsURLDescription": "Monitörün IP adresini veya URL'sini genel Durum sayfasında göster. Devre dışı bırakıldığında, hassas bilgileri korumak için yalnızca monitör adı gösterilecektir.", + "settingsURLSelectTitle": "Durum sayfasında IP/URL'yi göster", "settingsDistributedUptime": "Dağıtılmış çalışma süresi", "settingsDistributedUptimeDescription": "Dağıtılmış çalışma süresi izlemeyi etkinleştirin/devre dışı bırakın.", "settingsEnabled": "Etkin", @@ -124,7 +127,6 @@ "http": "HTTP", "monitor": "monitör", "aboutus": "Hakkımızda", - "now": "Şimdi", "delete": "Sil", "configure": "Yapılandır", @@ -397,7 +399,9 @@ "pageSpeedWarning": "Uyarı: Google PageSpeed API anahtarı eklemediniz. Bu olmadan, PageSpeed monitörü çalışmayacaktır.", "pageSpeedLearnMoreLink": "Daha fazla bilgi için tıklayın", "pageSpeedAddApiKey": "API anahtarınızı nasıl ekleyeceğinizi öğrenin.", - "pageSpeedApiKeyFieldDescription": "Sayfa hızı izlemeyi etkinleştirmek için Google PageSpeed API anahtarınızı girin. Anahtarı güncellemek için Sıfırla'ya tıklayın.", + "pageSpeedApiKeyFieldTitle": "Google PageSpeed API anahtarı", + "pageSpeedApiKeyFieldLabel": "PageSpeed API anahtarı", + "pageSpeedApiKeyFieldDescription": "PageSpeed izlemeyi etkinleştirmek için Google PageSpeed API anahtarınızı girin. Anahtarı güncellemek için Sıfırla'ya tıklayın.", "pageSpeedApiKeyFieldResetLabel": "API anahtarı ayarlandı. Değiştirmek için Sıfırla'ya tıklayın.", "reset": "Sıfırla", "invalidFileFormat": "", @@ -513,4 +517,4 @@ "saving": "Kaydediliyor..." }, "uptimeCreateSelectURL": "İzlenecek URL veya IP adresini girin (örn. https://example.com/ veya 192.168.1.100) ve kontrol panelinde görünecek net bir görüntü adı ekleyin." -} +} \ No newline at end of file diff --git a/server/validation/joi.js b/server/validation/joi.js index 3dfee80c4..8db68b6d6 100755 --- a/server/validation/joi.js +++ b/server/validation/joi.js @@ -427,6 +427,7 @@ const updateAppSettingsBodyValidation = joi.object({ checkTTL: joi.number().allow(""), pagespeedApiKey: joi.string().allow(""), language: joi.string().allow(""), + statusURL: joi.string().required(), systemEmailHost: joi.string().allow(""), systemEmailPort: joi.number().allow(""), systemEmailAddress: joi.string().allow(""),