feat: add command list to DataTable column header (#18867)
* feat: add command list to DataTable column header * disable hiding and sorting for some columns * disable hiding & sorting
This commit is contained in:
@@ -191,6 +191,10 @@
|
||||
<path d="m6 17 5-5-5-5" ></path>
|
||||
<path d="m13 17 5-5-5-5" ></path>
|
||||
</symbol>
|
||||
<symbol class="lucide lucide-chevrons-up-down" viewBox="0 0 24 24" fill="inherit" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" id="chevrons-up-down">
|
||||
<path d="m7 15 5 5 5-5" ></path>
|
||||
<path d="m7 9 5-5 5 5" ></path>
|
||||
</symbol>
|
||||
<symbol class="lucide lucide-circle-alert" viewBox="0 0 24 24" fill="inherit" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" id="circle-alert">
|
||||
<circle cx="12" cy="12" r="10" ></circle>
|
||||
<line x1="12" x2="12" y1="8" y2="12" ></line>
|
||||
|
||||
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
@@ -2941,6 +2941,9 @@
|
||||
"add_preset" : "Add Preset",
|
||||
"authorize": "Authorize",
|
||||
"next": "Next",
|
||||
"hide": "Hide",
|
||||
"asc": "Asc",
|
||||
"desc": "Desc",
|
||||
"verify_email": "Verify email",
|
||||
"ADD_NEW_STRINGS_ABOVE_THIS_LINE_TO_PREVENT_MERGE_CONFLICTS": "↑↑↑↑↑↑↑↑↑↑↑↑↑ Add your new strings above here ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑"
|
||||
}
|
||||
|
||||
@@ -2,15 +2,30 @@
|
||||
|
||||
import type { Row } from "@tanstack/react-table";
|
||||
import { flexRender } from "@tanstack/react-table";
|
||||
import type { Table as ReactTableType } from "@tanstack/react-table";
|
||||
import type { Table as ReactTableType, Header } from "@tanstack/react-table";
|
||||
import { useVirtualizer, type Virtualizer } from "@tanstack/react-virtual";
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import kebabCase from "lodash/kebabCase";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { useEffect, memo } from "react";
|
||||
import { useEffect, useState, memo } from "react";
|
||||
|
||||
import classNames from "@calcom/lib/classNames";
|
||||
import { Icon, TableNew, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@calcom/ui";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import {
|
||||
TableNew,
|
||||
TableBody,
|
||||
TableCell,
|
||||
TableHead,
|
||||
TableHeader,
|
||||
TableRow,
|
||||
Popover,
|
||||
PopoverTrigger,
|
||||
PopoverContent,
|
||||
Command,
|
||||
CommandList,
|
||||
CommandItem,
|
||||
Icon,
|
||||
} from "@calcom/ui";
|
||||
|
||||
import { useColumnSizingVars } from "../hooks";
|
||||
import { usePersistentColumnResizing } from "../lib/resizing";
|
||||
@@ -132,27 +147,9 @@ export function DataTable<TData, TValue>({
|
||||
className={classNames(
|
||||
"relative flex shrink-0 items-center",
|
||||
"bg-subtle",
|
||||
header.column.getCanSort() ? "hover:bg-muted cursor-pointer select-none" : "",
|
||||
column.getIsPinned() && "top-0 z-20 sm:sticky"
|
||||
)}>
|
||||
<div
|
||||
className="flex h-full w-full items-center overflow-hidden"
|
||||
onClick={header.column.getToggleSortingHandler()}>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(header.column.columnDef.header, header.getContext())}
|
||||
{header.column.getIsSorted() && (
|
||||
<Icon
|
||||
name="arrow-up"
|
||||
className="ml-2 h-4 w-4"
|
||||
style={{
|
||||
transform:
|
||||
header.column.getIsSorted() === "asc" ? "rotate(0deg)" : "rotate(180deg)",
|
||||
transition: "transform 0.2s ease-in-out",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<TableHeadLabel header={header} />
|
||||
{Boolean(enableColumnResizing) && header.column.getCanResize() && (
|
||||
<div
|
||||
onMouseDown={header.getResizeHandler()}
|
||||
@@ -287,3 +284,84 @@ function DataTableBody<TData>({
|
||||
</TableBody>
|
||||
);
|
||||
}
|
||||
|
||||
const TableHeadLabel = ({ header }: { header: Header<any, any> }) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
const { t } = useLocale();
|
||||
|
||||
if (!header.column.getCanSort() && !header.column.getCanHide()) {
|
||||
return (
|
||||
<div className="-ml-2 px-2 py-1">
|
||||
{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Popover open={open} onOpenChange={setOpen}>
|
||||
<PopoverTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
className={classNames(
|
||||
"group -ml-2 flex items-center gap-2 rounded-md px-2 py-1",
|
||||
open && "bg-muted"
|
||||
)}>
|
||||
{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
|
||||
<Icon
|
||||
name="chevrons-up-down"
|
||||
className={classNames("text-subtle h-4 w-4", !open && "opacity-0 group-hover:opacity-100")}
|
||||
/>
|
||||
</button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent align="start" className="w-32 p-0">
|
||||
<Command>
|
||||
<CommandList>
|
||||
{header.column.getCanSort() && (
|
||||
<>
|
||||
<CommandItem
|
||||
className="flex cursor-pointer items-center gap-2 px-3 py-2"
|
||||
onSelect={() => {
|
||||
if (header.column.getIsSorted() === "asc") {
|
||||
header.column.clearSorting();
|
||||
} else {
|
||||
header.column.toggleSorting(false, true);
|
||||
}
|
||||
}}>
|
||||
<Icon name="arrow-up" className="h-4 w-4" />
|
||||
{t("asc")}
|
||||
<div className="flex-1" />
|
||||
{header.column.getIsSorted() === "asc" && <Icon name="check" className="h-4 w-4" />}
|
||||
</CommandItem>
|
||||
<CommandItem
|
||||
className="flex cursor-pointer items-center gap-2 px-3 py-2"
|
||||
onSelect={() => {
|
||||
if (header.column.getIsSorted() === "desc") {
|
||||
header.column.clearSorting();
|
||||
} else {
|
||||
header.column.toggleSorting(true, true);
|
||||
}
|
||||
}}>
|
||||
<Icon name="arrow-down" className="h-4 w-4" />
|
||||
{t("desc")}
|
||||
<div className="flex-1" />
|
||||
{header.column.getIsSorted() === "desc" && <Icon name="check" className="h-4 w-4" />}
|
||||
</CommandItem>
|
||||
</>
|
||||
)}
|
||||
{header.column.getCanHide() && (
|
||||
<CommandItem
|
||||
className="flex cursor-pointer items-center gap-2 px-3 py-2"
|
||||
onSelect={() => {
|
||||
header.column.toggleVisibility(false);
|
||||
setOpen(false);
|
||||
}}>
|
||||
<Icon name="eye-off" className="h-4 w-4" />
|
||||
{t("hide")}
|
||||
</CommandItem>
|
||||
)}
|
||||
</CommandList>
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -29,6 +29,8 @@ const GroupTeamMappingTable = () => {
|
||||
id: "name",
|
||||
header: t("team"),
|
||||
size: 200,
|
||||
enableHiding: false,
|
||||
enableSorting: false,
|
||||
cell: ({ row }) => {
|
||||
const { name } = row.original;
|
||||
|
||||
@@ -39,6 +41,8 @@ const GroupTeamMappingTable = () => {
|
||||
id: "group",
|
||||
header: t("group_name"),
|
||||
size: 200,
|
||||
enableHiding: false,
|
||||
enableSorting: false,
|
||||
cell: ({ row }) => {
|
||||
const { id, groupNames, directoryId } = row.original;
|
||||
|
||||
|
||||
@@ -95,6 +95,8 @@ export function AvailabilitySliderTable(props: { userTimeFormat: number | null;
|
||||
{
|
||||
id: "member",
|
||||
accessorFn: (data) => data.username,
|
||||
enableHiding: false,
|
||||
enableSorting: false,
|
||||
header: "Member",
|
||||
size: 200,
|
||||
cell: ({ row }) => {
|
||||
@@ -127,6 +129,8 @@ export function AvailabilitySliderTable(props: { userTimeFormat: number | null;
|
||||
id: "timezone",
|
||||
accessorFn: (data) => data.timeZone,
|
||||
header: "Timezone",
|
||||
enableHiding: false,
|
||||
enableSorting: false,
|
||||
size: 160,
|
||||
cell: ({ row }) => {
|
||||
const { timeZone } = row.original;
|
||||
@@ -152,6 +156,8 @@ export function AvailabilitySliderTable(props: { userTimeFormat: number | null;
|
||||
meta: {
|
||||
autoWidth: true,
|
||||
},
|
||||
enableHiding: false,
|
||||
enableSorting: false,
|
||||
header: () => {
|
||||
return (
|
||||
<div className="flex items-center space-x-2">
|
||||
|
||||
@@ -141,6 +141,7 @@ export const lucideIconList = new Set([
|
||||
"zap",
|
||||
"waypoints",
|
||||
"chevrons-down-up",
|
||||
"chevrons-up-down",
|
||||
"sliders-horizontal",
|
||||
"calendar-range",
|
||||
]);
|
||||
|
||||
@@ -38,6 +38,7 @@ export type IconName =
|
||||
| "chevrons-down-up"
|
||||
| "chevrons-left"
|
||||
| "chevrons-right"
|
||||
| "chevrons-up-down"
|
||||
| "circle-alert"
|
||||
| "circle-arrow-up"
|
||||
| "circle-check-big"
|
||||
|
||||
Reference in New Issue
Block a user