Turn on strict mode in tsconfig.json, some helpful lints, and required cleanup where strictness necessitates it (#5195)

* Turn on strict mode in tsconfig.json

- Add route, clusterRoute, and payloadValidatedClusterRoute helper
  functions to improve types with backend routes

- Turn on the following new lints:
  - react/jsx-first-prop-new-line
  - react/jsx-wrap-multilines
  - react/jsx-one-expression-per-line
  - react/jsx-max-props-per-line
  - react/jsx-indent
  - react/jsx-indent-props

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix build

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Replace KubeObject scope strings with enum

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Revert package.json version changes

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* revert move hostedCluster(Id)

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* change some type param names to be not single letters

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove copy-extension-themes

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* add new make clean action

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix build to not use webpack for generating types

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix kube-object-menu.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix select.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix catalog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* revert move fileNameMigration to index

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix ref logic error

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix log-resource-selector.test.tsx tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix dock-store.test.ts test by overriding createStorage to not touch file system

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix cluster.test.ts tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix kube=api.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fixed hotbar-store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix kubeconfig-manager.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix cluster-role-bindings/__tests__/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix role-bindings/__tests__/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix pods.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix delete-cluster-dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix daemonset.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix replicaset.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix statefulsets/dialog/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix replicasets/scale-dialog/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix deployments.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix deployments/scale/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix cronjob.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix stateful-set.api.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix deployment.api.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix api-manager.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix statefulset.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix job.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix pods.store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix scroll-spy.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix hotbar-remove-command.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix catalog-entity-registry.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix welcome.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix verify-that-all-routes-have-route-component.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix pod-tolerations.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* better fix for previous 3 fixes, plus also select.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix kube-object-menu.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix app-paths.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix dock-tabs.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix isReactNode typing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix sub-title.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix drawer.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix list-layout.tsx and header.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix error-boundary.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix upgrade-chart/store.ts and dock-tab.store.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix install-chart/store.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix edit-resource/store.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix create-resource/store.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix namespace-select.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix namespace-select-filter.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix crd-list.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix wrong types for extensions

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix circular dependency

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix circular dependency on catalogCategoryRegistry

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix api-kube

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix type errors, most <Select /> errors

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fixing more type errors

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* some more fixing type errors

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* convert all KubeApis to injectable with legacy global backups

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* factor out into a common file all the exports

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* convert all KubeObjectStores to injectable with legacy global backups

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix lint

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove unused legacy KubeApi globals

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix bad previous commit

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* more crash fixing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* try and fix behavioural tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix sidebar-and-tab-navigation-for-core.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix sidebar-and-tab-navigation-for-extensions.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-using-application-menu.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix catalog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Make ThemeStore non-singleton and fix navigation-to-terminal-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* extensions.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix catalog-entity-registry.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-using-application-menu.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix log-resource-selector.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix dock-tabs.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix delete-cluster-dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-kubernetes-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-editor-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-proxy-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-using-application-menu.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-application-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix dock-store.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix select.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix role-bindings/__tests__/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix hotbar-remove-command.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix cluster-role-bindings/__tests__/dialog.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-extension-specific-preferences.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-telemetry-preferences.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix closing-preferences.test.tsx

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-editor-preferences.test.ts

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix navigation-to-proxy-preferences.test.ts

- Fix other type errors too

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* final tweaks

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add more tsconfig files, fix bug in <Catalog>

- Make all of history, navigation injectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix type errors

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Convert all of kube-details-params/ and navigate/ to injectable

- This fixes a runtime error that was encountered during testing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix runtime errors on renderer

- remove all static uses of `createPageParam` (and then removed the
  legacy global)
- Made LensRendererExtension and LensMainExtension just used
  dependencies and not the getLegacyDi
- Fixed circular dep in extension-loader

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Move registerStore calls to after injectMany

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* replace all the rest of the legacy uses of apiManager

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix stack overflow and cycles in DI

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix NamespaceSelectFilter not opening

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix WizardStep and AddNamespaceDialog

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix KubeApi's not being registered

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* cleanup WindowManager

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Proper fix for Wizard, fix NamespaceStore.subscribe

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Rewrite withTooltip to be more type correct

- Fixes mobx related "too many recursive actions" error

- Change all the uses of withTooltips to be functional components

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add e2e test to cover kube api registration

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* cleanup internal-commands

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove cast in <Animate>

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix command-palette e2e test

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix type error after rebase

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix test name

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix lint

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix code to help CodeQL scanner

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* update intree extension lock files

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix build-extensions picking wrong @types/react

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix tests from rebase

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix type error

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Make KubeconfigSyncManager more injectable

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix crash in test mode for Dialog

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* make Select snapshots deterministic

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix new type error

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix kube-object.store.test.ts typing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix merge build issues

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix snapshots after merge

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix lint after merge

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* reexport BaseKubeJsonApiObjectMetadata

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix typo in terminalSpawningPool

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove duplicate license header

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix typo to waitUntilDefined

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove iter use from getLegacyGlobalDiForExtensionApi

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove complex createStorage override

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* override logger with mocks only when needed for tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove specialized overrideStore flags for getDiForUnitTesting

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove unnecessary | undefined types from the exactOptionalFieldTypes experiment

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* use more descriptive name for local test mocks

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove unnecessary addition to 'make clean' target

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove oddity of KubeObjectStore.getById(undefined) being allowed

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* rename KubeObject.getDescriptor in favour of name without fundemental JS meaning

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Simplify legacyRegisterApi when working in behaviour unit tests

- Don't emit within main environment as there should be no auto
  registering there

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* change confusing variable name in ReactiveDuration

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* make visitor pattern more explicit for Entity contextMenuOpen

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* toggleDetails -> toggleKubeDetailsPane is more specific

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* remove outdated comment

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix bug where LensExtension dependencies are not set

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Fix tests from the revert of react 18

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix more tests from merge

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix typings with new is-compatible-extension tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* more type fixing

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Revert in-tree extension versions

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Improve name of guarding injectable for stores and apis

- New name better implies that it is just a guard state and does not do
  anything

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add helper for <Select>.isMulti for storing in a Set<Value>

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* fix is-compatible-extension.test.ts types

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton authored and GitHub committed 2022-05-16 07:17:57 -04:00
1 parent 381d77c633
commit dfcb7c3330
1062 files changed
+26512 -28689

No files matched your search

@@ -0,0 +1,19 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import createPageParamInjectable from "../../navigation/create-page-param.injectable";
const orderByUrlParamInjectable = getInjectable({
id: "order-by-url-param",
instantiate: (di) => {
const createPageParam = di.inject(createPageParamInjectable);
return createPageParam({
name: "order",
});
},
});
export default orderByUrlParamInjectable;
@@ -16,6 +16,7 @@
}
.tr {
@apply flex;
margin: calc(var(--margin) * 1.6) var(--margin);
}
@@ -40,4 +41,4 @@
.actions {
@apply justify-end;
}
}
+48 -35
View File
@@ -5,16 +5,16 @@
import styles from "./react-table.module.scss";
import React, { useCallback, useMemo } from "react";
import type { UseTableOptions } from "react-table";
import type { Row, UseTableOptions } from "react-table";
import { useFlexLayout, useSortBy, useTable } from "react-table";
import { Icon } from "../icon";
import { cssNames } from "../../utils";
export interface ReactTableProps extends UseTableOptions<any> {
export interface ReactTableProps<Data extends object> extends UseTableOptions<Data> {
headless?: boolean;
}
export function ReactTable({ columns, data, headless }: ReactTableProps) {
export function ReactTable<Data extends object>({ columns, data, headless }: ReactTableProps<Data>) {
const defaultColumn = useMemo(
() => ({
minWidth: 20,
@@ -39,54 +39,67 @@ export function ReactTable({ columns, data, headless }: ReactTableProps) {
useSortBy,
);
const RenderRow = useCallback(
({ index, style }) => {
const row = rows[index];
const renderRow = useCallback(
(row: Row<Data>) => {
prepareRow(row);
return (
<div
{...row.getRowProps({
style,
})}
className={styles.tr}
>
<div className={styles.tr} key={row.id}>
{row.cells.map((cell, index) => (
<div {...cell.getCellProps()} key={cell.getCellProps().key} className={cssNames(styles.td, columns[index].accessor)}>
<div
{...cell.getCellProps()}
key={cell.getCellProps().key}
className={cssNames(styles.td, columns[index].accessor)}
>
{cell.render("Cell")}
</div>
))}
</div>
);
},
[columns, prepareRow, rows],
[columns, prepareRow],
);
return (
<div {...getTableProps()} className={styles.table}>
{!headless && <div className={styles.thead}>
{headerGroups.map(headerGroup => (
<div {...headerGroup.getHeaderGroupProps()} key={headerGroup.getHeaderGroupProps().key} className={styles.tr}>
{headerGroup.headers.map(column => (
<div {...column.getHeaderProps(column.getSortByToggleProps())} key={column.getHeaderProps().key} className={styles.th}>
{column.render("Header")}
{/* Sort direction indicator */}
<span>
{column.isSorted
? column.isSortedDesc
? <Icon material="arrow_drop_down" small/>
: <Icon material="arrow_drop_up" small/>
: !column.disableSortBy && <Icon material="arrow_drop_down" small className={styles.disabledArrow}/>}
</span>
</div>
))}
</div>
))}
</div>}
{!headless && (
<div className={styles.thead}>
{headerGroups.map(headerGroup => (
<div
{...headerGroup.getHeaderGroupProps()}
key={headerGroup.getHeaderGroupProps().key}
className={styles.tr}
>
{headerGroup.headers.map(column => (
<div
{...column.getHeaderProps(column.getSortByToggleProps())}
key={column.getHeaderProps().key}
className={styles.th}
>
{column.render("Header")}
{/* Sort direction indicator */}
<span>
{column.isSorted
? column.isSortedDesc
? <Icon material="arrow_drop_down" small/>
: <Icon material="arrow_drop_up" small/>
: !column.disableSortBy && (
<Icon
material="arrow_drop_down"
small
className={styles.disabledArrow}
/>
)}
</span>
</div>
))}
</div>
))}
</div>
)}
<div {...getTableBodyProps()}>
{rows.map((row, index) => RenderRow({ index }))}
{rows.map(renderRow)}
</div>
</div>
);
@@ -0,0 +1,19 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import createPageParamInjectable from "../../navigation/create-page-param.injectable";
const sortByUrlParamInjectable = getInjectable({
id: "sort-by-url-param",
instantiate: (di) => {
const createPageParam = di.inject(createPageParamInjectable);
return createPageParam({
name: "sort",
});
},
});
export default sortByUrlParamInjectable;
+1 -2
View File
@@ -27,9 +27,8 @@ export function getSorted<T>(rawItems: T[], sortingCallback: TableSortCallback<T
const zipIter = tuple.zip(leftSortBy, rightSortBy);
let r = zipIter.next();
for (; r.done === false; r = zipIter.next()) {
for (; !r.done; r = zipIter.next()) {
const [nextL, nextR] = r.value;
const sortOrder = rectifyOrdering(sortCompare(nextL, nextR), orderBy);
if (sortOrder !== Ordering.EQUAL) {
+34 -17
View File
@@ -84,27 +84,26 @@ export class TableCell extends React.Component<TableCellProps> {
}
onClick(evt: React.MouseEvent<HTMLDivElement>) {
if (this.props.onClick) {
this.props.onClick(evt);
const { _sort, sortBy, onClick } = this.props;
onClick?.(evt);
if (_sort && typeof sortBy === "string") {
_sort(sortBy);
}
if (this.isSortable) {
this.props._sort(this.props.sortBy);
}
}
get isSortable() {
const { _sorting, sortBy } = this.props;
return _sorting && sortBy !== undefined;
}
renderSortIcon() {
const { sortBy, _sorting } = this.props;
if (!this.isSortable) return null;
if (!_sorting || !sortBy) {
return null;
}
const sortActive = _sorting.sortBy === sortBy;
const sortIconName = (!sortActive || _sorting.orderBy === "desc") ? "arrow_drop_down" : "arrow_drop_up";
const sortIconName = (!sortActive || _sorting.orderBy === "desc")
? "arrow_drop_down"
: "arrow_drop_up";
return (
<Icon
@@ -126,18 +125,36 @@ export class TableCell extends React.Component<TableCellProps> {
}
render() {
const { className, checkbox, isChecked, scrollable, sortBy, _sort, _sorting, _nowrap, children, title, renderBoolean: displayBoolean, showWithColumn, ...cellProps } = this.props;
const {
className,
checkbox,
isChecked,
scrollable,
sortBy,
_sort,
_sorting,
_nowrap,
children,
title,
renderBoolean: displayBoolean = false,
showWithColumn,
...cellProps
} = this.props;
const classNames = cssNames("TableCell", className, {
checkbox,
scrollable,
nowrap: _nowrap,
sorting: this.isSortable,
sorting: _sort && typeof sortBy === "string",
});
const content = displayBooleans(displayBoolean, title || children);
return (
<div {...cellProps} className={classNames} onClick={this.onClick}>
<div
{...cellProps}
className={classNames}
onClick={this.onClick}
>
{this.renderCheckbox()}
{_nowrap ? <div className="content">{content}</div> : content}
{this.renderSortIcon()}
@@ -2,7 +2,7 @@
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import type { StorageHelper } from "../../../utils";
import type { StorageLayer } from "../../../utils";
import type { TableSortParams } from "../table";
export interface TableStorageModel {
@@ -12,7 +12,7 @@ export interface TableStorageModel {
}
interface Dependencies {
storage: StorageHelper<TableStorageModel>;
storage: StorageLayer<TableStorageModel>;
}
export class TableModel {
+5 -6
View File
@@ -8,21 +8,20 @@ import "./table-row.scss";
import type { CSSProperties } from "react";
import React from "react";
import { cssNames } from "../../utils";
import type { ItemObject } from "../../../common/item.store";
export type TableRowElem = React.ReactElement<TableRowProps>;
export type TableRowElem<Item> = React.ReactElement<TableRowProps<Item>>;
export interface TableRowProps extends React.DOMAttributes<HTMLDivElement> {
export interface TableRowProps<Item> extends React.DOMAttributes<HTMLDivElement> {
className?: string;
selected?: boolean;
style?: CSSProperties;
nowrap?: boolean; // white-space: nowrap, align inner <TableCell> in one line
sortItem?: ItemObject | any; // data for sorting callback in <Table sortable={}/>
searchItem?: ItemObject | any; // data for searching filters in <Table searchable={}/>
sortItem?: Item; // data for sorting callback in <Table sortable={}/>
searchItem?: Item; // data for searching filters in <Table searchable={}/>
disabled?: boolean;
}
export class TableRow extends React.Component<TableRowProps> {
export class TableRow<Item> extends React.Component<TableRowProps<Item>> {
render() {
const { className, nowrap, selected, disabled, children, sortItem, searchItem, ...rowProps } = this.props;
const classNames = cssNames("TableRow", className, { selected, nowrap, disabled });
+52 -44
View File
@@ -7,27 +7,31 @@ import "./table.scss";
import React from "react";
import { observer } from "mobx-react";
import { autoBind, cssNames } from "../../utils";
import { autoBind, cssNames, isDefined } from "../../utils";
import type { TableRowElem, TableRowProps } from "./table-row";
import { TableRow } from "./table-row";
import type { TableHeadElem, TableHeadProps } from "./table-head";
import type { TableHeadElem } from "./table-head";
import { TableHead } from "./table-head";
import type { TableCellElem } from "./table-cell";
import { VirtualList } from "../virtual-list";
import { createPageParam } from "../../navigation";
import type { PageParam } from "../../navigation";
import { computed, makeObservable } from "mobx";
import { getSorted } from "./sorting";
import type { TableModel } from "./table-model/table-model";
import { withInjectables } from "@ogre-tools/injectable-react";
import tableModelInjectable from "./table-model/table-model.injectable";
import type { ItemObject } from "../../../common/item.store";
import assert from "assert";
import orderByUrlParamInjectable from "./order-by-url-param.injectable";
import sortByUrlParamInjectable from "./sort-by-url-param.injectable";
export type TableSortBy = string;
export type TableOrderBy = "asc" | "desc" | string;
export type TableOrderBy = "asc" | "desc";
export interface TableSortParams {
sortBy: TableSortBy;
orderBy: TableOrderBy;
}
export type TableSortCallback<Item> = (data: Item) => string | number | (string | number)[];
export type TableSortCallback<Item> = (data: Item) => undefined | string | number | (string | number)[];
export type TableSortCallbacks<Item> = Record<string, TableSortCallback<Item>>;
export interface TableProps<Item> extends React.DOMAttributes<HTMLDivElement> {
@@ -69,24 +73,18 @@ export interface TableProps<Item> extends React.DOMAttributes<HTMLDivElement> {
*/
rowLineHeight?: number;
customRowHeights?: (item: Item, lineHeight: number, paddings: number) => number;
getTableRow?: (uid: string) => React.ReactElement<TableRowProps>;
renderRow?: (item: Item) => React.ReactElement<TableRowProps>;
getTableRow?: (uid: string) => React.ReactElement<TableRowProps<Item>> | undefined | null;
renderRow?: (item: Item) => React.ReactElement<TableRowProps<Item>> | undefined | null;
}
export const sortByUrlParam = createPageParam({
name: "sort",
});
export const orderByUrlParam = createPageParam({
name: "order",
});
interface Dependencies {
model: TableModel;
sortByUrlParam: PageParam<string>;
orderByUrlParam: PageParam<string>;
}
@observer
class NonInjectedTable<Item> extends React.Component<TableProps<Item> & Dependencies> {
class NonInjectedTable<Item extends ItemObject> extends React.Component<TableProps<Item> & Dependencies> {
static defaultProps: TableProps<any> = {
scrollable: true,
autoSize: true,
@@ -117,13 +115,17 @@ class NonInjectedTable<Item> extends React.Component<TableProps<Item> & Dependen
}
@computed get sortParams() {
return Object.assign({}, this.props.sortByDefault, this.props.model.getSortParams(this.props.tableId));
const modelParams = this.props.tableId
? this.props.model.getSortParams(this.props.tableId)
: {};
return Object.assign({}, this.props.sortByDefault, modelParams);
}
renderHead() {
const { children } = this.props;
const content = React.Children.toArray(children) as (TableRowElem | TableHeadElem)[];
const headElem: React.ReactElement<TableHeadProps> = content.find(elem => elem.type === TableHead);
const content = React.Children.toArray(children) as (TableRowElem<Item> | TableHeadElem)[];
const headElem = content.find(elem => elem.type === TableHead);
if (!headElem) {
return null;
@@ -157,18 +159,23 @@ class NonInjectedTable<Item> extends React.Component<TableProps<Item> & Dependen
}
getSorted(rawItems: Item[]) {
const { sortBy, orderBy: orderByRaw } = this.sortParams;
const { sortBy, orderBy } = this.sortParams;
return getSorted(rawItems, this.props.sortable[sortBy], orderByRaw);
if (!sortBy || !orderBy) {
return rawItems;
}
return getSorted(rawItems, this.props.sortable?.[sortBy], orderBy);
}
protected onSort({ sortBy, orderBy }: TableSortParams) {
assert(this.props.tableId);
this.props.model.setSortParams(this.props.tableId, { sortBy, orderBy });
const { sortSyncWithUrl, onSort } = this.props;
if (sortSyncWithUrl) {
sortByUrlParam.set(sortBy);
orderByUrlParam.set(orderBy);
this.props.sortByUrlParam.set(sortBy);
this.props.orderByUrlParam.set(orderBy);
}
onSort?.({ sortBy, orderBy });
@@ -187,11 +194,11 @@ class NonInjectedTable<Item> extends React.Component<TableProps<Item> & Dependen
}
private getContent() {
const { items, renderRow, children } = this.props;
const content = React.Children.toArray(children) as (TableRowElem | TableHeadElem)[];
const { items = [], renderRow, children } = this.props;
const content = React.Children.toArray(children) as (TableRowElem<Item> | TableHeadElem)[];
if (renderRow) {
content.push(...items.map(renderRow));
content.push(...items.map(renderRow).filter(isDefined));
}
return content;
@@ -199,18 +206,24 @@ class NonInjectedTable<Item> extends React.Component<TableProps<Item> & Dependen
renderRows() {
const {
noItems, virtual, customRowHeights, rowLineHeight, rowPadding, items,
noItems, virtual, customRowHeights, rowLineHeight, rowPadding, items = [],
getTableRow, selectedItemId, className, virtualHeight,
} = this.props;
const content = this.getContent();
let rows: React.ReactElement<TableRowProps>[] = content.filter(elem => elem.type === TableRow);
let sortedItems = rows.length ? rows.map(row => row.props.sortItem) : [...items];
let rows: React.ReactElement<TableRowProps<Item>>[] = content.filter(elem => elem.type === TableRow);
let sortedItems = (
rows.length
? rows.map(row => row.props.sortItem)
: items
).filter(isDefined);
if (this.isSortable) {
sortedItems = this.getSorted(sortedItems);
if (rows.length) {
rows = sortedItems.map(item => rows.find(row => item == row.props.sortItem));
rows = sortedItems
.map(item => rows.find(row => item == row.props.sortItem))
.filter(isDefined);
}
}
@@ -219,6 +232,7 @@ class NonInjectedTable<Item> extends React.Component<TableProps<Item> & Dependen
}
if (virtual) {
assert(customRowHeights && rowLineHeight && rowPadding);
const rowHeights = sortedItems.map(item => customRowHeights(item, rowLineHeight, rowPadding * 2));
return (
@@ -251,18 +265,12 @@ class NonInjectedTable<Item> extends React.Component<TableProps<Item> & Dependen
}
}
const InjectedTable = withInjectables<Dependencies, TableProps<any>>(
NonInjectedTable,
{
getProps: (di, props) => ({
model: di.inject(tableModelInjectable),
...props,
}),
},
);
export function Table<Item>(props: TableProps<Item>) {
return <InjectedTable {...props} />;
}
export const Table = withInjectables<Dependencies, TableProps<ItemObject>>(NonInjectedTable, {
getProps: (di, props) => ({
...props,
model: di.inject(tableModelInjectable),
orderByUrlParam: di.inject(orderByUrlParamInjectable),
sortByUrlParam: di.inject(sortByUrlParamInjectable),
}),
}) as <Item>(props: TableProps<Item>) => React.ReactElement;