-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add PersonTable #114
base: main
Are you sure you want to change the base?
Add PersonTable #114
Conversation
330f95b
to
51ee57d
Compare
51ee57d
to
9e01de4
Compare
import PersonTable from '@/app/admin/_components/personTable'; | ||
import { memberAttributeResults } from '@/lib/actions'; | ||
|
||
const PersonTab = async (searchParams) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure to set a type for searchParams, it would probably be: searchParams: { searchUid: string }
. Also I recommend changing the searchParam from searchUid
to uhIdentifier
because that naming would cover both uid and uhUuid.
import { memberAttributeResults } from '@/lib/actions'; | ||
|
||
const PersonTab = async (searchParams) => { | ||
const searchUid = searchParams.searchParams.searchUid; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also I'm not sure why the searchParams object would make you access .searchParams
const groupingsInfo = await managePersonResults(searchUid); | ||
const userInfo = searchUid === undefined ? undefined : (await memberAttributeResults([searchUid])).results[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's call these variables managePersonResults and memberAttributeResults so it's more clear what exactly we are passing into the PersonTable.
const props = { groupingsInfo: groupingsInfo, userInfo: userInfo, searchUid: searchUid }; | ||
|
||
return ( | ||
<> | ||
<div className="container"> | ||
<PersonTable {...props} /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of defining a props object, follow the other components and how they define each prop individually.
Make sure all the file names are kebab case like person-table.tsx instead of camelCase like personTable.tsx. |
const [rowSelection, setRowSelection] = useState<RowSelectionState>({}); | ||
const [modalOpen, setModalOpen] = useState(false); | ||
const [modalData, setModalData] = useState([]); | ||
const [dummyBool, setDummyBool] = useState(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's this dummyBool for?
const numSelected = table.getSelectedRowModel().rows.length; | ||
const arr = []; | ||
let i; | ||
for (i = 0; i < numSelected; i++) { | ||
const original = table.getSelectedRowModel().rows[i].original; | ||
if (original.inOwner) arr.push(original.path + ':owners'); | ||
if (original.inInclude) arr.push(original.path + ':include'); | ||
if (original.inExclude) arr.push(original.path + ':exclude'); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a very nice way to rewrite this code using the .flatMap function: (Generated by ChatGPT!)
const groups = table.getSelectedRowModel().rows.flatMap(({ original }) => {
const { path, inOwner, inInclude, inExclude } = original;
return [
inOwner && `${path}:owners`,
inInclude && `${path}:include`,
inExclude && `${path}:exclude`,
].filter(groupPath => groupPath);
});
<p className="text-[1.2rem] font-medium text-text-color md:justify-end pt-5 ps-2"> | ||
{userInfo === undefined | ||
? '' | ||
: '(' + userInfo.name + ', ' + userInfo.uid + ', ' + userInfo.uhUuid + ')'} | ||
</p> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of the ternary operator, it's nicer to use the && operator:
{userInfo !== undefined && <p className="text-[1.2rem] font-medium text-text-color md:justify-end pt-5 ps-2">
{'(' + userInfo.name + ', ' + userInfo.uid + ', ' + userInfo.uhUuid + ')'}
</p>}
{validUid === 'FAILURE' && searchUid !== undefined ? ( | ||
<Alert variant="destructive" className="w-fit mb-7"> | ||
<AlertDescription>{searchUid} is not in any grouping.</AlertDescription> | ||
</Alert> | ||
) : ( | ||
'' | ||
)} | ||
{validUid === undefined && searchUid !== '' ? ( | ||
<Alert variant="destructive" className="w-fit mb-7"> | ||
<AlertDescription> | ||
There was an error searching for {searchUid}. <br /> | ||
Please ensure you have entered a valid UH member and try again. | ||
</AlertDescription> | ||
</Alert> | ||
) : ( | ||
'' | ||
)} | ||
{searchUid === '' ? ( | ||
<Alert variant="destructive" className="w-fit mb-7"> | ||
<AlertDescription>You must enter a UH member to search.</AlertDescription> | ||
</Alert> | ||
) : ( | ||
'' | ||
)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same goes for here, use the && operator instead of the ternary.
onClick={ | ||
header.column.id === 'name' | ||
? header.column.getToggleSortingHandler() | ||
: () => void 0 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should be able to disable sorting for a certain column in your person-table-columns.tsx file. Then you can just use the getToggleSortingHandler() without this ternary,
{userInfo === undefined ? ( | ||
'' | ||
) : ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the && operator instead of the ternary, thanks.
<PersonTableTooltip | ||
value={'Manage grouping.'} | ||
side={'top'} | ||
desc={ | ||
<Link | ||
href={`/groupings/${cell.row.original.path}`} | ||
rel="noopener noreferrer" | ||
target="_blank" | ||
> | ||
<ArrowUpRightFromSquare | ||
size="1.25em" | ||
className="text-text-primary" | ||
data-testid={'arrow-up-right-from-square-icon'} | ||
/> | ||
</Link> | ||
} | ||
></PersonTableTooltip> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's preferred to pass in components as children instead of as a prop. Also the props value
and side
can be normal strings instead of strings wrapped {}.
{cell.column.id === 'inOwner' && ( | ||
<div className="ml-1"> | ||
<p className={`${cell.row.original.inOwner ? 'text-red-500' : ''}`}> | ||
{cell.row.original.inOwner ? 'Yes' : 'No'} | ||
</p> | ||
</div> | ||
)} | ||
{cell.column.id === 'inBasisAndInclude' && ( | ||
<div> | ||
<p | ||
className={`${ | ||
cell.row.original.inBasisAndInclude ? 'text-red-500' : '' | ||
}`} | ||
> | ||
{cell.row.original.inBasisAndInclude ? 'Yes' : 'No'} | ||
</p> | ||
</div> | ||
)} | ||
{cell.column.id === 'inInclude' && ( | ||
<div className="ml-2"> | ||
<p | ||
className={`${ | ||
cell.row.original.inInclude ? 'text-red-500' : '' | ||
}`} | ||
> | ||
{cell.row.original.inInclude ? 'Yes' : 'No'} | ||
</p> | ||
</div> | ||
)} | ||
{cell.column.id === 'inExclude' && ( | ||
<div className="ml-2"> | ||
<p | ||
className={`${ | ||
cell.row.original.inExclude ? 'text-red-500' : '' | ||
}`} | ||
> | ||
{cell.row.original.inExclude ? 'Yes' : 'No'} | ||
</p> | ||
</div> | ||
)} | ||
{cell.column.id === 'remove' && ( | ||
<div className="ml-3"> | ||
<input | ||
type="checkbox" | ||
checked={row.getIsSelected()} | ||
onChange={row.getToggleSelectedHandler()} | ||
/> | ||
</div> | ||
)} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These && statements should be moved to the person-table-columns.tsx file. Reference how the groupings-table-columns.tsx file does it.
</TableBody> | ||
)} | ||
</Table> | ||
{userInfo === undefined ? '' : <PaginationBar table={table} />} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use the && operator here too.
}: { | ||
desc: React.ReactNode; | ||
value: string; | ||
side: Side | undefined; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the type for side is supposed to be a string or more precisely: "top" | "right" | "bottom" | "left"
`z-50 overflow-hidden rounded-md border border-slate-200 bg-white px-3 py-1.5 | ||
text-sm text-slate-950 shadow-md animate-in fade-in-0 zoom-in-95 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep the tooltip as bg-black and text-white since most of the tooltips are those colors. If you are planning to use the tooltip with a white background and black text, change that component individually.
type="search" | ||
className="rounded-[-0.25rem] rounded-l-[0.25rem]" | ||
maxLength={8} | ||
placeholder={searchUid === null || searchUid === '' ? 'UH Username' : searchUid} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the placeholder needs to be the searchUid since the placeholder is just the text that displays when the input is empty.
modalData | ||
}: { | ||
open: boolean; | ||
close: MouseEventHandler; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The type for close seems incorrect, maybe close should be renamed to onClose and the type would be: () => void
<Button | ||
className="rounded-[-0.25rem] rounded-r-[0.25rem]" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I always thought it was weird that our button is not rounded on the left side. Let's keep the button normal and not straighten the left side, thanks.
I would love to see a manage-person-table-skeleton.tsx (similar to groupings-table-skeleton.tsx) as the loading file. The page seems unresponsive when fetching a lot of data, for example when searching mhodges. Note that since this table doesn't use localStorage, you can just create a loading.tsx file next to page.tsx: https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming |
Ticket Link
Groupings-1761
List of squashed commits
Test Checklist