import {
Button,
Card,
Col,
Form,
Input,
Popconfirm,
Row,
Select,
Space,
Table,
Tooltip,
Typography,
Upload,
notification,
} from "antd";
import { useEffect, useState } from "react";
import {
Constants,
EncodeStringToBase64,
FormatDatetime,
getConnectionStatusItem,
getUserSessionFromLocalStorage,
hasPermission,
isEmailValid,
myFetch,
} from "../../utils";
import { Link } from "react-router-dom";
import { useTranslation } from "react-i18next";
import {
CopyOutlined,
EyeInvisibleOutlined,
EyeOutlined,
FileTextOutlined,
KeyOutlined,
} from "@ant-design/icons";
import { MyUserAvatar } from "../../Components/MyAvatar";
import { useUserProfileContext } from "../../Contexts/UserProfileContext";
import { useWebSocketContext } from "../../Contexts/WebSocketContext";
import { useAppContext } from "../../Contexts/AppContext";
import { useSideBarContext } from "../../Contexts/SideBarContext";
import { SentMessagesCommands } from "../../Handlers/WebSocketMessageHandler";
export default function UserProfile() {
const webSocketContext = useWebSocketContext();
const appContext = useAppContext();
const sideBarContext = useSideBarContext();
const userProfileContext = useUserProfileContext();
const [notificationApi, notificationContextHolder] =
notification.useNotification();
const { t, i18n } = useTranslation();
const [username, setUsername] = useState(Constants.LOADING);
const [email, setEmail] = useState(Constants.LOADING);
const [oldPassword, setOldPassword] = useState("");
const [newPassword, setNewPassword] = useState("");
const [repeatedNewPassword, setRepeatedNewPassword] = useState("");
const [newApiKeyName, setNewApikeyName] = useState("");
const [showApiKeyPassword, setShowApiKeyPassword] = useState(false);
const getSessionTableColumns = () => {
return [
{
title: t("userProfile.column.userAgent"),
dataIndex: "userAgent",
key: "userAgent",
},
{
title: t("userProfile.column.connectionStatus"),
dataIndex: "connectionStatus",
key: "connectionStatus",
},
{
title: t("userProfile.column.lastUsed"),
dataIndex: "lastUsed",
key: "lastUsed",
},
{
title: t("userProfile.column.expiresAt"),
dataIndex: "expiresAt",
key: "expiresAt",
},
{
title: t("userProfile.column.action.title"),
dataIndex: "action",
key: "action",
render: (_, record) => {
return (
myFetch(`/user/session/${record.key}`, "DELETE")}
>
{t("userProfile.column.action.signOut")}
);
},
},
];
};
const getApiKeyTableColumns = () => {
return [
{
title: t("userProfile.column.name"),
dataIndex: "name",
key: "name",
},
{
title: t("userProfile.column.token"),
dataIndex: "token",
key: "token",
render: (text) => (
{showApiKeyPassword ? text : "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"}
{showApiKeyPassword ? (
setShowApiKeyPassword(false)}
/>
) : (
setShowApiKeyPassword(true)} />
)}
{showApiKeyPassword && (
{
navigator.clipboard.writeText(text);
setShowApiKeyPassword(false);
notificationApi["info"]({
message: t(
"userProfile.button.copyToClipboard.notification"
),
});
}}
/>
)}
),
},
{
title: t("userProfile.column.usageCount"),
dataIndex: "usageCount",
key: "usageCount",
},
{
title: t("userProfile.column.lastUsed"),
dataIndex: "lastUsed",
key: "lastUsed",
},
{
title: t("userProfile.column.createdAt"),
dataIndex: "createdAt",
key: "createdAt",
},
{
title: t("userProfile.column.action.title"),
dataIndex: "action",
key: "action",
render: (_, record) => (
webSocketContext.SendSocketMessage(
SentMessagesCommands.DeleteUserApiKey,
{ Id: record.key }
)
}
>
{t("userProfile.column.deleteApiKey.link")}
),
},
];
};
const getApiKeyTableItems = () => {
let items = [];
userProfileContext.apiKeys.forEach((apiKey) => {
items.push({
key: apiKey.Id,
name: apiKey.Name,
token: apiKey.Token,
usageCount: apiKey.UsageCount,
createdAt: FormatDatetime(apiKey.CreatedAt),
lastUsed: FormatDatetime(apiKey.LastUsed),
});
});
return items;
};
const getSessionTableItems = () => {
let items = [];
userProfileContext.sessions.sort(
(a, b) => b.ConnectionStatus - a.ConnectionStatus
);
userProfileContext.sessions.forEach((session) => {
items.push({
key: session.IdForDeletion,
userAgent: session.UserAgent,
connectionStatus: getConnectionStatusItem(session.ConnectionStatus),
lastUsed: FormatDatetime(session.LastUsed),
expiresAt: FormatDatetime(session.ExpiresAt),
});
});
return items;
};
const beforeUpload = (file) => {
if (file.size > Constants.MAX_AVATAR_SIZE) {
notificationApi["error"]({
message: t("userProfile.changeAvatarError.notification.message"),
description: t(
"userProfile.changeAvatarError.notification.description",
{ MAX_AVATAR_SIZE: Constants.MAX_AVATAR_SIZE / 1024 / 1024 }
),
});
return false;
}
return true;
};
const isButtonDisabled = () => {
if (
!isEmailValid(email) ||
sideBarContext.username.length < Constants.GLOBALS.MIN_USERNAME_LENGTH
) {
return true;
}
if (
username !== sideBarContext.username ||
email !== userProfileContext.email ||
(oldPassword !== "" &&
newPassword !== "" &&
newPassword === repeatedNewPassword)
) {
return false;
}
return true;
};
const handleOnSubmit = () => {
const changes = {};
if (sideBarContext.username !== username) {
changes.username = username;
}
if (userProfileContext.email !== email) {
changes.email = email;
}
if (
oldPassword !== "" &&
newPassword !== "" &&
newPassword === repeatedNewPassword
) {
changes.oldPassword = EncodeStringToBase64(oldPassword);
changes.newPassword = EncodeStringToBase64(newPassword);
}
webSocketContext.SendSocketMessage(SentMessagesCommands.UpdateUserProfile, {
changes: changes,
});
};
const onCreateNewApiKeyConfirm = () => {
webSocketContext.SendSocketMessage(
SentMessagesCommands.CreateNewUserApiKey,
{ Name: newApiKeyName }
);
setNewApikeyName("");
};
useEffect(() => {
myFetch("/user/profile", "GET").then((data) => {
userProfileContext.setEmail(data.Email);
userProfileContext.setSessions(data.Sessions);
userProfileContext.setApiKeys(data.ApiKeys);
setEmail(data.Email);
});
}, []);
useEffect(
() => setUsername(sideBarContext.username),
[sideBarContext.username]
);
useEffect(
() => setEmail(userProfileContext.email),
[userProfileContext.email]
);
return (
<>
{notificationContextHolder}
{t("userProfile.header.yourProfile")}
setUsername(e.target.value)}
minLength={Constants.GLOBALS.MIN_USERNAME_LENGTH}
maxLength={Constants.GLOBALS.MAX_USERNAME_LENGTH}
/>
setEmail(e.target.value)}
/>
setOldPassword(e.target.value)}
minLength={Constants.GLOBALS.MIN_PASSWORD_LENGTH}
maxLength={Constants.GLOBALS.MAX_PASSWORD_LENGTH}
/>
setNewPassword(e.target.value)}
minLength={Constants.GLOBALS.MIN_PASSWORD_LENGTH}
maxLength={Constants.GLOBALS.MAX_PASSWORD_LENGTH}
/>
setRepeatedNewPassword(e.target.value)}
minLength={Constants.GLOBALS.MIN_PASSWORD_LENGTH}
maxLength={Constants.GLOBALS.MAX_PASSWORD_LENGTH}
/>
{t("userProfile.header.yourSessions")} (
{userProfileContext.sessions.length})
{hasPermission(
appContext.userPermissions,
Constants.PERMISSIONS.USER_PROFILE.API_KEYS
) && (
<>
{" "}
{t("userProfile.header.yourApiKeys")} (
{userProfileContext.apiKeys.length}){" "}
setNewApikeyName(e.target.value)}
/>
}
okText={t("userProfile.button.createApiKey.popconfirm.okText")}
cancelText={t("common.button.cancel")}
onConfirm={() => onCreateNewApiKeyConfirm()}
>
}>
{t("userProfile.button.createApiKey.title")}
>
)}
>
);
}