From b89f40f6221bed60c2442f78bde8d765f2781fa2 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 18 May 2023 22:03:06 +0200 Subject: [PATCH] user avatar --- src/Components/SideMenu/index.js | 20 +++++++-- src/Pages/UserProfile/index.js | 74 +++++++++++++++++++++++++++----- src/Pages/Users/index.js | 72 ++++++++++++++++++++++++++++++- src/utils.js | 59 +++++++++++++++++++++++-- 4 files changed, 205 insertions(+), 20 deletions(-) diff --git a/src/Components/SideMenu/index.js b/src/Components/SideMenu/index.js index 8450832..0aea869 100644 --- a/src/Components/SideMenu/index.js +++ b/src/Components/SideMenu/index.js @@ -2,14 +2,18 @@ import { AppstoreOutlined, LogoutOutlined, SnippetsOutlined, - UserOutlined, } from "@ant-design/icons"; import { Badge, Divider, Menu } from "antd"; import Sider from "antd/es/layout/Sider"; import { useContext, useEffect, useState } from "react"; import { useLocation, useNavigate } from "react-router-dom"; import PropTypes from "prop-types"; -import { Constants, UseUserSession, WebSocketContext } from "../../utils"; +import { + Constants, + MyAvatar, + UseUserSession, + WebSocketContext, +} from "../../utils"; export default function SideMenu({ setUserSession }) { const { userSession } = UseUserSession(); @@ -87,8 +91,16 @@ export default function SideMenu({ setUserSession }) { key: "/users", }, { - label: webSocketContext.User.Username, - icon: , + label: " " + webSocketContext.User.Username, + icon: ( + user.Id === webSocketContext.User.Id + )?.Avatar + } + /> + ), key: "/user-profile", }, { diff --git a/src/Pages/UserProfile/index.js b/src/Pages/UserProfile/index.js index 0982c32..6c6276e 100644 --- a/src/Pages/UserProfile/index.js +++ b/src/Pages/UserProfile/index.js @@ -1,6 +1,13 @@ -import { Badge, Space, Table } from "antd"; +import { Button, Card, Form, Input, Space, Table, Upload, message } from "antd"; import { useContext } from "react"; -import { Constants, FormatDatetime, WebSocketContext } from "../../utils"; +import { + Constants, + FormatDatetime, + MyAvatar, + WebSocketContext, + getConnectionStatusItem, + getUserSessionFromLocalStorage, +} from "../../utils"; const columns = [ { @@ -37,9 +44,7 @@ const columns = [ method: "DELETE", headers: { "Content-Type": "application/json", - "X-Authorization": JSON.parse( - localStorage.getItem("session") - ), + "X-Authorization": getUserSessionFromLocalStorage(), }, }).catch((err) => { console.error(err); @@ -68,12 +73,7 @@ export default function UserProfile() { items.push({ key: session.IdForDeletion, userAgent: session.UserAgent, - connectionStatus: - session.ConnectionStatus === 0 ? ( - - ) : ( - - ), + connectionStatus: getConnectionStatusItem(session.ConnectionStatus), lastUsed: FormatDatetime(session.LastUsed), expiresAt: FormatDatetime(session.ExpiresAt), }); @@ -82,8 +82,60 @@ export default function UserProfile() { return items; }; + const beforeUpload = (file) => { + if (file.size > Constants.MAX_AVATAR_SIZE) { + message.error( + `Image must be smaller than ${ + Constants.MAX_AVATAR_SIZE / 1024 / 1024 + } MB` + ); + return false; + } + return true; + }; + return ( <> +

Your Profile

+ + + + user.Id === webSocketContext.User.Id + )?.Avatar + } + avatarWidth={200} + /> + + +
+ + + + + + + + + +
+
+ +
+

Your Sessions ({webSocketContext.User.Sessions.length})

diff --git a/src/Pages/Users/index.js b/src/Pages/Users/index.js index c55a187..54f7966 100644 --- a/src/Pages/Users/index.js +++ b/src/Pages/Users/index.js @@ -1,5 +1,73 @@ -import { Button } from "antd"; +import { Popover, Table } from "antd"; +import { + MyAvatar, + WebSocketContext, + getConnectionStatusItem, +} from "../../utils"; +import { useContext } from "react"; + +const columns = [ + { + title: "Avatar", + dataIndex: "avatar", + key: "avatar", + }, + { + title: "Username", + dataIndex: "username", + key: "username", + }, + { + title: "Connection status", + dataIndex: "connectionStatus", + key: "connectionStatus", + }, + { + title: "Last online", + dataIndex: "lastOnline", + key: "lastOnline", + }, +]; export default function Users() { - return ; + const webSocketContext = useContext(WebSocketContext); + + const getTableItems = () => { + let items = []; + + webSocketContext.AllUsers.sort( + (a, b) => b.ConnectionStatus - a.ConnectionStatus + ); + + webSocketContext.AllUsers.forEach((user) => { + items.push({ + key: user.Id, + avatar: ( + } + > + <> + + + + ), + connectionStatus: getConnectionStatusItem(user.ConnectionStatus), + username: user.Username, + }); + }); + + return items; + }; + + return ( + <> +

+ All users ({webSocketContext.AllUsers.length}) +

+ + + + ); } diff --git a/src/utils.js b/src/utils.js index 1284fe7..d47ba0b 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,3 +1,5 @@ +import { UserOutlined } from "@ant-design/icons"; +import { Avatar, Badge } from "antd"; import { createContext, useEffect, useRef, useState } from "react"; import { useNavigate } from "react-router-dom"; @@ -12,6 +14,7 @@ export const Constants = { }, TEXT_EMPTY_PLACEHOLDER: "-/-", API_ADDRESS: "http://localhost:8080/v1", + STATIC_CONTENT_ADDRESS: "http://localhost:8080/", WS_ADDRESS: "ws://localhost:8080/ws", ROUTE_PATHS: { GROUP_TASKS: "/group-tasks", @@ -30,6 +33,8 @@ export const Constants = { MIN_PASSWORD_LENGTH: 6, MAX_PASSWORD_LENGTH: 64, }, + MAX_AVATAR_SIZE: 5 * 1024 * 1024, + ACCEPTED_FILE_TYPES: ["image/png", "image/jpeg", "image/jpg"], }; /** @@ -37,7 +42,7 @@ export const Constants = { */ export function UseUserSession() { const getUserSession = () => { - return JSON.parse(localStorage.getItem("session")); + return getUserSessionFromLocalStorage(); }; const [userSession, setUserSession] = useState(getUserSession()); @@ -58,6 +63,10 @@ export function UseUserSession() { }; } +export function getUserSessionFromLocalStorage() { + return JSON.parse(localStorage.getItem("session")); +} + /** * websocket */ @@ -65,10 +74,12 @@ let l = "loading..."; let webSocketContextPreview = { User: { + Id: "", Username: l, Email: l, Sessions: [], }, + AllUsers: [], ConnectionBadgeStatus: "error", ConnectedWebSocketUsersCount: 0, CategoryGroups: [], @@ -89,6 +100,7 @@ const ReceivedMessagesCommands = { ReloadingGroupTasks: 7, GroupTasksReloaded: 8, UpdateUserSessions: 9, + UpdateAllUsersUserAvatar: 10, }; // commands sent to the backend server @@ -112,6 +124,7 @@ export function WebSocketProvider({ const [connectedWebSocketUsersCount, setConnectedWebSocketUsersCount] = useState(0); const [user, setUser] = useState(webSocketContextPreview.User); + const [allUsers, setAllUsers] = useState(webSocketContextPreview.AllUsers); const [categoryGroups, setCategoryGroups] = useState( webSocketContextPreview.CategoryGroups ); @@ -145,12 +158,22 @@ export function WebSocketProvider({ switch (cmd) { case ReceivedMessagesCommands.InitUserSocketConnection: setUser(body.User); + setAllUsers(body.AllUsers); setCategoryGroups(body.CategoryGroups); setGroupTasks(body.GroupTasks); setGroupTasksSteps(body.GroupTasksSteps); break; case ReceivedMessagesCommands.UpdateConnectedUsers: - setConnectedWebSocketUsersCount(body); + setConnectedWebSocketUsersCount(body.WebSocketUsersCount); + setAllUsers((arr) => { + const newArr = [...arr]; + + newArr[ + arr.findIndex((arr1) => arr1.Id === body.UserId) + ].ConnectionStatus = body.ConnectionStatus; + + return newArr; + }); break; case ReceivedMessagesCommands.NewGroupTaskStarted: setGroupTasks((arr) => [...arr, body]); @@ -207,7 +230,17 @@ export function WebSocketProvider({ case ReceivedMessagesCommands.UpdateUserSessions: setUser((arr) => ({ ...arr, Sessions: body })); break; - case ReceivedMessagesCommands.default: + case ReceivedMessagesCommands.UpdateAllUsersUserAvatar: + setAllUsers((arr) => { + const newArr = [...arr]; + + newArr[arr.findIndex((arr1) => arr1.Id === body.UserId)].Avatar = + body.Avatar; + + return newArr; + }); + break; + default: console.error("unknown command", cmd); break; } @@ -257,6 +290,7 @@ export function WebSocketProvider({ CategoryGroups: categoryGroups, GroupTasks: groupTasks, User: user, + AllUsers: allUsers, SendSocketMessage: SendSocketMessage, GroupTasksSteps: groupTasksSteps, setGroupTasksSteps: setGroupTasksSteps, @@ -318,3 +352,22 @@ export function GetDuration(startTime, endTime) { return result.trim(); } + +export function getConnectionStatusItem(connectionStatus) { + return connectionStatus === 0 ? ( + + ) : ( + + ); +} + +export function MyAvatar({ avatarWidth, avatar }) { + return avatar !== undefined && avatar !== "" ? ( + + ) : ( + } /> + ); +}