diff --git a/src/backend/langflow/api/v1/users.py b/src/backend/langflow/api/v1/users.py index 7365e7cc1..5094409cb 100644 --- a/src/backend/langflow/api/v1/users.py +++ b/src/backend/langflow/api/v1/users.py @@ -43,7 +43,9 @@ def add_user( db.refresh(new_user) except IntegrityError as e: db.rollback() - raise HTTPException(status_code=400, detail="This username is unavailable.") from e + raise HTTPException( + status_code=400, detail="This username is unavailable." + ) from e return new_user diff --git a/src/frontend/src/components/DropdownButtonComponent/index.tsx b/src/frontend/src/components/DropdownButtonComponent/index.tsx new file mode 100644 index 000000000..20c956365 --- /dev/null +++ b/src/frontend/src/components/DropdownButtonComponent/index.tsx @@ -0,0 +1,49 @@ +import { useState } from "react"; +import IconComponent from "../genericIconComponent"; +import { Button } from "../ui/button"; + +export default function DropdownButton({ + firstButtonName, + onFirstBtnClick, + options, +}): JSX.Element { + const [showOptions, setShowOptions] = useState(false); + + return ( +
+
+ +
+
+ +
+ {showOptions && ( +
+ {options.map((optionName) => ( + + ))} +
+ )} +
+ ); +} diff --git a/src/frontend/src/components/headerComponent/index.tsx b/src/frontend/src/components/headerComponent/index.tsx index c74cdaa76..039b8895c 100644 --- a/src/frontend/src/components/headerComponent/index.tsx +++ b/src/frontend/src/components/headerComponent/index.tsx @@ -33,14 +33,14 @@ export default function Header(): JSX.Element { )} {!autoLogin && location.pathname !== `/flow/${tabId}` && ( { - logout(); - navigate("/login"); - }} - className="text-sm font-medium text-muted-foreground transition-colors hover:text-primary cursor-pointer mx-5" - > - Sign out - + onClick={() => { + logout(); + navigate("/login"); + }} + className="mx-5 cursor-pointer text-sm font-medium text-muted-foreground transition-colors hover:text-primary" + > + Sign out + )} {location.pathname === "/admin" && ( @@ -48,7 +48,7 @@ export default function Header(): JSX.Element { onClick={() => { navigate("/"); }} - className="text-sm font-medium text-muted-foreground transition-colors hover:text-primary cursor-pointer" + className="cursor-pointer text-sm font-medium text-muted-foreground transition-colors hover:text-primary" > Home @@ -59,11 +59,11 @@ export default function Header(): JSX.Element { location.pathname !== "/admin" && location.pathname !== `/flow/${tabId}` && ( navigate("/admin")} - > - Admin page - + className="cursor-pointer text-sm font-medium text-muted-foreground transition-colors hover:text-primary" + onClick={() => navigate("/admin")} + > + Admin page + )}
diff --git a/src/frontend/src/pages/AdminPage/index.tsx b/src/frontend/src/pages/AdminPage/index.tsx index fc963fee8..08e83f700 100644 --- a/src/frontend/src/pages/AdminPage/index.tsx +++ b/src/frontend/src/pages/AdminPage/index.tsx @@ -4,6 +4,7 @@ import { useContext, useEffect, useRef, useState } from "react"; import PaginatorComponent from "../../components/PaginatorComponent"; import ShadTooltip from "../../components/ShadTooltipComponent"; import IconComponent from "../../components/genericIconComponent"; +import Header from "../../components/headerComponent"; import { Button } from "../../components/ui/button"; import { Checkbox } from "../../components/ui/checkbox"; import { Input } from "../../components/ui/input"; @@ -25,9 +26,8 @@ import { } from "../../controllers/API"; import ConfirmationModal from "../../modals/ConfirmationModal"; import UserManagementModal from "../../modals/UserManagementModal"; -import { UserInputType } from "../../types/components"; -import Header from "../../components/headerComponent"; import { Users } from "../../types/api"; +import { UserInputType } from "../../types/components"; export default function AdminPage() { const [inputValue, setInputValue] = useState(""); @@ -89,7 +89,7 @@ export default function AdminPage() { if (input === "") { setFilterUserList(userList.current); } else { - const filteredList = userList.current.filter((user:Users) => + const filteredList = userList.current.filter((user: Users) => user.username.toLowerCase().includes(input.toLowerCase()) ); setFilterUserList(filteredList); @@ -183,249 +183,254 @@ export default function AdminPage() { return ( <> -
-
- {userData && ( -
-
-
-
-
-
-

- Welcome back! -

-

- Navigate through this section to efficiently oversee all - application users. From here, you can seamlessly manage - user accounts. -

+
+
+ {userData && ( +
+
+
+
+
+
+

+ Welcome back! +

+

+ Navigate through this section to efficiently oversee all + application users. From here, you can seamlessly manage + user accounts. +

+
+
-
-
- {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 - Active - Superuser - Created At - Updated At - - - - {!loadingUsers && ( - - {filterUserList.map((user:UserInputType, index) => ( - - - - - {user.id} - - - - - - - {user.username} - - - - - { - handleDisableUser( - user.is_active, - 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); - }} - > - - + {loadingUsers && ( +
+ Loading... +
+ )} +
+
+ + + Id + Username + Active + Superuser + Created At + Updated At + + + + {!loadingUsers && ( + + {filterUserList.map( + (user: UserInputType, index) => ( + + + + + {user.id} + - - - { - handleDeleteUser(user); - }} - > - - + + + + + {user.username} + - - - - - ))} - - )} -
-
+ + + { + handleDisableUser( + user.is_active, + 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/FlowPage/components/PageComponent/index.tsx b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx index 058be6e5c..620170fbb 100644 --- a/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx +++ b/src/frontend/src/pages/FlowPage/components/PageComponent/index.tsx @@ -421,7 +421,7 @@ export default function Page({ zoomOnScroll={!view} zoomOnPinch={!view} panOnDrag={!view} - proOptions={{hideAttribution: true}} + proOptions={{ hideAttribution: true }} > {!view && ( diff --git a/src/frontend/src/pages/loginPage/index.tsx b/src/frontend/src/pages/loginPage/index.tsx index 14e04708b..a3ac0fbcd 100644 --- a/src/frontend/src/pages/loginPage/index.tsx +++ b/src/frontend/src/pages/loginPage/index.tsx @@ -19,7 +19,8 @@ export default function LoginPage(): JSX.Element { useState(CONTROL_LOGIN_STATE); const { password, username } = inputState; - const { login, getAuthentication, setUserData, setIsAdmin } = useContext(AuthContext); + const { login, getAuthentication, setUserData, setIsAdmin } = + useContext(AuthContext); const navigate = useNavigate(); const { setErrorData } = useContext(alertContext); diff --git a/src/frontend/src/types/components/index.ts b/src/frontend/src/types/components/index.ts index f7b974a93..24e538e98 100644 --- a/src/frontend/src/types/components/index.ts +++ b/src/frontend/src/types/components/index.ts @@ -268,7 +268,7 @@ export type UserInputType = { is_superuser?: boolean; id?: string; create_at?: string; - updated_at?:string; + updated_at?: string; }; export type ApiKeyType = { diff --git a/src/frontend/src/utils/styleUtils.ts b/src/frontend/src/utils/styleUtils.ts index 31a7adf7e..e74bb0e34 100644 --- a/src/frontend/src/utils/styleUtils.ts +++ b/src/frontend/src/utils/styleUtils.ts @@ -5,6 +5,7 @@ import { ChevronDown, ChevronLeft, ChevronRight, + ChevronUp, ChevronsLeft, ChevronsRight, ChevronsUpDown, @@ -300,4 +301,5 @@ export const nodeIconsLucide: iconsType = { UserCog2, Key, Unplug, + ChevronUp, };