-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3a420dc
commit adc1c62
Showing
26 changed files
with
1,633 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,27 @@ | ||
const Groupings = () => { | ||
import GroupingsTable from '@/components/table/GroupingsTable'; | ||
import {ownerGroupings} from '@/actions/groupings-api'; | ||
|
||
const Groupings = async () => { | ||
const res = await ownerGroupings(); | ||
const groupingPaths = res.groupingPaths; | ||
return ( | ||
<div className="bg-white"> | ||
<div className="container">{/* GroupingsTable goes here */}</div> | ||
</div> | ||
<main> | ||
<div className="bg-seafoam pt-3"> | ||
<div className="container"> | ||
<h1 className="mb-1 font-bold text-[2rem] text-center md:text-left">Manage My Groupings</h1> | ||
<p className="pb-3 text-xl text-center md:text-left"> | ||
View and manage groupings I own. Manage members, | ||
configure grouping options and sync destinations. | ||
</p> | ||
</div> | ||
<div className="bg-white"> | ||
<div className="container"> | ||
<GroupingsTable data={groupingPaths}/> | ||
</div> | ||
</div> | ||
</div> | ||
</main> | ||
); | ||
}; | ||
} | ||
|
||
export default Groupings; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
'use client'; | ||
import { | ||
useReactTable, | ||
flexRender, | ||
getCoreRowModel, | ||
getPaginationRowModel, | ||
getFilteredRowModel, | ||
getSortedRowModel, | ||
SortingState | ||
} from '@tanstack/react-table'; | ||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'; | ||
import ColumnSettings from '@/components/table/table-element/ColumnSettings'; | ||
import GroupingsTableHeaders from '@/components/table/table-element/GroupingsTableHeaders'; | ||
import PaginationBar from '@/components/table/table-element/Pagination'; | ||
import GlobalFilter from '@/components/table/table-element/GlobalFilter'; | ||
import SortArrow from '@/components/table/table-element/SortArrow'; | ||
import { useState } from 'react'; | ||
import { SquarePen } from 'lucide-react'; | ||
import GroupingPathCell from '@/components/table/table-element/GroupingPathCell'; | ||
import { GroupingPath } from '@/models/groupings-api-results'; | ||
|
||
interface GroupingTableProps { | ||
data: GroupingPath[]; | ||
} | ||
|
||
const GroupingsTable = ({ data }: GroupingTableProps) => { | ||
const [globalFilter, setGlobalFilter] = useState(''); | ||
const [sorting, setSorting] = useState<SortingState>([]); | ||
|
||
const table = useReactTable({ | ||
columns: GroupingsTableHeaders, | ||
data: data, | ||
getCoreRowModel: getCoreRowModel(), | ||
getPaginationRowModel: getPaginationRowModel(), | ||
getFilteredRowModel: getFilteredRowModel(), | ||
getSortedRowModel: getSortedRowModel(), | ||
state: { globalFilter, sorting }, | ||
initialState: {pagination: {pageSize: 20}}, | ||
onGlobalFilterChange: setGlobalFilter, | ||
onSortingChange: setSorting | ||
}); | ||
|
||
const columnCount = table.getHeaderGroups()[0].headers.length; | ||
|
||
return ( | ||
<div className="px-2"> | ||
<div className="flex flex-col md:flex-row md:justify-between pt-5 mb-4"> | ||
<h1 className="text-[2rem] font-medium text-text-color text-center pt-3">Manage Groupings</h1> | ||
<div className="flex items-center space-x-2"> | ||
<GlobalFilter filter={globalFilter} setFilter={setGlobalFilter}/> | ||
<div className="hidden sm:block"> | ||
<ColumnSettings table={table}/> | ||
</div> | ||
</div> | ||
</div> | ||
<Table className="relative overflow-x-auto"> | ||
<TableHeader> | ||
{table.getHeaderGroups().map(headerGroup => ( | ||
<TableRow key={headerGroup.id}> | ||
{headerGroup.headers.map((header, index) => ( | ||
<TableHead | ||
key={header.id} | ||
onClick={header.column.getToggleSortingHandler()} | ||
className={`font-semibold text-uh-black border-solid | ||
border-t-[1px] border-b-[2px] py-3 size-[0.1rem] ${ | ||
columnCount === 2 && index === 1 ? 'w-2/3' : 'w-1/3' | ||
} ${header.column.id !== 'GROUPING NAME' ? 'hidden sm:table-cell' : ''}`} | ||
> | ||
<div className="flex items-center text-[0.8rem] font-bold"> | ||
{flexRender(header.column.columnDef.header, header.getContext())} | ||
{header.column.getIsSorted() && ( | ||
<SortArrow direction={header.column.getIsSorted()}/> | ||
)} | ||
</div> | ||
</TableHead> | ||
))} | ||
</TableRow> | ||
))} | ||
</TableHeader> | ||
<TableBody> | ||
{table.getRowModel().rows.map((row, index) => ( | ||
<TableRow key={row.id} className={index % 2 === 0 ? 'bg-light-grey' : ''}> | ||
{row.getVisibleCells().map(cell => ( | ||
<TableCell | ||
key={cell.id} | ||
className={`p-0 ${cell.column.id !== 'GROUPING NAME' ? | ||
'hidden sm:table-cell' : ''}`} | ||
width={cell.column.columnDef.size} | ||
> | ||
<div className="flex items-center pl-2 pr-2 text-[15.5px] | ||
overflow-hidden whitespace-nowrap"> | ||
<div className="m-2"> | ||
{cell.column.id === 'GROUPING NAME' && ( | ||
<div className="flex"> | ||
<SquarePen className="text-text-primary w-[1.25em] h-[1.25em]" | ||
data-testid={`square-pen-icon-${row.id}`}/> | ||
<div className="text-table-text text-[1rem] pl-2"> | ||
{flexRender(cell.column.columnDef.cell, cell.getContext())} | ||
</div> | ||
</div> | ||
)} | ||
</div> | ||
|
||
{cell.column.id === 'DESCRIPTION' && ( | ||
<div | ||
className={`text-table-text text-[1rem] | ||
${columnCount === 3 ? | ||
'truncate sm:max-w-[calc(6ch+1em)] md:max-w-none' : ''}`}> | ||
{flexRender(cell.column.columnDef.cell, cell.getContext())} | ||
</div> | ||
)} | ||
|
||
{cell.column.id === 'GROUPING PATH' && ( | ||
<GroupingPathCell data={cell.row.getValue('GROUPING PATH')} | ||
uniqueId={cell.row.id}/> | ||
)} | ||
</div> | ||
</TableCell> | ||
))} | ||
</TableRow> | ||
))} | ||
</TableBody> | ||
</Table> | ||
<PaginationBar table={table}/> | ||
</div> | ||
); | ||
}; | ||
|
||
export default GroupingsTable; | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
'use client'; | ||
import { Label } from '@/components/ui/label'; | ||
import { Switch } from '@/components/ui/switch'; | ||
import { useState } from 'react'; | ||
import { GroupingPath } from '@/models/groupings-api-results'; | ||
import { Button } from '@/components/ui/button'; | ||
import { | ||
DropdownMenu, | ||
DropdownMenuTrigger, | ||
DropdownMenuContent, | ||
DropdownMenuRadioGroup, | ||
DropdownMenuRadioItem | ||
} from '@/components/ui/dropdown-menu'; | ||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; | ||
import { faSliders } from '@fortawesome/free-solid-svg-icons'; | ||
import {Table} from '@tanstack/table-core'; | ||
|
||
interface ToggleProps { | ||
table: Table<GroupingPath>; | ||
} | ||
const ColumnSettings = ({ table } : ToggleProps) => { | ||
|
||
interface ColumnVisibilityState { | ||
DESCRIPTION: boolean; | ||
'GROUPING PATH': boolean; | ||
} | ||
|
||
const [columnVisibility, setColumnVisibility] = useState<ColumnVisibilityState>({ | ||
DESCRIPTION: true, | ||
'GROUPING PATH': true, | ||
}) | ||
|
||
const toggleColumnVisibility = (columnKey: keyof ColumnVisibilityState) => (checked: boolean) => { | ||
setColumnVisibility((prevState) => { | ||
const newState = checked; | ||
table.getColumn(columnKey)?.toggleVisibility(newState); | ||
return { ...prevState, [columnKey]: newState }; | ||
}); | ||
}; | ||
|
||
return ( | ||
<div> | ||
<DropdownMenu> | ||
<DropdownMenuTrigger asChild> | ||
<Button variant="outline" | ||
className="border border-gray-300 hover:bg-transparent" | ||
data-testid="column-settings-button"> | ||
<FontAwesomeIcon icon={faSliders} className="w-5 h-5 text-text-color"/> | ||
</Button> | ||
</DropdownMenuTrigger> | ||
<DropdownMenuContent> | ||
<DropdownMenuRadioGroup> | ||
<DropdownMenuRadioItem value="description" className="px-2"> | ||
<div className="flex items-center space-x-2"> | ||
<Switch id="description" checked={columnVisibility.DESCRIPTION} | ||
onCheckedChange={toggleColumnVisibility('DESCRIPTION')} | ||
className="data-[state=checked]:bg-uh-teal" data-testid="description-switch" /> | ||
<Label htmlFor="description">Description</Label> | ||
</div> | ||
</DropdownMenuRadioItem> | ||
<DropdownMenuRadioItem value="grouping path" className="px-2"> | ||
<div className="flex items-center space-x-2"> | ||
<Switch id="grouping-path" checked={columnVisibility['GROUPING PATH']} | ||
onCheckedChange={toggleColumnVisibility('GROUPING PATH')} | ||
className="data-[state=checked]:bg-uh-teal" | ||
data-testid="grouping-path-switch"/> | ||
<Label htmlFor="grouping-path">Grouping Path</Label> | ||
</div> | ||
</DropdownMenuRadioItem> | ||
</DropdownMenuRadioGroup> | ||
</DropdownMenuContent> | ||
</DropdownMenu> | ||
</div> | ||
); | ||
}; | ||
|
||
export default ColumnSettings; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { Input } from '@/components/ui/input' | ||
import { Dispatch, SetStateAction } from 'react'; | ||
|
||
interface FilterProps { | ||
filter: string; | ||
setFilter: Dispatch<SetStateAction<string>>; | ||
} | ||
const GlobalFilter = ( {filter, setFilter} : FilterProps) => ( | ||
<Input | ||
placeholder='Filter Groupings...' | ||
value={filter || ''} | ||
onChange={e => setFilter(e.target.value)} | ||
/> | ||
|
||
); | ||
|
||
export default GlobalFilter; | ||
|
53 changes: 53 additions & 0 deletions
53
ui/src/components/table/table-element/GroupingPathCell.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
import { ClipboardIcon } from 'lucide-react'; | ||
import { Input } from '@/components/ui/input'; | ||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'; | ||
import { useState } from 'react'; | ||
|
||
const GroupingPathCell = ({data, uniqueId}: { data: string, uniqueId: string }) => { | ||
const [tooltipContent, setTooltipContent] = useState('copy'); | ||
const [tooltipVisible, setTooltipVisible] = useState(false); | ||
|
||
const handleClick = async () => { | ||
await navigator.clipboard.writeText(data); | ||
setTooltipContent('copied!'); | ||
setTooltipVisible(true); | ||
|
||
setTimeout(() => { | ||
setTooltipContent('copy'); | ||
setTooltipVisible(false); | ||
}, 2000); | ||
}; | ||
|
||
return ( | ||
<div className="flex items-center w-full outline outline-1 rounded h-6 m-1"> | ||
<Input | ||
id={`dataInput-${uniqueId}`} | ||
value={data} | ||
readOnly | ||
className="flex-1 h-6 text-input-text-grey text-[0.875rem] | ||
border-none rounded-none w-[161] truncate" | ||
/> | ||
<TooltipProvider> | ||
<Tooltip open={tooltipVisible} onOpenChange={setTooltipVisible}> | ||
<TooltipTrigger asChild> | ||
<button | ||
onClick={handleClick} | ||
className="relative flex-shrink-0 flex items-center | ||
justify-center hover:bg-green-blue h-6 p-2" | ||
data-testid={`clipboard-button-${uniqueId}`} | ||
> | ||
<ClipboardIcon className="h-4 w-4 text-gray-600" | ||
data-testid={`clipboard-icon-${uniqueId}`}/> | ||
</button> | ||
</TooltipTrigger> | ||
<TooltipContent> | ||
<p data-testid="tooltip">{tooltipContent}</p> | ||
</TooltipContent> | ||
</Tooltip> | ||
</TooltipProvider> | ||
</div> | ||
); | ||
}; | ||
|
||
export default GroupingPathCell; | ||
|
20 changes: 20 additions & 0 deletions
20
ui/src/components/table/table-element/GroupingsTableHeaders.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
const GroupingsTableHeaders = [ | ||
{ | ||
header: 'GROUPING NAME', | ||
accessorKey: 'name', | ||
id: 'GROUPING NAME' | ||
}, | ||
{ | ||
header: 'DESCRIPTION', | ||
accessorKey: 'description', | ||
id: 'DESCRIPTION', | ||
}, | ||
{ | ||
header: 'GROUPING PATH', | ||
accessorKey: 'path', | ||
id: 'GROUPING PATH', | ||
} | ||
]; | ||
|
||
export default GroupingsTableHeaders; | ||
|
Oops, something went wrong.