1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

add more typing to sorting of tables

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2020-12-15 13:44:57 -05:00
parent f66d84ae4a
commit 0015770739

View File

@ -18,24 +18,73 @@ export type TableOrderBy = "asc" | "desc" | string;
export type TableSortParams<SortingOption extends string> = { sortBy: SortingOption; orderBy: TableOrderBy }; export type TableSortParams<SortingOption extends string> = { sortBy: SortingOption; orderBy: TableOrderBy };
export type TableSortCallback<D> = (data: D) => string | number | (string | number)[]; export type TableSortCallback<D> = (data: D) => string | number | (string | number)[];
export interface TableProps<T, SortingOption extends string = string> extends React.DOMAttributes<HTMLDivElement> { export interface TableProps<Entry extends ItemObject, SortingOption extends string> extends React.DOMAttributes<HTMLDivElement> {
items?: ItemObject[]; // Raw items data /**
* Raw items data
*/
items?: Entry[];
/**
* Optional className for the root element
*/
className?: string; className?: string;
autoSize?: boolean; // Setup auto-sizing for all columns (flex: 1 0)
selectable?: boolean; // Highlight rows on hover /**
scrollable?: boolean; // Use scrollbar if content is bigger than parent's height * Setup auto-sizing for all columns (flex: 1 0)
storageKey?: string; // Keep some data in localStorage & restore on page reload, e.g sorting params */
sortable?: { autoSize?: boolean;
// Define sortable callbacks for every column in <TableHead><TableCell sortBy="someCol"><TableHead>
// @sortItem argument in the callback is an object, provided in <TableRow sortItem={someColDataItem}/> /**
[sortBy: string]: TableSortCallback<T>; * Highlight rows on hover
}; */
sortSyncWithUrl?: boolean; // sorting state is managed globally from url params selectable?: boolean;
sortByDefault?: Partial<TableSortParams<SortingOption>>; // default sorting params
onSort?: (params: TableSortParams<SortingOption>) => void; // callback on sort change, default: global sync with url /**
noItems?: React.ReactNode; // Show no items state table list is empty * Use scrollbar if content is bigger than parent's height
selectedItemId?: string; // Allows to scroll list to selected item */
virtual?: boolean; // Use virtual list component to render only visible rows scrollable?: boolean
/**
* Keep some data in localStorage & restore on page reload, e.g sorting params
*/
storageKey?: string;
/**
* Define sortable callbacks for every column in <TableHead><TableCell sortBy="someCol"><TableHead>
* @sortItem argument in the callback is an object, provided in <TableRow sortItem={someColDataItem}/>
*/
sortable?: Record<SortingOption, TableSortCallback<Entry>>;
/**
* sorting state is managed globally from url params
*/
sortSyncWithUrl?: boolean;
/**
* default sorting params
*/
sortByDefault?: Partial<TableSortParams<SortingOption>>;
/**
* callback on sort change, default: global sync with url
*/
onSort?: (params: TableSortParams<SortingOption>) => void;
/**
* Show no items state table list is empty
*/
noItems?: React.ReactNode;
/**
* Allows to scroll list to selected item
*/
selectedItemId?: string;
/**
* Use virtual list component to render only visible rows
*/
virtual?: boolean;
rowPadding?: string; rowPadding?: string;
rowLineHeight?: string; rowLineHeight?: string;
customRowHeights?: (item: object, lineHeight: number, paddings: number) => number; customRowHeights?: (item: object, lineHeight: number, paddings: number) => number;
@ -43,8 +92,8 @@ export interface TableProps<T, SortingOption extends string = string> extends Re
} }
@observer @observer
export class Table<T> extends React.Component<TableProps<T>> { export class Table<Entry extends ItemObject = ItemObject, SortingOption extends string = string> extends React.Component<TableProps<Entry, SortingOption>> {
static defaultProps: TableProps<any> = { static defaultProps: TableProps<ItemObject, string> = {
scrollable: true, scrollable: true,
autoSize: true, autoSize: true,
rowPadding: "8px", rowPadding: "8px",
@ -54,9 +103,9 @@ export class Table<T> extends React.Component<TableProps<T>> {
@observable sortParamsLocal = this.props.sortByDefault; @observable sortParamsLocal = this.props.sortByDefault;
@computed get sortParams(): Partial<TableSortParams> { @computed get sortParams(): Partial<TableSortParams<SortingOption>> {
if (this.props.sortSyncWithUrl) { if (this.props.sortSyncWithUrl) {
const sortBy = navigation.searchParams.get("sortBy"); const sortBy = navigation.searchParams.get("sortBy") as SortingOption;
const orderBy = navigation.searchParams.get("orderBy"); const orderBy = navigation.searchParams.get("orderBy");
return { sortBy, orderBy }; return { sortBy, orderBy };
@ -111,7 +160,7 @@ export class Table<T> extends React.Component<TableProps<T>> {
} }
@autobind() @autobind()
protected onSort(params: TableSortParams) { protected onSort(params: TableSortParams<SortingOption>) {
const { sortSyncWithUrl, onSort } = this.props; const { sortSyncWithUrl, onSort } = this.props;
if (sortSyncWithUrl) { if (sortSyncWithUrl) {
@ -127,14 +176,14 @@ export class Table<T> extends React.Component<TableProps<T>> {
} }
@autobind() @autobind()
sort(colName: TableSortBy) { sort(colName: SortingOption) {
const { sortBy, orderBy } = this.sortParams; const { sortBy, orderBy } = this.sortParams;
const sameColumn = sortBy == colName; const sameColumn = sortBy == colName;
const newSortBy: TableSortBy = colName; const newSortBy: SortingOption = colName;
const newOrderBy: TableOrderBy = (!orderBy || !sameColumn || orderBy === "desc") ? "asc" : "desc"; const newOrderBy: TableOrderBy = (!orderBy || !sameColumn || orderBy === "desc") ? "asc" : "desc";
this.onSort({ this.onSort({
sortBy: String(newSortBy), sortBy: newSortBy,
orderBy: newOrderBy, orderBy: newOrderBy,
}); });
} }
@ -185,15 +234,13 @@ export class Table<T> extends React.Component<TableProps<T>> {
} }
render() { render() {
const { selectable, scrollable, sortable, autoSize, virtual } = this.props; const { selectable, scrollable, sortable, autoSize, virtual, className } = this.props;
let { className } = this.props; const classNames = cssNames("Table flex column", className, {
className = cssNames("Table flex column", className, {
selectable, scrollable, sortable, autoSize, virtual, selectable, scrollable, sortable, autoSize, virtual,
}); });
return ( return (
<div className={className}> <div className={classNames}>
{this.renderHead()} {this.renderHead()}
{this.renderRows()} {this.renderRows()}
</div> </div>