diff --git a/open-lens/src/renderer/index.ts b/open-lens/src/renderer/index.ts
index 5981151da9..49662da117 100644
--- a/open-lens/src/renderer/index.ts
+++ b/open-lens/src/renderer/index.ts
@@ -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";
@@ -49,7 +50,8 @@ runInAction(() => {
keyboardShortcutsFeature,
reactApplicationFeature,
routingFeature,
- metricsFeature
+ metricsFeature,
+ tableFeature,
);
autoRegister({
diff --git a/package-lock.json b/package-lock.json
index 3cccd40daa..cf1f675640 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -3833,6 +3833,10 @@
"resolved": "packages/utility-features/startable-stoppable",
"link": true
},
+ "node_modules/@k8slens/table-tokens": {
+ "resolved": "packages/table",
+ "link": true
+ },
"node_modules/@k8slens/test-utils": {
"resolved": "packages/utility-features/test-utils",
"link": true
@@ -34324,6 +34328,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",
@@ -35304,6 +35309,19 @@
"rimraf": "^4.4.1"
}
},
+ "packages/table": {
+ "name": "@k8slens/table-tokens",
+ "version": "6.5.0-alpha.7",
+ "license": "MIT",
+ "devDependencies": {
+ "@k8slens/webpack": "^6.5.0-alpha.8",
+ "rimraf": "^4.4.1"
+ },
+ "peerDependencies": {
+ "@ogre-tools/injectable": "^16.1.0",
+ "react": "^17.0.2"
+ }
+ },
"packages/technical-features/application/agnostic": {
"name": "@k8slens/application",
"version": "6.5.0-alpha.9",
diff --git a/packages/core/package.json b/packages/core/package.json
index 7c8052fb12..51ca511003 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -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",
diff --git a/packages/core/src/features/table/table-component.injectable.ts b/packages/core/src/features/table/table-component.injectable.ts
new file mode 100644
index 0000000000..976b941f38
--- /dev/null
+++ b/packages/core/src/features/table/table-component.injectable.ts
@@ -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;
diff --git a/packages/core/src/features/table/table-feature.ts b/packages/core/src/features/table/table-feature.ts
new file mode 100644
index 0000000000..3ecb298443
--- /dev/null
+++ b/packages/core/src/features/table/table-feature.ts
@@ -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);
+ },
+});
diff --git a/packages/core/src/renderer/components/config-pod-disruption-budgets/__tests__/pod-distruption-budgets.test.tsx b/packages/core/src/renderer/components/config-pod-disruption-budgets/__tests__/pod-distruption-budgets.test.tsx
index c423962e68..33ab10f4aa 100644
--- a/packages/core/src/renderer/components/config-pod-disruption-budgets/__tests__/pod-distruption-budgets.test.tsx
+++ b/packages/core/src/renderer/components/config-pod-disruption-budgets/__tests__/pod-distruption-budgets.test.tsx
@@ -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("", () => {
let di: DiContainer;
@@ -69,6 +72,10 @@ describe("", () => {
}),
} as any,
}));
+
+ runInAction(() => {
+ registerFeature(di, tableFeature);
+ });
});
describe("PDB with minAvailable 0", () => {
diff --git a/packages/core/src/renderer/components/item-object-list/content.tsx b/packages/core/src/renderer/components/item-object-list/content.tsx
index de19c1c058..6e5c37dbb2 100644
--- a/packages/core/src/renderer/components/item-object-list/content.tsx
+++ b/packages/core/src/renderer/components/item-object-list/content.tsx
@@ -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";
@@ -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- {
getFilters: () => Filter[];
@@ -54,6 +56,7 @@ export interface ItemListLayoutContentProps
- Partial>;
addRemoveButtons?: Partial;
virtual?: boolean;
+ columns?: GeneralKubeObjectListLayoutColumn[];
// item details view
hasDetailsView?: boolean;
@@ -79,6 +82,7 @@ interface Dependencies {
openConfirmDialog: OpenConfirmDialog;
toggleTableColumnVisibility: ToggleTableColumnVisibility;
isTableColumnHidden: IsTableColumnHidden;
+ table: TableComponent;
}
@observer
@@ -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);
@@ -307,8 +312,9 @@ class NonInjectedItemListLayoutContent<
return (
-
{this.renderTableHeader()}
{this.renderItems()}
-
+
{() => (
@@ -385,5 +391,6 @@ export const ItemListLayoutContent = withInjectables(props: ItemListLayoutContentProps- ) => React.ReactElement;
diff --git a/packages/core/src/renderer/components/item-object-list/list-layout.tsx b/packages/core/src/renderer/components/item-object-list/list-layout.tsx
index 32f46e7a2a..fd1d34eac0 100644
--- a/packages/core/src/renderer/components/item-object-list/list-layout.tsx
+++ b/packages/core/src/renderer/components/item-object-list/list-layout.tsx
@@ -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";
@@ -98,6 +100,7 @@ export type ItemListLayoutProps
- ;
customizeHeader?: HeaderCustomizer | HeaderCustomizer[];
+ columns?: GeneralKubeObjectListLayoutColumn[];
// items list configuration
isReady?: boolean; // show loading indicator while not ready
@@ -304,6 +307,7 @@ class NonInjectedItemListLayout
+ columns={this.props.columns}
getItems={() => this.items}
getFilters={() => this.filters}
tableId={this.props.tableId}
diff --git a/packages/core/src/renderer/components/kube-object-list-layout/kube-object-list-layout.test.tsx b/packages/core/src/renderer/components/kube-object-list-layout/kube-object-list-layout.test.tsx
index ee52707837..9239310005 100644
--- a/packages/core/src/renderer/components/kube-object-list-layout/kube-object-list-layout.test.tsx
+++ b/packages/core/src/renderer/components/kube-object-list-layout/kube-object-list-layout.test.tsx
@@ -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;
@@ -54,6 +57,10 @@ describe("kube-object-list-layout", () => {
get: () => ({}),
}));
+ runInAction(() => {
+ registerFeature(di, tableFeature);
+ });
+
podStore = di.inject(podStoreInjectable);
});
diff --git a/packages/core/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx b/packages/core/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx
index fe8b87dc68..87fd84504e 100644
--- a/packages/core/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx
+++ b/packages/core/src/renderer/components/kube-object-list-layout/kube-object-list-layout.tsx
@@ -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,
D extends KubeJsonApiDataFor,
-> extends Omit, "getItems" | "dependentStores" | "preloadStores"> {
+> extends Omit, "getItems" | "dependentStores" | "preloadStores" | "columns"> {
items?: K[];
getItems?: () => K[];
store: KubeItemListStore;
@@ -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: (
diff --git a/packages/core/src/renderer/components/test-utils/get-application-builder.tsx b/packages/core/src/renderer/components/test-utils/get-application-builder.tsx
index c2822c4fb5..ba69f8015e 100644
--- a/packages/core/src/renderer/components/test-utils/get-application-builder.tsx
+++ b/packages/core/src/renderer/components/test-utils/get-application-builder.tsx
@@ -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;
type WindowDiCallback = (container: { windowDi: DiContainer }) => void | Promise;
@@ -256,6 +257,7 @@ export const getApplicationBuilder = () => {
registerFeature(
windowDi,
applicationFeature,
+ tableFeature,
);
windowDi.register(rendererExtensionsStateInjectable);
diff --git a/packages/core/src/renderer/library.ts b/packages/core/src/renderer/library.ts
index 8ed023c559..2d239e7393 100644
--- a/packages/core/src/renderer/library.ts
+++ b/packages/core/src/renderer/library.ts
@@ -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";
diff --git a/packages/logger/src/logger.injectable.ts b/packages/logger/src/logger.injectable.ts
index 5a2b95e2a4..2148de334e 100644
--- a/packages/logger/src/logger.injectable.ts
+++ b/packages/logger/src/logger.injectable.ts
@@ -63,7 +63,10 @@ export const logSillyInjectionToken = getInjectionToken({
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$/, ""))}]: `
: "";
diff --git a/packages/logger/src/logger.test.ts b/packages/logger/src/logger.test.ts
index 1904cc0b05..d7282bb242 100644
--- a/packages/logger/src/logger.test.ts
+++ b/packages/logger/src/logger.test.ts
@@ -90,7 +90,6 @@ describe("logger", () => {
instantiate: (di) => di.inject(injectionToken),
});
-
const someFeature = getFeature({
id: "some-feature",
@@ -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);
diff --git a/packages/logger/src/transports.ts b/packages/logger/src/transports.ts
index 1407eb91b8..510dcbd7da 100644
--- a/packages/logger/src/transports.ts
+++ b/packages/logger/src/transports.ts
@@ -6,6 +6,8 @@
import { getInjectionToken } from "@ogre-tools/injectable";
import type TransportStream from "winston-transport";
-export const loggerTransportInjectionToken = getInjectionToken({
- id: "logger-transport",
-});
+export const loggerTransportInjectionToken = getInjectionToken(
+ {
+ id: "logger-transport",
+ }
+);
diff --git a/packages/table/README.md b/packages/table/README.md
new file mode 100644
index 0000000000..e66efd11b8
--- /dev/null
+++ b/packages/table/README.md
@@ -0,0 +1,3 @@
+# Description
+
+The package exports tokens needed for external table configuration.
diff --git a/packages/table/index.ts b/packages/table/index.ts
new file mode 100644
index 0000000000..b6f785dfb2
--- /dev/null
+++ b/packages/table/index.ts
@@ -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
+ | SpecificKubeListLayoutColumn
+ | GeneralKubeObjectListLayoutColumn
+);
+
+export interface TableComponentProps {
+ tableId?: string;
+ columns?: Column[];
+ save?: (state: object) => void;
+ load?: (tableId: string) => object;
+}
+
+export interface TableComponent {
+ Component: React.ComponentType;
+}
+
+export const tableComponentInjectionToken = getInjectionToken({
+ id: "table-component-injection-token",
+});
diff --git a/packages/table/package.json b/packages/table/package.json
new file mode 100644
index 0000000000..5e8d5db658
--- /dev/null
+++ b/packages/table/package.json
@@ -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"
+ }
+}
diff --git a/packages/table/tsconfig.json b/packages/table/tsconfig.json
new file mode 100644
index 0000000000..1819203dc1
--- /dev/null
+++ b/packages/table/tsconfig.json
@@ -0,0 +1,4 @@
+{
+ "extends": "@k8slens/typescript/config/base.json",
+ "include": ["**/*.ts"]
+}
diff --git a/packages/table/webpack.config.js b/packages/table/webpack.config.js
new file mode 100644
index 0000000000..3183f30179
--- /dev/null
+++ b/packages/table/webpack.config.js
@@ -0,0 +1 @@
+module.exports = require("@k8slens/webpack").configForNode;