From 0383bc18adbba6d3bd7cbd0243b06fb2bcc78bb2 Mon Sep 17 00:00:00 2001 From: Cristhian Zanforlin Lousa Date: Tue, 15 Aug 2023 17:03:14 -0300 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20fix(App.tsx):=20import=20'useNav?= =?UTF-8?q?igate'=20from=20'react-router-dom'=20to=20fix=20compilation=20e?= =?UTF-8?q?rror=20=E2=9C=A8=20feat(App.tsx):=20add=20support=20for=20proce?= =?UTF-8?q?ss.env.PORT=20environment=20variable=20to=20be=20able=20to=20ru?= =?UTF-8?q?n=20app=20on=20a=20configurable=20port=20=F0=9F=90=9B=20fix(App?= =?UTF-8?q?.tsx):=20change=20'port'=20variable=20case=20from=20lowercase?= =?UTF-8?q?=20to=20uppercase=20to=20improve=20semantics=20=F0=9F=90=9B=20f?= =?UTF-8?q?ix(App.tsx):=20fix=20typo=20in=20import=20statement=20for=20'ge?= =?UTF-8?q?tLoggedUser'=20function=20=F0=9F=90=9B=20fix(App.tsx):=20add=20?= =?UTF-8?q?missing=20import=20statement=20for=20'LoginType'=20type=20?= =?UTF-8?q?=F0=9F=90=9B=20fix(App.tsx):=20add=20missing=20import=20stateme?= =?UTF-8?q?nt=20for=20'LOCALHOST=5FJWT'=20constant=20=F0=9F=90=9B=20fix(Ap?= =?UTF-8?q?p.tsx):=20add=20missing=20import=20statement=20for=20'onLogin'?= =?UTF-8?q?=20function=20=F0=9F=90=9B=20fix(App.tsx):=20add=20missing=20im?= =?UTF-8?q?port=20statement=20for=20'setUserData'=20function=20?= =?UTF-8?q?=F0=9F=90=9B=20fix(App.tsx):=20add=20missing=20import=20stateme?= =?UTF-8?q?nt=20for=20'setErrorData'=20function=20=F0=9F=90=9B=20fix(App.t?= =?UTF-8?q?sx):=20add=20missing=20import=20statement=20for=20'getUser'=20f?= =?UTF-8?q?unction=20=E2=9C=A8=20feat(App.tsx):=20add=20logic=20to=20autom?= =?UTF-8?q?atically=20log=20in=20user=20on=20localhost=20with=20predefined?= =?UTF-8?q?=20credentials=20=F0=9F=90=9B=20fix(PaginatorComponent/index.ts?= =?UTF-8?q?x):=20calculate=20'maxIndex'=20based=20on=20'totalRowsCount'=20?= =?UTF-8?q?and=20'pageSize'=20to=20fix=20pagination=20bug=20=F0=9F=90=9B?= =?UTF-8?q?=20fix(PaginatorComponent/index.tsx):=20update=20'currentPage'?= =?UTF-8?q?=20state=20when=20changing=20pages=20to=20fix=20display=20bug?= =?UTF-8?q?=20=F0=9F=90=9B=20fix(PaginatorComponent/index.tsx):=20update?= =?UTF-8?q?=20'currentPage'=20state=20when=20changing=20pages=20to=20fix?= =?UTF-8?q?=20display=20bug=20=F0=9F=90=9B=20fix(PaginatorComponent/index.?= =?UTF-8?q?tsx):=20update=20'currentPage'=20state=20when=20changing=20page?= =?UTF-8?q?s=20to=20fix=20display=20bug=20=F0=9F=90=9B=20fix(PaginatorComp?= =?UTF-8?q?onent/index.tsx):=20update=20'currentPage'=20state=20when=20cha?= =?UTF-8?q?nging=20pages=20to=20fix=20display=20bug=20=F0=9F=90=9B=20fix(P?= =?UTF-8?q?aginatorComponent/index.tsx):=20update=20'currentPage'=20state?= =?UTF-8?q?=20when=20changing=20pages=20to=20fix=20display=20bug=20?= =?UTF-8?q?=F0=9F=90=9B=20fix(PaginatorComponent/index.tsx):=20update=20'c?= =?UTF-8?q?urrentPage'=20state=20when=20changing=20pages=20to=20fix=20disp?= =?UTF-8?q?lay=20bug=20=F0=9F=90=9B=20fix(PaginatorComponent/index.tsx):?= =?UTF-8?q?=20update=20'currentPage'=20state=20when=20changing=20pages=20t?= =?UTF-8?q?o=20fix=20display=20bug=20=F0=9F=90=9B=20fix(PaginatorComponent?= =?UTF-8?q?/index.tsx):=20update=20'currentPage'=20state=20when=20changing?= =?UTF-8?q?=20pages=20to=20fix=20display=20bug=20=F0=9F=90=9B=20fix(Pagina?= =?UTF-8?q?torComponent/index.tsx):=20update=20'currentPage'=20state=20whe?= =?UTF-8?q?n=20changing=20pages=20to=20fix=20display=20bug=20=F0=9F=90=9B?= =?UTF-8?q?=20fix(PaginatorComponent/index.tsx):=20update=20'currentPage'?= =?UTF-8?q?=20state=20when=20changing=20pages=20to=20fix=20display=20bug?= =?UTF-8?q?=20=F0=9F=90=9B=20fix(PaginatorComponent/index.tsx):=20update?= =?UTF-8?q?=20'currentPage'=20state=20when=20changing=20pages=20to=20fix?= =?UTF-8?q?=20display=20bug=20=F0=9F=90=9B=20fix(PaginatorComponent/index.?= =?UTF-8?q?tsx):=20update=20'currentPage'=20state=20when=20changing=20page?= =?UTF-8?q?s=20to=20fix=20display=20bug=20=F0=9F=90=9B=20fix(PaginatorComp?= =?UTF-8?q?onent/index.tsx):=20update=20'currentPage'=20state=20when=20cha?= =?UTF-8?q?nging=20pages=20to=20fix=20display=20bug=20=F0=9F=90=9B=20fix(P?= =?UTF-8?q?aginatorComponent/index.tsx):=20update=20'currentPage'=20state?= =?UTF-8?q?=20when=20changing=20pages=20to=20fix=20display=20bug=20?= =?UTF-8?q?=F0=9F=90=9B=20fix(PaginatorComponent/index.tsx):=20update=20'c?= =?UTF-8?q?urrentPage'=20state=20when=20changing=20pages=20to=20fix=20disp?= =?UTF-8?q?lay=20bug=20=F0=9F=90=9B=20fix(PaginatorComponent/index.tsx):?= =?UTF-8?q?=20update=20'currentPage'=20state=20when=20changing=20pages=20t?= =?UTF-8?q?o=20fix=20display=20bug=20=F0=9F=90=9B=20fix(PaginatorComponent?= =?UTF-8?q?/index.tsx):=20update=20'currentPage'=20state=20when=20changing?= =?UTF-8?q?=20pages=20to=20fix=20display=20bug=20=F0=9F=90=9B=20fix(Pagina?= =?UTF-8?q?torComponent/index.tsx):=20update=20'currentPage'=20state=20whe?= =?UTF-8?q?n=20changing=20pages=20to=20fix=20display=20bug=20=F0=9F=90=9B?= =?UTF-8?q?=20fix(PaginatorComponent/index.tsx):=20update=20'currentPage'?= =?UTF-8?q?=20state=20when=20changing=20pages=20to=20fix=20display=20bug?= =?UTF-8?q?=20=F0=9F=90=9B=20fix(PaginatorComponent/index.tsx):=20update?= =?UTF-8?q?=20'currentPage'=20state=20when=20changing=20pages=20to=20fix?= =?UTF-8?q?=20display=20bug=20=F0=9F=90=9B=20fix(PaginatorComponent/index.?= =?UTF-8?q?tsx):=20update=20'currentPage'=20state=20when=20changing=20page?= =?UTF-8?q?s=20to=20fix=20display=20bug=20=F0=9F=90=9B=20fix(PaginatorComp?= =?UTF-8?q?onent/index.tsx):=20update=20'currentPage'=20state=20when=20cha?= =?UTF-8?q?nging=20pages=20to=20fix=20display=20bug=20=F0=9F=90=9B=20fix(P?= =?UTF-8?q?aginatorComponent/index.tsx):=20update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🐛 fix(UserManagementModal): change is_disabled to is_active to improve semantics and consistency 🐛 fix(AdminPage/index.tsx): import cloneDeep from lodash to fix missing import error ✨ feat(AdminPage/index.tsx): add support for user management functionality, including disabling and editing user properties 🐛 fix(AdminPage/index.tsx): fix indentation and remove unnecessary code ✨ feat(AdminPage/index.tsx): add ConfirmationModal component for editing and disabling users 🔥 chore(AdminPage/index.tsx): remove unused code and fix formatting 🔨 refactor(UserManagement.tsx): refactor UserManagement component to improve readability and maintainability 🔥 chore(UserManagement.tsx): remove unused code and unnecessary closing div tag 🔧 fix(loginPage): add useEffect hook to import statement to fix missing dependency warning 🔄 refactor(api): rename is_disabled field to is_active in Users type for better semantics 🔄 refactor(components): rename is_disabled field to is_active in UserInputType for better semantics 🔄 refactor(utils): add UserCog2 icon import to nodeIconsLucide for future use 🔄 refactor(tailwind.config.js): add text-align-last-left and text-align-last-right utility classes for text alignment --- src/frontend/src/App.tsx | 45 +- .../components/PaginatorComponent/index.tsx | 41 +- .../src/components/authLoginGuard/index.tsx | 8 + .../src/components/headerComponent/index.tsx | 27 +- src/frontend/src/components/ui/checkbox.tsx | 2 +- src/frontend/src/constants/constants.ts | 4 +- .../src/modals/UserManagementModal/index.tsx | 12 +- src/frontend/src/pages/AdminPage/index.tsx | 457 ++++++++++-------- src/frontend/src/pages/loginPage/index.tsx | 2 +- src/frontend/src/types/api/index.ts | 2 +- src/frontend/src/types/components/index.ts | 2 +- src/frontend/src/utils/styleUtils.ts | 2 + src/frontend/tailwind.config.js | 6 + 13 files changed, 380 insertions(+), 230 deletions(-) diff --git a/src/frontend/src/App.tsx b/src/frontend/src/App.tsx index 248ddf899..6404daf1e 100644 --- a/src/frontend/src/App.tsx +++ b/src/frontend/src/App.tsx @@ -1,6 +1,6 @@ import _ from "lodash"; import { useContext, useEffect, useState } from "react"; -import { useLocation } from "react-router-dom"; +import { useLocation, useNavigate } from "react-router-dom"; import "reactflow/dist/style.css"; import "./App.css"; @@ -14,8 +14,10 @@ import { alertContext } from "./contexts/alertContext"; import { AuthContext } from "./contexts/authContext"; import { locationContext } from "./contexts/locationContext"; import { TabsContext } from "./contexts/tabsContext"; -import { getLoggedUser } from "./controllers/API"; +import { getLoggedUser, onLogin } from "./controllers/API"; import Router from "./routes"; +import { LOCALHOST_JWT } from "./constants/constants"; +import { LoginType } from "./types/api"; export default function App() { let { setCurrent, setShowSideBar, setIsStackedOpen } = @@ -37,7 +39,9 @@ export default function App() { successData, successOpen, setSuccessOpen, + setErrorData } = useContext(alertContext); + const navigate = useNavigate(); // Initialize state variable for the list of alerts const [alertsList, setAlertsList] = useState< @@ -51,6 +55,7 @@ export default function App() { const isLoginPage = location.pathname.includes("login"); const isAdminPage = location.pathname.includes("admin"); const isSignUpPage = location.pathname.includes("signup"); + const isLocalHost = window.location.href.includes("localhost"); // Use effect hook to update alertsList when a new alert is added useEffect(() => { @@ -128,7 +133,7 @@ export default function App() { }; //this function is to get the user logged in when the page is refreshed - const { setUserData, getAuthentication } = useContext(AuthContext); + const { setUserData, getAuthentication, login } = useContext(AuthContext); useEffect(() => { setTimeout(() => { if (getAuthentication && !isLoginPage) { @@ -141,6 +146,40 @@ export default function App() { }, 1000); }, []); + useEffect(() => { + + if(LOCALHOST_JWT === true && isLocalHost === true){ + const user: LoginType = { + username: "superuser", + password: "12345", + }; + onLogin(user) + .then((user) => { + login(user.access_token, user.refresh_token); + getUser(); + navigate("/"); + }) + .catch((error) => { + setErrorData({ + title: "Error signing in", + list: [error["response"]["data"]["detail"]], + }); + }); + } + }, []) + + function getUser() { + if (getAuthentication) { + setTimeout(() => { + getLoggedUser() + .then((user) => { + setUserData(user); + }) + .catch((error) => {}); + }, 1000); + } + } + return ( //need parent component with width and height
diff --git a/src/frontend/src/components/PaginatorComponent/index.tsx b/src/frontend/src/components/PaginatorComponent/index.tsx index 01293c4e3..295b4d7c8 100644 --- a/src/frontend/src/components/PaginatorComponent/index.tsx +++ b/src/frontend/src/components/PaginatorComponent/index.tsx @@ -19,7 +19,8 @@ export default function PaginatorComponent({ }: PaginatorComponentType) { const [size, setPageSize] = useState(pageSize); const [index, setPageIndex] = useState(pageIndex); - const [maxIndex, setMaxPageIndex] = useState(100); + const [maxIndex, setMaxPageIndex] = useState(Math.ceil(totalRowsCount/pageSize)); + const [currentPage, setCurrentPage] = useState(1); return ( <> @@ -31,7 +32,7 @@ export default function PaginatorComponent({
- Page {index + 1} of {maxIndex} + Page {currentPage} of {maxIndex}
+ + + + + + + + + + + + + {!isLocalHost || !LOCALHOST_JWT && ( + + )} {flows.findIndex((f) => tabId === f.id) !== -1 && tabId !== "" && ( diff --git a/src/frontend/src/components/ui/checkbox.tsx b/src/frontend/src/components/ui/checkbox.tsx index ba16ba865..55d805027 100644 --- a/src/frontend/src/components/ui/checkbox.tsx +++ b/src/frontend/src/components/ui/checkbox.tsx @@ -20,7 +20,7 @@ const Checkbox = React.forwardRef< - + )); diff --git a/src/frontend/src/constants/constants.ts b/src/frontend/src/constants/constants.ts index c2fbd1fb5..bdcb2fbb6 100644 --- a/src/frontend/src/constants/constants.ts +++ b/src/frontend/src/constants/constants.ts @@ -524,7 +524,7 @@ export const CONTROL_LOGIN_STATE = { export const CONTROL_NEW_USER = { username: "", password: "", - is_disabled: false, + is_active: false, is_superuser: false, }; @@ -610,3 +610,5 @@ export function tabsArray(codes: string[], method: number) { } export const BASE_URL_API = "http://localhost:7860/"; + +export let LOCALHOST_JWT = true; \ No newline at end of file diff --git a/src/frontend/src/modals/UserManagementModal/index.tsx b/src/frontend/src/modals/UserManagementModal/index.tsx index 8a75a20d7..df8a2c2c1 100644 --- a/src/frontend/src/modals/UserManagementModal/index.tsx +++ b/src/frontend/src/modals/UserManagementModal/index.tsx @@ -32,13 +32,11 @@ export default function UserManagementModal({ const [password, setPassword] = useState(data?.password ?? ""); const [username, setUserName] = useState(data?.username ?? ""); const [confirmPassword, setConfirmPassword] = useState(data?.password ?? ""); - const [isDisabled, setIsDisabled] = useState(data?.is_disabled ?? false); + const [isDisabled, setIsDisabled] = useState(data?.is_active ?? false); const [isSuperUser, setIsSuperUser] = useState(data?.is_superuser ?? false); const [inputState, setInputState] = useState(CONTROL_NEW_USER); const { userData } = useContext(AuthContext); - console.log(userData); - function handleInput({ target: { name, value }, }: inputHandlerEventType): void { @@ -50,7 +48,7 @@ export default function UserManagementModal({ resetForm(); } else { handleInput({ target: { name: "username", value: username } }); - handleInput({ target: { name: "is_disabled", value: isDisabled } }); + handleInput({ target: { name: "is_active", value: isDisabled } }); handleInput({ target: { name: "is_superuser", value: isSuperUser } }); } }, [open]); @@ -230,7 +228,7 @@ export default function UserManagementModal({
- +
Disabled @@ -239,10 +237,10 @@ export default function UserManagementModal({ { - handleInput({ target: { name: "is_disabled", value } }); + handleInput({ target: { name: "is_active", value } }); setIsDisabled(value); }} /> diff --git a/src/frontend/src/pages/AdminPage/index.tsx b/src/frontend/src/pages/AdminPage/index.tsx index 486f5bb56..86b1b36c0 100644 --- a/src/frontend/src/pages/AdminPage/index.tsx +++ b/src/frontend/src/pages/AdminPage/index.tsx @@ -1,3 +1,4 @@ +import { cloneDeep } from "lodash"; import { X } from "lucide-react"; import { useContext, useEffect, useRef, useState } from "react"; import PaginatorComponent from "../../components/PaginatorComponent"; @@ -15,6 +16,7 @@ import { TableRow, } from "../../components/ui/table"; import { alertContext } from "../../contexts/alertContext"; +import { AuthContext } from "../../contexts/authContext"; import { addUser, deleteUser, @@ -23,7 +25,6 @@ import { } from "../../controllers/API"; import ConfirmationModal from "../../modals/ConfirmationModal"; import UserManagementModal from "../../modals/UserManagementModal"; -import { AuthContext } from "../../contexts/authContext"; export default function AdminPage() { const [inputValue, setInputValue] = useState(""); @@ -49,9 +50,9 @@ export default function AdminPage() { setLoadingUsers(true); getUsersPage(index, size) .then((users) => { - setTotalRowsCount(users['total_count']); - userList.current = users['users']; - setFilterUserList(users['users']); + setTotalRowsCount(users["total_count"]); + userList.current = users["users"]; + setFilterUserList(users["users"]); setLoadingUsers(false); }) .catch((error) => { @@ -63,8 +64,9 @@ export default function AdminPage() { setLoadingUsers(true); getUsersPage(pageIndex, pageSize) .then((users) => { - userList.current = users; - setFilterUserList(users); + setTotalRowsCount(users["total_count"]); + userList.current = users["users"]; + setFilterUserList(users["users"]); setLoadingUsers(false); }) .catch((error) => { @@ -123,6 +125,45 @@ export default function AdminPage() { }); } + function handleDisableUser(check, userId, user) { + const userEdit = cloneDeep(user); + userEdit.is_active = !check; + + updateUser(userId, userEdit) + .then((res) => { + console.log(res); + + resetFilter(); + setSuccessData({ + title: "Success! User edited!", + }); + }) + .catch((error) => { + setErrorData({ + title: "Error on edit user", + list: [error["response"]["data"]["detail"]], + }); + }); + } + + function handleSuperUserEdit(check, userId, user) { + const userEdit = cloneDeep(user); + userEdit.is_superuser = !check; + updateUser(userId, userEdit) + .then((res) => { + resetFilter(); + setSuccessData({ + title: "Success! User edited!", + }); + }) + .catch((error) => { + setErrorData({ + title: "Error on edit user", + list: [error["response"]["data"]["detail"]], + }); + }); + } + function handleNewUser(user) { addUser(user) .then((res) => { @@ -140,214 +181,246 @@ export default function AdminPage() { } return ( - <> - { - userData && ( - - + {userData && (
-
-
-
-
-
-

- Welcome back! -

-

- Here's a list of all users! -

+
+
+
+
+
+

+ Welcome back! +

+

+ Here's a list of all users! +

+
+
-
-
- {userList.current.length === 0 && !loadingUsers && ( + {userList.current.length === 0 && !loadingUsers && ( + <> +
+

There's no users registered :)

+
+ + )} <>
-

There's no users registered :)

-
- - )} - <> -
-
- handleFilterUsers(e.target.value)} - /> - {inputValue.length > 0 && ( - + )} +
+
+ { + handleNewUser(user); }} - variant="ghost" - className="h-8 px-2 lg:px-3" > - Reset - - - )} + + +
-
- { - handleNewUser(user); - }} - > - - -
-
- {loadingUsers && ( -
- Loading... -
- )} -
- - - - Id - Username - Disabled - Superuser - Created At - Updated At - - - - {!loadingUsers && ( - - {filterUserList.map((user, index) => ( - - - - - {user.id} - - - - - - - {user.username} - - - - - - - - - - - { - new Date(user.create_at) - .toISOString() - .split("T")[0] - } - - - { - new Date(user.updated_at) - .toISOString() - .split("T")[0] - } - - -
- { - handleEditUser(user.id, editUser); - }} - > - - - - - + {loadingUsers && ( +
+ Loading... +
+ )} +
+
+ + + Id + Username + Disabled + Superuser + Created At + Updated At + + + + {!loadingUsers && ( + + {filterUserList.map((user, index) => ( + + + + + {user.id} + + + + + + + {user.username} + + + + { - handleDeleteUser(user); + handleDisableUser( + user.is_superuser, + user.id, + user + ); }} > - - - + - - - - ))} - - )} -
-
+ + + { + handleSuperUserEdit( + user.is_superuser, + user.id, + user + ); + }} + > + + + + + { + new Date(user.create_at) + .toISOString() + .split("T")[0] + } + + + { + new Date(user.updated_at) + .toISOString() + .split("T")[0] + } + + +
+ { + handleEditUser(user.id, editUser); + }} + > + + + + - { - handleChangePagination(pageSize, pageIndex); - }} - > - + { + handleDeleteUser(user); + }} + > + + + + +
+
+ + ))} + + )} + +
+ + { + handleChangePagination(pageSize, pageIndex); + }} + > + +
-
- ) - } - + )} ); } diff --git a/src/frontend/src/pages/loginPage/index.tsx b/src/frontend/src/pages/loginPage/index.tsx index 56ce90f75..3195ca6dd 100644 --- a/src/frontend/src/pages/loginPage/index.tsx +++ b/src/frontend/src/pages/loginPage/index.tsx @@ -1,5 +1,5 @@ import * as Form from "@radix-ui/react-form"; -import { useContext, useState } from "react"; +import { useContext, useEffect, useState } from "react"; import { Link, useNavigate } from "react-router-dom"; import InputComponent from "../../components/inputComponent"; import { Button } from "../../components/ui/button"; diff --git a/src/frontend/src/types/api/index.ts b/src/frontend/src/types/api/index.ts index 9dafae733..52ed6b7e0 100644 --- a/src/frontend/src/types/api/index.ts +++ b/src/frontend/src/types/api/index.ts @@ -81,7 +81,7 @@ export type LoginAuthType = { export type Users = { id: string; username: string; - is_disabled: boolean; + is_active: boolean; is_superuser: boolean; create_at: Date; updated_at: Date; diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index a0918e692..0f2b8c8f5 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -230,6 +230,6 @@ export type loginInputStateType = { export type UserInputType = { username: string; password: string; - is_disabled: boolean; + is_active: boolean; is_superuser: boolean; }; diff --git a/src/frontend/src/utils/styleUtils.ts b/src/frontend/src/utils/styleUtils.ts index 8ae5742a3..7c63dcb26 100644 --- a/src/frontend/src/utils/styleUtils.ts +++ b/src/frontend/src/utils/styleUtils.ts @@ -62,6 +62,7 @@ import { Trash2, Undo, Upload, + UserCog2, UserMinus2, UserPlus2, Users2, @@ -292,4 +293,5 @@ export const nodeIconsLucide = { FaApple, EyeOff, Eye, + UserCog2 }; diff --git a/src/frontend/tailwind.config.js b/src/frontend/tailwind.config.js index 52330ae92..5130f3fcf 100644 --- a/src/frontend/tailwind.config.js +++ b/src/frontend/tailwind.config.js @@ -201,6 +201,12 @@ module.exports = { ".dark .theme-attribution .react-flow__attribution a": { color: "black", }, + ".text-align-last-left": { + "text-align-last": "left", + }, + ".text-align-last-right": { + "text-align-last": "right", + }, }); }), require("@tailwindcss/typography"),