diff --git a/package-lock.json b/package-lock.json
index 6072cb650..b496af154 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9152,9 +9152,9 @@
"license": "MIT"
},
"node_modules/@types/react": {
- "version": "18.3.18",
- "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz",
- "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==",
+ "version": "18.3.19",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.19.tgz",
+ "integrity": "sha512-fcdJqaHOMDbiAwJnXv6XCzX0jDW77yI3tJqYh1Byn8EL5/S628WRx9b/y3DnNe55zTukUQKrfYxiZls2dHcUMw==",
"license": "MIT",
"dependencies": {
"@types/prop-types": "*",
diff --git a/src/Components/MonitorStatusHeader/index.jsx b/src/Components/MonitorStatusHeader/index.jsx
index cbbba52b2..e1007bbf5 100644
--- a/src/Components/MonitorStatusHeader/index.jsx
+++ b/src/Components/MonitorStatusHeader/index.jsx
@@ -8,10 +8,10 @@ import ConfigButton from "./ConfigButton";
import SkeletonLayout from "./skeleton";
import PropTypes from "prop-types";
-const MonitorStatusHeader = ({ path, shouldRender = true, isAdmin, monitor }) => {
+const MonitorStatusHeader = ({ path, isLoading = false, isAdmin, monitor }) => {
const theme = useTheme();
- const { statusColor, statusMsg, determineState } = useUtils();
- if (!shouldRender) {
+ const { statusColor, determineState } = useUtils();
+ if (isLoading) {
return ;
}
@@ -48,7 +48,7 @@ const MonitorStatusHeader = ({ path, shouldRender = true, isAdmin, monitor }) =>
MonitorStatusHeader.propTypes = {
path: PropTypes.string.isRequired,
- shouldRender: PropTypes.bool,
+ isLoading: PropTypes.bool,
isAdmin: PropTypes.bool,
monitor: PropTypes.object,
};
diff --git a/src/Components/MonitorTimeFrameHeader/index.jsx b/src/Components/MonitorTimeFrameHeader/index.jsx
index 9ac8b8b6a..97f113897 100644
--- a/src/Components/MonitorTimeFrameHeader/index.jsx
+++ b/src/Components/MonitorTimeFrameHeader/index.jsx
@@ -4,14 +4,14 @@ import SkeletonLayout from "./skeleton";
import PropTypes from "prop-types";
const MonitorTimeFrameHeader = ({
- shouldRender = true,
+ isLoading = false,
hasDateRange = true,
dateRange,
setDateRange,
}) => {
const theme = useTheme();
- if (!shouldRender) {
+ if (isLoading) {
return ;
}
@@ -77,7 +77,7 @@ const MonitorTimeFrameHeader = ({
};
MonitorTimeFrameHeader.propTypes = {
- shouldRender: PropTypes.bool,
+ isLoading: PropTypes.bool,
hasDateRange: PropTypes.bool,
dateRange: PropTypes.string,
setDateRange: PropTypes.func,
diff --git a/src/Components/NotificationIntegrationModal/NotificationIntegrationModal.jsx b/src/Components/NotificationIntegrationModal/Components/NotificationIntegrationModal.jsx
similarity index 78%
rename from src/Components/NotificationIntegrationModal/NotificationIntegrationModal.jsx
rename to src/Components/NotificationIntegrationModal/Components/NotificationIntegrationModal.jsx
index 30587833a..8077aa3a6 100644
--- a/src/Components/NotificationIntegrationModal/NotificationIntegrationModal.jsx
+++ b/src/Components/NotificationIntegrationModal/Components/NotificationIntegrationModal.jsx
@@ -1,5 +1,6 @@
import { useState, useMemo } from "react";
import { useTranslation } from "react-i18next";
+
import {
Dialog,
DialogContent,
@@ -8,11 +9,29 @@ import {
Typography,
Box,
Tabs,
- Tab
+ Tab,
+ CircularProgress
} from "@mui/material";
import { useTheme } from "@emotion/react";
import TabPanel from "./TabPanel";
import TabComponent from "./TabComponent";
+import useNotifications from "../Hooks/useNotification";
+
+// Define constants for notification types to avoid magic values
+const NOTIFICATION_TYPES = {
+ SLACK: 'slack',
+ DISCORD: 'discord',
+ TELEGRAM: 'telegram',
+ WEBHOOK: 'webhook'
+};
+
+// Define constants for field IDs
+const FIELD_IDS = {
+ WEBHOOK: 'webhook',
+ TOKEN: 'token',
+ CHAT_ID: 'chatId',
+ URL: 'url'
+};
const NotificationIntegrationModal = ({
open,
@@ -26,15 +45,30 @@ const NotificationIntegrationModal = ({
const theme = useTheme();
const [tabValue, setTabValue] = useState(0);
+ const [loading, _, sendTestNotification] = useNotifications();
+
+ // Helper to get the field state key with error handling
+ const getFieldKey = (typeId, fieldId) => {
+ if (typeof typeId !== 'string' || typeId === '') {
+ throw new Error('Invalid typeId provided to getFieldKey');
+ }
+
+ if (typeof fieldId !== 'string' || fieldId === '') {
+ throw new Error('Invalid fieldId provided to getFieldKey');
+ }
+
+ return `${typeId}${fieldId.charAt(0).toUpperCase() + fieldId.slice(1)}`;
+ };
+
// Define notification types
const DEFAULT_NOTIFICATION_TYPES = [
{
- id: 'slack',
+ id: NOTIFICATION_TYPES.SLACK,
label: t('notifications.slack.label'),
description: t('notifications.slack.description'),
fields: [
{
- id: 'webhook',
+ id: FIELD_IDS.WEBHOOK,
label: t('notifications.slack.webhookLabel'),
placeholder: t('notifications.slack.webhookPlaceholder'),
type: 'text'
@@ -42,12 +76,12 @@ const NotificationIntegrationModal = ({
]
},
{
- id: 'discord',
+ id: NOTIFICATION_TYPES.DISCORD,
label: t('notifications.discord.label'),
description: t('notifications.discord.description'),
fields: [
{
- id: 'webhook',
+ id: FIELD_IDS.WEBHOOK,
label: t('notifications.discord.webhookLabel'),
placeholder: t('notifications.discord.webhookPlaceholder'),
type: 'text'
@@ -55,18 +89,18 @@ const NotificationIntegrationModal = ({
]
},
{
- id: 'telegram',
+ id: NOTIFICATION_TYPES.TELEGRAM,
label: t('notifications.telegram.label'),
description: t('notifications.telegram.description'),
fields: [
{
- id: 'token',
+ id: FIELD_IDS.TOKEN,
label: t('notifications.telegram.tokenLabel'),
placeholder: t('notifications.telegram.tokenPlaceholder'),
type: 'text'
},
{
- id: 'chatId',
+ id: FIELD_IDS.CHAT_ID,
label: t('notifications.telegram.chatIdLabel'),
placeholder: t('notifications.telegram.chatIdPlaceholder'),
type: 'text'
@@ -74,12 +108,12 @@ const NotificationIntegrationModal = ({
]
},
{
- id: 'webhook',
+ id: NOTIFICATION_TYPES.WEBHOOK,
label: t('notifications.webhook.label'),
description: t('notifications.webhook.description'),
fields: [
{
- id: 'url',
+ id: FIELD_IDS.URL,
label: t('notifications.webhook.urlLabel'),
placeholder: t('notifications.webhook.urlPlaceholder'),
type: 'text'
@@ -101,7 +135,7 @@ const NotificationIntegrationModal = ({
// Add state for each field in the notification type
type.fields.forEach(field => {
- const fieldKey = `${type.id}${field.id.charAt(0).toUpperCase() + field.id.slice(1)}`;
+ const fieldKey = getFieldKey(type.id, field.id);
state[fieldKey] = monitor?.notifications?.find(n => n.type === type.id)?.[field.id] || "";
});
});
@@ -129,11 +163,26 @@ const NotificationIntegrationModal = ({
}));
};
- const handleTestNotification = (type) => {
- console.log(`Testing ${type} notification`);
- //implement the test notification functionality
+ const handleTestNotification = async (type) => {
+ // Get the notification type details
+ const notificationType = activeNotificationTypes.find(t => t.id === type);
+
+ if (typeof notificationType === "undefined") {
+ return;
+ }
+
+ // Prepare config object based on notification type
+ const config = {};
+
+ // Add each field value to the config object
+ notificationType.fields.forEach(field => {
+ const fieldKey = getFieldKey(type, field.id);
+ config[field.id] = integrations[fieldKey];
+ });
+
+ await sendTestNotification(type, config);
};
-
+
const handleSave = () => {
//notifications array for selected integrations
const notifications = [...(monitor?.notifications || [])];
@@ -155,7 +204,7 @@ const NotificationIntegrationModal = ({
// Add each field value to the notification object
type.fields.forEach(field => {
- const fieldKey = `${type.id}${field.id.charAt(0).toUpperCase() + field.id.slice(1)}`;
+ const fieldKey = getFieldKey(type.id, field.id);
notificationObject[field.id] = integrations[fieldKey];
});
@@ -240,6 +289,7 @@ const NotificationIntegrationModal = ({
handleIntegrationChange={handleIntegrationChange}
handleInputChange={handleInputChange}
handleTestNotification={handleTestNotification}
+ isLoading={loading}
/>
))}
@@ -257,13 +307,14 @@ const NotificationIntegrationModal = ({
variant="contained"
color="accent"
onClick={handleSave}
+ loading={loading}
sx={{
width: 'auto',
minWidth: theme.spacing(60),
px: theme.spacing(8)
}}
>
- {t('common.save', 'Save')}
+ {t('commonSave')}
diff --git a/src/Components/NotificationIntegrationModal/TabComponent.jsx b/src/Components/NotificationIntegrationModal/Components/TabComponent.jsx
similarity index 84%
rename from src/Components/NotificationIntegrationModal/TabComponent.jsx
rename to src/Components/NotificationIntegrationModal/Components/TabComponent.jsx
index 89216a8c1..e46a8cdd5 100644
--- a/src/Components/NotificationIntegrationModal/TabComponent.jsx
+++ b/src/Components/NotificationIntegrationModal/Components/TabComponent.jsx
@@ -2,19 +2,21 @@ import React from "react";
import {
Typography,
Box,
- Button
+ Button,
+ CircularProgress
} from "@mui/material";
import { useTranslation } from "react-i18next";
import { useTheme } from "@emotion/react";
-import TextInput from "../../../src/Components/Inputs/TextInput";
-import Checkbox from "../../../src/Components/Inputs/Checkbox";
+import TextInput from "../../../Components/Inputs/TextInput";
+import Checkbox from "../../../Components/Inputs/Checkbox";
const TabComponent = ({
type,
integrations,
handleIntegrationChange,
handleInputChange,
- handleTestNotification
+ handleTestNotification,
+ isLoading
}) => {
const theme = useTheme();
const { t } = useTranslation();
@@ -55,6 +57,7 @@ const TabComponent = ({
label={t('notifications.enableNotifications', { platform: type.label })}
isChecked={integrations[type.id]}
onChange={(e) => handleIntegrationChange(type.id, e.target.checked)}
+ disabled={isLoading}
/>
@@ -77,7 +80,7 @@ const TabComponent = ({
placeholder={field.placeholder}
value={integrations[fieldKey]}
onChange={(e) => handleInputChange(fieldKey, e.target.value)}
- disabled={!integrations[type.id]}
+ disabled={!integrations[type.id] || isLoading}
/>
);
@@ -88,8 +91,14 @@ const TabComponent = ({
variant="text"
color="info"
onClick={() => handleTestNotification(type.id)}
- disabled={!integrations[type.id] || !areAllFieldsFilled()}
+ disabled={!integrations[type.id] || !areAllFieldsFilled() || isLoading}
>
+ {isLoading ? (
+
+ ) : null}
{t('notifications.testNotification')}
diff --git a/src/Components/NotificationIntegrationModal/TabPanel.jsx b/src/Components/NotificationIntegrationModal/Components/TabPanel.jsx
similarity index 100%
rename from src/Components/NotificationIntegrationModal/TabPanel.jsx
rename to src/Components/NotificationIntegrationModal/Components/TabPanel.jsx
diff --git a/src/Components/NotificationIntegrationModal/Hooks/useNotification.js b/src/Components/NotificationIntegrationModal/Hooks/useNotification.js
new file mode 100644
index 000000000..08343760b
--- /dev/null
+++ b/src/Components/NotificationIntegrationModal/Hooks/useNotification.js
@@ -0,0 +1,119 @@
+import { useState } from 'react';
+import { toast } from 'react-toastify';
+import { useTranslation } from "react-i18next";
+import { networkService } from '../../../Utils/NetworkService';
+
+// Define constants for notification types to avoid magic values
+const NOTIFICATION_TYPES = {
+ SLACK: 'slack',
+ DISCORD: 'discord',
+ TELEGRAM: 'telegram',
+ WEBHOOK: 'webhook'
+};
+
+// Define constants for field IDs
+const FIELD_IDS = {
+ WEBHOOK: 'webhook',
+ TOKEN: 'token',
+ CHAT_ID: 'chatId',
+ URL: 'url'
+};
+
+/**
+ * Custom hook for notification-related operations
+ */
+const useNotifications = () => {
+ const [loading, setLoading] = useState(false);
+ const [error, setError] = useState(undefined);
+ const { t } = useTranslation();
+
+ /**
+ * Send a test notification
+ * @param {string} type - The notification type (slack, discord, telegram, webhook)
+ * @param {object} config - Configuration object with necessary params
+ */
+ const sendTestNotification = async (type, config) => {
+ setLoading(true);
+ setError(undefined);
+
+ // Validation based on notification type
+ let payload = { platform: type };
+ let isValid = true;
+ let errorMessage = '';
+
+ switch(type) {
+ case NOTIFICATION_TYPES.SLACK:
+ payload.webhookUrl = config.webhook;
+ if (typeof payload.webhookUrl === 'undefined' || payload.webhookUrl === '') {
+ isValid = false;
+ errorMessage = t('notifications.slack.webhookRequired');
+ }
+ break;
+
+ case NOTIFICATION_TYPES.DISCORD:
+ payload.webhookUrl = config.webhook;
+ if (typeof payload.webhookUrl === 'undefined' || payload.webhookUrl === '') {
+ isValid = false;
+ errorMessage = t('notifications.discord.webhookRequired');
+ }
+ break;
+
+ case NOTIFICATION_TYPES.TELEGRAM:
+ payload.botToken = config.token;
+ payload.chatId = config.chatId;
+ if (typeof payload.botToken === 'undefined' || payload.botToken === '' ||
+ typeof payload.chatId === 'undefined' || payload.chatId === '') {
+ isValid = false;
+ errorMessage = t('notifications.telegram.fieldsRequired');
+ }
+ break;
+
+ case NOTIFICATION_TYPES.WEBHOOK:
+ payload.webhookUrl = config.url;
+ payload.platform = NOTIFICATION_TYPES.SLACK;
+ if (typeof payload.webhookUrl === 'undefined' || payload.webhookUrl === '') {
+ isValid = false;
+ errorMessage = t('notifications.webhook.urlRequired');
+ }
+ break;
+
+ default:
+ isValid = false;
+ errorMessage = t('notifications.unsupportedType');
+ }
+
+ // If validation fails, show error and return
+ if (isValid === false) {
+ toast.error(errorMessage);
+ setLoading(false);
+ return;
+ }
+
+ try {
+ const response = await networkService.testNotification({
+ platform: type,
+ payload: payload
+ });
+
+ if (response.data.success === true) {
+ toast.success(t('notifications.testSuccess'));
+ } else {
+ throw new Error(response.data.msg || t('notifications.testFailed'));
+ }
+ } catch (error) {
+ const errorMsg = error.response?.data?.msg || error.message || t('notifications.networkError');
+ toast.error(`${t('notifications.testFailed')}: ${errorMsg}`);
+ setError(errorMsg);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return [
+ loading,
+ error,
+ sendTestNotification
+ ];
+};
+
+export default useNotifications;
\ No newline at end of file
diff --git a/src/Hooks/useFetchUptimeMonitorDetails.js b/src/Hooks/useFetchUptimeMonitorDetails.js
new file mode 100644
index 000000000..c8cb81e65
--- /dev/null
+++ b/src/Hooks/useFetchUptimeMonitorDetails.js
@@ -0,0 +1,36 @@
+import { useEffect, useState } from "react";
+import { networkService } from "../main";
+import { useNavigate } from "react-router-dom";
+import { createToast } from "../Utils/toastUtils";
+
+export const useFetchUptimeMonitorDetails = ({ monitorId, dateRange }) => {
+ const [networkError, setNetworkError] = useState(false);
+ const [isLoading, setIsLoading] = useState(true);
+ const [monitor, setMonitor] = useState(undefined);
+ const [monitorStats, setMonitorStats] = useState(undefined);
+ const navigate = useNavigate();
+
+ useEffect(() => {
+ const fetchMonitors = async () => {
+ try {
+ const res = await networkService.getUptimeDetailsById({
+ monitorId: monitorId,
+ dateRange: dateRange,
+ normalize: true,
+ });
+ const { monitorData, monitorStats } = res?.data?.data ?? {};
+ setMonitor(monitorData);
+ setMonitorStats(monitorStats);
+ } catch (error) {
+ setNetworkError(true);
+ createToast({ body: error.message });
+ } finally {
+ setIsLoading(false);
+ }
+ };
+ fetchMonitors();
+ }, [dateRange, monitorId, navigate]);
+ return [monitor, monitorStats, isLoading, networkError];
+};
+
+export default useFetchUptimeMonitorDetails;
diff --git a/src/Pages/StatusPage/StatusPages/Components/StatusPagesTable/index.jsx b/src/Pages/StatusPage/StatusPages/Components/StatusPagesTable/index.jsx
index 20226d6d3..a7b69ded0 100644
--- a/src/Pages/StatusPage/StatusPages/Components/StatusPagesTable/index.jsx
+++ b/src/Pages/StatusPage/StatusPages/Components/StatusPagesTable/index.jsx
@@ -27,7 +27,7 @@ const StatusPagesTable = ({ data }) => {
row.type === "distributed"
? `/status/distributed/public/${row.url}`
: `/status/uptime/public/${row.url}`;
- window.open(url, "_blank", "noopener,noreferrer")
+ window.open(url, "_blank", "noopener,noreferrer");
}
},
render: (row) => {
@@ -40,13 +40,12 @@ const StatusPagesTable = ({ data }) => {
gap={theme.spacing(2)}
paddingLeft={theme.spacing(2)}
paddingRight={theme.spacing(2)}
- borderRadius={theme.spacing(4)}
sx={{
...(row.isPublished && {
+ display: "inline-flex",
":hover": {
- backgroundColor: `${theme.palette.primary.light}`,
cursor: "pointer",
- borderRadius: 1,
+ borderBottom: 1,
},
}),
}}
diff --git a/src/Pages/Uptime/Create/index.jsx b/src/Pages/Uptime/Create/index.jsx
index 4338bb76e..bc757984d 100644
--- a/src/Pages/Uptime/Create/index.jsx
+++ b/src/Pages/Uptime/Create/index.jsx
@@ -4,13 +4,13 @@ import { useNavigate, useParams } from "react-router-dom";
import { useEffect } from "react";
import { useState } from "react";
import { useSelector, useDispatch } from "react-redux";
+import { useTranslation } from "react-i18next";
// Utility and Network
import { checkEndpointResolution } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice";
import { monitorValidation } from "../../../Validation/validation";
import { getUptimeMonitorById } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice";
import { createUptimeMonitor } from "../../../Features/UptimeMonitors/uptimeMonitorsSlice";
-import { useTranslation } from "react-i18next";
// MUI
import { Box, Stack, Typography, Button, ButtonGroup } from "@mui/material";
@@ -23,7 +23,7 @@ import Radio from "../../../Components/Inputs/Radio";
import Checkbox from "../../../Components/Inputs/Checkbox";
import Select from "../../../Components/Inputs/Select";
import ConfigBox from "../../../Components/ConfigBox";
-import NotificationIntegrationModal from "../../../Components/NotificationIntegrationModal/NotificationIntegrationModal";
+import NotificationIntegrationModal from "../../../Components/NotificationIntegrationModal/Components/NotificationIntegrationModal";
const CreateMonitor = () => {
const MS_PER_MINUTE = 60000;
const SELECT_VALUES = [
@@ -84,8 +84,8 @@ const CreateMonitor = () => {
const [isNotificationModalOpen, setIsNotificationModalOpen] = useState(false);
const handleOpenNotificationModal = () => {
- setIsNotificationModalOpen(true);
- };
+ setIsNotificationModalOpen(true);
+ };
const [errors, setErrors] = useState({});
const [https, setHttps] = useState(true);
const [monitor, setMonitor] = useState({
@@ -210,7 +210,7 @@ const CreateMonitor = () => {
const handleAddNotification = () => {
console.log("Add notification clicked");
- };
+ };
useEffect(() => {
const fetchMonitor = async () => {
@@ -354,9 +354,7 @@ const CreateMonitor = () => {
{t("settingsGeneralSettings")}
-
- {t("distributedUptimeCreateSelectURL")}
-
+ {t("distributedUptimeCreateSelectURL")}
{
- {t("distributedUptimeCreateIncidentNotification")}
+
+ {t("distributedUptimeCreateIncidentNotification")}
+
{t("distributedUptimeCreateIncidentDescription")}
@@ -415,21 +415,22 @@ const CreateMonitor = () => {
onChange={(event) => handleNotifications(event, "email")}
/>
- {/*
-
- */}
-
+
+
+
- {t("distributedUptimeCreateAdvancedSettings")}
+
+ {t("distributedUptimeCreateAdvancedSettings")}
+
setIsNotificationModalOpen(false)}
- monitor={monitor}
- setMonitor={setMonitor}
- />
+ open={isNotificationModalOpen}
+ onClose={() => setIsNotificationModalOpen(false)}
+ monitor={monitor}
+ setMonitor={setMonitor}
+ />
);
};
diff --git a/src/Pages/Uptime/Details/Components/ChartBoxes/index.jsx b/src/Pages/Uptime/Details/Components/ChartBoxes/index.jsx
index 1875ef760..d8c2a6385 100644
--- a/src/Pages/Uptime/Details/Components/ChartBoxes/index.jsx
+++ b/src/Pages/Uptime/Details/Components/ChartBoxes/index.jsx
@@ -12,29 +12,23 @@ import SkeletonLayout from "./skeleton";
import { formatDateWithTz } from "../../../../../Utils/timeUtils";
import PropTypes from "prop-types";
import { useTheme } from "@emotion/react";
+import { useState } from "react";
const ChartBoxes = ({
- shouldRender = true,
- monitor,
+ isLoading = false,
+ monitorData,
dateRange,
uiTimezone,
dateFormat,
- hoveredUptimeData,
- setHoveredUptimeData,
- hoveredIncidentsData,
- setHoveredIncidentsData,
}) => {
+ // Local state
+ const [hoveredUptimeData, setHoveredUptimeData] = useState(null);
+ const [hoveredIncidentsData, setHoveredIncidentsData] = useState(null);
const theme = useTheme();
-
- if (!shouldRender) {
+ if (isLoading) {
return ;
}
- const totalUpChecks = monitor?.upChecks?.totalChecks ?? 0;
- const totalDownChecks = monitor?.downChecks?.totalChecks ?? 0;
- const denominator =
- totalUpChecks + totalDownChecks > 0 ? totalUpChecks + totalDownChecks : 1;
- const groupedUptimePercentage = (totalUpChecks / denominator) * 100;
const noIncidentsMessage = "Great. No Incidents, yet!";
return (
@@ -46,7 +40,7 @@ const ChartBoxes = ({
}
header="Uptime"
- isEmpty={monitor?.uptimePercentage === 0 && !monitor?.upChecks?.length}
+ isEmpty={monitorData?.groupedUpChecks?.length === 0}
>
{hoveredUptimeData !== null
? hoveredUptimeData.totalChecks
- : (monitor?.groupedUpChecks?.reduce((count, checkGroup) => {
+ : (monitorData?.groupedUpChecks?.reduce((count, checkGroup) => {
return count + checkGroup.totalChecks;
}, 0) ?? 0)}
@@ -81,7 +75,7 @@ const ChartBoxes = ({
{hoveredUptimeData !== null
? Math.floor(hoveredUptimeData?.avgResponseTime ?? 0)
- : Math.floor(groupedUptimePercentage)}
+ : Math.floor(monitorData?.groupedUptimePercentage * 100 ?? 0)}
{hoveredUptimeData !== null ? " ms" : " %"}
@@ -89,7 +83,7 @@ const ChartBoxes = ({
@@ -98,14 +92,14 @@ const ChartBoxes = ({
icon={}
header="Incidents"
noDataMessage={noIncidentsMessage}
- isEmpty={monitor?.groupedDownChecks?.length === 0}
+ isEmpty={monitorData?.groupedDownChecks?.length === 0}
>
{hoveredIncidentsData !== null
? hoveredIncidentsData.totalChecks
- : (monitor?.groupedDownChecks?.reduce((count, checkGroup) => {
+ : (monitorData?.groupedDownChecks?.reduce((count, checkGroup) => {
return count + checkGroup.totalChecks;
}, 0) ?? 0)}
@@ -123,7 +117,7 @@ const ChartBoxes = ({
@@ -132,7 +126,7 @@ const ChartBoxes = ({
icon={}
header="Average Response Time"
>
-
+
);
@@ -141,8 +135,8 @@ const ChartBoxes = ({
export default ChartBoxes;
ChartBoxes.propTypes = {
- shouldRender: PropTypes.bool,
- monitor: PropTypes.object,
+ isLoading: PropTypes.bool,
+ monitorData: PropTypes.object,
dateRange: PropTypes.string.isRequired,
uiTimezone: PropTypes.string.isRequired,
dateFormat: PropTypes.string.isRequired,
diff --git a/src/Pages/Uptime/Details/Components/Charts/DownBarChart.jsx b/src/Pages/Uptime/Details/Components/Charts/DownBarChart.jsx
index 5d6c48b58..662abc831 100644
--- a/src/Pages/Uptime/Details/Components/Charts/DownBarChart.jsx
+++ b/src/Pages/Uptime/Details/Components/Charts/DownBarChart.jsx
@@ -4,7 +4,7 @@ import { ResponsiveContainer, BarChart, XAxis, Bar, Cell } from "recharts";
import PropTypes from "prop-types";
import CustomLabels from "./CustomLabels";
-const DownBarChart = memo(({ monitor, type, onBarHover }) => {
+const DownBarChart = memo(({ groupedDownChecks = [], type, onBarHover }) => {
const theme = useTheme();
const [chartHovered, setChartHovered] = useState(false);
@@ -19,7 +19,7 @@ const DownBarChart = memo(({ monitor, type, onBarHover }) => {
{
setChartHovered(true);
onBarHover({ time: null, totalChecks: 0 });
@@ -40,10 +40,8 @@ const DownBarChart = memo(({ monitor, type, onBarHover }) => {
y={0}
width="100%"
height="100%"
- firstDataPoint={monitor?.groupedDownChecks?.[0] ?? {}}
- lastDataPoint={
- monitor?.groupedDownChecks?.[monitor?.groupedDownChecks?.length - 1] ?? {}
- }
+ firstDataPoint={groupedDownChecks?.[0] ?? {}}
+ lastDataPoint={groupedDownChecks?.[groupedDownChecks?.length - 1] ?? {}}
type={type}
/>
}
@@ -53,7 +51,7 @@ const DownBarChart = memo(({ monitor, type, onBarHover }) => {
maxBarSize={7}
background={{ fill: "transparent" }}
>
- {monitor?.groupedDownChecks?.map((entry, index) => {
+ {groupedDownChecks?.map((entry, index) => {
return (
{
- if (!shouldRender) {
+const ResponseTImeChart = ({ isLoading = false, groupedChecks = [], dateRange }) => {
+ if (isLoading) {
return ;
}
@@ -15,7 +15,7 @@ const ResponseTImeChart = ({ shouldRender = true, monitor, dateRange }) => {
header="Response Times"
>
@@ -23,8 +23,8 @@ const ResponseTImeChart = ({ shouldRender = true, monitor, dateRange }) => {
};
ResponseTImeChart.propTypes = {
- shouldRender: PropTypes.bool,
- monitor: PropTypes.object,
+ isLoading: PropTypes.bool,
+ groupedChecks: PropTypes.array,
dateRange: PropTypes.string,
};
diff --git a/src/Pages/Uptime/Details/Components/Charts/UpBarChart.jsx b/src/Pages/Uptime/Details/Components/Charts/UpBarChart.jsx
index 1df79c26e..02df41f9a 100644
--- a/src/Pages/Uptime/Details/Components/Charts/UpBarChart.jsx
+++ b/src/Pages/Uptime/Details/Components/Charts/UpBarChart.jsx
@@ -14,7 +14,7 @@ const getThemeColor = (responseTime) => {
}
};
-const UpBarChart = memo(({ monitor, type, onBarHover }) => {
+const UpBarChart = memo(({ groupedUpChecks = [], type, onBarHover }) => {
const theme = useTheme();
const [chartHovered, setChartHovered] = useState(false);
const [hoveredBarIndex, setHoveredBarIndex] = useState(null);
@@ -28,7 +28,7 @@ const UpBarChart = memo(({ monitor, type, onBarHover }) => {
{
setChartHovered(true);
onBarHover({ time: null, totalChecks: 0, avgResponseTime: 0 });
@@ -49,10 +49,8 @@ const UpBarChart = memo(({ monitor, type, onBarHover }) => {
y={0}
width="100%"
height="100%"
- firstDataPoint={monitor?.groupedUpChecks?.[0]}
- lastDataPoint={
- monitor?.groupedUpChecks?.[monitor?.groupedUpChecks?.length - 1]
- }
+ firstDataPoint={groupedUpChecks?.[0]}
+ lastDataPoint={groupedUpChecks?.[groupedUpChecks?.length - 1]}
type={type}
/>
}
@@ -62,7 +60,7 @@ const UpBarChart = memo(({ monitor, type, onBarHover }) => {
maxBarSize={7}
background={{ fill: "transparent" }}
>
- {monitor?.groupedUpChecks?.map((entry, index) => {
+ {groupedUpChecks?.map((entry, index) => {
const themeColor = getThemeColor(entry.avgResponseTime);
return (
| {
const { t } = useTranslation();
- if (!shouldRender) {
+ if (isLoading) {
return ;
}
@@ -78,7 +78,7 @@ const ResponseTable = ({
};
ResponseTable.propTypes = {
- shouldRender: PropTypes.bool,
+ isLoading: PropTypes.bool,
checks: PropTypes.array,
checksCount: PropTypes.number,
uiTimezone: PropTypes.string.isRequired,
diff --git a/src/Pages/Uptime/Details/Components/UptimeStatusBoxes/index.jsx b/src/Pages/Uptime/Details/Components/UptimeStatusBoxes/index.jsx
index 5597ce2ac..66c021aa2 100644
--- a/src/Pages/Uptime/Details/Components/UptimeStatusBoxes/index.jsx
+++ b/src/Pages/Uptime/Details/Components/UptimeStatusBoxes/index.jsx
@@ -1,23 +1,36 @@
import StatusBoxes from "../../../../../Components/StatusBoxes";
import StatBox from "../../../../../Components/StatBox";
+
+import PropTypes from "prop-types";
import { getHumanReadableDuration } from "../../../../../Utils/timeUtils";
import { useTheme } from "@mui/material/styles";
import { Typography } from "@mui/material";
import useUtils from "../../../Monitors/Hooks/useUtils";
-const UptimeStatusBoxes = ({ shouldRender, monitor, certificateExpiry }) => {
+const UptimeStatusBoxes = ({
+ isLoading = false,
+ monitor,
+ monitorStats,
+ certificateExpiry,
+}) => {
const theme = useTheme();
const { determineState } = useUtils();
- const { time: streakTime, units: streakUnits } = getHumanReadableDuration(
- monitor?.uptimeStreak
- );
+ // Determine time since last failure
+ const timeOfLastFailure = monitorStats?.timeOfLastFailure;
+ const timeSinceLastFailure = timeOfLastFailure > 0 ? Date.now() - timeOfLastFailure : 0;
- const { time: lastCheckTime, units: lastCheckUnits } = getHumanReadableDuration(
- monitor?.timeSinceLastCheck
- );
+ // Determine time since last check
+ const timeOfLastCheck = monitorStats?.lastCheckTimestamp;
+ const timeSinceLastCheck = Date.now() - timeOfLastCheck;
+
+ const { time: streakTime, units: streakUnits } =
+ getHumanReadableDuration(timeSinceLastFailure);
+
+ const { time: lastCheckTime, units: lastCheckUnits } =
+ getHumanReadableDuration(timeSinceLastCheck);
return (
-
+
{
heading="last response time"
subHeading={
<>
- {monitor?.latestResponseTime}
+ {monitorStats?.lastResponseTime}
{"ms"}
>
}
@@ -64,4 +77,11 @@ const UptimeStatusBoxes = ({ shouldRender, monitor, certificateExpiry }) => {
);
};
+UptimeStatusBoxes.propTypes = {
+ shouldRender: PropTypes.bool,
+ monitor: PropTypes.object,
+ monitorStats: PropTypes.object,
+ certificateExpiry: PropTypes.string,
+};
+
export default UptimeStatusBoxes;
diff --git a/src/Pages/Uptime/Details/index.jsx b/src/Pages/Uptime/Details/index.jsx
index e404c214a..df5efbca4 100644
--- a/src/Pages/Uptime/Details/index.jsx
+++ b/src/Pages/Uptime/Details/index.jsx
@@ -16,7 +16,7 @@ import { useParams } from "react-router-dom";
import { useSelector } from "react-redux";
import { useTheme } from "@emotion/react";
import { useIsAdmin } from "../../../Hooks/useIsAdmin";
-import useMonitorFetch from "./Hooks/useMonitorFetch";
+import useFetchUptimeMonitorDetails from "../../../Hooks/useFetchUptimeMonitorDetails";
import useCertificateFetch from "./Hooks/useCertificateFetch";
import useChecksFetch from "./Hooks/useChecksFetch";
import { useTranslation } from "react-i18next";
@@ -36,8 +36,7 @@ const UptimeDetails = () => {
// Local state
const [dateRange, setDateRange] = useState("recent");
- const [hoveredUptimeData, setHoveredUptimeData] = useState(null);
- const [hoveredIncidentsData, setHoveredIncidentsData] = useState(null);
+
const [page, setPage] = useState(0);
const [rowsPerPage, setRowsPerPage] = useState(5);
@@ -49,10 +48,13 @@ const UptimeDetails = () => {
const isAdmin = useIsAdmin();
const { t } = useTranslation();
- const [monitor, monitorIsLoading, monitorNetworkError] = useMonitorFetch({
- monitorId,
- dateRange,
- });
+ const [monitorData, monitorStats, monitorIsLoading, monitorNetworkError] =
+ useFetchUptimeMonitorDetails({
+ monitorId,
+ dateRange,
+ });
+
+ const monitor = monitorData?.monitor;
const [certificateExpiry, certificateIsLoading] = useCertificateFetch({
monitor,
@@ -62,7 +64,6 @@ const UptimeDetails = () => {
});
const monitorType = monitor?.type;
-
const [checks, checksCount, checksAreLoading, checksNetworkError] = useChecksFetch({
monitorId,
monitorType,
@@ -71,6 +72,8 @@ const UptimeDetails = () => {
rowsPerPage,
});
+ console.log("render");
+
// Handlers
const handlePageChange = (_, newPage) => {
setPage(newPage);
@@ -119,38 +122,35 @@ const UptimeDetails = () => {
} The response from the axios POST request.
+ */
+ async testNotification(config) {
+ return this.axiosInstance.post('/notifications/test-webhook', {
+ platform: config.platform,
+ ...config.payload
+ }, {
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ }
+
/**
* ************************************
* Creates a maintenance window
diff --git a/src/Utils/timeUtils.js b/src/Utils/timeUtils.js
index 2fd6c6654..3a84dfcf4 100644
--- a/src/Utils/timeUtils.js
+++ b/src/Utils/timeUtils.js
@@ -83,8 +83,11 @@ export const getHumanReadableDuration = (ms) => {
const days = Math.floor(durationObj.asDays());
return { time: days, units: days === 1 ? "day" : "days" };
} else if (durationObj.asHours() >= 1) {
- const hours = Math.floor(durationObj.asHours());
- return { time: hours, units: hours === 1 ? "hour" : "hours" };
+ const hoursRounded = Math.round(durationObj.asHours() * 10) / 10;
+ const hours = Number.isInteger(hoursRounded)
+ ? Math.floor(hoursRounded)
+ : hoursRounded;
+ return { time: hours, units: hours <= 1 ? "hour" : "hours" };
} else if (durationObj.asMinutes() >= 1) {
const minutes = Math.floor(durationObj.asMinutes());
return { time: minutes, units: minutes === 1 ? "minute" : "minutes" };
diff --git a/src/locales/gb.json b/src/locales/gb.json
index ab5b581d1..73ece5bc3 100644
--- a/src/locales/gb.json
+++ b/src/locales/gb.json
@@ -107,28 +107,6 @@
"aboutus": "About Us",
"signUP": "Sign Up",
"now": "Now",
- "createYour": "Create your",
- "createMonitor": "Create monitor",
- "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",
@@ -165,79 +143,6 @@
"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",
- "message": "Message",
- "low": "low",
- "high": "high",
- "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.",
- "maintenanceTableActionMenuDialogTitle": "Do you really want to remove this maintenance window?",
"notifications": {
"enableNotifications": "Enable {{platform}} notifications",
"testNotification": "Test notification",
@@ -268,7 +173,8 @@
"urlLabel": "Webhook URL",
"urlPlaceholder": "https://your-server.com/webhook"
},
- "testNotificationDevelop": "Test notification 2"
+ "testNotificationDevelop": "Test notification 2",
+ "integrationButton": "Notification Integration"
},
"testLocale": "",
"add": "Add",
@@ -362,5 +268,101 @@
"integrationsDiscord": "Discord",
"integrationsDiscordInfo": "Connect with Discord and view incidents directly in a channel",
"integrationsZapier": "Zapier",
- "integrationsZapierInfo": "Send all incidents to Zapier, and then see them everywhere"
+ "integrationsZapierInfo": "Send all incidents to Zapier, and then see them everywhere",
+ "commonSave": "Save",
+ "createYour": "Create your",
+ "createMonitor": "Create monitor",
+ "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.",
+ "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",
+ "message": "Message",
+ "low": "low",
+ "high": "high",
+ "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.",
+ "maintenanceTableActionMenuDialogTitle": "Do you really want to remove this maintenance window?"
}
diff --git a/src/locales/ru.json b/src/locales/ru.json
new file mode 100644
index 000000000..1bb3fdf24
--- /dev/null
+++ b/src/locales/ru.json
@@ -0,0 +1,364 @@
+{
+ "dontHaveAccount": "Нет аккаунта",
+ "email": "Почта",
+ "forgotPassword": "Забыли пароль",
+ "password": "пароль",
+ "signUp": "Зарегистрироваться",
+ "submit": "Подтвердить",
+ "title": "Название",
+ "continue": "Продолжить",
+ "enterEmail": "Введите свой email",
+ "authLoginTitle": "Войти",
+ "authLoginEnterPassword": "Введите свой пароль",
+ "commonPassword": "Пароль",
+ "commonBack": "Назад",
+ "authForgotPasswordTitle": "Забыли пароль?",
+ "authForgotPasswordResetPassword": "Сбросить пароль",
+ "createPassword": "Создайте свой пароль",
+ "createAPassword": "Создайте пароль",
+ "authRegisterAlreadyHaveAccount": "Уже есть аккаунт?",
+ "commonAppName": "Checkmate",
+ "authLoginEnterEmail": "Введите свой email",
+ "authRegisterTitle": "Создать аккаунт",
+ "authRegisterStepOneTitle": "Создайте свой аккаут",
+ "authRegisterStepOneDescription": "Введите свои данные, чтобы начать",
+ "authRegisterStepTwoTitle": "Настройте свой профиль",
+ "authRegisterStepTwoDescription": "Расскажите нам о себе",
+ "authRegisterStepThreeTitle": "Почти готово!",
+ "authRegisterStepThreeDescription": "Проверьте свою информацию",
+ "authForgotPasswordDescription": "Не волнуйтесь, мы вышлем вам инструкции по сбросу настроек.",
+ "authForgotPasswordSendInstructions": "Отправить инструкции",
+ "authForgotPasswordBackTo": "Назад к",
+ "authCheckEmailTitle": "Проверьте свою почту",
+ "authCheckEmailDescription": "Мы отправили ссылку для сброса пароля",
+ "authCheckEmailResendEmail": "Отправить письмо повторно",
+ "authCheckEmailBackTo": "Назад к",
+ "goBackTo": "Назад к",
+ "authCheckEmailDidntReceiveEmail": "Не получили письмо?",
+ "authCheckEmailClickToResend": "Нажмите, чтобы отправить повторно",
+ "authSetNewPasswordTitle": "Установите новый пароль",
+ "authSetNewPasswordDescription": "Ваш новый пароль должен отличаться от ранее использованных паролей.",
+ "authSetNewPasswordNewPassword": "Новый пароль",
+ "authSetNewPasswordConfirmPassword": "Подтвердите пароль",
+ "confirmPassword": "Подтвердите ваш пароль",
+ "authSetNewPasswordResetPassword": "Сбросить пароль",
+ "authSetNewPasswordBackTo": "Назад к",
+ "authPasswordMustBeAtLeast": "Должно быть как минимум",
+ "authPasswordCharactersLong": "длиной 8 символов",
+ "authPasswordMustContainAtLeast": "Должен содержать как минимум",
+ "authPasswordSpecialCharacter": "один специальный символ",
+ "authPasswordOneNumber": "одно число",
+ "authPasswordUpperCharacter": "один верхний символ",
+ "authPasswordLowerCharacter": "один нижний символ",
+ "authPasswordConfirmAndPassword": "Подтвердите пароль и пароль",
+ "authPasswordMustMatch": "должен совпадать",
+ "authRegisterCreateAccount": "Создайте свою учетную запись, чтобы начать",
+ "authRegisterCreateSuperAdminAccount": "Создайте учетную запись суперадминистратора, чтобы начать работу",
+ "authRegisterSignUpWithEmail": "Зарегистрироваться по электронной почте",
+ "authRegisterBySigningUp": "Регистрируясь, вы соглашаетесь с нашими",
+ "distributedStatusHeaderText": "Охват реального времени и реального устройства",
+ "distributedStatusSubHeaderText": "Работает на миллионах устройств по всему миру, просматривайте производительность системы по глобальному региону, стране или городу",
+ "settingsGeneralSettings": "Общие настройки",
+ "settingsDisplayTimezone": "Отображать часовой пояс",
+ "settingsDisplayTimezoneDescription": "Часовой пояс панели мониторинга, которую вы публично отображаете.",
+ "settingsAppearance": "Внешний вид",
+ "settingsAppearanceDescription": "Переключение между светлым и темным режимом или изменение языка пользовательского интерфейса",
+ "settingsThemeMode": "Тема",
+ "settingsLanguage": "Язык",
+ "settingsDistributedUptime": "Distributed uptime",
+ "settingsDistributedUptimeDescription": "Включить/выключить distributed uptime monitoring.",
+ "settingsEnabled": "Включено",
+ "settingsDisabled": "Выключено",
+ "settingsHistoryAndMonitoring": "История и мониторинг",
+ "settingsHistoryAndMonitoringDescription": "Определите здесь, как долго вы хотите хранить данные. Вы также можете удалить все прошлые данные.",
+ "settingsTTLLabel": "Дни, за которыми вы хотите следить.",
+ "settingsTTLOptionalLabel": "0 для бесконечности",
+ "settingsClearAllStats": "Очистить всю статистику. Это необратимо.",
+ "settingsClearAllStatsButton": "Очистить всю статистику",
+ "settingsClearAllStatsDialogTitle": "Хотите очистить всю статистику?",
+ "settingsClearAllStatsDialogDescription": "После удаления ваши мониторы не могут быть восстановлены.",
+ "settingsClearAllStatsDialogConfirm": "Да, очистить всю статистику",
+ "settingsDemoMonitors": "Демо мониторы",
+ "settingsDemoMonitorsDescription": "Здесь вы можете добавлять и удалять демонстрационные мониторы.",
+ "settingsAddDemoMonitors": "Добавьте демонстрационные мониторы",
+ "settingsAddDemoMonitorsButton": "Добавьте демонстрационные мониторы",
+ "settingsRemoveAllMonitors": "Удалить все демонстрационные мониторы",
+ "settingsRemoveAllMonitorsButton": "Удалить все демонстрационные мониторы",
+ "settingsRemoveAllMonitorsDialogTitle": "Хотите удалить все мониторы?",
+ "settingsRemoveAllMonitorsDialogConfirm": "Да, очистить все мониторы",
+ "settingsWallet": "Кошелёк",
+ "settingsWalletDescription": "Подключите свой кошелек здесь. Это необходимо для того, чтобы монитор Distributed Uptime мог подключиться к нескольким узлам по всему миру.",
+ "settingsAbout": "О",
+ "settingsDevelopedBy": "Developed by Bluewave Labs.",
+ "settingsSave": "Сохранить",
+ "settingsSuccessSaved": "Настройки успешно сохранены",
+ "settingsFailedToSave": "Не удалось сохранить настройки",
+ "settingsStatsCleared": "Статистика успешно очищена",
+ "settingsFailedToClearStats": "Не удалось очистить статистику",
+ "settingsDemoMonitorsAdded": "Успешно добавлены демонстрационные мониторы",
+ "settingsFailedToAddDemoMonitors": "Не удалось добавить демонстрационные мониторы",
+ "settingsMonitorsDeleted": "Успешно удалены все мониторы",
+ "settingsFailedToDeleteMonitors": "Не удалось удалить все мониторы",
+ "starPromptTitle": "Star Checkmate",
+ "starPromptDescription": "Ознакомьтесь с последними релизами и помогите развить сообщество на GitHub",
+ "https": "HTTPS",
+ "http": "HTTP",
+ "monitor": "монитор",
+ "aboutus": "О Нас",
+ "signUP": "Зарегистрироваться",
+ "now": "Сейчас",
+ "delete": "Удалить",
+ "configure": "Настроить",
+ "networkError": "Ошибка сети",
+ "responseTime": "Время ответа:",
+ "ms": "мс",
+ "bar": "Bar",
+ "area": "Area",
+ "country": "СТРАНА",
+ "city": "ГОРОД",
+ "response": "ОТВЕТ",
+ "checkConnection": "Пожалуйста, проверьте ваше соединение",
+ "passwordreset": "Сброс пароля",
+ "authRegisterStepOnePersonalDetails": "Введите свои личные данные",
+ "authCheckEmailOpenEmailButton": "Откройте приложение почты",
+ "authNewPasswordConfirmed": "Ваш пароль успешно сброшен. Нажмите ниже, чтобы войти в систему магическим образом.",
+ "monitorStatusUp": "Монитор {name} ({url}) теперь включен и отвечает",
+ "monitorStatusDown": "Монитор {name} ({url}) ОТКЛЮЧЕН и не отвечает",
+ "webhookSendSuccess": "Уведомление Webhook успешно отправлено",
+ "webhookSendError": "Ошибка отправки уведомления webhook на {platform}",
+ "webhookUnsupportedPlatform": "Неподдерживаемая платформа: {platform}",
+ "distributedRightCategoryTitle": "Монитор",
+ "distributedStatusServerMonitors": "Серверные мониторы",
+ "distributedStatusServerMonitorsDescription": "Мониторинг состояния связанных серверов",
+ "distributedUptimeCreateSelectURL": "Здесь вы можете выбрать URL-адрес хоста, а также тип монитора.",
+ "distributedUptimeCreateChecks": "Проверки, которые необходимо выполнить",
+ "distributedUptimeCreateChecksDescription": "Вы всегда можете добавить или удалить проверки после добавления своего сайта.",
+ "distributedUptimeCreateIncidentNotification": "Уведомления об инцидентах",
+ "distributedUptimeCreateIncidentDescription": "В случае возникновения инцидента сообщите об этом пользователям.",
+ "distributedUptimeCreateAdvancedSettings": "Расширенные настройки",
+ "distributedUptimeDetailsNoMonitorHistory": "Для этого монитора пока нет истории проверок.",
+ "distributedUptimeDetailsFooterHeading": "Made with ❤️ by UpRock & Bluewave Labs",
+ "distributedUptimeDetailsFooterBuilt": "Built on",
+ "distributedUptimeDetailsFooterSolana": "Solana",
+ "distributedUptimeDetailsMonitorHeader": "Distributed Uptime Monitoring powered by DePIN",
+ "distributedUptimeDetailsStatusHeaderUptime": "Аптайм:",
+ "distributedUptimeDetailsStatusHeaderLastUpdate": "Последнее обновление",
+ "notifications": {
+ "enableNotifications": "Включить уведомления {{platform}}",
+ "testNotification": "Тестовое уведомление",
+ "addOrEditNotifications": "Добавить или изменить уведомления",
+ "slack": {
+ "label": "Slack",
+ "description": "Чтобы включить уведомления Slack, создайте приложение Slack и включите входящие вебхуки. После этого просто укажите URL вебхука здесь.",
+ "webhookLabel": "URL вебхука",
+ "webhookPlaceholder": "https://hooks.slack.com/services/..."
+ },
+ "discord": {
+ "label": "Discord",
+ "description": "Чтобы отправить данные на канал Discord из Checkmate через уведомления Discord с использованием веб-хуков, вы можете использовать функцию входящих веб-хуков Discord.",
+ "webhookLabel": "Discord Webhook URL",
+ "webhookPlaceholder": "https://discord.com/api/webhooks/..."
+ },
+ "telegram": {
+ "label": "Telegram",
+ "description": "Чтобы включить уведомления Telegram, создайте бота Telegram с помощью BotFather, официального бота для создания и управления ботами Telegram. Затем получите токен API и идентификатор чата и запишите их здесь.",
+ "tokenLabel": "Ваш токен бота",
+ "tokenPlaceholder": "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11",
+ "chatIdLabel": "ID Вашего Чата",
+ "chatIdPlaceholder": "-1001234567890"
+ },
+ "webhook": {
+ "label": "Вебхуки",
+ "description": "Вы можете настроить пользовательский вебхук для получения уведомлений о возникновении инцидентов.",
+ "urlLabel": "URL вебхука",
+ "urlPlaceholder": "https://your-server.com/webhook"
+ },
+ "testNotificationDevelop": "Тестовое уведомление 2",
+ "integrationButton": ""
+ },
+ "testLocale": "testLocale",
+ "add": "Добавить",
+ "monitors": "мониторы",
+ "distributedUptimeStatusCreateStatusPage": "страница статуса",
+ "distributedUptimeStatusCreateStatusPageAccess": "Доступ",
+ "distributedUptimeStatusCreateStatusPageReady": "Если ваша страница статуса готова, вы можете отметить ее как опубликованную.",
+ "distributedUptimeStatusBasicInfoHeader": "Основная информация",
+ "distributedUptimeStatusBasicInfoDescription": "Определите название компании и поддомен, на который ссылается ваша страница статуса.",
+ "distributedUptimeStatusLogoHeader": "Логотип",
+ "distributedUptimeStatusLogoDescription": "Загрузите логотип для своей страницы статуса",
+ "distributedUptimeStatusLogoUploadButton": "Загрузить логотип",
+ "distributedUptimeStatusStandardMonitorsHeader": "Стандартные Мониторы",
+ "distributedUptimeStatusStandardMonitorsDescription": "Прикрепите стандартные мониторы к своей странице статуса.",
+ "distributedUptimeStatusCreateYour": "Создайте свой",
+ "distributedUptimeStatusEditYour": "Отредактируйте свой",
+ "distributedUptimeStatusPublishedLabel": "Опубликовано и доступно для общественности",
+ "distributedUptimeStatusCompanyNameLabel": "Название компании",
+ "distributedUptimeStatusPageAddressLabel": "Адрес вашей страницы статуса",
+ "distributedUptimeStatus30Days": "30 дней",
+ "distributedUptimeStatus60Days": "60 дней",
+ "distributedUptimeStatus90Days": "90 дней",
+ "distributedUptimeStatusPageNotSetUp": "Страница статуса не настроена.",
+ "distributedUptimeStatusContactAdmin": "Пожалуйста, свяжитесь с вашим администратором",
+ "distributedUptimeStatusPageNotPublic": "Эта страница статуса не является публичной.",
+ "distributedUptimeStatusPageDeleteDialog": "Вы хотите удалить эту страницу статуса?",
+ "distributedUptimeStatusPageDeleteConfirm": "Да, удалить страницу статуса",
+ "distributedUptimeStatusPageDeleteDescription": "После удаления ваша страница статуса не может быть восстановлена.",
+ "distributedUptimeStatusDevices": "Устройства",
+ "distributedUptimeStatusUpt": "UPT",
+ "distributedUptimeStatusUptBurned": "UPT Burned",
+ "distributedUptimeStatusUptLogo": "Upt Logo",
+ "incidentsTableNoIncidents": "Инцидентов не зафиксировано",
+ "incidentsTablePaginationLabel": "инциденты",
+ "incidentsTableMonitorName": "Имя Монитора",
+ "incidentsTableStatus": "Статус",
+ "incidentsTableDateTime": "Дата и Время",
+ "incidentsTableStatusCode": "Код Статуса",
+ "incidentsTableMessage": "Сообщение",
+ "incidentsOptionsHeader": "Инцидент для:",
+ "incidentsOptionsHeaderFilterBy": "Фильтровать по:",
+ "incidentsOptionsHeaderFilterAll": "Все",
+ "incidentsOptionsHeaderFilterDown": "Недоступно",
+ "incidentsOptionsHeaderFilterCannotResolve": "Невозможно решить",
+ "incidentsOptionsHeaderShow": "Показать:",
+ "incidentsOptionsHeaderLastHour": "Последний час",
+ "incidentsOptionsHeaderLastDay": "Последний день",
+ "incidentsOptionsHeaderLastWeek": "Последняя неделя",
+ "incidentsOptionsPlaceholderAllServers": "Все сервера",
+ "infrastructureCreateYour": "Создайте свой",
+ "infrastructureCreateGeneralSettingsDescription": "Здесь вы можете выбрать URL-адрес хоста, а также понятное имя и секретный ключ авторизации для подключения к агенту сервера.",
+ "infrastructureServerRequirement": "Сервер, который вы отслеживаете, должен быть запущен",
+ "infrastructureCustomizeAlerts": "Настройте оповещения",
+ "infrastructureAlertNotificationDescription": "Отправлять уведомления пользователям, когда пороговые значения превышают указанный процент.",
+ "infrastructureCreateMonitor": "Создать Монитор Инфраструктуры",
+ "infrastructureProtocol": "Протокол",
+ "infrastructureServerUrlLabel": "URL Сервера",
+ "infrastructureDisplayNameLabel": "Отображаемое имя",
+ "infrastructureAuthorizationSecretLabel": "Секрет авторизации",
+ "gb": "ГБ",
+ "mb": "МБ",
+ "mem": "Mem",
+ "memoryUsage": "Использование памяти",
+ "cpu": "CPU",
+ "cpuUsage": "Использование CPU",
+ "cpuTemperature": "Температура CPU",
+ "diskUsage": "Использование диска",
+ "used": "Использовал",
+ "total": "Всего",
+ "cores": "Ядра",
+ "frequency": "Частота",
+ "status": "Статус",
+ "cpuPhysical": "CPU (физический)",
+ "cpuLogical": "CPU (логический)",
+ "cpuFrequency": "Частота CPU",
+ "avgCpuTemperature": "Средняя температура CPU",
+ "memory": "Память",
+ "disk": "Диск",
+ "uptime": "Аптайм",
+ "os": "ОС",
+ "host": "Хост",
+ "actions": "Действия",
+ "integrations": "Интеграции",
+ "integrationsPrism": "Подключите Prism к вашему любимому сервису.",
+ "integrationsSlack": "Slack",
+ "integrationsSlackInfo": "Подключитесь к Slack и просматривайте инциденты в канале",
+ "integrationsDiscord": "Discord",
+ "integrationsDiscordInfo": "Подключитесь к Discord и просматривайте инциденты прямо в канале",
+ "integrationsZapier": "Zapier",
+ "integrationsZapierInfo": "Отправляйте все инциденты в Zapier, и тогда вы сможете видеть их везде",
+ "commonSave": "",
+ "createYour": "",
+ "createMonitor": "",
+ "pause": "",
+ "resume": "",
+ "editing": "",
+ "url": "",
+ "access": "",
+ "timezone": "",
+ "features": "",
+ "administrator": "",
+ "loginHere": "",
+ "displayName": "",
+ "urlMonitor": "",
+ "portToMonitor": "",
+ "websiteMonitoring": "",
+ "websiteMonitoringDescription": "",
+ "pingMonitoring": "",
+ "pingMonitoringDescription": "",
+ "dockerContainerMonitoring": "",
+ "dockerContainerMonitoringDescription": "",
+ "portMonitoring": "",
+ "portMonitoringDescription": "",
+ "createMaintenanceWindow": "",
+ "createMaintenance": "",
+ "editMaintenance": "",
+ "maintenanceWindowName": "",
+ "friendlyNameInput": "",
+ "friendlyNamePlaceholder": "",
+ "maintenanceRepeat": "",
+ "maintenance": "",
+ "duration": "",
+ "addMonitors": "",
+ "window": "",
+ "cancel": "",
+ "message": "",
+ "low": "",
+ "high": "",
+ "statusCode": "",
+ "date&Time": "",
+ "type": "",
+ "statusPageName": "",
+ "publicURL": "",
+ "repeat": "",
+ "edit": "",
+ "createA": "",
+ "remove": "",
+ "maintenanceWindowDescription": "",
+ "startTime": "",
+ "timeZoneInfo": "",
+ "monitorsToApply": "",
+ "nextWindow": "",
+ "notFoundButton": "",
+ "pageSpeedConfigureSettingsDescription": "",
+ "monitorDisplayName": "",
+ "whenNewIncident": "",
+ "notifySMS": "",
+ "notifyEmails": "",
+ "seperateEmails": "",
+ "checkFrequency": "",
+ "matchMethod": "",
+ "expectedValue": "",
+ "deleteDialogTitle": "",
+ "deleteDialogDescription": "",
+ "pageSpeedMonitor": "",
+ "shown": "",
+ "ago": "",
+ "companyName": "",
+ "pageSpeedDetailsPerformanceReport": "",
+ "pageSpeedDetailsPerformanceReportCalculator": "",
+ "checkingEvery": "",
+ "statusPageCreateSettings": "",
+ "basicInformation": "",
+ "statusPageCreateBasicInfoDescription": "",
+ "statusPageCreateSelectTimeZoneDescription": "",
+ "statusPageCreateAppearanceDescription": "",
+ "statusPageCreateSettingsCheckboxLabel": "",
+ "statusPageCreateBasicInfoStatusPageAddress": "",
+ "statusPageCreateTabsContent": "",
+ "statusPageCreateTabsContentDescription": "",
+ "statusPageCreateTabsContentFeaturesDescription": "",
+ "showCharts": "",
+ "showUptimePercentage": "",
+ "removeLogo": "",
+ "statusPageStatus": "",
+ "statusPageStatusContactAdmin": "",
+ "statusPageStatusNotPublic": "",
+ "statusPageStatusNoPage": "",
+ "statusPageStatusServiceStatus": "",
+ "deleteStatusPage": "",
+ "deleteStatusPageConfirm": "",
+ "deleteStatusPageDescription": "",
+ "uptimeCreate": "",
+ "uptimeCreateJsonPath": "",
+ "uptimeCreateJsonPathQuery": "",
+ "maintenanceTableActionMenuDialogTitle": ""
+}
diff --git a/src/locales/tr.json b/src/locales/tr.json
index bfdb542b6..75476ef2f 100644
--- a/src/locales/tr.json
+++ b/src/locales/tr.json
@@ -173,68 +173,69 @@
"urlLabel": "Web kanca URL:",
"urlPlaceholder": "https://sunucu-adresiniz.com/webhook"
},
- "testNotificationDevelop": "Test bildirimi 2"
+ "testNotificationDevelop": "Test bildirimi 2",
+ "integrationButton": "Bildirim Entegrasyonu"
},
"testLocale": "TEST13 UPLOAD",
- "add": "",
- "monitors": "",
- "distributedUptimeStatusCreateStatusPage": "",
- "distributedUptimeStatusCreateStatusPageAccess": "",
- "distributedUptimeStatusCreateStatusPageReady": "",
- "distributedUptimeStatusBasicInfoHeader": "",
+ "add": "Ekle",
+ "monitors": "Monitörler",
+ "distributedUptimeStatusCreateStatusPage": "durum sayfası",
+ "distributedUptimeStatusCreateStatusPageAccess": "Erişim",
+ "distributedUptimeStatusCreateStatusPageReady": "Durum sayfanız hazırsa yayınlayabilirsiniz.",
+ "distributedUptimeStatusBasicInfoHeader": "Temel bilgiler",
"distributedUptimeStatusBasicInfoDescription": "",
- "distributedUptimeStatusLogoHeader": "",
- "distributedUptimeStatusLogoDescription": "",
- "distributedUptimeStatusLogoUploadButton": "",
- "distributedUptimeStatusStandardMonitorsHeader": "",
- "distributedUptimeStatusStandardMonitorsDescription": "",
+ "distributedUptimeStatusLogoHeader": "Logo",
+ "distributedUptimeStatusLogoDescription": "Durum sayfanız için bir logo yükleyin",
+ "distributedUptimeStatusLogoUploadButton": "Logo yükle",
+ "distributedUptimeStatusStandardMonitorsHeader": "Standart monitörler",
+ "distributedUptimeStatusStandardMonitorsDescription": "Durum sayfanıza standart monitörleri ekleyin.",
"distributedUptimeStatusCreateYour": "",
"distributedUptimeStatusEditYour": "",
- "distributedUptimeStatusPublishedLabel": "",
- "distributedUptimeStatusCompanyNameLabel": "",
- "distributedUptimeStatusPageAddressLabel": "",
- "distributedUptimeStatus30Days": "",
- "distributedUptimeStatus60Days": "",
- "distributedUptimeStatus90Days": "",
- "distributedUptimeStatusPageNotSetUp": "",
- "distributedUptimeStatusContactAdmin": "",
- "distributedUptimeStatusPageNotPublic": "",
- "distributedUptimeStatusPageDeleteDialog": "",
- "distributedUptimeStatusPageDeleteConfirm": "",
- "distributedUptimeStatusPageDeleteDescription": "",
- "distributedUptimeStatusDevices": "",
- "distributedUptimeStatusUpt": "",
- "distributedUptimeStatusUptBurned": "",
- "distributedUptimeStatusUptLogo": "",
- "incidentsTableNoIncidents": "",
- "incidentsTablePaginationLabel": "",
- "incidentsTableMonitorName": "",
- "incidentsTableStatus": "",
- "incidentsTableDateTime": "",
- "incidentsTableStatusCode": "",
- "incidentsTableMessage": "",
- "incidentsOptionsHeader": "",
- "incidentsOptionsHeaderFilterBy": "",
- "incidentsOptionsHeaderFilterAll": "",
- "incidentsOptionsHeaderFilterDown": "",
- "incidentsOptionsHeaderFilterCannotResolve": "",
- "incidentsOptionsHeaderShow": "",
- "incidentsOptionsHeaderLastHour": "",
- "incidentsOptionsHeaderLastDay": "",
- "incidentsOptionsHeaderLastWeek": "",
- "incidentsOptionsPlaceholderAllServers": "",
+ "distributedUptimeStatusPublishedLabel": "Yayında ve herkes tarafından görülebilir",
+ "distributedUptimeStatusCompanyNameLabel": "Şirket adı",
+ "distributedUptimeStatusPageAddressLabel": "Durum sayfası adresi",
+ "distributedUptimeStatus30Days": "30 gün",
+ "distributedUptimeStatus60Days": "60 gün",
+ "distributedUptimeStatus90Days": "90 gün",
+ "distributedUptimeStatusPageNotSetUp": "Henüz bir durum sayfası oluşturulmadı.",
+ "distributedUptimeStatusContactAdmin": "Lütfen yöneticiniz ile görüşün",
+ "distributedUptimeStatusPageNotPublic": "Bu durum sayfası herkese açık değil",
+ "distributedUptimeStatusPageDeleteDialog": "Bu durum sayfasını silmek istiyor musunuz? ",
+ "distributedUptimeStatusPageDeleteConfirm": "Evet, durum sayfasını sil",
+ "distributedUptimeStatusPageDeleteDescription": "Silindiği zaman durum sayfalarını geri getiremezsiniz.",
+ "distributedUptimeStatusDevices": "Cihazlar",
+ "distributedUptimeStatusUpt": "UPT",
+ "distributedUptimeStatusUptBurned": "Yakılan UPT",
+ "distributedUptimeStatusUptLogo": "Upt Logo",
+ "incidentsTableNoIncidents": "Hiç olay kaydedilmedi",
+ "incidentsTablePaginationLabel": "olaylar",
+ "incidentsTableMonitorName": "Monitör adı",
+ "incidentsTableStatus": "Durum",
+ "incidentsTableDateTime": "Tarih ve saat",
+ "incidentsTableStatusCode": "Durum kodu",
+ "incidentsTableMessage": "Mesaj",
+ "incidentsOptionsHeader": "Servisler:",
+ "incidentsOptionsHeaderFilterBy": "Filtrele:",
+ "incidentsOptionsHeaderFilterAll": "Tümü",
+ "incidentsOptionsHeaderFilterDown": "Erişilemiyor",
+ "incidentsOptionsHeaderFilterCannotResolve": "Çözümlenemiyor",
+ "incidentsOptionsHeaderShow": "Göster:",
+ "incidentsOptionsHeaderLastHour": "Son saat",
+ "incidentsOptionsHeaderLastDay": "Son gün",
+ "incidentsOptionsHeaderLastWeek": "Son hafta",
+ "incidentsOptionsPlaceholderAllServers": "Tüm sunucular",
"infrastructureCreateYour": "",
"infrastructureCreateGeneralSettingsDescription": "",
"infrastructureServerRequirement": "",
- "infrastructureCustomizeAlerts": "",
+ "infrastructureCustomizeAlerts": "Alarmları özelleştir",
"infrastructureAlertNotificationDescription": "",
- "infrastructureCreateMonitor": "",
- "infrastructureProtocol": "",
- "infrastructureServerUrlLabel": "",
- "infrastructureDisplayNameLabel": "",
- "infrastructureAuthorizationSecretLabel": "",
- "gb": "",
- "mb": "",
+ "infrastructureCreateMonitor": "Altyapı Monitörü oluştur",
+ "infrastructureProtocol": "Protokol",
+ "infrastructureServerUrlLabel": "Sunucu adresi",
+ "infrastructureDisplayNameLabel": "Görünen adı",
+ "infrastructureAuthorizationSecretLabel": "Kimlik denetimi parolası",
+ "gb": "GB",
+ "mb": "MB",
"mem": "",
"memoryUsage": "",
"cpu": "",
@@ -247,21 +248,117 @@
"frequency": "",
"status": "",
"cpuPhysical": "",
- "cpuLogical": "",
- "cpuFrequency": "",
- "avgCpuTemperature": "",
- "memory": "",
- "disk": "",
+ "cpuLogical": "CPU (Mantıksal)",
+ "cpuFrequency": "CPU Frekansı",
+ "avgCpuTemperature": "Ortalama CPU Isısı",
+ "memory": "Bellek",
+ "disk": "Disk",
"uptime": "",
- "os": "",
- "host": "",
- "actions": "",
- "integrations": "",
+ "os": "İşletim sistemi",
+ "host": "Makine",
+ "actions": "İşlemler",
+ "integrations": "Entegrasyonlar",
"integrationsPrism": "",
- "integrationsSlack": "",
+ "integrationsSlack": "Slack",
"integrationsSlackInfo": "",
- "integrationsDiscord": "",
+ "integrationsDiscord": "Discord",
"integrationsDiscordInfo": "",
- "integrationsZapier": "",
- "integrationsZapierInfo": ""
+ "integrationsZapier": "Zapier",
+ "integrationsZapierInfo": "",
+ "commonSave": "Kaydet",
+ "createYour": "",
+ "createMonitor": "",
+ "pause": "",
+ "resume": "",
+ "editing": "",
+ "url": "",
+ "access": "",
+ "timezone": "",
+ "features": "",
+ "administrator": "",
+ "loginHere": "",
+ "displayName": "",
+ "urlMonitor": "",
+ "portToMonitor": "",
+ "websiteMonitoring": "",
+ "websiteMonitoringDescription": "",
+ "pingMonitoring": "",
+ "pingMonitoringDescription": "",
+ "dockerContainerMonitoring": "",
+ "dockerContainerMonitoringDescription": "",
+ "portMonitoring": "",
+ "portMonitoringDescription": "",
+ "createMaintenanceWindow": "",
+ "createMaintenance": "Bakım oluştur",
+ "editMaintenance": "Bakımı düzenle",
+ "maintenanceWindowName": "",
+ "friendlyNameInput": "Görünen ad",
+ "friendlyNamePlaceholder": "",
+ "maintenanceRepeat": "Bakım Tekrarı",
+ "maintenance": "bakım",
+ "duration": "Süre",
+ "addMonitors": "Monitör ekle",
+ "window": "pencere",
+ "cancel": "İptal",
+ "message": "Mesaj",
+ "low": "düşük",
+ "high": "",
+ "statusCode": "",
+ "date&Time": "",
+ "type": "",
+ "statusPageName": "",
+ "publicURL": "",
+ "repeat": "",
+ "edit": "",
+ "createA": "",
+ "remove": "",
+ "maintenanceWindowDescription": "",
+ "startTime": "Başlangıç saati",
+ "timeZoneInfo": "",
+ "monitorsToApply": "",
+ "nextWindow": "Sonraki pencere",
+ "notFoundButton": "",
+ "pageSpeedConfigureSettingsDescription": "",
+ "monitorDisplayName": "",
+ "whenNewIncident": "Yeni bir olay oluştuğunda,",
+ "notifySMS": "",
+ "notifyEmails": "",
+ "seperateEmails": "",
+ "checkFrequency": "Frekansı denetle",
+ "matchMethod": "",
+ "expectedValue": "Beklenen değer",
+ "deleteDialogTitle": "Gerçekten bu monitörü silmek istiyor musunuz?",
+ "deleteDialogDescription": "Bir kez silindiği zaman tekrar getiremezsiniz.",
+ "pageSpeedMonitor": "Sayfa Hızı Monitörü",
+ "shown": "",
+ "ago": "",
+ "companyName": "Firma adı",
+ "pageSpeedDetailsPerformanceReport": "",
+ "pageSpeedDetailsPerformanceReportCalculator": "",
+ "checkingEvery": "",
+ "statusPageCreateSettings": "",
+ "basicInformation": "",
+ "statusPageCreateBasicInfoDescription": "",
+ "statusPageCreateSelectTimeZoneDescription": "",
+ "statusPageCreateAppearanceDescription": "",
+ "statusPageCreateSettingsCheckboxLabel": "",
+ "statusPageCreateBasicInfoStatusPageAddress": "",
+ "statusPageCreateTabsContent": "",
+ "statusPageCreateTabsContentDescription": "",
+ "statusPageCreateTabsContentFeaturesDescription": "",
+ "showCharts": "",
+ "showUptimePercentage": "",
+ "removeLogo": "",
+ "statusPageStatus": "",
+ "statusPageStatusContactAdmin": "",
+ "statusPageStatusNotPublic": "",
+ "statusPageStatusNoPage": "",
+ "statusPageStatusServiceStatus": "Servis durumu",
+ "deleteStatusPage": "Gerçekten bu durum sayfasını silmek istiyor musunuz?",
+ "deleteStatusPageConfirm": "Evet, durum sayfasını sil",
+ "deleteStatusPageDescription": "Silindikten sonra durum sayfasını geri getiremezsiniz.",
+ "uptimeCreate": "",
+ "uptimeCreateJsonPath": "",
+ "uptimeCreateJsonPathQuery": "",
+ "maintenanceTableActionMenuDialogTitle": "Gerçekten bu bakım aralığını silmek istiyor musunuz?"
}
| |