From 76f82abda30a86d02c1a2e33ca996fafc1ddbcb7 Mon Sep 17 00:00:00 2001 From: sansho88 <sansho88@hotmail.fr> Date: Mon, 23 Oct 2023 21:44:49 +0200 Subject: [PATCH 1/4] Mise a jour en temps reel a chaque fin de match des stats, ainsi que du matchHistory. Tentative de reduction des requetes recu avec les ws a chaque partie mais bizarre. --- front-end/src/app/home/page.tsx | 1 + .../(ben_proto)/DevTools/NavBarDev.tsx | 3 +- front-end/src/components/AvatarComponent.tsx | 1 + .../src/components/LeaderboardComponent.tsx | 29 ++++++++++++++--- .../src/components/MatchHistoryComponent.tsx | 22 ++++++++++--- front-end/src/components/ProfileComponent.tsx | 3 ++ front-end/src/components/StatsComponent.tsx | 20 ++++++++++-- .../src/components/UserListComponent.tsx | 32 ++++++++++--------- 8 files changed, 83 insertions(+), 28 deletions(-) diff --git a/front-end/src/app/home/page.tsx b/front-end/src/app/home/page.tsx index 4c6ae9c2..6176ef26 100644 --- a/front-end/src/app/home/page.tsx +++ b/front-end/src/app/home/page.tsx @@ -18,6 +18,7 @@ export default function ShowHomePage() { router.push("/auth"); else setIsTokenExists(true); + return; }); return ( isTokenExists ? diff --git a/front-end/src/components/(ben_proto)/DevTools/NavBarDev.tsx b/front-end/src/components/(ben_proto)/DevTools/NavBarDev.tsx index 72971ff3..96449e49 100644 --- a/front-end/src/components/(ben_proto)/DevTools/NavBarDev.tsx +++ b/front-end/src/components/(ben_proto)/DevTools/NavBarDev.tsx @@ -8,7 +8,7 @@ import * as apiReq from '@/components/api/ApiReq' export function NavBar({className}: {className: string}) { - const {userContext, setUserContext} = useContext(UserContext); + const {userContext} = useContext(UserContext); const {logged, setLogged} = useContext(LoggedContext); const [isHovered, setIsHovered] = useState(false); const [turnOffAuth, setTurnOffAuth] = useState<boolean>(false); @@ -25,6 +25,7 @@ export function NavBar({className}: {className: string}) { | <div className=' text-violet-700'>{userContext?.nickname}</div> </div>) + return; }, [userContext]) diff --git a/front-end/src/components/AvatarComponent.tsx b/front-end/src/components/AvatarComponent.tsx index bf0124c8..316d44f4 100644 --- a/front-end/src/components/AvatarComponent.tsx +++ b/front-end/src/components/AvatarComponent.tsx @@ -54,6 +54,7 @@ const Avatar: React.FC<avatarProps> = ({path, width, height, playerStatus, isMai useEffect(() => { setStatusColor(getEnumNameByIndex(Colors, playerStatus)); + return; }, [playerStatus]); path = !path ? "/tests/avatar.jpg" : path; diff --git a/front-end/src/components/LeaderboardComponent.tsx b/front-end/src/components/LeaderboardComponent.tsx index f95fd28e..5fccdc7c 100644 --- a/front-end/src/components/LeaderboardComponent.tsx +++ b/front-end/src/components/LeaderboardComponent.tsx @@ -1,15 +1,22 @@ -import React, {useEffect, useState} from "react"; -import {ILeaderboard} from "@/shared/types"; +import React, {useContext, useEffect, useRef, useState} from "react"; +import {EStatus, ILeaderboard, IUser} from "@/shared/types"; import {getApi} from "@/components/api/ApiReq"; import {v4 as uuidv4} from "uuid"; import Profile from "@/components/ProfileComponent"; +import {SocketContextChat, UserContext} from "@/context/globalContext"; const Leaderboard : React.FC = () => { const [leaderboard, setLeaderboard] = useState<ILeaderboard[]>([]); let leaderboardElements: React.JSX.Element[] = []; + const socketChat = useContext(SocketContextChat); + const socketChatRef = useRef(socketChat); + const {userContext} = useContext(UserContext); + let refreshLeaderboard = true; useEffect(() => { - if (leaderboard && leaderboard.length == 0) + if (refreshLeaderboard) + { + //if (leaderboard && leaderboard.length == 0) getApi.getLeaderboard() .then((res) => { setLeaderboard(res.data); @@ -20,12 +27,24 @@ const Leaderboard : React.FC = () => { setLeaderboard(res.data); }) }, 30000); - + refreshLeaderboard = false; return () => { clearInterval(timer); }; - }, ) + } + + }, [refreshLeaderboard] ) + + socketChatRef.current?.on("userUpdate", (data: IUser) => { + if (data.UserID == userContext.UserID && data.status == EStatus.Online) + { + refreshLeaderboard = true; + console.log("refresh leaderboard"); + } + }); + + socketChatRef.current?.off("userUpdate", () => {}); if (leaderboard.length > 0 ){ const rankColorsArray = ["gold", "silver", "sienna"] diff --git a/front-end/src/components/MatchHistoryComponent.tsx b/front-end/src/components/MatchHistoryComponent.tsx index d82326d5..16d3f622 100644 --- a/front-end/src/components/MatchHistoryComponent.tsx +++ b/front-end/src/components/MatchHistoryComponent.tsx @@ -1,8 +1,8 @@ -import React, {useContext, useEffect, useState} from "react"; -import {IMatch, IRelationships} from "@/shared/types"; +import React, {useContext, useEffect, useRef, useState} from "react"; +import {EStatus, IMatch, IRelationships, IUser} from "@/shared/types"; import {getApi} from "@/components/api/ApiReq"; import {v4 as uuidv4} from "uuid"; -import {SelectedUserContext} from "@/context/globalContext"; +import {SelectedUserContext, SocketContextChat} from "@/context/globalContext"; import UserOptions from "@/components/UserOptions"; const MatchHistory : React.FC = () => { @@ -11,6 +11,8 @@ const MatchHistory : React.FC = () => { const [selectedUserRelationships, setSelectedUserRelationships] = useState<IRelationships>({followed:[], blocked:[]}); const [refresh, setRefresh] = useState(false); let matchElements : React.JSX.Element[] = []; + const socketChat = useContext(SocketContextChat); + const socketChatRef = useRef(socketChat); useEffect(() => { if (selectedUserContext) @@ -37,6 +39,15 @@ const MatchHistory : React.FC = () => { } }, [selectedUserContext]) + socketChatRef.current?.on("userUpdate", (data: IUser) => { + if (selectedUserContext && data.UserID == selectedUserContext.UserID && selectedUserContext.status == EStatus.Online) + { + setSelectedUserContext(data); + } + }); + + socketChatRef.current?.off("userUpdate", () => {}); + if (matchesList.length > 0 && matchesList.at(0).ID >= 0){ for (const match of matchesList) { @@ -70,8 +81,9 @@ const MatchHistory : React.FC = () => { <h1>MATCHES HISTORY</h1> {selectedUserContext ? <ul> - <div>{selectedUserContext.nickname}</div> - ({selectedUserContext.login}) <UserOptions user={selectedUserContext} relationships={selectedUserRelationships} setRefresh={setRefresh}/> + {selectedUserContext.nickname} + <span style={{position: "absolute", right: "0"}}>({selectedUserContext.login})</span> + <UserOptions user={selectedUserContext} relationships={selectedUserRelationships} setRefresh={setRefresh}/> <div>{matchElements}</div> </ul> : "No user selected" diff --git a/front-end/src/components/ProfileComponent.tsx b/front-end/src/components/ProfileComponent.tsx index b50daae4..58d36572 100644 --- a/front-end/src/components/ProfileComponent.tsx +++ b/front-end/src/components/ProfileComponent.tsx @@ -31,6 +31,7 @@ const Profile: React.FC<ProfileProps> = ({children, className ,user, avatarSize, useEffect(() => { setStatusColor(getEnumNameByIndex(Colors, user.status)); + return; }, [user.login]); socketChatRef.current?.on("userUpdate", (data: IUser) => { @@ -41,6 +42,8 @@ const Profile: React.FC<ProfileProps> = ({children, className ,user, avatarSize, } }); + socketChatRef.current?.off("userUpdate", () => {}); + useEffect(() => { if (isNicknameUsed && modifiedNick !== user.nickname) { setNickErrMsg("Unavailable"); diff --git a/front-end/src/components/StatsComponent.tsx b/front-end/src/components/StatsComponent.tsx index eb7036d1..e546911b 100644 --- a/front-end/src/components/StatsComponent.tsx +++ b/front-end/src/components/StatsComponent.tsx @@ -1,7 +1,8 @@ -import React, {useEffect, useState} from "react"; +import React, {useContext, useEffect, useRef, useState} from "react"; import {getApi} from "@/components/api/ApiReq"; import {IGameStats, IUser} from "@/shared/types"; import getUserStatsById = getApi.getUserStatsById; +import {SocketContextChat} from "@/context/globalContext"; interface StatsProps { user: IUser; @@ -10,6 +11,8 @@ interface StatsProps { const Stats: React.FC<StatsProps> = ({className, user})=>{ const [stats, setStats] = useState<IGameStats>({nbWin:0, level:-1, rank:0, nbLoose:0, exp: 0}); + const socketChat = useContext(SocketContextChat); + const socketChatRef = useRef(socketChat); useEffect(() => { if (stats.level < 0) @@ -17,10 +20,23 @@ const Stats: React.FC<StatsProps> = ({className, user})=>{ setStats(result.data); }) .catch((error) => console.error("Request for STATS failed: " + error)); + return () => {}; }) + socketChatRef.current?.on("userUpdate", (data: IUser) => { + if (data.UserID == user.UserID && data.status != user.status) + { + getUserStatsById(user.UserID).then((result) => { + setStats(result.data); + }) + .catch((error) => console.error("Request for STATS failed: " + error)); + } + }); + socketChatRef.current?.off("userUpdate", () => {}); + + return ( - <div className={className}> + <div className={className} style={{marginTop: "1ch"}}> <span style={{color: "green", marginInline: "4px", fontFamily: "sans-serif", lineHeight: "1.5em", transition: "1000ms"}}>{" " + stats.nbWin + "🏆 "}</span> <span style={{color: "red", marginInline: "4px", fontFamily: "sans-serif", lineHeight: "1.5em", transition: "1000ms"}}>{" " + stats.nbLoose + " 🏳 "}</span> <span style={{color: "gold", marginInline: "4px", fontFamily: "sans-serif", lineHeight: "1.5em", transition: "1000ms"}}>{" " + stats.rank +" 🎖 "}️</span> diff --git a/front-end/src/components/UserListComponent.tsx b/front-end/src/components/UserListComponent.tsx index 81a886da..62b164e1 100644 --- a/front-end/src/components/UserListComponent.tsx +++ b/front-end/src/components/UserListComponent.tsx @@ -1,4 +1,4 @@ -import React, { use, useEffect, useState} from "react"; +import React, {useEffect, useState} from "react"; import Profile from "@/components/ProfileComponent"; import Button from "@/components/CustomButtonComponent"; import {v4 as uuidv4} from "uuid"; @@ -12,9 +12,9 @@ import { IUser } from "@/shared/types"; interface UserListProps{ avatarSize?: string | undefined; usersList?: string | undefined; - showUserProps?: boolean; adminMode?: boolean channelID?: number; + showUserProps?: boolean; } const UserList : React.FC<UserListProps> = ({className, id, userListIdProperty, avatarSize, showUserProps, usersList, adminMode, channelID}) => { @@ -44,7 +44,7 @@ const UserList : React.FC<UserListProps> = ({className, id, userListIdProperty, { if (subs.length > 0) { for (const user of subs) { - allDiv = allDivPush(allDiv, user, muteList, subs, blocked, undefined); + allDiv = allDivPush(allDiv, user, muteList, subs, blocked, undefined, true); } for (const user of bannedList) { allDiv = allDivPush(allDiv, user.user, muteList, subs, blocked, user.bannedID); @@ -78,25 +78,27 @@ const UserList : React.FC<UserListProps> = ({className, id, userListIdProperty, }) .catch((error) => console.error("[UserList] Impossible to get relationships of actual user: " + error)); } + return; }, [refresh]); const allDivPush = ( - allDiv: React.JSX.Element[], + allDiv: React.JSX.Element[], user: IUser, - muteList: channelsDTO.IMuteEntity[], - follow: IUser[], - blocked: IUser[], - banID?: number) => { + muteList: channelsDTO.IMuteEntity[], + follow: IUser[], + blocked: IUser[], + banID?: number, + showStats?: boolean) => { allDiv.push( <li key={user.login + "List" + uuidv4()}> - <Profile user={user} avatarSize={avatarSize}> - {showUserProps == true && <UserOptions - user={user} - relationships={{followed: follow, blocked:blocked}} - channelID={channelID} - showAdminOptions={adminMode} + <Profile user={user} avatarSize={avatarSize} showStats={showStats}> + {showUserProps == true && <UserOptions + user={user} + relationships={{followed: follow, blocked:blocked}} + channelID={channelID} + showAdminOptions={adminMode} setRefresh={setRefresh} - banID={banID} + banID={banID} muteID={muteList.find(muteUser => muteUser.user.UserID === user.UserID)?.muteID ?? undefined}/>} </Profile> </li> From b1995371284ac4dbc79d53c0012d5ff8319c04ed Mon Sep 17 00:00:00 2001 From: sansho88 <sansho88@hotmail.fr> Date: Wed, 25 Oct 2023 11:48:39 +0200 Subject: [PATCH 2/4] Creation de la popup pour les userAdminOptions --- front-end/src/app/globals.css | 15 ++++++++++ .../src/components/MatchHistoryComponent.tsx | 13 +++++---- front-end/src/components/UserOptions.tsx | 28 ++++++++++++++----- front-end/src/shared/routesApi.ts | 4 +-- 4 files changed, 45 insertions(+), 15 deletions(-) diff --git a/front-end/src/app/globals.css b/front-end/src/app/globals.css index 4506815d..6ab87605 100644 --- a/front-end/src/app/globals.css +++ b/front-end/src/app/globals.css @@ -429,6 +429,21 @@ body { padding-left: 0.4vw; } +#adminOptionsSettings{ + position: absolute; + top: 0; + right: 0; + margin: 0.5em; + padding: 0.5em; + border-radius: 0.5em; + background: rgba(0, 0, 0, 0.27); + border: 2px rgba(0, 0, 0, 0.11); + border-style: inherit ; + box-shadow: 3px 4px 10px rgba(0, 0, 0, 0.27); + border-radius: 8px; + z-index: 1; +} + .game{ display: inline; margin-inline: auto; diff --git a/front-end/src/components/MatchHistoryComponent.tsx b/front-end/src/components/MatchHistoryComponent.tsx index 16d3f622..b88b0dac 100644 --- a/front-end/src/components/MatchHistoryComponent.tsx +++ b/front-end/src/components/MatchHistoryComponent.tsx @@ -26,27 +26,28 @@ const MatchHistory : React.FC = () => { .then((res) => { setSelectedUserRelationships({followed:res.data.followed, blocked:res.data?.blocked}); }); - const timer = setInterval(() => { + /*const timer = setInterval(() => { getApi.getMatchHistoryFromUserId(selectedUserContext.UserID) .then((res) => { setMatchesList(res.data); }) }, 10000); - +*/ return () => { - clearInterval(timer); + //clearInterval(timer); }; } }, [selectedUserContext]) socketChatRef.current?.on("userUpdate", (data: IUser) => { if (selectedUserContext && data.UserID == selectedUserContext.UserID && selectedUserContext.status == EStatus.Online) - { setSelectedUserContext(data); - } }); - socketChatRef.current?.off("userUpdate", () => {}); + socketChatRef.current?.off("userUpdate", (data: IUser) => { + if (selectedUserContext && data.UserID == selectedUserContext.UserID && selectedUserContext.status == EStatus.Online) + setSelectedUserContext(data); + }); if (matchesList.length > 0 && matchesList.at(0).ID >= 0){ diff --git a/front-end/src/components/UserOptions.tsx b/front-end/src/components/UserOptions.tsx index 7e9402d9..d8b3c0f6 100644 --- a/front-end/src/components/UserOptions.tsx +++ b/front-end/src/components/UserOptions.tsx @@ -27,6 +27,7 @@ const UserOptions: React.FC<userOptionsProps> = ({classname, idProperty, user, s const [isWaitingChallenge, setIsWaitingChallenge] = useState<boolean>(false); const [isDurationVisible, setIsDurationVisible] = useState<boolean>(false); const [durType, setDurationType] = useState<typeof DurationType[keyof typeof DurationType]>(DurationType.Ban); + const [showPopupAdmin, setShowPopupAdmin] = useState<boolean>(false); const socketRef = useContext(SocketContextChat) const socketRefGame = useContext(SocketContextGame) @@ -142,6 +143,16 @@ const UserOptions: React.FC<userOptionsProps> = ({classname, idProperty, user, s } } + const adminOptionsSettings = () => { + + return ( + <div id={"adminOptionsSettings"} style={{marginTop:"10px"}}> + <Button image={`/block-message-${muteID === undefined ? "red" : "green"}.svg`} onClick={() => {handleMute()}} alt={"Mute"} margin={"0 5px 0 0"} title={`${muteID != undefined && "Un" || ""}Mute`}/> + <Button image={"/door-red.svg"} onClick={() => {handleKick()}} alt={"Kick"} margin={"0 5px 0 0"} title={"Kick"}/> + <Button image={`/hammer-${banID === undefined ? "red" : "green"}.svg`} onClick={() => {handleBan()}} alt={"Ban"} title={`${banID !== undefined && "Un" || ""}Ban`}/> + </div> + ) + } useEffect(() => { if (socketRefGame){ @@ -166,19 +177,22 @@ const UserOptions: React.FC<userOptionsProps> = ({classname, idProperty, user, s <Button image={"/send-message.svg"} onClick={handleMp} alt={"Send MP"} title={"MP"}/> - {showAdminOptions && - <span style={{float:"right"}}> - <Button image={`/block-message-${muteID === undefined ? "red" : "green"}.svg`} onClick={() => {handleMute()}} alt={"Mute"} margin={"0 5px 0 0"} title={`${muteID != undefined && "Un" || ""}Mute`}/> - <Button image={"/door-red.svg"} onClick={() => {handleKick()}} alt={"Kick"} margin={"0 5px 0 0"} title={"Kick"}/> - <Button image={`/hammer-${banID === undefined ? "red" : "green"}.svg`} onClick={() => {handleBan()}} alt={"Ban"} title={`${banID !== undefined && "Un" || ""}Ban`}/> - </span> - } { !isWaitingChallenge && user.status != EStatus.Offline && <> <Button image={"/sword.svg"} onClick={() => handleChallenge(EGameMod.classic)} alt={"Challenge"} title={"Classic Challenge"}/> <Button image={"/swordGhost.svg"} onClick={() => handleChallenge(EGameMod.ghost)} alt={"Challenge"} title={"Ghost Challenge"}/> </> } + + <Button image={"/joystick.svg"} onClick={() => setShowPopupAdmin(!showPopupAdmin)} alt={"Admin window"} title={"Admin window"}/> + + {showAdminOptions && showPopupAdmin && adminOptionsSettings()} + {/*<span style={{float:"right"}}> + <Button image={`/block-message-${muteID === undefined ? "red" : "green"}.svg`} onClick={() => {handleMute()}} alt={"Mute"} margin={"0 5px 0 0"} title={`${muteID != undefined && "Un" || ""}Mute`}/> + <Button image={"/door-red.svg"} onClick={() => {handleKick()}} alt={"Kick"} margin={"0 5px 0 0"} title={"Kick"}/> + <Button image={`/hammer-${banID === undefined ? "red" : "green"}.svg`} onClick={() => {handleBan()}} alt={"Ban"} title={`${banID !== undefined && "Un" || ""}Ban`}/> + </span>*/} + </span> {isDurationVisible && <PutDuration user={user} diff --git a/front-end/src/shared/routesApi.ts b/front-end/src/shared/routesApi.ts index 3ae3002b..d1839a35 100644 --- a/front-end/src/shared/routesApi.ts +++ b/front-end/src/shared/routesApi.ts @@ -153,10 +153,10 @@ export namespace strRoutes { return `${serverApi}/${routeUsers}/get/Relationships/${targetId}` } export const getUsersAll = () => { - return `${serverApi})${routeUsers}/get/` + return `${serverApi}/${routeUsers}/get/` } export const getUserById = () => { - return `${serverApi})${routeUsers}/get/` + return `${serverApi}/${routeUsers}/get/` } export const getUserByLogin = () => { return `${serverApi}/${routeUsers}/get/` From 0bd81a54c3d0b1c6a7547f8ca22721e64ab7c425 Mon Sep 17 00:00:00 2001 From: sansho88 <sansho88@hotmail.fr> Date: Wed, 25 Oct 2023 16:18:34 +0200 Subject: [PATCH 3/4] Les options admin s affichent en dessous et sont cachees + console.log removed --- front-end/public/slavery-whip.svg | 2 + front-end/src/app/globals.css | 35 +++++++++++++--- .../src/components/UserListComponent.tsx | 1 - front-end/src/components/UserOptions.tsx | 42 ++++++++----------- .../chat/subComponents/PutDuration.tsx | 20 ++++----- 5 files changed, 59 insertions(+), 41 deletions(-) create mode 100644 front-end/public/slavery-whip.svg diff --git a/front-end/public/slavery-whip.svg b/front-end/public/slavery-whip.svg new file mode 100644 index 00000000..a3aacff2 --- /dev/null +++ b/front-end/public/slavery-whip.svg @@ -0,0 +1,2 @@ +<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools --> +<svg width="21px" height="21px" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path fill="goldenrod" d="M375.04 37.43l-35.083 43.386L314.95 37.92l-4.055 46.084c63.786 18.442 66.642 100.816 27.71 132.69l85.49-13.003-43.322-14.56 77.688-45.347-75.374 3.55 61.728-79.298-78.498 35.002 8.725-65.607zM70.296 58.395c-15.223.03-31.116 5.526-48.545 16.935v47.135c43.16-38.49 90.794-21.734 133.76 24.56 23.57 29.96 48.492 64.923 98.338 78.166 37.686 10.014 77.26-8.695 87.326-45.94 3.85-14.245 4.485-29.96.107-44.334-4.376-14.372-14.476-27.512-30.585-33.684h-.002c-10.558-4.044-22.308-4.223-32.888-.554-10.582 3.668-20.198 11.696-24.35 23.586-2.616 7.492-2.486 15.654.41 23.072 2.897 7.42 9.143 14.25 18.01 16.82h.002c5.33 1.544 10.872 1.284 16.1-.896 4.803-2.004 9.515-6.272 11.41-12.166-11.492 10.304-28.43 5.458-28.97-14.328-.205-2.172.02-4.445.68-6.34v-.002c2.117-6.06 6.64-9.944 12.83-12.09 6.188-2.146 13.84-2.04 20.08.35h.003c10.562 4.046 16.314 11.563 19.394 21.677 3.08 10.116 2.78 22.718-.27 34.015-7.294 26.984-35.235 40.528-64.488 32.756-32.45-8.62-52.41-27.42-70.373-48.985l.15-.223C143.74 93.958 109.2 58.32 70.296 58.395zm228.437 90.863l1.01.576c.027-.112.06-.22.086-.332l-1.096-.244zm157.87 64.904c-17.884-.094-38.857 9.058-55.942 26.143-5.313 5.313-9.848 11.004-13.588 16.86-93.743-56.462-329.905 76.312-178.974 189.757l-.002.002H88.78l-26.452 47.74h257.164l-88.478-103.25c24.27-26.708 67.453-43.706 96.996-45.064 13.793 45.097 36.25 113.497 71.734 148.312h60.867c-43.07-46.548-76.537-109.094-81.936-179.85 1.615 3.23 3.692 6.19 6.283 8.782 18.664 18.663 55.953 11.632 83.29-15.703 27.335-27.335 34.364-64.623 15.7-83.286-7-7-16.615-10.385-27.345-10.442z"/></svg> \ No newline at end of file diff --git a/front-end/src/app/globals.css b/front-end/src/app/globals.css index 6ab87605..a94debc0 100644 --- a/front-end/src/app/globals.css +++ b/front-end/src/app/globals.css @@ -195,7 +195,7 @@ body { .friends { position: absolute; top: 5.9px; - right: 0vw; + right: 0; display: flex; flex-direction: row; align-items: center; @@ -430,20 +430,43 @@ body { } #adminOptionsSettings{ - position: absolute; - top: 0; + position: relative; + bottom: 0; right: 0; margin: 0.5em; padding: 0.5em; - border-radius: 0.5em; - background: rgba(0, 0, 0, 0.27); + background: rgba(0, 0, 0, 0.47); border: 2px rgba(0, 0, 0, 0.11); - border-style: inherit ; box-shadow: 3px 4px 10px rgba(0, 0, 0, 0.27); border-radius: 8px; z-index: 1; } +#muteDuration{ + position: relative; + width: 1vw; + bottom: 0; + right: 0; + margin: 0.5em; + padding: 0.5em; + background: rgba(0, 0, 0, 0.47); + border: 2px rgba(0, 0, 0, 0.11); + box-shadow: 3px 4px 10px rgba(0, 0, 0, 0.27); + border-radius: 8px; + z-index: 1; +} + +#muteDuration input{ + background-color: #2d3748; + padding: 0.5rem; + border-radius: 0.5rem; + color: #f56565; + height: 1rem; + text-align: center; + outline:inset; + width:42% +} + .game{ display: inline; margin-inline: auto; diff --git a/front-end/src/components/UserListComponent.tsx b/front-end/src/components/UserListComponent.tsx index 9bfdb0c4..77ac9972 100644 --- a/front-end/src/components/UserListComponent.tsx +++ b/front-end/src/components/UserListComponent.tsx @@ -130,7 +130,6 @@ const UserList : React.FC<UserListProps> = ({ banID={banID} muteID={muteList.find(muteUser => muteUser.user.UserID === user.UserID)?.muteID ?? undefined} adminID={userAdmin?.UserID ?? undefined} - isOwner={isOwner} />} </Profile> </li> diff --git a/front-end/src/components/UserOptions.tsx b/front-end/src/components/UserOptions.tsx index 44c7bb90..055ca580 100644 --- a/front-end/src/components/UserOptions.tsx +++ b/front-end/src/components/UserOptions.tsx @@ -18,11 +18,10 @@ export interface userOptionsProps { banID?: number; muteID?: number; adminID?: number; - isOwner?: boolean; setRefresh: React.Dispatch<React.SetStateAction<boolean>>; } -const UserOptions: React.FC<userOptionsProps> = ({classname, idProperty, user, showAdminOptions, relationships, channelID, setRefresh, banID, muteID, adminID, isOwner}) => { +const UserOptions: React.FC<userOptionsProps> = ({classname, idProperty, user, showAdminOptions, relationships, channelID, setRefresh, banID, muteID, adminID}) => { const {userContext} = useContext(UserContext); const [isFollowed, setIsFollowed] = useState(relationships.followed && !!relationships.followed.find(tmpUser => user.UserID === tmpUser.UserID)); const [isBlocked, setIsBlocked] = useState(relationships.blocked && !!relationships.blocked.find(tmpUser => user.UserID == tmpUser.UserID)); @@ -98,19 +97,19 @@ const UserOptions: React.FC<userOptionsProps> = ({classname, idProperty, user, s } function handleKick() { - if (!showAdminOptions || channelID === undefined) return console.log('NO RIGHTS TO DO THIS ACTION'); + if (!showAdminOptions || channelID === undefined) return NotificationManager.error(`You can\'t kick ${user.nickname} (${user.login})`); apiReq.putApi.putKickUser(channelID, user.UserID) .then(() => { - console.log('KICK SUCCESS') + NotificationManager.success(`You kicked ${user.nickname} (${user.login})`); setRefresh(true); }) .catch(() => { - console.log('KICK FAILED') + NotificationManager.error(`You can\'t kick ${user.nickname} (${user.login})`); }) } function handleBan() { - if (!showAdminOptions || channelID === undefined) return console.log('NO RIGHTS TO DO THIS ACTION'); + if (!showAdminOptions || channelID === undefined) return NotificationManager.error(`You can\'t ban ${user.nickname} (${user.login})`); if (banID === undefined) { setDurationType(DurationType.Ban); setIsDurationVisible(!isDurationVisible); @@ -118,17 +117,17 @@ const UserOptions: React.FC<userOptionsProps> = ({classname, idProperty, user, s else { apiReq.putApi.putUnbanUser(banID) .then(() => { - console.log('UNBAN SUCCESS') + NotificationManager.success(`You unbanned ${user.nickname} (${user.login})`); setRefresh(true); }) .catch(() => { - console.log('UNBAN FAILED') + NotificationManager.error(`You can\'t unban ${user.nickname} (${user.login})`); }) } } function handleMute() { - if (!showAdminOptions || channelID === undefined) return console.log('NO RIGHTS TO DO THIS ACTION'); + if (!showAdminOptions || channelID === undefined) return NotificationManager.error(`You can\'t mute ${user.nickname} (${user.login})`); if (muteID === undefined) { setDurationType(DurationType.Mute); setIsDurationVisible(!isDurationVisible); @@ -136,17 +135,16 @@ const UserOptions: React.FC<userOptionsProps> = ({classname, idProperty, user, s else { apiReq.putApi.putUnmuteUser(muteID ? muteID : -1) .then(() => { - console.log('UNMUTE SUCCESS') + NotificationManager.success(`You unmuted ${user.nickname} (${user.login})`); setRefresh(true); }) .catch(() => { - console.log('UNMUTE FAILED') + NotificationManager.error(`You can\'t unmute ${user.nickname} (${user.login})`); }) } } const adminOptionsSettings = () => { - return ( <div id={"adminOptionsSettings"} style={{marginTop:"10px"}}> <Button image={`/block-message-${muteID === undefined ? "red" : "green"}.svg`} onClick={() => {handleMute()}} alt={"Mute"} margin={"0 5px 0 0"} title={`${muteID != undefined && "Un" || ""}Mute`}/> @@ -157,25 +155,25 @@ const UserOptions: React.FC<userOptionsProps> = ({classname, idProperty, user, s ) } function handleGrant() { - if (!showAdminOptions || channelID === undefined) return console.log('NO RIGHTS TO DO THIS ACTION'); + if (!showAdminOptions || channelID === undefined) return NotificationManager.error(`You can\'t grant ${user.nickname} (${user.login})`); if (adminID === undefined) { apiReq.putApi.putGrantAdmin(channelID, user.UserID) .then(() => { - console.log('GRANT SUCCESS') + NotificationManager.success(`You granted ${user.nickname} (${user.login})`); setRefresh(true); }) .catch(() => { - console.log('GRANT FAILED') + NotificationManager.error(`You can\'t grant ${user.nickname} (${user.login})`); }) } else { apiReq.putApi.putRevokeAdmin(channelID, user.UserID) //adminID === user.UserID .then(() => { - console.log('REVOKE SUCCESS') + NotificationManager.success(`You revoked ${user.nickname} (${user.login})`); setRefresh(true); }) .catch(() => { - console.log('REVOKE FAILED') + NotificationManager.error(`You can\'t revoke ${user.nickname} (${user.login})`); }) } } @@ -211,21 +209,17 @@ const UserOptions: React.FC<userOptionsProps> = ({classname, idProperty, user, s </> } - <Button image={"/joystick.svg"} onClick={() => setShowPopupAdmin(!showPopupAdmin)} alt={"Admin window"} title={"Admin window"}/> + {showAdminOptions && <Button image={"/slavery-whip.svg"} onClick={() => setShowPopupAdmin(!showPopupAdmin)} alt={"Admin window"} title={"Admin window"}/>} {showAdminOptions && showPopupAdmin && adminOptionsSettings()} - {/*<span style={{float:"right"}}> - <Button image={`/block-message-${muteID === undefined ? "red" : "green"}.svg`} onClick={() => {handleMute()}} alt={"Mute"} margin={"0 5px 0 0"} title={`${muteID != undefined && "Un" || ""}Mute`}/> - <Button image={"/door-red.svg"} onClick={() => {handleKick()}} alt={"Kick"} margin={"0 5px 0 0"} title={"Kick"}/> - <Button image={`/hammer-${banID === undefined ? "red" : "green"}.svg`} onClick={() => {handleBan()}} alt={"Ban"} title={`${banID !== undefined && "Un" || ""}Ban`}/> - </span>*/} + </span> {isDurationVisible && <PutDuration user={user} channelID={channelID} handleType={durType} - isVisible={isDurationVisible} + isVisible={isDurationVisible && showPopupAdmin} setDurationType={setDurationType} setIsDurationVisible={setIsDurationVisible} setRefresh={setRefresh} diff --git a/front-end/src/components/chat/subComponents/PutDuration.tsx b/front-end/src/components/chat/subComponents/PutDuration.tsx index f8304250..e2224409 100644 --- a/front-end/src/components/chat/subComponents/PutDuration.tsx +++ b/front-end/src/components/chat/subComponents/PutDuration.tsx @@ -2,8 +2,9 @@ import { IUser } from "@/shared/types"; import Image from "next/image"; import * as apiReq from '@/components/api/ApiReq' import React, { useState } from "react"; -import { text } from "stream/consumers"; import { inherits } from "util"; +import {NotificationManager} from 'react-notifications'; + export const DurationType = { none: 0, @@ -37,21 +38,21 @@ const PutDuration: React.FC<PutDurationProps> = ({ user, channelID, handleType, if (handleType === DurationType.Ban) { apiReq.putApi.putBanUser(channelID, user.UserID, duration * 60) .then(() => { - console.log('BAN SUCCESS') + NotificationManager.success(`You banned ${user.nickname} (${user.login}) for ${duration} minutes.`); setRefresh(true); }) .catch(() => { - console.log('BAN FAILED') + NotificationManager.error(`You can\'t ban ${user.nickname} (${user.login})`); }) } else if (handleType === DurationType.Mute) { apiReq.putApi.putMuteUser(channelID, user.UserID, duration* 60) .then(() => { - console.log('MUTE SUCCESS') + NotificationManager.success(`You muted ${user.nickname} (${user.login}) for ${duration} minutes.`); setRefresh(true); }) .catch(() => { - console.log('MUTE FAILED') + NotificationManager.error(`You can\'t mute ${user.nickname} (${user.login})`); }) } setDurationType(DurationType.none); @@ -59,17 +60,16 @@ const PutDuration: React.FC<PutDurationProps> = ({ user, channelID, handleType, } return ( - <div> + <> {isVisible && ( - <div className="flex flex-col justify-center items-center text-white" style={{minWidth:"fit-content"}}> - <label htmlFor="duration">Duration (in minutes)<h6>0 for infinit</h6></label> + <div id="muteDuration" style={{minWidth:"fit-content"}}> + <label htmlFor="duration">Duration (in minutes)<h6>0 for infinite</h6></label> <input type="number" name="duration" id="duration" placeholder="duration in minutes" value={duration} - style={{backgroundColor: "#2d3748", padding: "0.5rem", borderRadius: "0.5rem", color: "#f56565", height: "1rem", textAlign: "center", outline:"inset", width:"100%"}} onChange={(e) => changeDuration(e)} /> {isVisible && (<button onClick={handleDuration} style={{ verticalAlign: "-webkit-baseline-middle" }}> @@ -83,7 +83,7 @@ const PutDuration: React.FC<PutDurationProps> = ({ user, channelID, handleType, </button>)} </div> )} - </div> + </> ); } From 233b56e1ca70dc94f48804fac46debf715fcc9bb Mon Sep 17 00:00:00 2001 From: sansho88 <sansho88@hotmail.fr> Date: Wed, 25 Oct 2023 16:23:49 +0200 Subject: [PATCH 4/4] SUPPRESSION DE LA NAVBAR (RIP) --- front-end/src/app/layout.tsx | 2 - .../(ben_proto)/DevTools/NavBarDev.tsx | 146 ------------------ 2 files changed, 148 deletions(-) delete mode 100644 front-end/src/components/(ben_proto)/DevTools/NavBarDev.tsx diff --git a/front-end/src/app/layout.tsx b/front-end/src/app/layout.tsx index e035accf..8c1f1834 100644 --- a/front-end/src/app/layout.tsx +++ b/front-end/src/app/layout.tsx @@ -1,5 +1,4 @@ import { Providers } from "@/context/providers"; -import { NavBar } from '@/components/(ben_proto)/DevTools/NavBarDev' import './globals.css' import { Inter } from 'next/font/google' @@ -24,7 +23,6 @@ export default function RootLayout({ {/* <div className='main-background'> */} <Providers> {children} - <NavBar className='absolute bottom-0 right-0 w-screen bg-slate-800' /> </Providers> </div> </body> diff --git a/front-end/src/components/(ben_proto)/DevTools/NavBarDev.tsx b/front-end/src/components/(ben_proto)/DevTools/NavBarDev.tsx deleted file mode 100644 index 96449e49..00000000 --- a/front-end/src/components/(ben_proto)/DevTools/NavBarDev.tsx +++ /dev/null @@ -1,146 +0,0 @@ -'use client' -import Link from 'next/link' -import React, {useState, useContext, useEffect, } from 'react' -import {UserContext, LoggedContext} from "@/context/globalContext"; -import * as apiReq from '@/components/api/ApiReq' - - - -export function NavBar({className}: {className: string}) { - - const {userContext} = useContext(UserContext); - const {logged, setLogged} = useContext(LoggedContext); - const [isHovered, setIsHovered] = useState(false); - const [turnOffAuth, setTurnOffAuth] = useState<boolean>(false); - // const [isHovered, setIsHovered] = useState(false); - - const [infoUser, setInfoUser] = useState<JSX.Element>(<></>) - - useEffect(() => { - setInfoUser( - <div className='flex'>id: - <div className=' text-red-700'>{userContext?.UserID}</div> - | - <div className=' text-green-700'>{userContext?.login}</div> - | - <div className=' text-violet-700'>{userContext?.nickname}</div> - </div>) - return; - }, [userContext]) - - - const handleMouseEnter = () => { - setIsHovered(true); - } - - const handleMouseLeave = () => { - setIsHovered(false); - } - - - function Dropdown() { - const [isOpen, setIsOpen] = useState(false); - - return ( - <div className="relative inline-block text-left"> - <div> - <button type="button" - className="inline-flex justify-center w-full rounded-md border border-gray-300 shadow-sm px-4 py-2 text-sm font-medium text-red-500 - hover: focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-indigo-500" - id="options-menu" - aria-haspopup="true" - aria-expanded="true" - onClick={() => setIsOpen(!isOpen)}> - EasyReqSQL - <svg className="-mr-1 ml-2 h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"> - <path fillRule="evenodd" d="M5 5a1 1 0 011.707-.707l4.586 4.586a1 1 0 010 1.414l-4.586 4.586A1 1 0 015 14V5z" clipRule="evenodd" /> - </svg> - </button> - </div> - {isOpen && ( - <div className="origin-bottom-right absolute right-0 bottom-full w-50 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5"> - <div className="py-1" role="menu" aria-orientation="vertical" aria-labelledby="options-menu"> - <button onClick={() => apiReq.deleteApi.deleteUsersAll()} className="block px-4 py-2 text-sm text-red-500 hover:bg-gray-100 hover:text-red-900" role="menuitem">DELETE ALL USERS</button> - </div> - </div> - )} - </div> - ); -} - - - - -function toggleAuthRequired() { - if (turnOffAuth) - { - setLogged(false); - setTurnOffAuth(false); - } - else - { - setLogged(true); - setTurnOffAuth(true); - } -} - - function SubNav() { - - return ( - <> - {/* <Link href="/home">HOME</Link> */} - {/* <Link href="/chat">CHAT v2</Link> */} - {/* <Link href="/proto/chat">CHATROOM</Link> */} - {/* <Link href={`/profile/${userContext?.login}`}>PROFILE</Link> */} - {/* <Link href="/auth">AUTH</Link> */} - {/* <Dropdown/> */} - {infoUser} - {/* <button onClick={() => {setLogged(false);localStorage.removeItem("login");}}> DISCONNECT </button> */} - </> - ) - } - - - function SubNavNotLog() { - - return ( - <> - {/* <Link href="/">HOME</Link> */} - {/* <Link href="/auth">AUTH LOGIN</Link> */} - <Dropdown/> - {/* <button onClick={toggleAuthRequired} >{turnOffAuth ? <>ON</> : <>OFF</>}</button> */} - {/* <Link href="/login">OLD LOGIN</Link> */} - <div className=' text-red-500'>user:(not logged)</div> - </> - ) - } - - - return ( - <> - <div - onMouseEnter={handleMouseEnter} - onMouseLeave={handleMouseLeave} - > - {!isHovered ? ( - <div className='absolute bottom-0 left-[48vw] w-auto rounded-t-xl px-2 bg-slate-800 opacity-40'> - <div className="h-10 flex justify-center items-center space-x-10"> - <button onClick={() => setIsHovered(false)} className=' text-white'> devbar </button> - </div> - </div> - ) : ( - <div className={className}> - <div className=" text-white h-10 flex justify-center items-center space-x-10"> - <div className=" text-red-600 absolute left-5">Navbar Dev </div> - {logged ? <SubNav /> : - // <SubNavNotLog /> - <SubNav /> - } - <button onClick={() => setIsHovered(false)}> ❌ </button> - </div> - </div> - )} - </div> - </> - ); -} \ No newline at end of file