Skip to content

Commit

Permalink
Table component injection tokens (#7754)
Browse files Browse the repository at this point in the history
Signed-off-by: Alex Andreev <[email protected]>
  • Loading branch information
aleksfront authored May 26, 2023
1 parent 4b63bc2 commit 1ffdb6c
Show file tree
Hide file tree
Showing 20 changed files with 167 additions and 18 deletions.
6 changes: 4 additions & 2 deletions open-lens/src/renderer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import {
rendererExtensionApi as Renderer,
commonExtensionApi as Common,
registerLensCore,
metricsFeature
metricsFeature,
tableFeature,
} from "@k8slens/core/renderer";
import { autoRegister } from "@ogre-tools/injectable-extension-for-auto-registration";
import { registerFeature } from "@k8slens/feature-core";
Expand Down Expand Up @@ -49,7 +50,8 @@ runInAction(() => {
keyboardShortcutsFeature,
reactApplicationFeature,
routingFeature,
metricsFeature
metricsFeature,
tableFeature,
);

autoRegister({
Expand Down
18 changes: 18 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@
"@k8slens/routing": "^1.0.0-alpha.5",
"@k8slens/run-many": "^1.0.0-alpha.1",
"@k8slens/startable-stoppable": "^1.0.0-alpha.1",
"@k8slens/table-tokens": "^6.5.0-alpha.7",
"@k8slens/tooltip": "^1.0.0-alpha.5",
"@k8slens/utilities": "^1.0.0-alpha.1",
"@kubernetes/client-node": "^0.18.1",
Expand Down
15 changes: 15 additions & 0 deletions packages/core/src/features/table/table-component.injectable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { tableComponentInjectionToken } from "@k8slens/table-tokens";
import { getInjectable } from "@ogre-tools/injectable";
import { Table } from "../../renderer/components/table/table";

const tableComponentInjectable = getInjectable({
id: "table-component",
instantiate: () => ({ Component: Table }),
injectionToken: tableComponentInjectionToken,
});

export default tableComponentInjectable;
14 changes: 14 additions & 0 deletions packages/core/src/features/table/table-feature.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getFeature } from "@k8slens/feature-core";
import tableComponentInjectable from "./table-component.injectable";

export const tableFeature = getFeature({
id: "core-table-feature",

register: (di) => {
di.register(tableComponentInjectable);
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ import { Cluster } from "../../../../common/cluster/cluster";
import hostedClusterInjectable from "../../../cluster-frame-context/hosted-cluster.injectable";
import userPreferencesStateInjectable from "../../../../features/user-preferences/common/state.injectable";
import type { DiContainer } from "@ogre-tools/injectable";
import { registerFeature } from "@k8slens/feature-core";
import { runInAction } from "mobx";
import { tableFeature } from "../../../library";

describe("<PodDisruptionBudgets />", () => {
let di: DiContainer;
Expand Down Expand Up @@ -69,6 +72,10 @@ describe("<PodDisruptionBudgets />", () => {
}),
} as any,
}));

runInAction(() => {
registerFeature(di, tableFeature);
});
});

describe("PDB with minAvailable 0", () => {
Expand Down
15 changes: 11 additions & 4 deletions packages/core/src/renderer/components/item-object-list/content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ import { computed, makeObservable } from "mobx";
import { Observer, observer } from "mobx-react";
import type { ConfirmDialogParams } from "../confirm-dialog";
import type { TableProps, TableRowProps, TableSortCallbacks } from "../table";
import { Table, TableCell, TableHead, TableRow } from "../table";
import { TableCell, TableHead, TableRow } from "../table";
import type { IClassName, StrictReactNode } from "@k8slens/utilities";
import { cssNames, isDefined, isReactNode, noop, prevDefault, stopPropagation } from "@k8slens/utilities";
import type { AddRemoveButtonsProps } from "../add-remove-buttons";
import { AddRemoveButtons } from "../add-remove-buttons";
import { NoItems } from "../no-items";
import { Spinner } from "../spinner";
import type { ItemObject, TableCellProps } from "@k8slens/list-layout";
import type { GeneralKubeObjectListLayoutColumn, ItemObject, TableCellProps } from "@k8slens/list-layout";
import type { Filter, PageFiltersStore } from "./page-filters/store";
import type { LensTheme } from "../../themes/lens-theme";
import { MenuActions } from "../menu/menu-actions";
Expand All @@ -35,6 +35,8 @@ import type { ToggleTableColumnVisibility } from "../../../features/user-prefere
import toggleTableColumnVisibilityInjectable from "../../../features/user-preferences/common/toggle-table-column-visibility.injectable";
import type { IsTableColumnHidden } from "../../../features/user-preferences/common/is-table-column-hidden.injectable";
import isTableColumnHiddenInjectable from "../../../features/user-preferences/common/is-table-column-hidden.injectable";
import type { TableComponent } from "@k8slens/table-tokens";
import { tableComponentInjectionToken } from "@k8slens/table-tokens";

export interface ItemListLayoutContentProps<Item extends ItemObject, PreLoadStores extends boolean> {
getFilters: () => Filter[];
Expand All @@ -54,6 +56,7 @@ export interface ItemListLayoutContentProps<Item extends ItemObject, PreLoadStor
customizeTableRowProps?: (item: Item) => Partial<TableRowProps<Item>>;
addRemoveButtons?: Partial<AddRemoveButtonsProps>;
virtual?: boolean;
columns?: GeneralKubeObjectListLayoutColumn[];

// item details view
hasDetailsView?: boolean;
Expand All @@ -79,6 +82,7 @@ interface Dependencies {
openConfirmDialog: OpenConfirmDialog;
toggleTableColumnVisibility: ToggleTableColumnVisibility;
isTableColumnHidden: IsTableColumnHidden;
table: TableComponent;
}

@observer
Expand Down Expand Up @@ -299,6 +303,7 @@ class NonInjectedItemListLayoutContent<
const {
store, hasDetailsView, addRemoveButtons = {}, virtual, sortingCallbacks,
detailsItem, className, tableProps = {}, tableId, getItems, activeTheme,
table,
} = this.props;
const selectedItemId = detailsItem && detailsItem.getId();
const classNames = cssNames(className, "box", "grow", activeTheme.get().type);
Expand All @@ -307,8 +312,9 @@ class NonInjectedItemListLayoutContent<

return (
<div className="items box grow flex column">
<Table
<table.Component
tableId={tableId}
columns={this.props.columns}
virtual={virtual}
selectable={hasDetailsView}
sortable={sortingCallbacks}
Expand All @@ -322,7 +328,7 @@ class NonInjectedItemListLayoutContent<
>
{this.renderTableHeader()}
{this.renderItems()}
</Table>
</table.Component>

<Observer>
{() => (
Expand Down Expand Up @@ -385,5 +391,6 @@ export const ItemListLayoutContent = withInjectables<Dependencies, ItemListLayou
openConfirmDialog: di.inject(openConfirmDialogInjectable),
toggleTableColumnVisibility: di.inject(toggleTableColumnVisibilityInjectable),
isTableColumnHidden: di.inject(isTableColumnHiddenInjectable),
table: di.inject(tableComponentInjectionToken),
}),
}) as <Item extends ItemObject, PreLoadStores extends boolean>(props: ItemListLayoutContentProps<Item, PreLoadStores>) => React.ReactElement;
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import type { TableProps, TableRowProps, TableSortCallbacks } from "../table";
import type { IClassName, StrictReactNode, SingleOrMany } from "@k8slens/utilities";
import { cssNames, noop } from "@k8slens/utilities";
import type { AddRemoveButtonsProps } from "../add-remove-buttons";
import type { ItemObject, TableCellProps } from "@k8slens/list-layout";
import type { ItemObject, TableCellProps,
GeneralKubeObjectListLayoutColumn,
} from "@k8slens/list-layout";
import type { SearchInputUrlProps } from "../input";
import type { PageFiltersStore } from "./page-filters/store";
import { FilterType } from "./page-filters/store";
Expand Down Expand Up @@ -98,6 +100,7 @@ export type ItemListLayoutProps<Item extends ItemObject, PreLoadStores extends b
headerClassName?: IClassName;
renderHeaderTitle?: RenderHeaderTitle<Item, PreLoadStores>;
customizeHeader?: HeaderCustomizer | HeaderCustomizer[];
columns?: GeneralKubeObjectListLayoutColumn[];

// items list configuration
isReady?: boolean; // show loading indicator while not ready
Expand Down Expand Up @@ -304,6 +307,7 @@ class NonInjectedItemListLayout<I extends ItemObject, PreLoadStores extends bool
/>

<ItemListLayoutContent<I, PreLoadStores>
columns={this.props.columns}
getItems={() => this.items}
getFilters={() => this.filters}
tableId={this.props.tableId}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ import type { PodStore } from "../workloads-pods/store";
import { Cluster } from "../../../common/cluster/cluster";
import isTableColumnHiddenInjectable from "../../../features/user-preferences/common/is-table-column-hidden.injectable";
import { podListLayoutColumnInjectionToken } from "@k8slens/list-layout";
import { registerFeature } from "@k8slens/feature-core";
import { runInAction } from "mobx";
import { tableFeature } from "../../library";

describe("kube-object-list-layout", () => {
let di: DiContainer;
Expand Down Expand Up @@ -54,6 +57,10 @@ describe("kube-object-list-layout", () => {
get: () => ({}),
}));

runInAction(() => {
registerFeature(di, tableFeature);
});

podStore = di.inject(podStoreInjectable);
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export interface KubeObjectListLayoutProps<
// eslint-disable-next-line unused-imports/no-unused-vars-ts, @typescript-eslint/no-unused-vars
A extends KubeApi<K, D>,
D extends KubeJsonApiDataFor<K>,
> extends Omit<ItemListLayoutProps<K, false>, "getItems" | "dependentStores" | "preloadStores"> {
> extends Omit<ItemListLayoutProps<K, false>, "getItems" | "dependentStores" | "preloadStores" | "columns"> {
items?: K[];
getItems?: () => K[];
store: KubeItemListStore<K>;
Expand Down Expand Up @@ -193,6 +193,7 @@ class NonInjectedKubeObjectListLayout<
getItems={() => this.props.items || store.contextItems}
preloadStores={false} // loading handled in kubeWatchApi.subscribeStores()
detailsItem={this.selectedItem}
columns={targetColumns as GeneralKubeObjectListLayoutColumn[]}
customizeHeader={[
({ filters, searchProps, info, ...headerPlaceHolders }) => ({
filters: (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ import { sendMessageToChannelInjectionToken } from "@k8slens/messaging";
import { getMessageBridgeFake } from "@k8slens/messaging-fake-bridge";
import { historyInjectionToken } from "@k8slens/routing";
import writeJsonSyncInjectable from "../../../common/fs/write-json-sync.injectable";
import { tableFeature } from "../../library";

type MainDiCallback = (container: { mainDi: DiContainer }) => void | Promise<void>;
type WindowDiCallback = (container: { windowDi: DiContainer }) => void | Promise<void>;
Expand Down Expand Up @@ -256,6 +257,7 @@ export const getApplicationBuilder = () => {
registerFeature(
windowDi,
applicationFeature,
tableFeature,
);

windowDi.register(rendererExtensionsStateInjectable);
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/renderer/library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ export * as ReactRouterDom from "react-router-dom";
export * as rendererExtensionApi from "../extensions/renderer-api";
export * as commonExtensionApi from "../extensions/common-api";
export { metricsFeature } from "../features/metrics/metrics-feature";
export { tableFeature } from "../features/table/table-feature";
5 changes: 4 additions & 1 deletion packages/logger/src/logger.injectable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ export const logSillyInjectionToken = getInjectionToken<LogFunction>({

const screamingKebabCase = (str: string) => pipeline(str, kebabCase, toUpper);

const getLogFunctionFor = (scenario: keyof Logger, namespace: string | undefined) => {
const getLogFunctionFor = (
scenario: keyof Logger,
namespace: string | undefined
) => {
const prefix = namespace
? `[${screamingKebabCase(namespace.replace(/-feature$/, ""))}]: `
: "";
Expand Down
13 changes: 7 additions & 6 deletions packages/logger/src/logger.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ describe("logger", () => {
instantiate: (di) => di.inject(injectionToken),
});


const someFeature = getFeature({
id: "some-feature",

Expand Down Expand Up @@ -124,11 +123,13 @@ describe("logger", () => {

registerFeature(di, loggerFeature);

di.register(getInjectable({
id: "some-transport",
instantiate: () => new TransportStream({ log }),
injectionToken: loggerTransportInjectionToken,
}))
di.register(
getInjectable({
id: "some-transport",
instantiate: () => new TransportStream({ log }),
injectionToken: loggerTransportInjectionToken,
})
);

const logger = di.inject(loggerInjectable);

Expand Down
8 changes: 5 additions & 3 deletions packages/logger/src/transports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import { getInjectionToken } from "@ogre-tools/injectable";
import type TransportStream from "winston-transport";

export const loggerTransportInjectionToken = getInjectionToken<TransportStream>({
id: "logger-transport",
});
export const loggerTransportInjectionToken = getInjectionToken<TransportStream>(
{
id: "logger-transport",
}
);
3 changes: 3 additions & 0 deletions packages/table/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Description

The package exports tokens needed for external table configuration.
28 changes: 28 additions & 0 deletions packages/table/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { getInjectionToken } from "@ogre-tools/injectable";
import type { KubeObject } from "@k8slens/kube-object/src/kube-object";
import type {
BaseKubeObjectListLayoutColumn,
GeneralKubeObjectListLayoutColumn,
SpecificKubeListLayoutColumn,
} from "@k8slens/list-layout";

type Column = (
| BaseKubeObjectListLayoutColumn<KubeObject>
| SpecificKubeListLayoutColumn<KubeObject>
| GeneralKubeObjectListLayoutColumn
);

export interface TableComponentProps {
tableId?: string;
columns?: Column[];
save?: (state: object) => void;
load?: (tableId: string) => object;
}

export interface TableComponent {
Component: React.ComponentType<TableComponentProps>;
}

export const tableComponentInjectionToken = getInjectionToken<TableComponent>({
id: "table-component-injection-token",
});
28 changes: 28 additions & 0 deletions packages/table/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "@k8slens/table-tokens",
"version": "6.5.0-alpha.7",
"description": "Injection token exporter for table components",
"license": "MIT",
"type": "commonjs",
"private": false,
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
},
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist"
],
"scripts": {
"clean": "rimraf dist/",
"build": "lens-webpack-build"
},
"devDependencies": {
"@k8slens/webpack": "^6.5.0-alpha.8",
"rimraf": "^4.4.1"
},
"peerDependencies": {
"@ogre-tools/injectable": "^16.1.0"
}
}
4 changes: 4 additions & 0 deletions packages/table/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "@k8slens/typescript/config/base.json",
"include": ["**/*.ts"]
}
Loading

0 comments on commit 1ffdb6c

Please sign in to comment.