feat: attributes filter / refactor of user data table (#17014)

* WIP restored from .git cache

* fix exports

* sortable row model

* feat column visibility component

* wip filters with nuqs

* pull in unique values from table into filters

* correctly assign filters via v/f

* inital selection bar refactor

* data-table selection bar + optmistic update of delete

* dynamic link

* migrate member list table to new data-table

* total list shows filtered value > db valuie

* add filters for attributes

* type errors

* make content bigger on lg

* add mb-6 to teams user datatable to match spacing spec

* correctly render multi-badge

* fix: masss asignment optimistic UI

* fix type errors

* remove log

* fix toolbar type error

* chore: Remove debug artifact

* type errors

* Update apps/web/public/static/locales/en/common.json

* use max-w-fit

* chore: Remove unused translation now we don't specify 'mass' in assign

* perf: fix: use the onBlur event to prevent focus loss whilst the list is rerendering

* Move the data-table exports together in the main barrel, then import

* fix exports that were lost in a merge

* fix exports that were lost in a merge

* fix groupteammapping/availbilityslider

* fix overflow problems

* add scrollbar-thin class

* fix type error

* user serverside values for faceted filters

* pass filters to serverside

* filter serverside

* fix team server side filter

* add loaded x of y

* attributes icon change

* correct implementation for text/input attr optimistic

* type check fixes

* fix platform checks

* fix types again

* fix types again

* fix types again

* add use client

* add use client

* fix-types

* fix: Add missing translation in EN

* fix e2e tests via testid

* fix e2e tests via testid

* fix: Member invite popup not popping up

* Update copyInviteLink to new-member-button testid

* Hopefully fix test ids this time

* fix: Use the right buttons on the right pages

---------

Co-authored-by: Alex van Andel <me@alexvanandel.com>
Co-authored-by: Peer Richelsen <peeroke@gmail.com>
Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
This commit is contained in:
sean-brydon
2024-10-15 17:45:11 +00:00
committed by GitHub
co-authored by Alex van Andel Peer Richelsen Udit Takkar
parent 0b914bef79
commit 7e44e686e8
43 changed files with 1462 additions and 1049 deletions
@@ -1,10 +1,11 @@
"use client";
import type { Table } from "@tanstack/react-table";
import type { Table as TableType } from "@tanstack/table-core/build/lib/types";
import { AnimatePresence } from "framer-motion";
import { Fragment } from "react";
import { forwardRef } from "react";
import { classNames } from "@calcom/lib";
import type { IconName } from "../..";
import { Button } from "../button";
export type ActionItem<TData> =
| {
@@ -20,51 +21,26 @@ export type ActionItem<TData> =
needsXSelected?: number;
};
interface DataTableSelectionBarProps<TData> {
table: Table<TData>;
actions?: ActionItem<TData>[];
renderAboveSelection?: (table: TableType<TData>) => React.ReactNode;
}
export function DataTableSelectionBar<TData>({
table,
actions,
renderAboveSelection,
}: DataTableSelectionBarProps<TData>) {
const numberOfSelectedRows = table.getSelectedRowModel().rows.length;
const isVisible = numberOfSelectedRows > 0;
// Hacky left % to center
const actionsVisible = actions?.filter((a) => {
if (!a.needsXSelected) return true;
return a.needsXSelected <= numberOfSelectedRows;
});
const Root = forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement> & { showSelectionCount?: boolean }
>(({ children, ...props }, ref) => {
return (
<AnimatePresence>
{isVisible ? (
<div className="fade-in fixed bottom-6 left-1/2 hidden -translate-x-1/2 gap-1 md:flex md:flex-col">
{renderAboveSelection && renderAboveSelection(table)}
<div className="bg-brand-default text-brand hidden items-center justify-between rounded-lg p-2 md:flex">
<p className="text-brand-subtle w-full px-2 text-center leading-none">
{numberOfSelectedRows} selected
</p>
{actionsVisible?.map((action, index) => {
return (
<Fragment key={index}>
{action.type === "action" ? (
<Button aria-label={action.label} onClick={action.onClick} StartIcon={action.icon}>
{action.label}
</Button>
) : action.type === "render" ? (
action.render(table)
) : null}
</Fragment>
);
})}
</div>
</div>
) : null}
</AnimatePresence>
<div
ref={ref}
className={classNames(
"bg-brand-default text-brand fixed bottom-4 left-1/2 flex w-fit -translate-x-1/2 transform items-center space-x-3 rounded-lg px-4 py-2",
props.className
)}
style={{ ...props.style }}
{...props}>
{children}
</div>
);
}
});
Root.displayName = "Root";
export const DataTableSelectionBar = {
Root,
};