Feat: Migrate Hardcoded Strings

This commit is contained in:
Br0wnHammer
2025-03-17 01:16:42 +05:30
parent b6113a176f
commit cdbabeb225
30 changed files with 334 additions and 187 deletions

View File

@@ -28,6 +28,7 @@ import {
} from "../../../Utils/timeUtils";
import { useNavigate, useParams } from "react-router-dom";
import { buildErrors, hasValidationErrors } from "../../../Validation/error";
import { useTranslation } from "react-i18next";
const getDurationAndUnit = (durationInMs) => {
if (durationInMs % MS_PER_DAY === 0) {
@@ -113,6 +114,7 @@ const CreateMaintenance = () => {
const { maintenanceWindowId } = useParams();
const navigate = useNavigate();
const theme = useTheme();
const { t } = useTranslation();
const { user } = useSelector((state) => state.auth);
const [monitors, setMonitors] = useState([]);
const [search, setSearch] = useState("");
@@ -293,7 +295,7 @@ const CreateMaintenance = () => {
component="span"
fontSize="inherit"
>
{`${maintenanceWindowId === undefined ? "Create a" : "Edit"}`}{" "}
{`${maintenanceWindowId === undefined ? t("createA") : t("edit")}`}{" "}
</Typography>
<Typography
component="span"
@@ -301,13 +303,13 @@ const CreateMaintenance = () => {
fontSize="inherit"
fontWeight="inherit"
>
maintenance{" "}
{t("maintenance")}{" "}
</Typography>
<Typography
component="span"
fontSize="inherit"
>
window
{t("window")}
</Typography>
</Typography>
<Typography
@@ -315,7 +317,7 @@ const CreateMaintenance = () => {
variant="body2"
fontSize={14}
>
Your pings won&apos;t be sent during this time frame
{t("maintenanceWindowDescription")}
</Typography>
</Box>
<ConfigBox>
@@ -324,14 +326,14 @@ const CreateMaintenance = () => {
component="h2"
variant="h2"
>
General Settings
{t("settingsGeneralSettings")}
</Typography>
</Box>
<Stack gap={theme.spacing(15)}>
<TextInput
id="name"
label="Friendly name"
placeholder="Maintenance at __ : __ for ___ minutes"
label={t("friendlyNameInput")}
placeholder={t("friendlyNamePlaceholder")}
value={form.name}
onChange={(event) => {
handleFormChange("name", event.target.value);
@@ -342,7 +344,7 @@ const CreateMaintenance = () => {
<Select
id="repeat"
name="maintenance-repeat"
label="Maintenance Repeat"
label={t("maintenanceRepeat")}
value={getIdByValue(repeatConfig, form.repeat)}
onChange={(event) => {
handleFormChange(
@@ -437,15 +439,15 @@ const CreateMaintenance = () => {
component="h2"
variant="h2"
>
Start time
{t("startTime")}
</Typography>
<Typography>All dates and times are in GMT+0 time zone.</Typography>
<Typography>{t("timeZoneInfo")}</Typography>
</Box>
<Stack gap={theme.spacing(15)}>
<LocalizationProvider dateAdapter={AdapterDayjs}>
<MobileTimePicker
id="startTime"
label="Start time"
label={t("startTime")}
value={form.startTime}
onChange={(newTime) => {
handleTimeChange("startTime", newTime);
@@ -486,7 +488,7 @@ const CreateMaintenance = () => {
<TextInput
type="number"
id="duration"
label="Duration"
label={t("duration")}
value={form.duration}
onChange={(event) => {
handleFormChange("duration", event.target.value);
@@ -516,13 +518,13 @@ const CreateMaintenance = () => {
component="h2"
variant="h2"
>
Monitors to apply maintenance window to
{t("monitorsToApply")}
</Typography>
</Box>
<Stack gap={theme.spacing(15)}>
<Search
id={"monitors"}
label="Add monitors"
label={t("addMonitors")}
multiple={true}
isAdorned={false}
options={monitors ? monitors : []}
@@ -547,7 +549,7 @@ const CreateMaintenance = () => {
onClick={() => navigate("/maintenance")}
sx={{ mr: theme.spacing(6) }}
>
Cancel
{t("cancel")}
</Button>
<Button
loading={isLoading}
@@ -558,8 +560,8 @@ const CreateMaintenance = () => {
>
{`${
maintenanceWindowId === undefined
? "Create maintenance"
: "Edit maintenance"
? t("createMaintenance")
: t("editMaintenance")
}`}
</Button>
</Box>

View File

@@ -8,6 +8,7 @@ import Settings from "../../../../assets/icons/settings-bold.svg?react";
import PropTypes from "prop-types";
import { networkService } from "../../../../main";
import { createToast } from "../../../../Utils/toastUtils";
import { useTranslation } from "react-i18next";
import Dialog from "../../../../Components/Dialog";
@@ -18,6 +19,7 @@ const ActionsMenu = ({ /* isAdmin, */ maintenanceWindow, updateCallback }) => {
const [isLoading, setIsLoading] = useState(false);
const theme = useTheme();
const { t } = useTranslation();
const handleRemove = async (event) => {
event.preventDefault();
@@ -124,7 +126,7 @@ const ActionsMenu = ({ /* isAdmin, */ maintenanceWindow, updateCallback }) => {
handleEdit();
}}
>
Edit
{t("edit")}
</MenuItem>
<MenuItem
onClick={(e) => {
@@ -142,7 +144,7 @@ const ActionsMenu = ({ /* isAdmin, */ maintenanceWindow, updateCallback }) => {
openRemove(e);
}}
>
Remove
{t("remove")}
</MenuItem>
</Menu>
<Dialog

View File

@@ -10,6 +10,7 @@ import { useDispatch, useSelector } from "react-redux";
import { formatDurationRounded } from "../../../Utils/timeUtils";
import { StatusLabel } from "../../../Components/Label";
import { setRowsPerPage } from "../../../Features/UI/uiSlice";
import { useTranslation } from "react-i18next";
import dayjs from "dayjs";
/**
* Component for pagination actions (first, previous, next, last).
@@ -49,13 +50,15 @@ const MaintenanceTable = ({
);
setPage(0);
};
const { t } = useTranslation();
const headers = [
{
id: "name",
content: (
<Box onClick={() => handleSort("name")}>
Maintenance Window Name
{t("maintenanceWindowName")}
<span
style={{
visibility: sort.field === "name" ? "visible" : "hidden",
@@ -76,7 +79,7 @@ const MaintenanceTable = ({
content: (
<Box onClick={() => handleSort("status")}>
{" "}
Status
{t("status")}
<span
style={{
visibility: sort.field === "active" ? "visible" : "hidden",
@@ -105,21 +108,21 @@ const MaintenanceTable = ({
},
{
id: "nextWindow",
content: "Next window",
content: t("nextWindow"),
render: (row) => {
return getTimeToNextWindow(row.start, row.end, row.repeat);
},
},
{
id: "repeat",
content: "Repeat",
content: t("repeat"),
render: (row) => {
return row.repeat === 0 ? "N/A" : formatDurationRounded(row.repeat);
},
},
{
id: "actions",
content: "Actions",
content: t("actions"),
render: (row) => (
<ActionsMenu
maintenanceWindow={row}

View File

@@ -9,9 +9,11 @@ import { networkService } from "../../main";
import Breadcrumbs from "../../Components/Breadcrumbs";
import { useNavigate } from "react-router-dom";
import { useIsAdmin } from "../../Hooks/useIsAdmin";
import { useTranslation } from "react-i18next";
const Maintenance = () => {
const theme = useTheme();
const { t } = useTranslation();
const navigate = useNavigate();
const { rowsPerPage } = useSelector((state) => state.ui.maintenance);
const isAdmin = useIsAdmin();
@@ -74,7 +76,7 @@ const Maintenance = () => {
}}
sx={{ fontWeight: 500 }}
>
Create maintenance window
{t("createMaintenanceWindow")}
</Button>
</Stack>
<MaintenanceTable

View File

@@ -4,6 +4,7 @@ import NotFoundSvg from "../../../src/assets/Images/sushi_404.svg";
import { Button, Stack, Typography } from "@mui/material";
import { useNavigate } from "react-router";
import { useTheme } from "@emotion/react";
import { useTranslation } from "react-i18next";
/**
* Support for defaultProps will be removed from function components in a future major release
@@ -33,6 +34,7 @@ const DefaultValue = {
const NotFound = ({ title = DefaultValue.title, desc = DefaultValue.desc }) => {
const navigate = useNavigate();
const theme = useTheme();
const { t } = useTranslation();
return (
<Stack
@@ -62,7 +64,7 @@ const NotFound = ({ title = DefaultValue.title, desc = DefaultValue.desc }) => {
sx={{ mt: theme.spacing(10) }}
onClick={() => navigate("/")}
>
Go to the main dashboard
{t("notFoundButton")}
</Button>
</Stack>
</Stack>

View File

@@ -13,6 +13,7 @@ import {
import { monitorValidation } from "../../../Validation/validation";
import { createToast } from "../../../Utils/toastUtils";
import { logger } from "../../../Utils/Logger";
import { useTranslation } from "react-i18next";
import ConfigBox from "../../../Components/ConfigBox";
import TextInput from "../../../Components/Inputs/TextInput";
import Select from "../../../Components/Inputs/Select";
@@ -28,6 +29,7 @@ import Dialog from "../../../Components/Dialog";
const PageSpeedConfigure = () => {
const theme = useTheme();
const { t } = useTranslation();
const navigate = useNavigate();
const dispatch = useDispatch();
const MS_PER_MINUTE = 60000;
@@ -256,7 +258,7 @@ const PageSpeedConfigure = () => {
},
}}
>
Editing...
{t("editing")}
</Typography>
</Stack>
</Box>
@@ -284,12 +286,12 @@ const PageSpeedConfigure = () => {
{monitor?.isActive ? (
<>
<PauseCircleOutlineIcon />
Pause
{t("pause")}
</>
) : (
<>
<PlayCircleOutlineRoundedIcon />
Resume
{t("resume")}
</>
)}
</Button>
@@ -302,16 +304,15 @@ const PageSpeedConfigure = () => {
ml: theme.spacing(6),
}}
>
Remove
{t("remove")}
</Button>
</Box>
</Stack>
<ConfigBox>
<Box>
<Typography component="h2">General settings</Typography>
<Typography component="h2">{t("settingsGeneralSettings")}</Typography>
<Typography component="p">
Here you can select the URL of the host, together with the type of
monitor.
{t("pageSpeedConfigureSettingsDescription")}
</Typography>
</Box>
<Stack
@@ -325,7 +326,7 @@ const PageSpeedConfigure = () => {
<TextInput
type="url"
id="monitor-url"
label="URL"
label={t("url")}
placeholder="random.website.com"
value={monitor?.url || ""}
onChange={handleChange}
@@ -336,7 +337,7 @@ const PageSpeedConfigure = () => {
<TextInput
type="text"
id="monitor-name"
label="Monitor display name"
label={t("monitorDisplayName")}
placeholder="Example monitor"
isOptional={true}
value={monitor?.name || ""}
@@ -348,16 +349,16 @@ const PageSpeedConfigure = () => {
</ConfigBox>
<ConfigBox>
<Box>
<Typography component="h2">Incident notifications</Typography>
<Typography component="h2">{t("distributedUptimeCreateIncidentNotification")}</Typography>
<Typography component="p">
When there is an incident, notify users.
{t("distributedUptimeCreateIncidentDescription")}
</Typography>
</Box>
<Stack gap={theme.spacing(6)}>
<Typography component="p">When there is a new incident,</Typography>
<Typography component="p">{t("whenNewIncident")}</Typography>
<Checkbox
id="notify-sms"
label="Notify via SMS (coming soon)"
label={t("notifySMS")}
isChecked={false}
value=""
onChange={() => logger.warn("disabled")}
@@ -376,7 +377,7 @@ const PageSpeedConfigure = () => {
/>
<Checkbox
id="notify-email"
label="Also notify via email to multiple addresses (coming soon)"
label={t("notifyEmails")}
isChecked={false}
value=""
onChange={() => logger.warn("disabled")}
@@ -394,7 +395,7 @@ const PageSpeedConfigure = () => {
onChange={() => logger.warn("disabled")}
/>
<Typography mt={theme.spacing(4)}>
You can separate multiple emails with a comma
{t("seperateEmails")}
</Typography>
</Box>
) : (
@@ -404,12 +405,12 @@ const PageSpeedConfigure = () => {
</ConfigBox>
<ConfigBox>
<Box>
<Typography component="h2">Advanced settings</Typography>
<Typography component="h2">{t("distributedUptimeCreateAdvancedSettings")}</Typography>
</Box>
<Stack gap={theme.spacing(20)}>
<Select
id="monitor-frequency"
label="Check frequency"
label={t("checkFrequency")}
items={frequencies}
value={monitor?.interval / MS_PER_MINUTE || 3}
onChange={(event) => handleChange(event, "interval")}
@@ -429,7 +430,7 @@ const PageSpeedConfigure = () => {
onClick={handleSave}
sx={{ px: theme.spacing(12) }}
>
Save
{t("settingsSave")}
</Button>
</Stack>
</Stack>
@@ -438,8 +439,8 @@ const PageSpeedConfigure = () => {
<Dialog
open={isOpen}
theme={theme}
title={"Do you really want to delete this monitor?"}
description={"Once deleted, this monitor cannot be retrieved."}
title={t("deleteDialogTitle")}
description={t("deleteDialogDescription")}
onCancel={() => setIsOpen(false)}
confirmationButtonLabel={"Delete"}
onConfirm={handleRemove}

View File

@@ -10,6 +10,7 @@ import {
checkEndpointResolution,
} from "../../../Features/PageSpeedMonitor/pageSpeedMonitorSlice";
import { parseDomainName } from "../../../Utils/monitorUtils";
import { useTranslation } from "react-i18next";
// MUI
import { useTheme } from "@emotion/react";
@@ -173,6 +174,8 @@ const CreatePageSpeed = () => {
}
};
const { t } = useTranslation();
return (
<Box
className="create-monitor"
@@ -200,7 +203,7 @@ const CreatePageSpeed = () => {
component="span"
fontSize="inherit"
>
Create your{" "}
{t("createYour")}{" "}
</Typography>
<Typography
component="span"
@@ -208,14 +211,14 @@ const CreatePageSpeed = () => {
fontWeight="inherit"
color={theme.palette.primary.contrastTextSecondary}
>
PageSpeed monitor
{t("pageSpeedMonitor")}
</Typography>
</Typography>
<ConfigBox>
<Box>
<Typography component="h2">General settings</Typography>
<Typography component="h2">{t("settingsGeneralSettings")}</Typography>
<Typography component="p">
Here you can select the URL of the host, together with the type of monitor.
{t("distributedUptimeCreateSelectURL")}
</Typography>
</Box>
<Stack gap={theme.spacing(15)}>
@@ -248,9 +251,9 @@ const CreatePageSpeed = () => {
</ConfigBox>
<ConfigBox>
<Box>
<Typography component="h2">Checks to perform</Typography>
<Typography component="h2">{t("distributedUptimeCreateChecks")}</Typography>
<Typography component="p">
You can always add or remove checks after adding your site.
{t("distributedUptimeCreateChecksDescription")}
</Typography>
</Box>
<Stack gap={theme.spacing(12)}>
@@ -269,14 +272,14 @@ const CreatePageSpeed = () => {
filled={https.toString()}
onClick={() => setHttps(true)}
>
HTTPS
{t("https")}
</Button>
<Button
variant="group" // Why does this work?
filled={(!https).toString()} // There's nothing in the docs about this either
onClick={() => setHttps(false)}
>
HTTP
{t("http")}
</Button>
</ButtonGroup>
</Stack>
@@ -297,13 +300,13 @@ const CreatePageSpeed = () => {
</ConfigBox>
<ConfigBox>
<Box>
<Typography component="h2">Incident notifications</Typography>
<Typography component="h2">{t("distributedUptimeCreateIncidentNotification")}</Typography>
<Typography component="p">
When there is an incident, notify users.
{t("distributedUptimeCreateIncidentDescription")}
</Typography>
</Box>
<Stack gap={theme.spacing(6)}>
<Typography component="p">When there is a new incident,</Typography>
<Typography component="p">{t("whenNewIncident")}</Typography>
<Checkbox
id="notify-email-default"
label={`Notify via email (to ${user.email})`}
@@ -317,7 +320,7 @@ const CreatePageSpeed = () => {
</ConfigBox>
<ConfigBox>
<Box>
<Typography component="h2">Advanced settings</Typography>
<Typography component="h2">{t("distributedUptimeCreateAdvancedSettings")}</Typography>
</Box>
<Stack gap={theme.spacing(12)}>
<Select
@@ -341,7 +344,7 @@ const CreatePageSpeed = () => {
disabled={!Object.values(errors).every((value) => value === undefined)}
loading={isLoading}
>
Create monitor
{t("createMonitor")}
</Button>
</Stack>
</Stack>

View File

@@ -2,11 +2,12 @@ import { Box, Typography, Divider } from "@mui/material";
import Checkbox from "../../../../../Components/Inputs/Checkbox";
import MetricsIcon from "../../../../../assets/icons/ruler-icon.svg?react";
import LegendBox from "../../../../../Components/Charts/LegendBox";
import { useTranslation } from "react-i18next";
import { useTheme } from "@emotion/react";
const AreaChartLegend = ({ metrics, handleMetrics }) => {
const theme = useTheme();
const { t } = useTranslation();
return (
<LegendBox
icon={<MetricsIcon />}
@@ -17,7 +18,7 @@ const AreaChartLegend = ({ metrics, handleMetrics }) => {
fontSize={11}
fontWeight={500}
>
Shown
{t("shown")}
</Typography>
<Divider sx={{ mt: theme.spacing(2) }} />
</Box>

View File

@@ -2,6 +2,7 @@ import StatusBoxes from "../../../../../Components/StatusBoxes";
import StatBox from "../../../../../Components/StatBox";
import { Typography } from "@mui/material";
import { getHumanReadableDuration } from "../../../../../Utils/timeUtils";
import { useTranslation } from "react-i18next";
const PageSpeedStatusBoxes = ({ shouldRender, monitor }) => {
const { time: uptimeDuration, units: uptimeUnits } = getHumanReadableDuration(
@@ -12,6 +13,8 @@ const PageSpeedStatusBoxes = ({ shouldRender, monitor }) => {
monitor?.lastChecked
);
const { t } = useTranslation();
return (
<StatusBoxes shouldRender={shouldRender}>
<StatBox
@@ -20,7 +23,7 @@ const PageSpeedStatusBoxes = ({ shouldRender, monitor }) => {
<>
{uptimeDuration}
<Typography component="span">{uptimeUnits}</Typography>
<Typography component="span">ago</Typography>
<Typography component="span">{t("ago")}</Typography>
</>
}
/>
@@ -30,7 +33,7 @@ const PageSpeedStatusBoxes = ({ shouldRender, monitor }) => {
<>
{lastCheckTime}
<Typography component="span">{lastCheckUnits}</Typography>
<Typography component="span">ago</Typography>
<Typography component="span">{t("ago")}</Typography>
</>
}
/>

View File

@@ -5,10 +5,12 @@ import { Typography } from "@mui/material";
import { useTheme } from "@emotion/react";
import PieChartLegend from "../Charts/PieChartLegend";
import SkeletonLayout from "./skeleton";
import { useTranslation } from "react-i18next";
const PerformanceReport = ({ shouldRender, audits }) => {
const theme = useTheme();
const { t } = useTranslation();
if (!shouldRender) {
return <SkeletonLayout />;
}
@@ -25,7 +27,7 @@ const PerformanceReport = ({ shouldRender, audits }) => {
variant="body1"
mt="auto"
>
Values are estimated and may vary.{" "}
{t("pageSpeedDetailsPerformanceReport")}{" "}
<Typography
component="span"
fontSize="inherit"
@@ -41,7 +43,7 @@ const PerformanceReport = ({ shouldRender, audits }) => {
},
}}
>
See calculator
{t("pageSpeedDetailsPerformanceReportCalculator")}
</Typography>
</Typography>
</ChartBox>

View File

@@ -14,6 +14,7 @@ import { useParams } from "react-router-dom";
import { useSelector } from "react-redux";
import { useMonitorFetch } from "./Hooks/useMonitorFetch";
import { useState } from "react";
import { useTranslation } from "react-i18next";
// Constants
const BREADCRUMBS = [
{ name: "pagespeed", path: "/pagespeed" },
@@ -23,6 +24,7 @@ const BREADCRUMBS = [
const PageSpeedDetails = () => {
const theme = useTheme();
const { t } = useTranslation();
const isAdmin = useIsAdmin();
const { monitorId } = useParams();
@@ -50,9 +52,9 @@ const PageSpeedDetails = () => {
marginY={theme.spacing(4)}
color={theme.palette.primary.contrastTextTertiary}
>
Network error
{t("networkError")}
</Typography>
<Typography>Please check your connection</Typography>
<Typography>{t("checkConnection")}</Typography>
</GenericFallback>
);
}
@@ -68,7 +70,7 @@ const PageSpeedDetails = () => {
monitor={monitor}
/>
<GenericFallback>
<Typography>There is no check history for this monitor yet.</Typography>
<Typography>{t("distributedUptimeDetailsNoMonitorHistory")}</Typography>
</GenericFallback>
</Stack>
);

View File

@@ -10,6 +10,7 @@ import { useSelector } from "react-redux";
import { formatDateWithTz, formatDurationSplit } from "../../../../../Utils/timeUtils";
import useUtils from "../../../../Uptime/Monitors/Hooks/useUtils";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import IconBox from "../../../../../Components/IconBox";
/**
* CustomToolTip displays a tooltip with formatted date and score information.
@@ -207,6 +208,7 @@ PagespeedAreaChart.propTypes = {
const Card = ({ monitor }) => {
const { determineState, pagespeedStatusMsg } = useUtils();
const theme = useTheme();
const { t } = useTranslation();
const navigate = useNavigate();
const monitorState = determineState(monitor);
@@ -297,7 +299,7 @@ const Card = ({ monitor }) => {
fontSize={11}
color={theme.palette.primary.contrastTextSecondary}
>
Checking every{" "}
{t("checkingEvery")}{" "}
{(() => {
const { time, format } = formatDurationSplit(monitor?.interval);
return (

View File

@@ -12,12 +12,13 @@ import { useSelector } from "react-redux";
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
import useMonitorsFetch from "./Hooks/useMonitorsFetch";
import GenericFallback from "../../../Components/GenericFallback";
import { useTranslation } from "react-i18next";
// Constants
const BREADCRUMBS = [{ name: `pagespeed`, path: "/pagespeed" }];
const PageSpeed = () => {
const theme = useTheme();
const { t } = useTranslation();
const isAdmin = useIsAdmin();
const { user } = useSelector((state) => state.auth);
@@ -33,9 +34,9 @@ const PageSpeed = () => {
marginY={theme.spacing(4)}
color={theme.palette.primary.contrastTextTertiary}
>
Network error
{t("networkError")}
</Typography>
<Typography>Please check your connection</Typography>
<Typography>{t("checkConnection")}</Typography>
</GenericFallback>
);
}

View File

@@ -1,9 +1,10 @@
import { Button, Box } from "@mui/material";
import ProgressUpload from "../../../../../Components/ProgressBars";
import ImageIcon from "@mui/icons-material/Image";
import { useTranslation } from "react-i18next";
import { formatBytes } from "../../../../../Utils/fileUtils";
const Progress = ({ isLoading, progressValue, logo, logoType, removeLogo, errors }) => {
const { t } = useTranslation();
if (isLoading) {
return (
<ProgressUpload
@@ -27,7 +28,7 @@ const Progress = ({ isLoading, progressValue, logo, logoType, removeLogo, errors
color="secondary"
onClick={removeLogo}
>
Remove Logo
{t("removeLogo")}
</Button>
</Box>
);

View File

@@ -7,6 +7,7 @@ import Checkbox from "../../../../../Components/Inputs/Checkbox";
// Utils
import { useState } from "react";
import { useTheme } from "@emotion/react";
import { useTranslation } from "react-i18next";
import ConfigStack from "./ConfigStack";
const Content = ({
tabValue,
@@ -30,13 +31,14 @@ const Content = ({
// Utils
const theme = useTheme();
const { t } = useTranslation();
return (
<TabPanel value={tabValue}>
<Stack gap={theme.spacing(10)}>
<ConfigStack
title="Status page servers"
description="You can add any number of servers that you monitor to your status page. You can also reorder them for the best viewing experience."
title={t("statusPageCreateTabsContent")}
description={t("statusPageCreateTabsContentDescription")}
>
<Stack>
<Stack
@@ -70,21 +72,21 @@ const Content = ({
</Stack>
</ConfigStack>
<ConfigStack
title="Features"
description="Show more details on the status page"
title={t("features")}
description={t("statusPageCreateTabsContentFeaturesDescription")}
>
<Stack>
<Checkbox
id="showCharts"
name="showCharts"
label={`Show charts`}
label={t("showCharts")}
isChecked={form.showCharts}
onChange={handleFormChange}
/>
<Checkbox
id="showUptimePercentage"
name="showUptimePercentage"
label={`Show uptime percentage`}
label={t("showUptimePercentage")}
isChecked={form.showUptimePercentage}
onChange={handleFormChange}
/>

View File

@@ -13,6 +13,7 @@ import Progress from "../Progress";
import { useTheme } from "@emotion/react";
import timezones from "../../../../../Utils/timezones.json";
import PropTypes from "prop-types";
import { useTranslation } from "react-i18next";
const TabSettings = ({
isCreate,
@@ -26,22 +27,23 @@ const TabSettings = ({
}) => {
// Utils
const theme = useTheme();
const { t } = useTranslation();
return (
<TabPanel value={tabValue}>
<Stack gap={theme.spacing(10)}>
<ConfigBox>
<Stack>
<Typography component="h2">Access</Typography>
<Typography component="h2">{t("access")}</Typography>
<Typography component="p">
If your status page is ready, you can mark it as published.
{t("statusPageCreateSettings")}
</Typography>
</Stack>
<Stack gap={theme.spacing(18)}>
<Checkbox
id="publish"
name="isPublished"
label={`Published and visible to the public`}
label={t("statusPageCreateSettingsCheckboxLabel")}
isChecked={form.isPublished}
onChange={handleFormChange}
/>
@@ -49,9 +51,9 @@ const TabSettings = ({
</ConfigBox>
<ConfigBox>
<Stack gap={theme.spacing(6)}>
<Typography component="h2">Basic Information</Typography>
<Typography component="h2">{t("basicInformation")}</Typography>
<Typography component="p">
Define company name and the subdomain that your status page points to.
{t("statusPageCreateBasicInfoDescription")}
</Typography>
</Stack>
<Stack gap={theme.spacing(18)}>
@@ -59,7 +61,7 @@ const TabSettings = ({
id="companyName"
name="companyName"
type="text"
label="Company name"
label={t("companyName")}
value={form.companyName}
onChange={handleFormChange}
helperText={errors["companyName"]}
@@ -70,7 +72,7 @@ const TabSettings = ({
name="url"
type="url"
disabled={!isCreate}
label="Your status page address"
label={t("statusPageCreateBasicInfoStatusPageAddress")}
value={form.url}
onChange={handleFormChange}
helperText={errors["url"]}
@@ -80,16 +82,16 @@ const TabSettings = ({
</ConfigBox>
<ConfigBox>
<Stack gap={theme.spacing(6)}>
<Typography component="h2">Timezone</Typography>
<Typography component="h2">{t("timezone")}</Typography>
<Typography component="p">
Select the timezone that your status page will be displayed in.
{t("statusPageCreateSelectTimeZoneDescription")}
</Typography>
</Stack>
<Stack gap={theme.spacing(6)}>
<Select
id="timezone"
name="timezone"
label="Display timezone"
label={t("settingsDisplayTimezone")}
items={timezones}
value={form.timezone}
onChange={handleFormChange}
@@ -98,9 +100,9 @@ const TabSettings = ({
</ConfigBox>
<ConfigBox>
<Stack gap={theme.spacing(6)}>
<Typography component="h2">Appearance</Typography>
<Typography component="h2">{t("settingsAppearance")}</Typography>
<Typography component="p">
Define the default look and feel of your public status page.
{t("statusPageCreateAppearanceDescription")}
</Typography>
</Stack>
<Stack gap={theme.spacing(6)}>

View File

@@ -14,7 +14,7 @@ import { createToast } from "../../../Utils/toastUtils";
import { useNavigate } from "react-router-dom";
import { useStatusPageFetch } from "../Status/Hooks/useStatusPageFetch";
import { useParams } from "react-router-dom";
import { useTranslation } from "react-i18next";
//Constants
const TAB_LIST = ["General settings", "Contents"];
@@ -54,6 +54,7 @@ const CreateStatusPage = () => {
const [createStatusPage, createStatusIsLoading, createStatusPageNetworkError] =
useCreateStatusPage(isCreate);
const navigate = useNavigate();
const { t } = useTranslation();
const [statusPage, statusPageMonitors, statusPageIsLoading, statusPageNetworkError] =
useStatusPageFetch(isCreate, url);
@@ -205,9 +206,9 @@ const CreateStatusPage = () => {
marginY={theme.spacing(4)}
color={theme.palette.primary.contrastTextTertiary}
>
Network error
{t("networkError")}
</Typography>
<Typography>Please check your connection</Typography>
<Typography>{t("checkConnection")}</Typography>
</GenericFallback>
);
}
@@ -241,7 +242,7 @@ const CreateStatusPage = () => {
color="accent"
onClick={handleSubmit}
>
Save
{t("settingsSave")}
</Button>
</Stack>
</Stack>

View File

@@ -4,9 +4,11 @@ import { Box, Typography } from "@mui/material";
// Utils
import { useTheme } from "@mui/material/styles";
import { useNavigate } from "react-router-dom";
import { useTranslation } from "react-i18next";
const AdminLink = () => {
const theme = useTheme();
const { t } = useTranslation();
const navigate = useNavigate();
return (
@@ -16,7 +18,7 @@ const AdminLink = () => {
display="inline-block"
color={theme.palette.primary.contrastText}
>
Administrator?
{t("administrator")}
</Typography>
<Typography
component="span"
@@ -25,7 +27,7 @@ const AdminLink = () => {
sx={{ cursor: "pointer" }}
onClick={() => navigate("/login")}
>
Login here
{t("loginHere")}
</Typography>
</Box>
);

View File

@@ -8,9 +8,11 @@ import { useTheme } from "@mui/material/styles";
import { useNavigate } from "react-router-dom";
import { useLocation } from "react-router-dom";
import PropTypes from "prop-types";
import { useTranslation } from "react-i18next";
const Controls = ({ isDeleteOpen, setIsDeleteOpen, isDeleting, url, type }) => {
const theme = useTheme();
const { t } = useTranslation();
const location = useLocation();
const currentPath = location.pathname;
const navigate = useNavigate();
@@ -35,7 +37,7 @@ const Controls = ({ isDeleteOpen, setIsDeleteOpen, isDeleting, url, type }) => {
onClick={() => setIsDeleteOpen(!isDeleteOpen)}
loading={isDeleting}
>
Delete
{t("delete")}
</Button>
</Box>
<Box>
@@ -59,7 +61,7 @@ const Controls = ({ isDeleteOpen, setIsDeleteOpen, isDeleting, url, type }) => {
},
}}
>
<SettingsIcon /> Configure
<SettingsIcon /> {t("configure")}
</Button>
</Box>
</Stack>

View File

@@ -17,6 +17,7 @@ import { useStatusPageDelete } from "./Hooks/useStatusPageDelete";
import { useState } from "react";
import { useParams } from "react-router-dom";
import { useNavigate } from "react-router-dom";
import { useTranslation } from "react-i18next";
const PublicStatus = () => {
const { url } = useParams();
@@ -24,6 +25,7 @@ const PublicStatus = () => {
const [isDeleteOpen, setIsDeleteOpen] = useState(false);
// Utils
const theme = useTheme();
const { t } = useTranslation();
const location = useLocation();
const navigate = useNavigate();
@@ -59,9 +61,9 @@ const PublicStatus = () => {
marginY={theme.spacing(4)}
color={theme.palette.primary.contrastTextTertiary}
>
Network error
{t("networkError")}
</Typography>
<Typography>Please check your connection</Typography>
<Typography>{t("checkConnection")}</Typography>
</GenericFallback>
);
}
@@ -76,9 +78,9 @@ const PublicStatus = () => {
marginY={theme.spacing(4)}
color={theme.palette.primary.contrastTextTertiary}
>
A public status page is not set up.
{t("statusPageStatus")}
</Typography>
<Typography>Please contact to your administrator</Typography>
<Typography>{t("statusPageStatusContactAdmin")}</Typography>
</GenericFallback>
</Stack>
);
@@ -94,9 +96,9 @@ const PublicStatus = () => {
marginY={theme.spacing(4)}
color={theme.palette.primary.contrastTextTertiary}
>
This status page is not public.
{t("statusPageStatusNotPublic")}
</Typography>
<Typography>Please contact to your administrator</Typography>
<Typography>{t("statusPageStatusContactAdmin")}</Typography>
</GenericFallback>
</Stack>
);
@@ -111,9 +113,9 @@ const PublicStatus = () => {
marginY={theme.spacing(4)}
color={theme.palette.primary.contrastTextTertiary}
>
There's no status page here.
{t("statusPageStatusNoPage")}
</Typography>
<Typography>Please contact to your administrator</Typography>
<Typography>{t("statusPageStatusContactAdmin")}</Typography>
</GenericFallback>
);
}
@@ -131,12 +133,12 @@ const PublicStatus = () => {
setIsDeleteOpen={setIsDeleteOpen}
url={url}
/>
<Typography variant="h2">Service status</Typography>
<Typography variant="h2">{t("statusPageStatusServiceStatus")}</Typography>
<StatusBar monitors={monitors} />
<MonitorsList monitors={monitors} />
{link}
<Dialog
title="Do you want to delete this status page?"
title={t("deleteStatusPage")}
onConfirm={() => {
deleteStatusPage();
setIsDeleteOpen(false);
@@ -146,8 +148,8 @@ const PublicStatus = () => {
setIsDeleteOpen(false);
}}
open={isDeleteOpen}
confirmationButtonLabel="Yes, delete status page"
description="Once deleted, your status page cannot be retrieved."
confirmationButtonLabel={t("deleteStatusPageConfirm")}
description={t("deleteStatusPageDescription")}
isLoading={isDeleting || isLoading}
/>
</Stack>

View File

@@ -4,20 +4,22 @@ import { useNavigate } from "react-router-dom";
import { StatusLabel } from "../../../../../Components/Label";
import ArrowOutwardIcon from "@mui/icons-material/ArrowOutward";
import { Stack, Typography } from "@mui/material";
import { useTranslation } from "react-i18next";
const StatusPagesTable = ({ data }) => {
const theme = useTheme();
const { t } = useTranslation();
const navigate = useNavigate();
const headers = [
{
id: "name",
content: "Status page name",
content: t("statusPageName"),
render: (row) => {
return row.companyName;
},
},
{
id: "url",
content: "Public URL",
content: t("publicURL"),
onClick: (e, row) => {
if (row.isPublished) {
e.stopPropagation();
@@ -57,14 +59,14 @@ const StatusPagesTable = ({ data }) => {
},
{
id: "type",
content: "Type",
content: t("type"),
render: (row) => {
return row.type;
},
},
{
id: "status",
content: "Status",
content: t("status"),
render: (row) => {
const status = row.isPublished ? "published" : "unpublished";
return (

View File

@@ -8,6 +8,7 @@ import StatusPagesTable from "./Components/StatusPagesTable";
import SkeletonLayout from "../../../Components/Skeletons/FullPage";
// Utils
import { useTheme } from "@emotion/react";
import { useTranslation } from "react-i18next";
import { useStatusPagesFetch } from "./Hooks/useStatusPagesFetch";
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
const BREADCRUMBS = [{ name: `Status Pages`, path: "" }];
@@ -15,6 +16,7 @@ const BREADCRUMBS = [{ name: `Status Pages`, path: "" }];
const StatusPages = () => {
// Utils
const theme = useTheme();
const { t } = useTranslation();
const isAdmin = useIsAdmin();
const [isLoading, networkError, statusPages] = useStatusPagesFetch();
@@ -30,9 +32,9 @@ const StatusPages = () => {
marginY={theme.spacing(4)}
color={theme.palette.primary.contrastTextTertiary}
>
Network error
{t("networkError")}
</Typography>
<Typography>Please check your connection</Typography>
<Typography>{t("checkConnection")}</Typography>
</GenericFallback>
);
}

View File

@@ -6,6 +6,7 @@ import { Box, Stack, Tooltip, Typography, Button } from "@mui/material";
import { monitorValidation } from "../../../Validation/validation";
import { createToast } from "../../../Utils/toastUtils";
import { logger } from "../../../Utils/Logger";
import { useTranslation } from "react-i18next";
import ConfigBox from "../../../Components/ConfigBox";
import {
updateUptimeMonitor,
@@ -207,6 +208,8 @@ const Configure = () => {
undefined: "Pending...",
};
const { t } = useTranslation();
return (
<Stack
className="configure-monitor"
@@ -293,7 +296,7 @@ const Configure = () => {
},
}}
>
Editing...
{t("editing")}
</Typography>
</Stack>
</Box>
@@ -326,12 +329,12 @@ const Configure = () => {
{monitor?.isActive ? (
<>
<PauseIcon />
Pause
{t("pause")}
</>
) : (
<>
<ResumeIcon />
Resume
{t("resume")}
</>
)}
</Button>
@@ -342,16 +345,15 @@ const Configure = () => {
sx={{ px: theme.spacing(8) }}
onClick={() => setIsOpen(true)}
>
Remove
{t("remove")}
</Button>
</Box>
</Stack>
<ConfigBox>
<Box>
<Typography component="h2">General settings</Typography>
<Typography component="h2">{t("settingsGeneralSettings")}</Typography>
<Typography component="p">
Here you can select the URL of the host, together with the type of
monitor.
{t("distributedUptimeCreateSelectURL")}
</Typography>
</Box>
<Stack gap={theme.spacing(20)}>
@@ -364,7 +366,7 @@ const Configure = () => {
)
}
id="monitor-url"
label="URL to monitor"
label={t("urlMonitor")}
placeholder="google.com"
value={parsedUrl?.host || monitor?.url || ""}
disabled={true}
@@ -372,7 +374,7 @@ const Configure = () => {
<TextInput
type="text"
id="monitor-name"
label="Display name"
label={t("displayName")}
isOptional={true}
placeholder="Google"
value={monitor?.name || ""}
@@ -384,13 +386,13 @@ const Configure = () => {
</ConfigBox>
<ConfigBox>
<Box>
<Typography component="h2">Incident notifications</Typography>
<Typography component="h2">{t("distributedUptimeCreateIncidentNotification")}</Typography>
<Typography component="p">
When there is an incident, notify users.
{t("distributedUptimeCreateIncidentDescription")}
</Typography>
</Box>
<Stack gap={theme.spacing(6)}>
<Typography component="p">When there is a new incident,</Typography>
<Typography component="p">{t("whenNewIncident")}</Typography>
{/* {Leaving components commented for future funtionality implimentation} */}
{/* <Checkbox
id="notify-sms"
@@ -441,12 +443,12 @@ const Configure = () => {
</ConfigBox>
<ConfigBox>
<Box>
<Typography component="h2">Advanced settings</Typography>
<Typography component="h2">{t("distributedUptimeCreateAdvancedSettings")}</Typography>
</Box>
<Stack gap={theme.spacing(20)}>
<Select
id="monitor-interval-configure"
label="Check frequency"
label={t("checkFrequency")}
value={monitor?.interval / MS_PER_MINUTE || 1}
onChange={(event) => handleChange(event, "interval")}
items={frequencies}
@@ -455,7 +457,7 @@ const Configure = () => {
<>
<Select
id="match-method"
label="Match Method"
label={t("matchMethod")}
value={monitor.matchMethod || "equal"}
onChange={(event) => handleChange(event, "matchMethod")}
items={matchMethodOptions}
@@ -464,7 +466,7 @@ const Configure = () => {
<TextInput
type="text"
id="expected-value"
label="Expected value"
label={t("expectedValue")}
isOptional={true}
placeholder={
expectedValuePlaceholders[monitor.matchMethod || "equal"]
@@ -479,8 +481,7 @@ const Configure = () => {
color={theme.palette.primary.contrastTextTertiary}
opacity={0.8}
>
The expected value is used to match against response result, and
the match determines the status.
{t("uptimeCreate")}
</Typography>
</Stack>
<Stack>
@@ -500,9 +501,7 @@ const Configure = () => {
color={theme.palette.primary.contrastTextTertiary}
opacity={0.8}
>
This expression will be evaluated against the reponse JSON data
and the result will be used to match against the expected value.
See&nbsp;
{t("uptimeCreateJsonPath")}&nbsp;
<Typography
component="a"
href="https://jmespath.org/"
@@ -511,7 +510,7 @@ const Configure = () => {
>
jmespath.org
</Typography>
&nbsp;for query language documentation.
&nbsp;{t("uptimeCreateJsonPathQuery")}
</Typography>
</Stack>
</>
@@ -530,7 +529,7 @@ const Configure = () => {
sx={{ px: theme.spacing(12) }}
onClick={handleSubmit}
>
Save
{t("settingsSave")}
</Button>
</Stack>
</Stack>

View File

@@ -10,7 +10,7 @@ import { checkEndpointResolution } from "../../../Features/UptimeMonitors/uptime
import { monitorValidation } from "../../../Validation/validation";
import { getUptimeMonitorById } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice";
import { createUptimeMonitor } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice";
import { useTranslation } from "react-i18next";
// MUI
import { Box, Stack, Typography, Button, ButtonGroup } from "@mui/material";
@@ -240,6 +240,8 @@ const CreateMonitor = () => {
fetchMonitor();
}, [monitorId, dispatch, navigate]);
const { t } = useTranslation();
return (
<Box className="create-monitor">
<Breadcrumbs list={crumbs} />
@@ -257,7 +259,7 @@ const CreateMonitor = () => {
component="span"
fontSize="inherit"
>
Create your{" "}
{t("createYour")}{" "}
</Typography>
<Typography
component="span"
@@ -265,22 +267,22 @@ const CreateMonitor = () => {
fontSize="inherit"
fontWeight="inherit"
>
monitor
{t("monitor")}
</Typography>
</Typography>
<ConfigBox>
<Box>
<Typography component="h2">Checks to perform</Typography>
<Typography component="h2">{t("distributedUptimeCreateChecks")}</Typography>
<Typography component="p">
You can always add or remove checks after adding your site.
{t("distributedUptimeCreateChecksDescription")}
</Typography>
</Box>
<Stack gap={theme.spacing(12)}>
<Stack gap={theme.spacing(6)}>
<Radio
id="monitor-checks-http"
title="Website monitoring"
desc="Use HTTP(s) to monitor your website or API endpoint."
title={t("websiteMonitoring")}
desc={t("websiteMonitoringDescription")}
size="small"
value="http"
checked={monitor.type === "http"}
@@ -293,14 +295,14 @@ const CreateMonitor = () => {
filled={https.toString()}
onClick={() => setHttps(true)}
>
HTTPS
{t("https")}
</Button>
<Button
variant="group"
filled={(!https).toString()}
onClick={() => setHttps(false)}
>
HTTP
{t("http")}
</Button>
</ButtonGroup>
) : (
@@ -309,8 +311,8 @@ const CreateMonitor = () => {
</Stack>
<Radio
id="monitor-checks-ping"
title="Ping monitoring"
desc="Check whether your server is available or not."
title={t("pingMonitoring")}
desc={t("pingMonitoringDescription")}
size="small"
value="ping"
checked={monitor.type === "ping"}
@@ -318,8 +320,8 @@ const CreateMonitor = () => {
/>
<Radio
id="monitor-checks-docker"
title="Docker container monitoring"
desc="Check whether your container is running or not."
title={t("dockerContainerMonitoring")}
desc={t("dockerContainerMonitoringDescription")}
size="small"
value="docker"
checked={monitor.type === "docker"}
@@ -327,8 +329,8 @@ const CreateMonitor = () => {
/>
<Radio
id="monitor-checks-port"
title="Port monitoring"
desc="Check whether your port is open or not."
title={t("portMonitoring")}
desc={t("portMonitoringDescription")}
size="small"
value="port"
checked={monitor.type === "port"}
@@ -351,9 +353,9 @@ const CreateMonitor = () => {
</ConfigBox>
<ConfigBox>
<Box>
<Typography component="h2">General settings</Typography>
<Typography component="h2">{t("settingsGeneralSettings")}</Typography>
<Typography component="p">
Here you can select the URL of the host, together with the type of monitor.
{t("distributedUptimeCreateSelectURL")}
</Typography>
</Box>
<Stack gap={theme.spacing(15)}>
@@ -374,7 +376,7 @@ const CreateMonitor = () => {
<TextInput
type="number"
id="monitor-port"
label="Port to monitor"
label={t("portToMonitor")}
placeholder="5173"
value={monitor.port}
onChange={(event) => handleChange(event, "port")}
@@ -385,7 +387,7 @@ const CreateMonitor = () => {
<TextInput
type="text"
id="monitor-name"
label="Display name"
label={t("displayName")}
isOptional={true}
placeholder={monitorTypeMaps[monitor.type].namePlaceholder || ""}
value={monitor.name}
@@ -397,9 +399,9 @@ const CreateMonitor = () => {
</ConfigBox>
<ConfigBox>
<Box>
<Typography component="h2">Incident notifications</Typography>
<Typography component="h2">{t("distributedUptimeCreateIncidentNotification")}</Typography>
<Typography component="p">
When there is an incident, notify users.
{t("distributedUptimeCreateIncidentDescription")}
</Typography>
</Box>
<Stack gap={theme.spacing(6)}>
@@ -427,7 +429,7 @@ const CreateMonitor = () => {
</ConfigBox>
<ConfigBox>
<Box>
<Typography component="h2">Advanced settings</Typography>
<Typography component="h2">{t("distributedUptimeCreateAdvancedSettings")}</Typography>
</Box>
<Stack gap={theme.spacing(12)}>
<Select
@@ -465,8 +467,7 @@ const CreateMonitor = () => {
color={theme.palette.primary.contrastTextTertiary}
opacity={0.8}
>
The expected value is used to match against response result, and the
match determines the status.
{t("uptimeCreate")}
</Typography>
</Stack>
<Stack>
@@ -486,8 +487,7 @@ const CreateMonitor = () => {
color={theme.palette.primary.contrastTextTertiary}
opacity={0.8}
>
This expression will be evaluated against the reponse JSON data and
the result will be used to match against the expected value. See&nbsp;
{t("uptimeCreateJsonPath")}&nbsp;
<Typography
component="a"
href="https://jmespath.org/"
@@ -496,7 +496,7 @@ const CreateMonitor = () => {
>
jmespath.org
</Typography>
&nbsp;for query language documentation.
&nbsp;{t("uptimeCreateJsonPathQuery")}
</Typography>
</Stack>
</>
@@ -514,7 +514,7 @@ const CreateMonitor = () => {
disabled={!Object.values(errors).every((value) => value === undefined)}
loading={isLoading}
>
Create monitor
{t("createMonitor")}
</Button>
</Stack>
</Stack>

View File

@@ -1,10 +1,11 @@
import PropTypes from "prop-types";
import { useTheme } from "@mui/material";
import { ResponsiveContainer, RadialBarChart, RadialBar, Cell } from "recharts";
import { useTranslation } from "react-i18next";
const ResponseGaugeChart = ({ avgResponseTime }) => {
const theme = useTheme();
const { t } = useTranslation();
let max = 1000; // max ms
const data = [
@@ -61,7 +62,7 @@ const ResponseGaugeChart = ({ avgResponseTime }) => {
textAnchor="start"
fontSize={11}
>
low
{t("low")}
</text>
<text
x="100%"
@@ -71,7 +72,7 @@ const ResponseGaugeChart = ({ avgResponseTime }) => {
textAnchor="end"
fontSize={11}
>
high
{t("high")}
</text>
<text
x="50%"

View File

@@ -4,6 +4,7 @@ import HistoryIcon from "../../../../../assets/icons/history-icon.svg?react";
import Table from "../../../../../Components/Table";
import TablePagination from "../../../../../Components/Table/TablePagination";
import { StatusLabel } from "../../../../../Components/Label";
import { useTranslation } from "react-i18next";
import { formatDateWithTz } from "../../../../../Utils/timeUtils";
import SkeletonLayout from "./skeleton";
const ResponseTable = ({
@@ -16,6 +17,7 @@ const ResponseTable = ({
rowsPerPage,
setRowsPerPage,
}) => {
const { t } = useTranslation();
if (!shouldRender) {
return <SkeletonLayout />;
}
@@ -23,7 +25,7 @@ const ResponseTable = ({
const headers = [
{
id: "status",
content: "Status",
content: t("status"),
render: (row) => {
const status = row.status === true ? "up" : "down";
@@ -38,18 +40,18 @@ const ResponseTable = ({
},
{
id: "date",
content: "Date & Time",
content: t("date&Time"),
render: (row) =>
formatDateWithTz(row.createdAt, "ddd, MMMM D, YYYY, HH:mm A", uiTimezone),
},
{
id: "statusCode",
content: "Status code",
content: t("statusCode"),
render: (row) => (row.statusCode ? row.statusCode : "N/A"),
},
{
id: "message",
content: "Message",
content: t("message"),
render: (row) => row.message,
},
];

View File

@@ -19,6 +19,7 @@ import { useIsAdmin } from "../../../Hooks/useIsAdmin";
import useMonitorFetch from "./Hooks/useMonitorFetch";
import useCertificateFetch from "./Hooks/useCertificateFetch";
import useChecksFetch from "./Hooks/useChecksFetch";
import { useTranslation } from "react-i18next";
// Constants
const BREADCRUMBS = [
@@ -46,6 +47,7 @@ const UptimeDetails = () => {
const { monitorId } = useParams();
const theme = useTheme();
const isAdmin = useIsAdmin();
const { t } = useTranslation();
const [monitor, monitorIsLoading, monitorNetworkError] = useMonitorFetch({
monitorId,
@@ -86,9 +88,9 @@ const UptimeDetails = () => {
marginY={theme.spacing(4)}
color={theme.palette.primary.contrastTextTertiary}
>
Network error
{t("networkError")}
</Typography>
<Typography>Please check your connection</Typography>
<Typography>{t("checkConnection")}</Typography>
</GenericFallback>
);
}
@@ -105,7 +107,7 @@ const UptimeDetails = () => {
monitor={monitor}
/>
<GenericFallback>
<Typography>There is no check history for this monitor yet.</Typography>
<Typography>{t("distributedUptimeDetailsNoMonitorHistory")}</Typography>
</GenericFallback>
</Stack>
);

View File

@@ -16,6 +16,7 @@ import { useTheme } from "@emotion/react";
import useUtils from "../../Hooks/useUtils";
import { useNavigate } from "react-router-dom";
import PropTypes from "prop-types";
import { useTranslation } from "react-i18next";
/**
* UptimeDataTable displays a table of uptime monitors with sorting, searching, and action capabilities
@@ -59,6 +60,7 @@ const UptimeDataTable = ({
const navigate = useNavigate();
const { determineState } = useUtils();
const theme = useTheme();
const { t } = useTranslation();
// Local state
// Handlers
@@ -82,7 +84,7 @@ const UptimeDataTable = ({
direction="row"
onClick={() => handleSort("name")}
>
Host
{t("host")}
<Stack
justifyContent="center"
style={{
@@ -118,7 +120,7 @@ const UptimeDataTable = ({
onClick={() => handleSort("status")}
>
{" "}
Status
{t("status")}
<Stack
justifyContent="center"
style={{
@@ -146,12 +148,12 @@ const UptimeDataTable = ({
},
{
id: "responseTime",
content: "Response Time",
content: t("responseTime"),
render: (row) => <BarChart checks={row.monitor.checks.slice().reverse()} />,
},
{
id: "type",
content: "Type",
content: t("type"),
render: (row) => (
<span style={{ textTransform: "uppercase" }}>
{row.monitor.type === "http" ? "HTTP(s)" : row.monitor.type}
@@ -160,7 +162,7 @@ const UptimeDataTable = ({
},
{
id: "actions",
content: "Actions",
content: t("actions"),
render: (row) => (
<ActionsMenu
monitor={row.monitor}

View File

@@ -30,6 +30,7 @@ import { setRowsPerPage } from "../../../Features/UI/uiSlice";
import PropTypes from "prop-types";
import useFetchMonitorsWithSummary from "../../../Hooks/useFetchMonitorsWithSummary";
import useFetchMonitorsWithChecks from "../../../Hooks/useFetchMonitorsWithChecks";
import { useTranslation } from "react-i18next";
const BREADCRUMBS = [{ name: `Uptime`, path: "/uptime" }];
const TYPES = ["http", "ping", "docker", "port"];
@@ -75,6 +76,7 @@ const UptimeMonitors = () => {
const theme = useTheme();
const isAdmin = useIsAdmin();
const dispatch = useDispatch();
const { t } = useTranslation();
// Handlers
const handleChangePage = (event, newPage) => {
@@ -130,9 +132,9 @@ const UptimeMonitors = () => {
marginY={theme.spacing(4)}
color={theme.palette.primary.contrastTextTertiary}
>
Network error
{t("networkError")}
</Typography>
<Typography>Please check your connection</Typography>
<Typography>{t("checkConnection")}</Typography>
</GenericFallback>
);
}

View File

@@ -107,6 +107,29 @@
"aboutus": "About Us",
"signUP": "Sign Up",
"now": "Now",
"createYour": "Create your",
"createMonitor": "Create monitor",
"actions": "Actions",
"pause": "Pause",
"resume": "Resume",
"editing": "Editing...",
"url": "URL",
"access": "Access",
"timezone": "Timezone",
"features": "Features",
"administrator": "Administrator?",
"loginHere": "Login here",
"displayName": "Display name",
"urlMonitor": "URL to monitor",
"portToMonitor": "Port to monitor",
"websiteMonitoring": "Website monitoring",
"websiteMonitoringDescription": "Use HTTP(s) to monitor your website or API endpoint.",
"pingMonitoring": "Ping monitoring",
"pingMonitoringDescription": "Check whether your server is available or not.",
"dockerContainerMonitoring": "Docker container monitoring",
"dockerContainerMonitoringDescription": "Check whether your Docker container is running or not.",
"portMonitoring": "Port monitoring",
"portMonitoringDescription": "Check whether your port is open or not.",
"delete": "Delete",
"configure": "Configure",
"networkError": "Network error",
@@ -143,6 +166,80 @@
"distributedUptimeDetailsMonitorHeader": "Distributed Uptime Monitoring powered by DePIN",
"distributedUptimeDetailsStatusHeaderUptime": "Uptime:",
"distributedUptimeDetailsStatusHeaderLastUpdate": "Last updated",
"createMaintenanceWindow": "Create maintenance window",
"createMaintenance": "Create maintenance",
"editMaintenance": "Edit maintenance",
"maintenanceWindowName": "Maintenance Window Name",
"friendlyNameInput": "Friendly name",
"friendlyNamePlaceholder": "Maintenance at __ : __ for ___ minutes",
"maintenanceRepeat": "Maintenance Repeat",
"maintenance": "maintenance",
"duration": "Duration",
"addMonitors": "Add monitors",
"window": "window",
"cancel": "Cancel",
"status": "Status",
"message": "Message",
"low": "low",
"high": "high",
"host": "Host",
"statusCode": "Status code",
"date&Time": "Date & Time",
"type": "Type",
"statusPageName": "Status page name",
"publicURL": "Public URL",
"repeat": "Repeat",
"edit": "Edit",
"createA": "Create a",
"remove": "Remove",
"maintenanceWindowDescription": "Your pings won't be sent during this time frame",
"startTime": "Start time",
"timeZoneInfo": "All dates and times are in GMT+0 time zone.",
"monitorsToApply": "Monitors to apply maintenance window to",
"nextWindow": "Next window",
"notFoundButton": "Go to the main dashboard",
"pageSpeedConfigureSettingsDescription": "Here you can select the URL of the host, together with the type of monitor.",
"monitorDisplayName": "Monitor display name",
"whenNewIncident,": "When there is a new incident,",
"notifySMS": "Notify via SMS (coming soon)",
"notifyEmails": "Also notify via email to multiple addresses (coming soon)",
"seperateEmails": "You can separate multiple emails with a comma",
"checkFrequency": "Check frequency",
"matchMethod": "Match Method",
"expectedValue": "Expected value",
"deleteDialogTitle": "Do you really want to delete this monitor?",
"deleteDialogDescription": "Once deleted, this monitor cannot be retrieved.",
"pageSpeedMonitor": "PageSpeed monitor",
"shown": "Shown",
"ago": "ago",
"companyName": "Company name",
"pageSpeedDetailsPerformanceReport": "Values are estimated and may vary.",
"pageSpeedDetailsPerformanceReportCalculator": "See calculator",
"checkingEvery": "Checking every",
"statusPageCreateSettings": "If your status page is ready, you can mark it as published.",
"basicInformation": "Basic Information",
"statusPageCreateBasicInfoDescription": "Define company name and the subdomain that your status page points to.",
"statusPageCreateSelectTimeZoneDescription": "Select the timezone that your status page will be displayed in.",
"statusPageCreateAppearanceDescription": "Define the default look and feel of your public status page.",
"statusPageCreateSettingsCheckboxLabel": "Published and visible to the public",
"statusPageCreateBasicInfoStatusPageAddress": "Your status page address",
"statusPageCreateTabsContent": "Status page servers",
"statusPageCreateTabsContentDescription": "You can add any number of servers that you monitor to your status page. You can also reorder them for the best viewing experience.",
"statusPageCreateTabsContentFeaturesDescription": "Show more details on the status page",
"showCharts": "Show charts",
"showUptimePercentage": "Show uptime percentage",
"removeLogo": "Remove Logo",
"statusPageStatus": "A public status page is not set up.",
"statusPageStatusContactAdmin": "Please contact to your administrator",
"statusPageStatusNotPublic": "This status page is not public.",
"statusPageStatusNoPage": "There's no status page here.",
"statusPageStatusServiceStatus": "Service status",
"deleteStatusPage": "Do you want to delete this status page?",
"deleteStatusPageConfirm": "Yes, delete status page",
"deleteStatusPageDescription": "Once deleted, your status page cannot be retrieved.",
"uptimeCreate": "The expected value is used to match against response result, and the match determines the status.",
"uptimeCreateJsonPath": "This expression will be evaluated against the reponse JSON data and the result will be used to match against the expected value. See",
"uptimeCreateJsonPathQuery": "for query language documentation.",
"notifications": {
"enableNotifications": "Enable {{platform}} notifications",
"testNotification": "Test notification",