expiration check
parent
f56a4235e7
commit
71c6a72308
|
@ -29,7 +29,8 @@
|
||||||
"copiedToClipboard": "In die Zwischenablage kopiert",
|
"copiedToClipboard": "In die Zwischenablage kopiert",
|
||||||
"copyToClipboard": "In die Zwischenablage kopieren",
|
"copyToClipboard": "In die Zwischenablage kopieren",
|
||||||
"show": "Anzeigen",
|
"show": "Anzeigen",
|
||||||
"hide": "Verbergen"
|
"hide": "Verbergen",
|
||||||
|
"reload": "Neu laden"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sideMenu": {
|
"sideMenu": {
|
||||||
|
@ -386,7 +387,6 @@
|
||||||
"repeatNewPassword": "Neues Passwort wiederholen",
|
"repeatNewPassword": "Neues Passwort wiederholen",
|
||||||
"language": "Sprache"
|
"language": "Sprache"
|
||||||
},
|
},
|
||||||
|
|
||||||
"button": {
|
"button": {
|
||||||
"createApiKey": {
|
"createApiKey": {
|
||||||
"title": "Neuen API-Schlüssel erstellen",
|
"title": "Neuen API-Schlüssel erstellen",
|
||||||
|
@ -396,7 +396,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"icon": { "viewApiDoc": "Api-Dokumentation anschauen" }
|
"icon": { "viewApiDoc": "Api-Dokumentation anschauen" },
|
||||||
|
"telegram": {
|
||||||
|
"title": "Telegram Benachrichtigungen",
|
||||||
|
"disconnectPopconfirm": {
|
||||||
|
"title": "Sind Sie sicher, dass Sie die Verbindung zu Telegram trennen wollen?",
|
||||||
|
"description": "Sie werden keine Benachrichtigungen mehr erhalten"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"scanners": {
|
"scanners": {
|
||||||
"column": {
|
"column": {
|
||||||
|
|
|
@ -29,7 +29,8 @@
|
||||||
"copiedToClipboard": "Copied to clipboard",
|
"copiedToClipboard": "Copied to clipboard",
|
||||||
"copyToClipboard": "Copy to clipboard",
|
"copyToClipboard": "Copy to clipboard",
|
||||||
"show": "Show",
|
"show": "Show",
|
||||||
"hide": "Hide"
|
"hide": "Hide",
|
||||||
|
"reload": "Reload"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sideMenu": {
|
"sideMenu": {
|
||||||
|
@ -415,7 +416,21 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"icon": { "viewApiDoc": "View API Documentation" }
|
"icon": { "viewApiDoc": "View API Documentation" },
|
||||||
|
"telegram": {
|
||||||
|
"title": "Telegram notifications",
|
||||||
|
"subscribeButton": "Subscribe",
|
||||||
|
"checkStatusButton": "Check Status",
|
||||||
|
"subscribed": "Subscribed",
|
||||||
|
"disconnectPopconfirm": {
|
||||||
|
"title": "Are you sure you want to disconnect your Telegram account?",
|
||||||
|
"description": "You will no longer receive notifications via Telegram"
|
||||||
|
},
|
||||||
|
"verificationPopover": {
|
||||||
|
"title": "Verification",
|
||||||
|
"description": "Add the bot on your telegram account and send the command {{command}} to the bot"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"scanners": {
|
"scanners": {
|
||||||
"column": {
|
"column": {
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
import {
|
import {
|
||||||
CopyOutlined,
|
CopyOutlined,
|
||||||
|
DisconnectOutlined,
|
||||||
EyeInvisibleOutlined,
|
EyeInvisibleOutlined,
|
||||||
EyeOutlined,
|
EyeOutlined,
|
||||||
|
ReloadOutlined,
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import { Tooltip } from "antd";
|
import { Tooltip } from "antd";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
|
@ -37,3 +39,13 @@ export function MyShowHiddenIcon({ setIsHidden, isHidden }) {
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function MyReloadIcon({ onClick }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip title={t("common.text.reload")}>
|
||||||
|
<ReloadOutlined onClick={onClick} />
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {
|
||||||
Form,
|
Form,
|
||||||
Input,
|
Input,
|
||||||
Popconfirm,
|
Popconfirm,
|
||||||
|
Popover,
|
||||||
Row,
|
Row,
|
||||||
Select,
|
Select,
|
||||||
Space,
|
Space,
|
||||||
|
@ -14,7 +15,7 @@ import {
|
||||||
Upload,
|
Upload,
|
||||||
notification,
|
notification,
|
||||||
} from "antd";
|
} from "antd";
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
import {
|
import {
|
||||||
Constants,
|
Constants,
|
||||||
EncodeStringToBase64,
|
EncodeStringToBase64,
|
||||||
|
@ -24,18 +25,29 @@ import {
|
||||||
hasPermission,
|
hasPermission,
|
||||||
isEmailValid,
|
isEmailValid,
|
||||||
myFetch,
|
myFetch,
|
||||||
|
myFetchContentType,
|
||||||
wsConnectionCustomEventName,
|
wsConnectionCustomEventName,
|
||||||
} from "../../utils";
|
} from "../../utils";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { useTranslation } from "react-i18next";
|
import { Trans, useTranslation } from "react-i18next";
|
||||||
import { FileTextOutlined, KeyOutlined } from "@ant-design/icons";
|
import {
|
||||||
|
DisconnectOutlined,
|
||||||
|
FileTextOutlined,
|
||||||
|
InfoCircleOutlined,
|
||||||
|
KeyOutlined,
|
||||||
|
NotificationOutlined,
|
||||||
|
} from "@ant-design/icons";
|
||||||
import { MyUserAvatar } from "../../Components/MyAvatar";
|
import { MyUserAvatar } from "../../Components/MyAvatar";
|
||||||
import { useUserProfileContext } from "../../Contexts/UserProfileContext";
|
import { useUserProfileContext } from "../../Contexts/UserProfileContext";
|
||||||
import { useWebSocketContext } from "../../Contexts/WebSocketContext";
|
import { useWebSocketContext } from "../../Contexts/WebSocketContext";
|
||||||
import { useAppContext } from "../../Contexts/AppContext";
|
import { useAppContext } from "../../Contexts/AppContext";
|
||||||
import { useSideBarContext } from "../../Contexts/SideBarContext";
|
import { useSideBarContext } from "../../Contexts/SideBarContext";
|
||||||
import { SentMessagesCommands } from "../../Handlers/WebSocketMessageHandler";
|
import { SentMessagesCommands } from "../../Handlers/WebSocketMessageHandler";
|
||||||
import { MyCopyIcon, MyShowHiddenIcon } from "../../Components/MyIcon";
|
import {
|
||||||
|
MyCopyIcon,
|
||||||
|
MyReloadIcon,
|
||||||
|
MyShowHiddenIcon,
|
||||||
|
} from "../../Components/MyIcon";
|
||||||
|
|
||||||
export default function UserProfile() {
|
export default function UserProfile() {
|
||||||
const webSocketContext = useWebSocketContext();
|
const webSocketContext = useWebSocketContext();
|
||||||
|
@ -53,6 +65,13 @@ export default function UserProfile() {
|
||||||
const [repeatedNewPassword, setRepeatedNewPassword] = useState("");
|
const [repeatedNewPassword, setRepeatedNewPassword] = useState("");
|
||||||
const [newApiKeyName, setNewApikeyName] = useState("");
|
const [newApiKeyName, setNewApikeyName] = useState("");
|
||||||
const [showApiKeyPassword, setShowApiKeyPassword] = useState(false);
|
const [showApiKeyPassword, setShowApiKeyPassword] = useState(false);
|
||||||
|
const [
|
||||||
|
telegramNotificationSubscribedStatus,
|
||||||
|
setTelegramNotificationSubscribedStatus,
|
||||||
|
] = useState(null);
|
||||||
|
|
||||||
|
const statusInterval = useRef(null);
|
||||||
|
const telegramVerifyCodeRequestTime = useRef(null);
|
||||||
|
|
||||||
const getSessionTableColumns = () => {
|
const getSessionTableColumns = () => {
|
||||||
return [
|
return [
|
||||||
|
@ -271,6 +290,165 @@ export default function UserProfile() {
|
||||||
setNewApikeyName("");
|
setNewApikeyName("");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const telegramVerifyStatusRequest = (updateOnlyOnVerified) =>
|
||||||
|
myFetch(
|
||||||
|
`/status/${appContext.userId.current}`,
|
||||||
|
"GET",
|
||||||
|
null,
|
||||||
|
{},
|
||||||
|
myFetchContentType.JSON,
|
||||||
|
Constants.TELEGRAM_BOT_MANAGER_ADDRESS
|
||||||
|
).then((data) => {
|
||||||
|
// manual check verify status by clicking reload icon
|
||||||
|
if (!updateOnlyOnVerified) {
|
||||||
|
setTelegramNotificationSubscribedStatus(data.Status);
|
||||||
|
}
|
||||||
|
|
||||||
|
// used for auto check verify status
|
||||||
|
if (data.Status === true) {
|
||||||
|
setTelegramNotificationSubscribedStatus(data.Status);
|
||||||
|
clearInterval(statusInterval.current);
|
||||||
|
telegramVerifyCodeRequestTime.current = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const TelegramNotificationSubscribedStatusItem = () => {
|
||||||
|
// check verified status
|
||||||
|
if (telegramNotificationSubscribedStatus === null) {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
onClick={() => telegramVerifyStatusRequest()}
|
||||||
|
>
|
||||||
|
{t("userProfile.telegram.checkStatusButton")}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// unsubscribe
|
||||||
|
if (telegramNotificationSubscribedStatus === true) {
|
||||||
|
return (
|
||||||
|
<Space>
|
||||||
|
<span>{t("userProfile.telegram.subscribed")}</span>
|
||||||
|
|
||||||
|
<Popconfirm
|
||||||
|
title={t("userProfile.telegram.disconnectPopconfirm.title")}
|
||||||
|
description={t(
|
||||||
|
"userProfile.telegram.disconnectPopconfirm.description"
|
||||||
|
)}
|
||||||
|
okText={t("common.button.confirm")}
|
||||||
|
cancelText={t("common.button.cancel")}
|
||||||
|
onConfirm={() => {
|
||||||
|
myFetch(
|
||||||
|
`/verifycode/${appContext.userId.current}`,
|
||||||
|
"DELETE",
|
||||||
|
null,
|
||||||
|
{},
|
||||||
|
myFetchContentType.JSON,
|
||||||
|
Constants.TELEGRAM_BOT_MANAGER_ADDRESS
|
||||||
|
).then(() => {
|
||||||
|
setTelegramNotificationSubscribedStatus(null);
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<DisconnectOutlined />
|
||||||
|
</Popconfirm>
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// subscribe
|
||||||
|
if (telegramNotificationSubscribedStatus === false) {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
icon={<NotificationOutlined />}
|
||||||
|
style={{ width: "100%" }}
|
||||||
|
onClick={() =>
|
||||||
|
myFetch(
|
||||||
|
`/verifycode/${appContext.userId.current}`,
|
||||||
|
"GET",
|
||||||
|
null,
|
||||||
|
{},
|
||||||
|
myFetchContentType.JSON,
|
||||||
|
Constants.TELEGRAM_BOT_MANAGER_ADDRESS
|
||||||
|
).then((data) => {
|
||||||
|
setTelegramNotificationSubscribedStatus(data.Code);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t("userProfile.telegram.subscribeButton")}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// verification code
|
||||||
|
return (
|
||||||
|
<Space>
|
||||||
|
<Popover
|
||||||
|
placement="left"
|
||||||
|
title={t("userProfile.telegram.verificationPopover.title")}
|
||||||
|
overlayStyle={{ maxWidth: 300 }}
|
||||||
|
content={
|
||||||
|
<Space direction="vertical">
|
||||||
|
<Trans
|
||||||
|
i18nKey="userProfile.telegram.verificationPopover.description"
|
||||||
|
values={{
|
||||||
|
command: `<strong>/verify ${telegramNotificationSubscribedStatus}</strong>`,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div style={{ textAlign: "center" }}>
|
||||||
|
<img
|
||||||
|
src={`${Constants.TELEGRAM_BOT_MANAGER_CONTENT_ADDRESS}qrcode.png`}
|
||||||
|
width={200}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Space>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<InfoCircleOutlined style={{ color: Constants.COLORS.ICON_INFO }} />
|
||||||
|
</Popover>
|
||||||
|
|
||||||
|
<span>{telegramNotificationSubscribedStatus}</span>
|
||||||
|
|
||||||
|
<MyCopyIcon
|
||||||
|
text={`/verify ${telegramNotificationSubscribedStatus}`}
|
||||||
|
notificationApi={notificationApi}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<MyReloadIcon onClick={() => telegramVerifyStatusRequest()} />
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
telegramNotificationSubscribedStatus !== true &&
|
||||||
|
telegramNotificationSubscribedStatus !== false &&
|
||||||
|
telegramNotificationSubscribedStatus !== null
|
||||||
|
) {
|
||||||
|
telegramVerifyCodeRequestTime.current = new Date();
|
||||||
|
|
||||||
|
statusInterval.current = setInterval(() => {
|
||||||
|
// check expiration time
|
||||||
|
if (
|
||||||
|
telegramVerifyCodeRequestTime.current !== null &&
|
||||||
|
new Date() - telegramVerifyCodeRequestTime.current >
|
||||||
|
Constants.GLOBALS.TELEGRAM_VERIFY_CODE_EXPIRATION_TIME
|
||||||
|
) {
|
||||||
|
clearInterval(statusInterval.current);
|
||||||
|
telegramVerifyCodeRequestTime.current = null;
|
||||||
|
setTelegramNotificationSubscribedStatus(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
telegramVerifyStatusRequest(true);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => clearInterval(statusInterval.current);
|
||||||
|
}, [telegramNotificationSubscribedStatus]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const userProfileRequest = () =>
|
const userProfileRequest = () =>
|
||||||
myFetch("/user/profile", "GET").then((data) => {
|
myFetch("/user/profile", "GET").then((data) => {
|
||||||
|
@ -342,6 +520,10 @@ export default function UserProfile() {
|
||||||
onChange={(e) => i18n.changeLanguage(e)}
|
onChange={(e) => i18n.changeLanguage(e)}
|
||||||
/>
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
|
||||||
|
<Form.Item label={t("userProfile.telegram.title")}>
|
||||||
|
<TelegramNotificationSubscribedStatusItem />
|
||||||
|
</Form.Item>
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
|
|
11
src/utils.js
11
src/utils.js
|
@ -14,6 +14,8 @@ let wsAddress = "";
|
||||||
let logApiAddress = "";
|
let logApiAddress = "";
|
||||||
let roboticsApiAddress = "";
|
let roboticsApiAddress = "";
|
||||||
var roboticsSwaggerAddress = "";
|
var roboticsSwaggerAddress = "";
|
||||||
|
var telegramBotManagerAddress = "";
|
||||||
|
var telegramBotManagerStaticContentAddress = "";
|
||||||
|
|
||||||
if (window.location.hostname === "localhost" && window.location.port === "") {
|
if (window.location.hostname === "localhost" && window.location.port === "") {
|
||||||
// for docker container testing on localhost
|
// for docker container testing on localhost
|
||||||
|
@ -23,6 +25,8 @@ if (window.location.hostname === "localhost" && window.location.port === "") {
|
||||||
logApiAddress = "http://localhost/lm/v1/log";
|
logApiAddress = "http://localhost/lm/v1/log";
|
||||||
roboticsApiAddress = "http://localhost/rcm/v1";
|
roboticsApiAddress = "http://localhost/rcm/v1";
|
||||||
roboticsSwaggerAddress = "http://localhost/rcm/swagger/index.html";
|
roboticsSwaggerAddress = "http://localhost/rcm/swagger/index.html";
|
||||||
|
telegramBotManagerAddress = "http://localhost/tnm/v1";
|
||||||
|
telegramBotManagerStaticContentAddress = "http://localhost/tnm/";
|
||||||
} else if (window.location.hostname === "localhost") {
|
} else if (window.location.hostname === "localhost") {
|
||||||
// programming on localhost
|
// programming on localhost
|
||||||
apiAddress = "http://localhost:50050/v1";
|
apiAddress = "http://localhost:50050/v1";
|
||||||
|
@ -31,6 +35,8 @@ if (window.location.hostname === "localhost" && window.location.port === "") {
|
||||||
logApiAddress = "http://127.0.0.1:50110/v1/log";
|
logApiAddress = "http://127.0.0.1:50110/v1/log";
|
||||||
roboticsApiAddress = "http://localhost:50055/v1";
|
roboticsApiAddress = "http://localhost:50055/v1";
|
||||||
roboticsSwaggerAddress = "http://localhost:50055/swagger/index.html";
|
roboticsSwaggerAddress = "http://localhost:50055/swagger/index.html";
|
||||||
|
telegramBotManagerAddress = "http://localhost:50056/v1";
|
||||||
|
telegramBotManagerStaticContentAddress = "http://localhost:50056/";
|
||||||
/*} else if (window.location.hostname === "192.168.178.93") {
|
/*} else if (window.location.hostname === "192.168.178.93") {
|
||||||
apiAddress = "http://192.168.178.93:50050/v1";
|
apiAddress = "http://192.168.178.93:50050/v1";
|
||||||
staticContentAddress = "http://192.168.178.93:50050/";
|
staticContentAddress = "http://192.168.178.93:50050/";
|
||||||
|
@ -43,6 +49,8 @@ if (window.location.hostname === "localhost" && window.location.port === "") {
|
||||||
logApiAddress = `${window.location.protocol}${window.location.hostname}/lm/v1/log`;
|
logApiAddress = `${window.location.protocol}${window.location.hostname}/lm/v1/log`;
|
||||||
roboticsApiAddress = `${window.location.protocol}${window.location.hostname}/rcm/v1`;
|
roboticsApiAddress = `${window.location.protocol}${window.location.hostname}/rcm/v1`;
|
||||||
roboticsSwaggerAddress = `${window.location.protocol}${window.location.hostname}/rcm/swagger/index.html`;
|
roboticsSwaggerAddress = `${window.location.protocol}${window.location.hostname}/rcm/swagger/index.html`;
|
||||||
|
telegramBotManagerAddress = `${window.location.protocol}${window.location.hostname}/tnm/v1`;
|
||||||
|
telegramBotManagerStaticContentAddress = `${window.location.protocol}${window.location.hostname}/tnm/`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Constants = {
|
export const Constants = {
|
||||||
|
@ -66,6 +74,8 @@ export const Constants = {
|
||||||
LOG_API_ADDRESS: logApiAddress,
|
LOG_API_ADDRESS: logApiAddress,
|
||||||
ROBOTICS_API_ADDRESS: roboticsApiAddress, // robot-control-manager
|
ROBOTICS_API_ADDRESS: roboticsApiAddress, // robot-control-manager
|
||||||
ROBOTICS_SWAGGER_ADDRESS: roboticsSwaggerAddress,
|
ROBOTICS_SWAGGER_ADDRESS: roboticsSwaggerAddress,
|
||||||
|
TELEGRAM_BOT_MANAGER_ADDRESS: telegramBotManagerAddress,
|
||||||
|
TELEGRAM_BOT_MANAGER_CONTENT_ADDRESS: telegramBotManagerStaticContentAddress,
|
||||||
ROUTE_PATHS: {
|
ROUTE_PATHS: {
|
||||||
EQUIPMENT_DOCUMENTATION: "/equipment-documentation",
|
EQUIPMENT_DOCUMENTATION: "/equipment-documentation",
|
||||||
EQUIPMENT_DOCUMENTATION_VIEW: "/equipment-documentation/",
|
EQUIPMENT_DOCUMENTATION_VIEW: "/equipment-documentation/",
|
||||||
|
@ -113,6 +123,7 @@ export const Constants = {
|
||||||
MAX_USER_API_KEY_NAME_LENGTH: 30,
|
MAX_USER_API_KEY_NAME_LENGTH: 30,
|
||||||
ROBOTICS_ROBOTS_PAGINATION_LIMIT: 5,
|
ROBOTICS_ROBOTS_PAGINATION_LIMIT: 5,
|
||||||
ROBOTICS_UNAUTHORIZED_PAGINATION_LIMIT: 5,
|
ROBOTICS_UNAUTHORIZED_PAGINATION_LIMIT: 5,
|
||||||
|
TELEGRAM_VERIFY_CODE_EXPIRATION_TIME: 10 * 60 * 1000, // 10 minutes
|
||||||
},
|
},
|
||||||
MAX_AVATAR_SIZE: 5 * 1024 * 1024,
|
MAX_AVATAR_SIZE: 5 * 1024 * 1024,
|
||||||
ACCEPTED_AVATAR_FILE_TYPES: [
|
ACCEPTED_AVATAR_FILE_TYPES: [
|
||||||
|
|
Loading…
Reference in New Issue