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"),