diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 402f5b15e..22252c301 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -16,7 +16,7 @@ Mention the issue number(s) this PR addresses (e.g., #123). - [ ] I have labelled the PR correctly. - [ ] The issue I am working on is assigned to me. - [ ] I didn't use any hardcoded values (otherwise it will not scale, and will make it difficult to maintain consistency across the application). -- [ ] I made sure font sizes, color choices etc are all referenced from the theme. +- [ ] I made sure font sizes, color choices etc are all referenced from the theme. I have no hardcoded dimensions. - [ ] My PR is granular and targeted to one specific feature. - [ ] I took a screenshot or a video and attached to this PR if there is a UI change. diff --git a/package-lock.json b/package-lock.json index 432f710eb..8921c721d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,7 +33,7 @@ "immutability-helper": "^3.1.1", "joi": "17.13.3", "jwt-decode": "^4.0.0", - "maplibre-gl": "5.1.1", + "maplibre-gl": "5.2.0", "mui-color-input": "^5.0.1", "react": "18.3.1", "react-dnd": "^16.0.1", @@ -2688,10 +2688,13 @@ "license": "MIT" }, "node_modules/@fontsource/roboto": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.1.1.tgz", - "integrity": "sha512-XwVVXtERDQIM7HPUIbyDe0FP4SRovpjF7zMI8M7pbqFp3ahLJsJTd18h+E6pkar6UbV3btbwkKjYARr5M+SQow==", - "license": "Apache-2.0" + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/@fontsource/roboto/-/roboto-5.2.5.tgz", + "integrity": "sha512-70r2UZ0raqLn5W+sPeKhqlf8wGvUXFWlofaDlcbt/S3d06+17gXKr3VNqDODB0I1ASme3dGT5OJj9NABt7OTZQ==", + "license": "OFL-1.1", + "funding": { + "url": "https://github.com/sponsors/ayuhito" + } }, "node_modules/@fractalwagmi/popup-connection": { "version": "1.1.1", @@ -11412,9 +11415,9 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.1.0.tgz", - "integrity": "sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", "dev": true, "license": "MIT", "engines": { @@ -14110,9 +14113,9 @@ } }, "node_modules/maplibre-gl": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.1.1.tgz", - "integrity": "sha512-0Z6ODzyFu/grwT6K1eIBpv6MZE4xnJD1AV+Yq1hPzOh/YCY36r9BlSaU7d7n2/HJOaoKOy0b2YF8cS4dD+iEVQ==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-5.2.0.tgz", + "integrity": "sha512-9zZKD0M80qtDsqBet+EDuAhoCeA/cnAuZAA0p3hcGKGbyjM/SH+R6wQvnBEgvJz9UhDynnkoKdUwhI+fUkHoXQ==", "license": "BSD-3-Clause", "dependencies": { "@mapbox/geojson-rewind": "^0.5.2", @@ -15639,9 +15642,9 @@ } }, "node_modules/prettier": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.2.tgz", - "integrity": "sha512-lc6npv5PH7hVqozBR7lkBNOGXV9vMwROAPlumdBkX0wTbbzPu/U1hk5yL8p2pt4Xoc+2mkT8t/sow2YrV/M5qg==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", "dev": true, "license": "MIT", "bin": { diff --git a/package.json b/package.json index 9684ff111..86d69c015 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "i18next": "^24.2.2", "immutability-helper": "^3.1.1", "joi": "17.13.3", - "maplibre-gl": "5.1.1", + "maplibre-gl": "5.2.0", "mui-color-input": "^5.0.1", "react": "18.3.1", "react-dnd": "^16.0.1", diff --git a/src/App.jsx b/src/App.jsx index 04dfeeb4f..feddfb60f 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -12,17 +12,28 @@ import { logger } from "./Utils/Logger"; // Import the logger import { networkService } from "./main"; import { Routes } from "./Routes"; import WalletProvider from "./Components/WalletProvider"; +import { useTranslation } from "react-i18next"; +import { setLanguage } from "./Features/UI/uiSlice"; function App() { const mode = useSelector((state) => state.ui.mode); const { authToken } = useSelector((state) => state.auth); const dispatch = useDispatch(); + const { i18n } = useTranslation(); useEffect(() => { if (authToken) { - dispatch(getAppSettings({ authToken })); + dispatch(getAppSettings({ authToken })).then((action) => { + if (action.payload && action.payload.success) { + const { language } = action.payload.data; + if (language) { + dispatch(setLanguage(language)); + i18n.changeLanguage(language); + } + } + }); } - }, [dispatch, authToken]); + }, [dispatch, authToken, i18n]); // Cleanup useEffect(() => { diff --git a/src/Components/Alert/index.jsx b/src/Components/Alert/index.jsx index a52761ca4..0b32fe2b1 100644 --- a/src/Components/Alert/index.jsx +++ b/src/Components/Alert/index.jsx @@ -36,8 +36,8 @@ const Alert = ({ variant, title, body, isToast, hasIcon = true, onClick }) => { */ const text = theme.palette.secondary.contrastText; - const bg = theme.palette.secondary.main; - const border = theme.palette.secondary.contrastText; + const border = theme.palette.alert.contrastText; + const bg = theme.palette.alert.main; const icon = icons[variant]; return ( diff --git a/src/Components/Charts/CustomGauge/index.jsx b/src/Components/Charts/CustomGauge/index.jsx index d29663004..3c7e13610 100644 --- a/src/Components/Charts/CustomGauge/index.jsx +++ b/src/Components/Charts/CustomGauge/index.jsx @@ -62,6 +62,7 @@ const CustomGauge = ({ progress = 0, radius = 70, strokeWidth = 15, threshold = className="radial-chart" width={radius} height={radius} + sx={{ backgroundColor: theme.palette.primary.main, borderRadius: "50%" }} > {`${progressWithinRange.toFixed(1)}%`} diff --git a/src/Components/LanguageSelector.jsx b/src/Components/LanguageSelector.jsx index ca8e9207c..70c41e640 100644 --- a/src/Components/LanguageSelector.jsx +++ b/src/Components/LanguageSelector.jsx @@ -14,7 +14,6 @@ const LanguageSelector = () => { i18n.changeLanguage(newLang); }; - // i18n instance'ından mevcut dilleri al const languages = Object.keys(i18n.options.resources || {}); return ( diff --git a/src/Components/StatBox/index.jsx b/src/Components/StatBox/index.jsx index 3c91e1aae..54a4af5ca 100644 --- a/src/Components/StatBox/index.jsx +++ b/src/Components/StatBox/index.jsx @@ -50,7 +50,7 @@ const StatBox = ({ borderColor: theme.palette[themeColor].lowContrast, } : { - background: `linear-gradient(340deg, ${theme.palette.tertiary.main} 20%, ${theme.palette.primary.main} 45%)`, + background: `linear-gradient(340deg, ${theme.palette.tertiary.main} 10%, ${theme.palette.primary.main} 45%)`, borderColor: theme.palette.primary.lowContrast, }; @@ -62,7 +62,7 @@ const StatBox = ({ color: theme.palette.primary.contrastTextSecondary, }; - const spanFixedStyles = { marginLeft: theme.spacing(2), fontSize: 15 }; + const spanFixedStyles = { marginLeft: theme.spacing(2), fontSize: 15, fontWeight: 600}; const detailTextStyles = gradient ? { color: theme.palette[themeColor].contrastText, @@ -120,7 +120,7 @@ const StatBox = ({ )} {heading} - {subHeading} + {subHeading} ); diff --git a/src/Features/Settings/settingsSlice.js b/src/Features/Settings/settingsSlice.js index a3d96ea0e..345a8a264 100644 --- a/src/Features/Settings/settingsSlice.js +++ b/src/Features/Settings/settingsSlice.js @@ -5,6 +5,7 @@ const initialState = { isLoading: false, apiBaseUrl: "", logLevel: "debug", + language: "", }; export const getAppSettings = createAsyncThunk( @@ -34,6 +35,7 @@ export const updateAppSettings = createAsyncThunk( const parsedSettings = { apiBaseUrl: settings.apiBaseUrl, logLevel: settings.logLevel, + language: settings.language, clientHost: settings.clientHost, jwtSecret: settings.jwtSecret, dbType: settings.dbType, @@ -68,6 +70,7 @@ const handleGetSettingsFulfilled = (state, action) => { state.msg = action.payload.msg; state.apiBaseUrl = action.payload.data.apiBaseUrl; state.logLevel = action.payload.data.logLevel; + state.language = action.payload.data.language; }; const handleGetSettingsRejected = (state, action) => { state.isLoading = false; diff --git a/src/Pages/Account/index.jsx b/src/Pages/Account/index.jsx index 00d805f34..48b0984f5 100644 --- a/src/Pages/Account/index.jsx +++ b/src/Pages/Account/index.jsx @@ -57,10 +57,6 @@ const Account = ({ open = "profile" }) => { className="account" px={theme.spacing(20)} py={theme.spacing(12)} - backgroundColor={theme.palette.primary.main} - border={1} - borderColor={theme.palette.primary.lowContrast} - borderRadius={theme.shape.borderRadius} > { const manufacturers = { diff --git a/src/Pages/DistributedUptime/Monitors/Components/MonitorTable/index.jsx b/src/Pages/DistributedUptime/Monitors/Components/MonitorTable/index.jsx index ebe0fb94a..fa8593cf1 100644 --- a/src/Pages/DistributedUptime/Monitors/Components/MonitorTable/index.jsx +++ b/src/Pages/DistributedUptime/Monitors/Components/MonitorTable/index.jsx @@ -20,7 +20,6 @@ const MonitorTable = ({ isLoading, monitors }) => { const theme = useTheme(); const navigate = useNavigate(); const { determineState } = useMonitorUtils(); - const headers = [ { id: "name", diff --git a/src/Pages/DistributedUptime/Monitors/Hooks/useSubscribeToMonitors.jsx b/src/Pages/DistributedUptime/Monitors/Hooks/useSubscribeToMonitors.jsx index 7c498d753..6855c44c5 100644 --- a/src/Pages/DistributedUptime/Monitors/Hooks/useSubscribeToMonitors.jsx +++ b/src/Pages/DistributedUptime/Monitors/Hooks/useSubscribeToMonitors.jsx @@ -24,7 +24,11 @@ const useSubscribeToMonitors = (page, rowsPerPage) => { const cleanup = networkService.subscribeToDistributedUptimeMonitors({ teamId: user.teamId, limit: 25, - types: ["distributed_http"], + types: [ + typeof import.meta.env.VITE_DEPIN_TESTING === "undefined" + ? "distributed_http" + : "distributed_test", + ], page, rowsPerPage, filter: null, diff --git a/src/Pages/Infrastructure/Details/Components/GaugeBoxes/Gauge.jsx b/src/Pages/Infrastructure/Details/Components/GaugeBoxes/Gauge.jsx index b1202682d..d374d1960 100644 --- a/src/Pages/Infrastructure/Details/Components/GaugeBoxes/Gauge.jsx +++ b/src/Pages/Infrastructure/Details/Components/GaugeBoxes/Gauge.jsx @@ -9,6 +9,16 @@ import PropTypes from "prop-types"; const Gauge = ({ value, heading, metricOne, valueOne, metricTwo, valueTwo }) => { const theme = useTheme(); + const valueStyle = { + borderRadius: theme.spacing(2), + backgroundColor: theme.palette.tertiary.main, + width: "40%", + mb: theme.spacing(2), + mt: theme.spacing(2), + pr: theme.spacing(2), + textAlign: 'right' + } + return ( gap={theme.spacing(2)} alignItems="center" > - - {heading} + + + {heading} + {metricOne} - {valueOne} + {valueOne} {metricTwo} - {valueTwo} + {valueTwo} diff --git a/src/Pages/Infrastructure/Details/Hooks/useHardwareUtils.jsx b/src/Pages/Infrastructure/Details/Hooks/useHardwareUtils.jsx index bc540dfe3..1752533d0 100644 --- a/src/Pages/Infrastructure/Details/Hooks/useHardwareUtils.jsx +++ b/src/Pages/Infrastructure/Details/Hooks/useHardwareUtils.jsx @@ -64,6 +64,7 @@ const useHardwareUtils = () => { return ( <> {Number(MB.toFixed(0))} + {space ? " " : ""} MB ); diff --git a/src/Pages/Infrastructure/Details/index.jsx b/src/Pages/Infrastructure/Details/index.jsx index f686fa9ff..fc704b444 100644 --- a/src/Pages/Infrastructure/Details/index.jsx +++ b/src/Pages/Infrastructure/Details/index.jsx @@ -62,7 +62,7 @@ const InfrastructureDetails = () => { monitor={monitor} /> - No check history for htis monitor yet. + No check history for this monitor yet. ); diff --git a/src/Pages/Settings/index.jsx b/src/Pages/Settings/index.jsx index 04b8658dc..4bbe2fbf9 100644 --- a/src/Pages/Settings/index.jsx +++ b/src/Pages/Settings/index.jsx @@ -27,19 +27,24 @@ import { setTimezone, setMode, setDistributedUptimeEnabled, + setLanguage, } from "../../Features/UI/uiSlice"; import timezones from "../../Utils/timezones.json"; import { useState, useEffect } from "react"; import { networkService } from "../../main"; import { settingsValidation } from "../../Validation/validation"; +import { updateAppSettings } from "../../Features/Settings/settingsSlice"; +import { useTranslation } from "react-i18next"; // Constants const SECONDS_PER_DAY = 86400; const Settings = () => { const theme = useTheme(); + const { t, i18n } = useTranslation(); const isAdmin = useIsAdmin(); const { user } = useSelector((state) => state.auth); + const { language } = useSelector((state) => state.ui); const { checkTTL } = user; const { isLoading } = useSelector((state) => state.uptimeMonitors); const { isLoading: authIsLoading } = useSelector((state) => state.auth); @@ -119,10 +124,13 @@ const Settings = () => { }); const updatedUser = { ...user, checkTTL: form.ttl }; const action = await dispatch(update({ localData: updatedUser })); + const settingsAction = await dispatch( + updateAppSettings({ settings: { language: language } }) + ); - if (action.payload.success) { + if (action.payload.success && settingsAction.payload.success) { createToast({ - body: "Settings saved successfully", + body: t("settingsSuccessSaved"), }); } else { if (action.payload) { @@ -139,7 +147,7 @@ const Settings = () => { } } catch (error) { console.log(error); - createToast({ body: "Failed to save settings" }); + createToast({ body: t("settingsFailedToSave") }); } finally { setChecksIsLoading(false); } @@ -147,18 +155,16 @@ const Settings = () => { const handleClearStats = async () => { try { - const action = await dispatch( - deleteMonitorChecksByTeamId({ teamId: user.teamId }) - ); + const action = await dispatch(deleteMonitorChecksByTeamId({ teamId: user.teamId })); if (deleteMonitorChecksByTeamId.fulfilled.match(action)) { - createToast({ body: "Stats cleared successfully" }); + createToast({ body: t("settingsStatsCleared") }); } else { - createToast({ body: "Failed to clear stats" }); + createToast({ body: t("settingsFailedToClearStats") }); } } catch (error) { logger.error(error); - createToast({ body: "Failed to clear stats" }); + createToast({ body: t("settingsFailedToClearStats") }); } finally { setIsOpen(deleteStatsMonitorsInitState); } @@ -168,13 +174,13 @@ const Settings = () => { try { const action = await dispatch(addDemoMonitors()); if (addDemoMonitors.fulfilled.match(action)) { - createToast({ body: "Successfully added demo monitors" }); + createToast({ body: t("settingsDemoMonitorsAdded") }); } else { - createToast({ body: "Failed to add demo monitors" }); + createToast({ body: t("settingsFailedToAddDemoMonitors") }); } } catch (error) { logger.error(error); - createToast({ Body: "Failed to add demo monitors" }); + createToast({ Body: t("settingsFailedToAddDemoMonitors") }); } }; @@ -182,18 +188,20 @@ const Settings = () => { try { const action = await dispatch(deleteAllMonitors()); if (deleteAllMonitors.fulfilled.match(action)) { - createToast({ body: "Successfully deleted all monitors" }); + createToast({ body: t("settingsMonitorsDeleted") }); } else { - createToast({ body: "Failed to add demo monitors" }); + createToast({ body: t("settingsFailedToDeleteMonitors") }); } } catch (error) { logger.error(error); - createToast({ Body: "Failed to delete all monitors" }); + createToast({ Body: t("settingsFailedToDeleteMonitors") }); } finally { setIsOpen(deleteStatsMonitorsInitState); } }; + const languages = Object.keys(i18n.options.resources || {}); + return ( { > - General settings + {t("settingsGeneralSettings")} - Display timezone- The timezone of - the dashboard you publicly display. + {t("settingsDisplayTimezone")}-{" "} + {t("settingsDisplayTimezoneDescription")} - Appearance + {t("settingsAppearance")} - Switch between light and dark mode. + {t("settingsAppearanceDescription")} + {isAdmin && ( - Distributed uptime + {t("settingsDistributedUptime")} - Enable/disable distributed uptime monitoring. + {t("settingsDistributedUptimeDescription")} @@ -266,109 +284,18 @@ const Settings = () => { dispatch(setDistributedUptimeEnabled(e.target.checked)); }} /> - {distributedUptimeEnabled === true ? "Enabled" : "Disabled"} + {distributedUptimeEnabled === true + ? t("settingsEnabled") + : t("settingsDisabled")} )} {isAdmin && ( - History and monitoring + {t("settingsWallet")} - Define here for how long you want to keep the data. You can also remove - all past data. - - - - - - Clear all stats. This is irreversible. - - - - setIsOpen(deleteStatsMonitorsInitState)} - confirmationButtonLabel="Yes, clear all stats" - onConfirm={handleClearStats} - isLoading={isLoading || authIsLoading || checksIsLoading} - /> - - )} - {isAdmin && ( - - - Demo monitors - - Here you can add and remove demo monitors. - - - - - Add demo monitors - - - - Remove all monitors - - - - setIsOpen(deleteStatsMonitorsInitState)} - confirmationButtonLabel="Yes, clear all monitors" - onConfirm={handleDeleteAllMonitors} - isLoading={isLoading || authIsLoading || checksIsLoading} - /> - - )} - {isAdmin && ( - - - Wallet - - Connect your wallet here. This is required for the Distributed Uptime - monitor to connect to multiple nodes globally. + {t("settingsWalletDescription")} @@ -382,15 +309,106 @@ const Settings = () => { )} + {isAdmin && ( + + + {t("settingsHistoryAndMonitoring")} + + {t("settingsHistoryAndMonitoringDescription")} + + + + + + {t("settingsClearAllStats")} + + + + setIsOpen(deleteStatsMonitorsInitState)} + confirmationButtonLabel={t("settingsClearAllStatsDialogConfirm")} + onConfirm={handleClearStats} + isLoading={isLoading || authIsLoading || checksIsLoading} + /> + + )} + {isAdmin && ( + + + {t("settingsDemoMonitors")} + + {t("settingsDemoMonitorsDescription")} + + + + + {t("settingsAddDemoMonitors")} + + + + {t("settingsRemoveAllMonitors")} + + + + setIsOpen(deleteStatsMonitorsInitState)} + confirmationButtonLabel={t("settingsRemoveAllMonitorsDialogConfirm")} + onConfirm={handleDeleteAllMonitors} + isLoading={isLoading || authIsLoading || checksIsLoading} + /> + + )} - About + {t("settingsAbout")} Checkmate {version} - Developed by Bluewave Labs. + {t("settingsDevelopedBy")} { sx={{ px: theme.spacing(12), mt: theme.spacing(20) }} onClick={handleSave} > - Save + {t("settingsSave")} diff --git a/src/Pages/StatusPage/Create/Components/Tabs/ConfigStack.jsx b/src/Pages/StatusPage/Create/Components/Tabs/ConfigStack.jsx new file mode 100644 index 000000000..6eb64a519 --- /dev/null +++ b/src/Pages/StatusPage/Create/Components/Tabs/ConfigStack.jsx @@ -0,0 +1,26 @@ +import { Stack, Typography } from "@mui/material"; +import ConfigBox from "../../../../../Components/ConfigBox"; +import PropTypes from "prop-types"; +import { useTheme } from "@emotion/react"; + +// This can be used to add any extra/additional section/stacks on top of existing sections on the tab +const ConfigStack = ({ title, description, children }) => { + const theme = useTheme(); + return ( + + + {title} + {description} + + {children} + + ); +}; + +ConfigStack.propTypes = { + title: PropTypes.string.isRequired, // Title must be a string and is required + description: PropTypes.string.isRequired, // Description must be a string and is required + children: PropTypes.node.isRequired, +}; + +export default ConfigStack; diff --git a/src/Pages/StatusPage/Create/Components/Tabs/Content.jsx b/src/Pages/StatusPage/Create/Components/Tabs/Content.jsx index 8eda4fe0a..f6945ab5b 100644 --- a/src/Pages/StatusPage/Create/Components/Tabs/Content.jsx +++ b/src/Pages/StatusPage/Create/Components/Tabs/Content.jsx @@ -1,13 +1,13 @@ // Components -import { Stack, Typography, Button } from "@mui/material"; +import { Stack, Typography } from "@mui/material"; import { TabPanel } from "@mui/lab"; -import ConfigBox from "../../../../../Components/ConfigBox"; import MonitorList from "../MonitorList"; import Search from "../../../../../Components/Inputs/Search"; import Checkbox from "../../../../../Components/Inputs/Checkbox"; // Utils import { useState } from "react"; import { useTheme } from "@emotion/react"; +import ConfigStack from "./ConfigStack"; const Content = ({ tabValue, form, @@ -34,14 +34,10 @@ const Content = ({ return ( - - - Status page servers - - You can add any number of servers that you monitor to your status page. You - can also reorder them for the best viewing experience. - - + - {" "} - - - Features - Show more details on the status page - - + + + - + - ); }; diff --git a/src/Pages/StatusPage/Create/Components/Tabs/Settings.jsx b/src/Pages/StatusPage/Create/Components/Tabs/Settings.jsx index 14f7ac20c..0fdf1a9b8 100644 --- a/src/Pages/StatusPage/Create/Components/Tabs/Settings.jsx +++ b/src/Pages/StatusPage/Create/Components/Tabs/Settings.jsx @@ -73,6 +73,8 @@ const TabSettings = ({ label="Your status page address" value={form.url} onChange={handleFormChange} + helperText={errors["url"]} + error={errors["url"] ? true : false} /> diff --git a/src/Utils/Theme/constants.js b/src/Utils/Theme/constants.js index cd2b2e316..915acedc5 100644 --- a/src/Utils/Theme/constants.js +++ b/src/Utils/Theme/constants.js @@ -40,7 +40,6 @@ const paletteColors = { blueGray150: "#667085", blueGray200: "#475467", blueGray400: "#344054", - blueGray900: "#1c2130", blueBlueWave: "#1570EF", blue700: "#4E5BA6", purple300: "#664EFF", @@ -89,11 +88,14 @@ const newColors = { gray100: "#F3F3F3", gray200: "#EFEFEF", gray500: "#A2A3A3", + gray900: "#1c1c1c", blueGray50: "#E8F0FE", blueGray500: "#475467", blueGray600: "#344054", blueGray800: "#1C2130", + blueGray900: "#515151", blueBlueWave: "#1570EF", + lightBlueWave: "#CDE2FF", /* I changed green 100 and green 700. Need to change red and warning as well, and refactor the object following the structure */ green100: "#67cd78", green200: "#4B9B77", @@ -171,6 +173,10 @@ const newSemanticColors = { light: newColors.gray200, dark: "#313131" /* newColors.blueGray600 */, }, + light: { + light: newColors.lightBlueWave, + dark: newColors.lightBlueWave, + }, contrastText: { light: newColors.blueGray600, dark: newColors.gray200, @@ -290,6 +296,16 @@ const newSemanticColors = { dark: "#C084FC", }, }, + alert: { + main: { + light: newColors.gray200, + dark: newColors.gray900, + }, + contrastText: { + light: newColors.blueGray600, + dark: newColors.blueGray900, + }, + }, }; export { typographyLevels, semanticColors as colors, newSemanticColors }; diff --git a/src/Validation/validation.js b/src/Validation/validation.js index a243b37e8..ed0aaf6b8 100644 --- a/src/Validation/validation.js +++ b/src/Validation/validation.js @@ -222,7 +222,14 @@ const statusPageValidation = joi.object({ .string() .trim() .messages({ "string.empty": "Company name is required." }), - url: joi.string().trim().messages({ "string.empty": "URL is required." }), + url: joi + .string() + .pattern(/^[a-zA-Z0-9_-]+$/) // Only allow alphanumeric, underscore, and hyphen + .required() + .messages({ + "string.pattern.base": + "URL can only contain letters, numbers, underscores, and hyphens", + }), timezone: joi.string().trim().messages({ "string.empty": "Timezone is required." }), color: joi.string().trim().messages({ "string.empty": "Color is required." }), theme: joi.string(), diff --git a/src/locales/gb.json b/src/locales/gb.json index e12309469..cf7711fa8 100644 --- a/src/locales/gb.json +++ b/src/locales/gb.json @@ -65,5 +65,47 @@ "distributedStatusSubHeaderText": "Powered by millions devices worldwide, view a system performance by global region, country or city", "distributedRightCategoryTitle": "Monitor", "distributedStatusServerMonitors": "Server Monitors", - "distributedStatusServerMonitorsDescription": "Monitor status of related servers" + "distributedStatusServerMonitorsDescription": "Monitor status of related servers", + + "settingsGeneralSettings": "General settings", + "settingsDisplayTimezone": "Display timezone", + "settingsDisplayTimezoneDescription": "The timezone of the dashboard you publicly display.", + "settingsAppearance": "Appearance", + "settingsAppearanceDescription": "Switch between light and dark mode, or change user interface language", + "settingsThemeMode": "Theme Mode", + "settingsLanguage": "Language", + "settingsDistributedUptime": "Distributed uptime", + "settingsDistributedUptimeDescription": "Enable/disable distributed uptime monitoring.", + "settingsEnabled": "Enabled", + "settingsDisabled": "Disabled", + "settingsHistoryAndMonitoring": "History and monitoring", + "settingsHistoryAndMonitoringDescription": "Define here for how long you want to keep the data. You can also remove all past data.", + "settingsTTLLabel": "The days you want to keep monitoring history.", + "settingsTTLOptionalLabel": "0 for infinite", + "settingsClearAllStats": "Clear all stats. This is irreversible.", + "settingsClearAllStatsButton": "Clear all stats", + "settingsClearAllStatsDialogTitle": "Do you want to clear all stats?", + "settingsClearAllStatsDialogDescription": "Once deleted, your monitors cannot be retrieved.", + "settingsClearAllStatsDialogConfirm": "Yes, clear all stats", + "settingsDemoMonitors": "Demo monitors", + "settingsDemoMonitorsDescription": "Here you can add and remove demo monitors.", + "settingsAddDemoMonitors": "Add demo monitors", + "settingsAddDemoMonitorsButton": "Add demo monitors", + "settingsRemoveAllMonitors": "Remove all monitors", + "settingsRemoveAllMonitorsButton": "Remove all monitors", + "settingsRemoveAllMonitorsDialogTitle": "Do you want to remove all monitors?", + "settingsRemoveAllMonitorsDialogConfirm": "Yes, clear all monitors", + "settingsWallet": "Wallet", + "settingsWalletDescription": "Connect your wallet here. This is required for the Distributed Uptime monitor to connect to multiple nodes globally.", + "settingsAbout": "About", + "settingsDevelopedBy": "Developed by Bluewave Labs.", + "settingsSave": "Save", + "settingsSuccessSaved": "Settings saved successfully", + "settingsFailedToSave": "Failed to save settings", + "settingsStatsCleared": "Stats cleared successfully", + "settingsFailedToClearStats": "Failed to clear stats", + "settingsDemoMonitorsAdded": "Successfully added demo monitors", + "settingsFailedToAddDemoMonitors": "Failed to add demo monitors", + "settingsMonitorsDeleted": "Successfully deleted all monitors", + "settingsFailedToDeleteMonitors": "Failed to delete all monitors" } diff --git a/src/locales/tr.json b/src/locales/tr.json index 5ff3448b7..abd358548 100644 --- a/src/locales/tr.json +++ b/src/locales/tr.json @@ -58,5 +58,48 @@ "authRegisterBySigningUp": "Kayıt olarak, aşağıdaki şartları kabul ediyorsunuz:", "distributedStatusHeaderText": "Gerçek zamanlı, Gerçek cihazlar kapsamı", "distributedStatusSubHeaderText": "Dünya çapında milyonlarca cihaz tarafından desteklenen sistem performansını küresel bölgeye, ülkeye veya şehre göre görüntüleyin", - "distributedRightCategoryTitle": "Monitör" + "distributedRightCatagoryTitle": "Monitör", + "distributedRightCatagoryDescription": "Mainnet Beta Kümesi", + + "settingsGeneralSettings": "Genel ayarlar", + "settingsDisplayTimezone": "Görüntüleme saat dilimi", + "settingsDisplayTimezoneDescription": "Herkese açık olarak görüntülediğiniz kontrol panelinin saat dilimi.", + "settingsAppearance": "Görünüm", + "settingsAppearanceDescription": "Açık ve koyu mod arasında geçiş yapın veya kullanıcı arayüzü dilini değiştirin", + "settingsThemeMode": "Tema", + "settingsLanguage": "Dil", + "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", + "settingsDisabled": "Devre dışı", + "settingsHistoryAndMonitoring": "Geçmiş ve izleme", + "settingsHistoryAndMonitoringDescription": "Verileri ne kadar süreyle saklamak istediğinizi burada tanımlayın. Ayrıca tüm geçmiş verileri kaldırabilirsiniz.", + "settingsTTLLabel": "İzleme geçmişini saklamak istediğiniz gün sayısı.", + "settingsTTLOptionalLabel": "Sınırsız için 0", + "settingsClearAllStats": "Tüm istatistikleri temizle. Bu geri alınamaz.", + "settingsClearAllStatsButton": "Tüm istatistikleri temizle", + "settingsClearAllStatsDialogTitle": "Tüm istatistikleri temizlemek istiyor musunuz?", + "settingsClearAllStatsDialogDescription": "Silindikten sonra, monitörleriniz geri alınamaz.", + "settingsClearAllStatsDialogConfirm": "Evet, tüm istatistikleri temizle", + "settingsDemoMonitors": "Demo monitörler", + "settingsDemoMonitorsDescription": "Burada demo monitörler ekleyebilir ve kaldırabilirsiniz.", + "settingsAddDemoMonitors": "Demo monitörler ekle", + "settingsAddDemoMonitorsButton": "Demo monitörler ekle", + "settingsRemoveAllMonitors": "Tüm monitörleri kaldır", + "settingsRemoveAllMonitorsButton": "Tüm monitörleri kaldır", + "settingsRemoveAllMonitorsDialogTitle": "Tüm monitörleri kaldırmak istiyor musunuz?", + "settingsRemoveAllMonitorsDialogConfirm": "Evet, tüm monitörleri temizle", + "settingsWallet": "Cüzdan", + "settingsWalletDescription": "Cüzdanınızı buradan bağlayın. Bu, Dağıtılmış Çalışma Süresi monitörünün küresel olarak birden çok düğüme bağlanması için gereklidir.", + "settingsAbout": "Hakkında", + "settingsDevelopedBy": "Bluewave Labs tarafından geliştirilmiştir.", + "settingsSave": "Kaydet", + "settingsSuccessSaved": "Ayarlar başarıyla kaydedildi", + "settingsFailedToSave": "Ayarlar kaydedilemedi", + "settingsStatsCleared": "İstatistikler başarıyla temizlendi", + "settingsFailedToClearStats": "İstatistikler temizlenemedi", + "settingsDemoMonitorsAdded": "Demo monitörler başarıyla eklendi", + "settingsFailedToAddDemoMonitors": "Demo monitörler eklenemedi", + "settingsMonitorsDeleted": "Tüm monitörler başarıyla silindi", + "settingsFailedToDeleteMonitors": "Monitörler silinemedi" }