mirror of
https://github.com/bluewave-labs/Checkmate.git
synced 2026-01-24 19:01:01 -06:00
resolve merge conflicts
This commit is contained in:
6
package-lock.json
generated
6
package-lock.json
generated
@@ -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": "*",
|
||||
|
||||
@@ -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 <SkeletonLayout />;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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 <SkeletonLayout />;
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ const MonitorTimeFrameHeader = ({
|
||||
};
|
||||
|
||||
MonitorTimeFrameHeader.propTypes = {
|
||||
shouldRender: PropTypes.bool,
|
||||
isLoading: PropTypes.bool,
|
||||
hasDateRange: PropTypes.bool,
|
||||
dateRange: PropTypes.string,
|
||||
setDateRange: PropTypes.func,
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
</TabPanel>
|
||||
))}
|
||||
@@ -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')}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
@@ -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}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
@@ -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}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
@@ -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 ? (
|
||||
<CircularProgress
|
||||
size={theme.spacing(8)}
|
||||
sx={{ mr: theme.spacing(1), color: theme.palette.accent.main}}
|
||||
/>
|
||||
) : null}
|
||||
{t('notifications.testNotification')}
|
||||
</Button>
|
||||
</Box>
|
||||
@@ -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;
|
||||
36
src/Hooks/useFetchUptimeMonitorDetails.js
Normal file
36
src/Hooks/useFetchUptimeMonitorDetails.js
Normal file
@@ -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;
|
||||
@@ -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,
|
||||
},
|
||||
}),
|
||||
}}
|
||||
|
||||
@@ -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 = () => {
|
||||
<ConfigBox>
|
||||
<Box>
|
||||
<Typography component="h2">{t("settingsGeneralSettings")}</Typography>
|
||||
<Typography component="p">
|
||||
{t("distributedUptimeCreateSelectURL")}
|
||||
</Typography>
|
||||
<Typography component="p">{t("distributedUptimeCreateSelectURL")}</Typography>
|
||||
</Box>
|
||||
<Stack gap={theme.spacing(15)}>
|
||||
<TextInput
|
||||
@@ -399,7 +397,9 @@ const CreateMonitor = () => {
|
||||
</ConfigBox>
|
||||
<ConfigBox>
|
||||
<Box>
|
||||
<Typography component="h2">{t("distributedUptimeCreateIncidentNotification")}</Typography>
|
||||
<Typography component="h2">
|
||||
{t("distributedUptimeCreateIncidentNotification")}
|
||||
</Typography>
|
||||
<Typography component="p">
|
||||
{t("distributedUptimeCreateIncidentDescription")}
|
||||
</Typography>
|
||||
@@ -415,21 +415,22 @@ const CreateMonitor = () => {
|
||||
onChange={(event) => handleNotifications(event, "email")}
|
||||
/>
|
||||
|
||||
{/* <Box mt={theme.spacing(2)}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="accent"
|
||||
onClick={handleOpenNotificationModal}
|
||||
>
|
||||
Notification Integration
|
||||
</Button>
|
||||
</Box> */}
|
||||
|
||||
<Box mt={theme.spacing(2)}>
|
||||
<Button
|
||||
variant="contained"
|
||||
color="accent"
|
||||
onClick={handleOpenNotificationModal}
|
||||
>
|
||||
{t("notifications.integrationButton")}
|
||||
</Button>
|
||||
</Box>
|
||||
</Stack>
|
||||
</ConfigBox>
|
||||
<ConfigBox>
|
||||
<Box>
|
||||
<Typography component="h2">{t("distributedUptimeCreateAdvancedSettings")}</Typography>
|
||||
<Typography component="h2">
|
||||
{t("distributedUptimeCreateAdvancedSettings")}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Stack gap={theme.spacing(12)}>
|
||||
<Select
|
||||
@@ -520,11 +521,11 @@ const CreateMonitor = () => {
|
||||
</Stack>
|
||||
|
||||
<NotificationIntegrationModal
|
||||
open={isNotificationModalOpen}
|
||||
onClose={() => setIsNotificationModalOpen(false)}
|
||||
monitor={monitor}
|
||||
setMonitor={setMonitor}
|
||||
/>
|
||||
open={isNotificationModalOpen}
|
||||
onClose={() => setIsNotificationModalOpen(false)}
|
||||
monitor={monitor}
|
||||
setMonitor={setMonitor}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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 <SkeletonLayout />;
|
||||
}
|
||||
|
||||
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 = ({
|
||||
<ChartBox
|
||||
icon={<UptimeIcon />}
|
||||
header="Uptime"
|
||||
isEmpty={monitor?.uptimePercentage === 0 && !monitor?.upChecks?.length}
|
||||
isEmpty={monitorData?.groupedUpChecks?.length === 0}
|
||||
>
|
||||
<Stack
|
||||
width={"100%"}
|
||||
@@ -58,7 +52,7 @@ const ChartBoxes = ({
|
||||
<Typography component="span">
|
||||
{hoveredUptimeData !== null
|
||||
? hoveredUptimeData.totalChecks
|
||||
: (monitor?.groupedUpChecks?.reduce((count, checkGroup) => {
|
||||
: (monitorData?.groupedUpChecks?.reduce((count, checkGroup) => {
|
||||
return count + checkGroup.totalChecks;
|
||||
}, 0) ?? 0)}
|
||||
</Typography>
|
||||
@@ -81,7 +75,7 @@ const ChartBoxes = ({
|
||||
<Typography component="span">
|
||||
{hoveredUptimeData !== null
|
||||
? Math.floor(hoveredUptimeData?.avgResponseTime ?? 0)
|
||||
: Math.floor(groupedUptimePercentage)}
|
||||
: Math.floor(monitorData?.groupedUptimePercentage * 100 ?? 0)}
|
||||
<Typography component="span">
|
||||
{hoveredUptimeData !== null ? " ms" : " %"}
|
||||
</Typography>
|
||||
@@ -89,7 +83,7 @@ const ChartBoxes = ({
|
||||
</Box>
|
||||
</Stack>
|
||||
<UpBarChart
|
||||
monitor={monitor}
|
||||
groupedUpChecks={monitorData?.groupedUpChecks}
|
||||
type={dateRange}
|
||||
onBarHover={setHoveredUptimeData}
|
||||
/>
|
||||
@@ -98,14 +92,14 @@ const ChartBoxes = ({
|
||||
icon={<IncidentsIcon />}
|
||||
header="Incidents"
|
||||
noDataMessage={noIncidentsMessage}
|
||||
isEmpty={monitor?.groupedDownChecks?.length === 0}
|
||||
isEmpty={monitorData?.groupedDownChecks?.length === 0}
|
||||
>
|
||||
<Stack width={"100%"}>
|
||||
<Box position="relative">
|
||||
<Typography component="span">
|
||||
{hoveredIncidentsData !== null
|
||||
? hoveredIncidentsData.totalChecks
|
||||
: (monitor?.groupedDownChecks?.reduce((count, checkGroup) => {
|
||||
: (monitorData?.groupedDownChecks?.reduce((count, checkGroup) => {
|
||||
return count + checkGroup.totalChecks;
|
||||
}, 0) ?? 0)}
|
||||
</Typography>
|
||||
@@ -123,7 +117,7 @@ const ChartBoxes = ({
|
||||
</Box>
|
||||
</Stack>
|
||||
<DownBarChart
|
||||
monitor={monitor}
|
||||
groupedDownChecks={monitorData?.groupedDownChecks}
|
||||
type={dateRange}
|
||||
onBarHover={setHoveredIncidentsData}
|
||||
/>
|
||||
@@ -132,7 +126,7 @@ const ChartBoxes = ({
|
||||
icon={<AverageResponseIcon />}
|
||||
header="Average Response Time"
|
||||
>
|
||||
<ResponseGaugeChart avgResponseTime={monitor?.avgResponseTime ?? 0} />
|
||||
<ResponseGaugeChart avgResponseTime={monitorData?.groupedAvgResponseTime ?? 0} />
|
||||
</ChartBox>
|
||||
</Stack>
|
||||
);
|
||||
@@ -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,
|
||||
|
||||
@@ -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 }) => {
|
||||
<BarChart
|
||||
width="100%"
|
||||
height="100%"
|
||||
data={monitor?.groupedDownChecks}
|
||||
data={groupedDownChecks}
|
||||
onMouseEnter={() => {
|
||||
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 (
|
||||
<Cell
|
||||
key={`cell-${entry.time}`}
|
||||
|
||||
@@ -4,8 +4,8 @@ import ResponseTimeIcon from "../../../../../assets/icons/response-time-icon.svg
|
||||
import SkeletonLayout from "./ResponseTimeChartSkeleton";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
const ResponseTImeChart = ({ shouldRender = true, monitor, dateRange }) => {
|
||||
if (!shouldRender) {
|
||||
const ResponseTImeChart = ({ isLoading = false, groupedChecks = [], dateRange }) => {
|
||||
if (isLoading) {
|
||||
return <SkeletonLayout />;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ const ResponseTImeChart = ({ shouldRender = true, monitor, dateRange }) => {
|
||||
header="Response Times"
|
||||
>
|
||||
<MonitorDetailsAreaChart
|
||||
checks={monitor?.groupedChecks ?? []}
|
||||
checks={groupedChecks}
|
||||
dateRange={dateRange}
|
||||
/>
|
||||
</ChartBox>
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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 }) => {
|
||||
<BarChart
|
||||
width="100%"
|
||||
height="100%"
|
||||
data={monitor?.groupedUpChecks}
|
||||
data={groupedUpChecks}
|
||||
onMouseEnter={() => {
|
||||
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 (
|
||||
<Cell
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useTranslation } from "react-i18next";
|
||||
import { formatDateWithTz } from "../../../../../Utils/timeUtils";
|
||||
import SkeletonLayout from "./skeleton";
|
||||
const ResponseTable = ({
|
||||
shouldRender = true,
|
||||
isLoading = false,
|
||||
checks = [],
|
||||
checksCount,
|
||||
uiTimezone,
|
||||
@@ -18,7 +18,7 @@ const ResponseTable = ({
|
||||
setRowsPerPage,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
if (!shouldRender) {
|
||||
if (isLoading) {
|
||||
return <SkeletonLayout />;
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ const ResponseTable = ({
|
||||
};
|
||||
|
||||
ResponseTable.propTypes = {
|
||||
shouldRender: PropTypes.bool,
|
||||
isLoading: PropTypes.bool,
|
||||
checks: PropTypes.array,
|
||||
checksCount: PropTypes.number,
|
||||
uiTimezone: PropTypes.string.isRequired,
|
||||
|
||||
@@ -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 (
|
||||
<StatusBoxes shouldRender={shouldRender}>
|
||||
<StatusBoxes shouldRender={!isLoading}>
|
||||
<StatBox
|
||||
gradient={true}
|
||||
status={determineState(monitor)}
|
||||
@@ -43,7 +56,7 @@ const UptimeStatusBoxes = ({ shouldRender, monitor, certificateExpiry }) => {
|
||||
heading="last response time"
|
||||
subHeading={
|
||||
<>
|
||||
{monitor?.latestResponseTime}
|
||||
{monitorStats?.lastResponseTime}
|
||||
<Typography component="span">{"ms"}</Typography>
|
||||
</>
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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 = () => {
|
||||
<MonitorStatusHeader
|
||||
path={"uptime"}
|
||||
isAdmin={isAdmin}
|
||||
shouldRender={!monitorIsLoading}
|
||||
isLoading={monitorIsLoading}
|
||||
monitor={monitor}
|
||||
/>
|
||||
<UptimeStatusBoxes
|
||||
shouldRender={!monitorIsLoading}
|
||||
isLoading={monitorIsLoading}
|
||||
monitor={monitor}
|
||||
monitorStats={monitorStats}
|
||||
certificateExpiry={certificateExpiry}
|
||||
/>
|
||||
<MonitorTimeFrameHeader
|
||||
shouldRender={!monitorIsLoading}
|
||||
isLoading={monitorIsLoading}
|
||||
hasDateRange={true}
|
||||
dateRange={dateRange}
|
||||
setDateRange={setDateRange}
|
||||
/>
|
||||
<ChartBoxes
|
||||
shouldRender={!monitorIsLoading}
|
||||
monitor={monitor}
|
||||
isLoading={monitorIsLoading}
|
||||
monitorData={monitorData}
|
||||
uiTimezone={uiTimezone}
|
||||
dateRange={dateRange}
|
||||
dateFormat={dateFormat}
|
||||
hoveredUptimeData={hoveredUptimeData}
|
||||
setHoveredUptimeData={setHoveredUptimeData}
|
||||
hoveredIncidentsData={hoveredIncidentsData}
|
||||
setHoveredIncidentsData={setHoveredIncidentsData}
|
||||
/>
|
||||
<ResponseTimeChart
|
||||
shouldRender={!monitorIsLoading}
|
||||
monitor={monitor}
|
||||
isLoading={monitorIsLoading}
|
||||
groupedChecks={monitorData?.groupedChecks}
|
||||
dateRange={dateRange}
|
||||
/>
|
||||
<ResponseTable
|
||||
shouldRender={!checksAreLoading}
|
||||
isLoading={checksAreLoading}
|
||||
checks={checks}
|
||||
uiTimezone={uiTimezone}
|
||||
page={page}
|
||||
|
||||
@@ -669,6 +669,28 @@ class NetworkService {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* ************************************
|
||||
* Test a notification integration
|
||||
* ************************************
|
||||
*
|
||||
* @async
|
||||
* @param {Object} config - The configuration object.
|
||||
* @param {string} config.platform - The notification platform (slack, discord, telegram, webhook).
|
||||
* @param {Object} config.payload - The payload with configuration for the notification.
|
||||
* @returns {Promise<AxiosResponse>} 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
|
||||
|
||||
@@ -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" };
|
||||
|
||||
@@ -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?"
|
||||
}
|
||||
|
||||
364
src/locales/ru.json
Normal file
364
src/locales/ru.json
Normal file
@@ -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": ""
|
||||
}
|
||||
@@ -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?"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user