From df8b424a6421fe6612ae72f82d0c8eff633d9e99 Mon Sep 17 00:00:00 2001 From: Tin Geber <tin@greenhost.nl> Date: Fri, 1 Dec 2023 13:15:05 +0100 Subject: [PATCH] UI cleanup, ready for tagging --- frontend/src/modules/users/Users.tsx | 155 +++++++++------------------ 1 file changed, 48 insertions(+), 107 deletions(-) diff --git a/frontend/src/modules/users/Users.tsx b/frontend/src/modules/users/Users.tsx index 329e61e5..897ded47 100644 --- a/frontend/src/modules/users/Users.tsx +++ b/frontend/src/modules/users/Users.tsx @@ -21,7 +21,6 @@ import { ChevronRightIcon, } from '@heroicons/react/solid'; import { CogIcon } from '@heroicons/react/outline'; -import { Menu, Transition } from '@headlessui/react'; // avatars import Gravatar from 'react-gravatar'; @@ -89,14 +88,21 @@ export const Users: React.FC = () => { }; }, []); - users.sort((a, b) => a.name.localeCompare(b.name)); + function sortSanitizeUsers() { + // remove the superadmin user created on setup. BRITTLE? + const sanitizedUsers = users.filter((id) => !id.email.match(/^admin+.*stackspin\.net$/g)); + // sort remaining users alphabetically + return sanitizedUsers.sort((a, b) => a.name.localeCompare(b.name)); + } + const sortedSanitizedUsers: User[] = sortSanitizeUsers(); + const filterSearch = useMemo(() => { - return users.filter( + return sortedSanitizedUsers.filter( (item: any) => item.email?.toLowerCase().includes(search.toLowerCase()) || item.name?.toLowerCase().includes(search.toLowerCase()), ); - }, [search, users]); + }, [search, sortedSanitizedUsers]); const configureModalOpen = (id: any) => { setUserId(id); @@ -118,11 +124,6 @@ export const Users: React.FC = () => { // setSelectedRowsIds(rows); // }, []); - // class function for the new user table - function classNames(...classes: string[]) { - return classes.filter(Boolean).join(' '); - } - const userCard = (person: User) => { return ( <div className="flex min-w-0 gap-x-4 items-center"> @@ -209,8 +210,8 @@ export const Users: React.FC = () => { }, { header: 'Name', - footer: (props) => props.column.id, accessorKey: 'name', + footer: (props) => props.column.id, cell: (props) => { const { row } = props; return userCard(row.original); @@ -221,15 +222,23 @@ export const Users: React.FC = () => { // footer: (props) => props.column.id, // accessorKey: 'email', // }, - { - header: 'Role', - accessorKey: 'admin', - footer: (props) => props.column.id, - cell: (props) => { - const { row } = props; - return <>{row.original.admin ? <span>Admin</span> : <span>User</span>}</>; - }, - }, + // { + // header: 'Role', + // accessorKey: 'admin', + // footer: (props) => props.column.id, + // cell: (props) => { + // const { row } = props; + // return ( + // <> + // {row.original.admin && ( + // <span className="inline-flex items-center rounded-md bg-gray-50 px-2 py-1 text-xs font-medium text-gray-500 ring-1 ring-inset ring-gray-300"> + // Admin + // </span> + // )} + // </> + // ); + // }, + // }, // { // header: 'Status', // footer: (props) => props.column.id, @@ -237,27 +246,28 @@ export const Users: React.FC = () => { // }, { header: ' ', + accessorKey: 'admin', + footer: (props) => props.column.id, cell: (props: any) => { const { row } = props; - - if (isAdmin) { - return ( - <div className="text-right relative"> - <div className="absolute inline-flex px-2 py-1 text-transparent items-center font-medium border border-transparent right-0 z-0"> - Configure <CogIcon className="-mr-0.5 ml-2 h-4 w-4 text-gray-500" /> - </div> - <button - onClick={() => configureModalOpen(row.original.id)} - type="button" - className="relative z-10 opacity-0 group-hover:opacity-100 transition-opacity inline-flex items-center px-2 py-1 border border-gray-200 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500" - > - Configure <CogIcon className="-mr-0.5 ml-2 h-4 w-4" /> - </button> + return ( + <div className="flex justify-end gap-4"> + <div className="flex flex-col items-end"> + {row.original.admin && ( + <div className="inline-flex items-center rounded-md bg-gray-50 px-2 py-1 text-xs font-medium text-gray-500 ring-1 ring-inset ring-gray-300"> + Admin + </div> + )} + {/* <div className="mt-1 text-xs leading-5 text-gray-500">last seen on DATE</div> */} </div> - ); - } - return null; + {isAdmin && ( + <button onClick={() => configureModalOpen(row.original.id)} type="button" className=""> + <CogIcon className=" h-5 w-5 text-gray-500 hover:text-gray-700" /> + </button> + )} + </div> + ); }, }, ], @@ -394,7 +404,7 @@ export const Users: React.FC = () => { key={header.id} colSpan={header.colSpan} scope="col" - className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer" + className="pl-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider cursor-pointer" > {header.isPlaceholder ? null : ( <div @@ -434,7 +444,7 @@ export const Users: React.FC = () => { key={cell.id} className={ cell.id.substring(2) === 'select' - ? 'w-4 px-6 py-4 whitespace-nowrap text-sm text-gray-500' + ? 'w-4 pl-6 pr-0 py-4 whitespace-nowrap text-sm text-gray-500' : 'px-6 py-4 whitespace-nowrap text-sm text-gray-500' } > @@ -505,75 +515,6 @@ export const Users: React.FC = () => { </div> </div> - <ul className="divide-y divide-gray-100"> - {filterSearch.map((person) => ( - <li key={person.email} className="flex justify-between gap-x-6 py-5 px-4 group"> - {userCard(person)} - <div className="flex shrink-0 items-center gap-x-6"> - <div className="hidden sm:flex sm:flex-col sm:items-end"> - <p className="text-sm leading-6 text-gray-900">{person.status}</p> - {person.status ? ( - <p className="mt-1 text-xs leading-5 text-gray-500"> - {person.admin ? <span>Admin</span> : <span>User</span>} - </p> - ) : ( - <div className="mt-1 flex items-center gap-x-1.5"> - <div className="flex-none rounded-full bg-emerald-500/20 p-1"> - <div className="h-1.5 w-1.5 rounded-full bg-emerald-500" /> - </div> - <p className="text-xs leading-5 text-gray-500">Online</p> - </div> - )} - </div> - <Menu as="div" className="relative flex-none"> - <Menu.Button className="-m-2.5 block p-2.5 text-gray-500 hover:text-gray-900"> - <span className="sr-only">Open options</span> - <CogIcon className="h-5 w-5" aria-hidden="true" /> - </Menu.Button> - <Transition - as={Fragment} - enter="transition ease-out duration-100" - enterFrom="transform opacity-0 scale-95" - enterTo="transform opacity-100 scale-100" - leave="transition ease-in duration-75" - leaveFrom="transform opacity-100 scale-100" - leaveTo="transform opacity-0 scale-95" - > - <Menu.Items className="absolute right-0 z-10 mt-2 w-32 origin-top-right rounded-md bg-white py-2 shadow-lg ring-1 ring-gray-900/5 focus:outline-none"> - <Menu.Item> - {({ active }) => ( - <a - href="#" - className={classNames( - active ? 'bg-gray-50' : '', - 'block px-3 py-1 text-sm leading-6 text-gray-900', - )} - > - View profile<span className="sr-only">, {person.name}</span> - </a> - )} - </Menu.Item> - <Menu.Item> - {({ active }) => ( - <a - href="#" - className={classNames( - active ? 'bg-gray-50' : '', - 'block px-3 py-1 text-sm leading-6 text-gray-900', - )} - > - Message<span className="sr-only">, {person.name}</span> - </a> - )} - </Menu.Item> - </Menu.Items> - </Transition> - </Menu> - </div> - </li> - ))} - </ul> - {configureModal && ( <UserModal open={configureModal} -- GitLab