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

some more work on react-table

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2021-04-28 09:15:00 -04:00
parent ce27d704ae
commit f8afab2efe
4 changed files with 182 additions and 49 deletions

View File

@ -172,6 +172,7 @@
"@hapi/call": "^8.0.0", "@hapi/call": "^8.0.0",
"@hapi/subtext": "^7.0.3", "@hapi/subtext": "^7.0.3",
"@kubernetes/client-node": "^0.12.0", "@kubernetes/client-node": "^0.12.0",
"@types/react-table": "^7.0.29",
"abort-controller": "^3.0.0", "abort-controller": "^3.0.0",
"array-move": "^3.0.0", "array-move": "^3.0.0",
"await-lock": "^2.1.0", "await-lock": "^2.1.0",
@ -213,6 +214,7 @@
"react": "^17.0.1", "react": "^17.0.1",
"react-dom": "^17.0.1", "react-dom": "^17.0.1",
"react-router": "^5.2.0", "react-router": "^5.2.0",
"react-table": "^7.7.0",
"readable-stream": "^3.6.0", "readable-stream": "^3.6.0",
"request": "^2.88.2", "request": "^2.88.2",
"request-promise-native": "^1.0.8", "request-promise-native": "^1.0.8",

View File

@ -5,41 +5,41 @@ import { observer } from "mobx-react";
import { computed } from "mobx"; import { computed } from "mobx";
import { Icon } from "../icon"; import { Icon } from "../icon";
import { SubHeader } from "../layout/sub-header"; import { SubHeader } from "../layout/sub-header";
import { Table, TableCell, TableHead, TableRow } from "../table";
import { nodesStore } from "../+nodes/nodes.store"; import { nodesStore } from "../+nodes/nodes.store";
import { eventStore } from "../+events/event.store"; import { eventStore } from "../+events/event.store";
import { autobind, cssNames, prevDefault } from "../../utils"; import { cssNames } from "../../utils";
import { ItemObject } from "../../item.store";
import { Spinner } from "../spinner"; import { Spinner } from "../spinner";
import { ThemeStore } from "../../theme.store";
import { lookupApiLink } from "../../api/kube-api"; import { lookupApiLink } from "../../api/kube-api";
import { kubeSelectedUrlParam, showDetails } from "../kube-object"; import { ReactiveTable } from "../reactive-table/reactive-table";
import { Column } from "react-table";
interface Props { interface Props {
className?: string; className?: string;
} }
interface IWarning extends ItemObject { interface IWarning {
kind: string; kind: string;
id: string;
name: string;
message: string; message: string;
selfLink: string; selfLink: string;
age: string | number; age: string | number;
timeDiffFromNow: number; timeDiffFromNow: number;
} }
enum sortBy { // enum sortBy {
type = "type", // type = "type",
object = "object", // object = "object",
age = "age", // age = "age",
} // }
@observer @observer
export class ClusterIssues extends React.Component<Props> { export class ClusterIssues extends React.Component<Props> {
private sortCallbacks = { // private sortCallbacks = {
[sortBy.type]: (warning: IWarning) => warning.kind, // [sortBy.type]: (warning: IWarning) => warning.kind,
[sortBy.object]: (warning: IWarning) => warning.getName(), // [sortBy.object]: (warning: IWarning) => warning.getName(),
[sortBy.age]: (warning: IWarning) => warning.timeDiffFromNow, // [sortBy.age]: (warning: IWarning) => warning.timeDiffFromNow,
}; // };
@computed get warnings() { @computed get warnings() {
const warnings: IWarning[] = []; const warnings: IWarning[] = [];
@ -51,8 +51,8 @@ export class ClusterIssues extends React.Component<Props> {
node.getWarningConditions().forEach(({ message }) => { node.getWarningConditions().forEach(({ message }) => {
warnings.push({ warnings.push({
age: getAge(), age: getAge(),
getId, id: getId(),
getName, name: getName(),
timeDiffFromNow: getTimeDiffFromNow(), timeDiffFromNow: getTimeDiffFromNow(),
kind, kind,
message, message,
@ -69,8 +69,8 @@ export class ClusterIssues extends React.Component<Props> {
const { uid, name, kind } = involvedObject; const { uid, name, kind } = involvedObject;
warnings.push({ warnings.push({
getId: () => uid, id: uid,
getName: () => name, name,
timeDiffFromNow: getTimeDiffFromNow(), timeDiffFromNow: getTimeDiffFromNow(),
age: getAge(), age: getAge(),
message, message,
@ -82,34 +82,57 @@ export class ClusterIssues extends React.Component<Props> {
return warnings; return warnings;
} }
@autobind() columns: Column<IWarning>[] = [
getTableRow(uid: string) { {
const { warnings } = this; id: "message",
const warning = warnings.find(warn => warn.getId() == uid); Header: "Message",
const { getId, getName, message, kind, selfLink, age } = warning; accessor: "message",
},
{
id: "name",
Header: "Object Name",
accessor: "name",
},
{
id: "kind",
Header: "Kind",
accessor: "kind",
},
{
id: "age",
Header: "Age",
accessor: "age",
},
];
return ( // @autobind()
<TableRow // getTableRow(uid: string) {
key={getId()} // const { warnings } = this;
sortItem={warning} // const warning = warnings.find(warn => warn.getId() == uid);
selected={selfLink === kubeSelectedUrlParam.get()} // const { getId, getName, message, kind, selfLink, age } = warning;
onClick={prevDefault(() => showDetails(selfLink))}
> // return (
<TableCell className="message"> // <TableRow
{message} // key={getId()}
</TableCell> // sortItem={warning}
<TableCell className="object"> // selected={selfLink === kubeSelectedUrlParam.get()}
{getName()} // onClick={prevDefault(() => showDetails(selfLink))}
</TableCell> // >
<TableCell className="kind"> // <TableCell className="message">
{kind} // {message}
</TableCell> // </TableCell>
<TableCell className="age"> // <TableCell className="object">
{age} // {getName()}
</TableCell> // </TableCell>
</TableRow> // <TableCell className="kind">
); // {kind}
} // </TableCell>
// <TableCell className="age">
// {age}
// </TableCell>
// </TableRow>
// );
// }
renderContent() { renderContent() {
const { warnings } = this; const { warnings } = this;
@ -136,7 +159,11 @@ export class ClusterIssues extends React.Component<Props> {
<Icon material="error_outline"/>{" "} <Icon material="error_outline"/>{" "}
<>Warnings: {warnings.length}</> <>Warnings: {warnings.length}</>
</SubHeader> </SubHeader>
<Table <ReactiveTable
columns={this.columns}
data={this.warnings}
/>
{/* <Table
tableId="cluster_issues" tableId="cluster_issues"
items={warnings} items={warnings}
virtual virtual
@ -153,7 +180,7 @@ export class ClusterIssues extends React.Component<Props> {
<TableCell className="kind" sortBy={sortBy.type}>Type</TableCell> <TableCell className="kind" sortBy={sortBy.type}>Type</TableCell>
<TableCell className="timestamp" sortBy={sortBy.age}>Age</TableCell> <TableCell className="timestamp" sortBy={sortBy.age}>Age</TableCell>
</TableHead> </TableHead>
</Table> </Table> */}
</> </>
); );
} }

View File

@ -0,0 +1,92 @@
import React from "react";
import { useTable, useBlockLayout, useResizeColumns, Column, HeaderGroup, UseResizeColumnsColumnProps } from "react-table";
export interface TableProps<T extends object> {
columns: Column<T>[];
data: T[];
}
export function ReactiveTable<T extends object>({ columns, data }: TableProps<T>) {
const defaultColumn = React.useMemo(
() => ({
minWidth: 30,
width: 150,
maxWidth: 400,
}),
[]
);
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
state,
} = useTable<T>(
{
columns,
data,
defaultColumn,
},
useBlockLayout,
useResizeColumns
);
return (
<>
<div>
<div {...getTableProps()} className="table">
<div>
{headerGroups.map(headerGroup => {
const { key, ...headerProps } = headerGroup.getHeaderGroupProps();
return (
<div key={key} {...headerProps} className="tr">
{headerGroup.headers.map(c => {
const column = c as HeaderGroup<T> & UseResizeColumnsColumnProps<T>; // needed until react table v8 is done
const { key, ...columnProps } = column.getHeaderProps();
return (
<div key={key} {...columnProps} className="th">
{column.render("Header")}
<div
{...column.getResizerProps()}
className={`resizer ${column.isResizing ? "isResizing" : ""}`}
/>
</div>
);
})}
</div>
);
})}
</div>
<div {...getTableBodyProps()}>
{rows.map(row => {
prepareRow(row);
const { key, ...rowProps } = row.getRowProps();
return (
<div key={key} {...rowProps} className="tr">
{row.cells.map(cell => {
const { key, ...cellProps } = cell.getCellProps();
return (
<div key={key} {...cellProps} className="td">
{cell.render("Cell")}
</div>
);
})}
</div>
);
})}
</div>
</div>
</div>
<pre>
<code>{JSON.stringify(state, null, 2)}</code>
</pre>
</>
);
}

View File

@ -1618,6 +1618,13 @@
"@types/react-dom" "*" "@types/react-dom" "*"
"@types/react-transition-group" "*" "@types/react-transition-group" "*"
"@types/react-table@^7.0.29":
version "7.0.29"
resolved "https://registry.yarnpkg.com/@types/react-table/-/react-table-7.0.29.tgz#af2c82f2d6a39be5bc0f191b30501309a8db0949"
integrity sha512-RCGVKGlTDv3jbj37WJ5HhN3sPb0W/2rqlvyGUtvawnnyrxgI2BGgASvU93rq2jwanVp5J9l1NYAeiGlNhdaBGw==
dependencies:
"@types/react" "*"
"@types/react-transition-group@*", "@types/react-transition-group@^4.2.0": "@types/react-transition-group@*", "@types/react-transition-group@^4.2.0":
version "4.4.0" version "4.4.0"
resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.0.tgz#882839db465df1320e4753e6e9f70ca7e9b4d46d" resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.0.tgz#882839db465df1320e4753e6e9f70ca7e9b4d46d"
@ -11565,6 +11572,11 @@ react-select@^3.1.0:
react-input-autosize "^2.2.2" react-input-autosize "^2.2.2"
react-transition-group "^4.3.0" react-transition-group "^4.3.0"
react-table@^7.7.0:
version "7.7.0"
resolved "https://registry.yarnpkg.com/react-table/-/react-table-7.7.0.tgz#e2ce14d7fe3a559f7444e9ecfe8231ea8373f912"
integrity sha512-jBlj70iBwOTvvImsU9t01LjFjy4sXEtclBovl3mTiqjz23Reu0DKnRza4zlLtOPACx6j2/7MrQIthIK1Wi+LIA==
react-transition-group@^4.3.0, react-transition-group@^4.4.0: react-transition-group@^4.3.0, react-transition-group@^4.4.0:
version "4.4.1" version "4.4.1"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9"