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

Add some documentation

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-01-19 09:44:28 -05:00
parent b134cdca97
commit 4aae3f3fcd
10 changed files with 159 additions and 63 deletions

View File

@ -103,8 +103,12 @@ publish-npm: node_modules build-npm
cd src/extensions/npm/extensions && npm publish --access=public --tag=$(NPM_RELEASE_TAG) cd src/extensions/npm/extensions && npm publish --access=public --tag=$(NPM_RELEASE_TAG)
git restore src/extensions/npm/extensions/package.json git restore src/extensions/npm/extensions/package.json
.PHONY: build-docs
build-docs:
yarn typedocs-extensions-api
.PHONY: docs .PHONY: docs
docs: docs: build-docs
yarn mkdocs-serve-local yarn mkdocs-serve-local
.PHONY: clean-extensions .PHONY: clean-extensions

View File

@ -14,26 +14,28 @@ Each guide or code sample includes the following:
## Guides ## Guides
| Guide | APIs | | Guide | APIs |
| ----- | ----- | | ------------------------------------------------------------------ | ---------------------- |
| [Generate new extension project](generator.md) || | [Generate new extension project](generator.md) | |
| [Main process extension](main-extension.md) | Main.LensExtension | | [Main process extension](main-extension.md) | Main.LensExtension |
| [Renderer process extension](renderer-extension.md) | Renderer.LensExtension | | [Renderer process extension](renderer-extension.md) | Renderer.LensExtension |
| [Resource stack (cluster feature)](resource-stack.md) | | | [Resource stack (cluster feature)](resource-stack.md) | |
| [Extending KubernetesCluster)](extending-kubernetes-cluster.md) | | | [Extending KubernetesCluster)](extending-kubernetes-cluster.md) | |
| [Stores](stores.md) | | | [Stores](stores.md) | |
| [Components](components.md) | | | [Components](components.md) | |
| [KubeObjectListLayout](kube-object-list-layout.md) | | | [KubeObjectListLayout](kube-object-list-layout.md) | |
| [Working with mobx](working-with-mobx.md) | | | [Working with mobx](working-with-mobx.md) | |
| [Protocol Handlers](protocol-handlers.md) | | | [Protocol Handlers](protocol-handlers.md) | |
| [Sending Data between main and renderer](ipc.md) | | | [Sending Data between main and renderer](ipc.md) | |
| [Catalog Entities and Categories](catalog.md) | |
| [Adding Custom Columns for Categories](custom-category-columns.md) | |
## Samples ## Samples
| Sample | APIs | | Sample | APIs |
| ----- | ----- | | ---------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
[hello-world](https://github.com/lensapp/lens-extension-samples/tree/master/helloworld-sample) | LensMainExtension <br> LensRendererExtension <br> Renderer.Component.Icon <br> Renderer.Component.IconProps | | [hello-world](https://github.com/lensapp/lens-extension-samples/tree/master/helloworld-sample) | LensMainExtension <br> LensRendererExtension <br> Renderer.Component.Icon <br> Renderer.Component.IconProps |
[styling-css-modules-sample](https://github.com/lensapp/lens-extension-samples/tree/master/styling-css-modules-sample) | LensMainExtension <br> LensRendererExtension <br> Renderer.Component.Icon <br> Renderer.Component.IconProps | | [styling-css-modules-sample](https://github.com/lensapp/lens-extension-samples/tree/master/styling-css-modules-sample) | LensMainExtension <br> LensRendererExtension <br> Renderer.Component.Icon <br> Renderer.Component.IconProps |
[styling-emotion-sample](https://github.com/lensapp/lens-extension-samples/tree/master/styling-emotion-sample) | LensMainExtension <br> LensRendererExtension <br> Renderer.Component.Icon <br> Renderer.Component.IconProps | | [styling-emotion-sample](https://github.com/lensapp/lens-extension-samples/tree/master/styling-emotion-sample) | LensMainExtension <br> LensRendererExtension <br> Renderer.Component.Icon <br> Renderer.Component.IconProps |
[styling-sass-sample](https://github.com/lensapp/lens-extension-samples/tree/master/styling-sass-sample) | LensMainExtension <br> LensRendererExtension <br> Renderer.Component.Icon <br> Renderer.Component.IconProps | | [styling-sass-sample](https://github.com/lensapp/lens-extension-samples/tree/master/styling-sass-sample) | LensMainExtension <br> LensRendererExtension <br> Renderer.Component.Icon <br> Renderer.Component.IconProps |
[custom-resource-page](https://github.com/lensapp/lens-extension-samples/tree/master/custom-resource-page) | LensRendererExtension <br> Renderer.K8sApi.KubeApi <br> Renderer.K8sApi.KubeObjectStore <br> Renderer.Component.KubeObjectListLayout <br> Renderer.Component.KubeObjectDetailsProps <br> Renderer.Component.IconProps | | [custom-resource-page](https://github.com/lensapp/lens-extension-samples/tree/master/custom-resource-page) | LensRendererExtension <br> Renderer.K8sApi.KubeApi <br> Renderer.K8sApi.KubeObjectStore <br> Renderer.Component.KubeObjectListLayout <br> Renderer.Component.KubeObjectDetailsProps <br> Renderer.Component.IconProps |

View File

@ -1,5 +1,27 @@
# Catalog (WIP) # Catalog (WIP)
## CatalogCategoryRegistry This guide is a brief overview about how the catalog works within Lens.
The catalog should be thought of as the single source of truth about data within Lens.
## CatalogEntityRegistry The data flow is unidirectional, it only flows from the main side to the renderer side.
All data is public within the catalog.
## Categories
A cateogry is the declaration to the catalog of a specific kind of entity.
It declares the currently supported versions of that kind of entity but providing the constructors for the entity classes.
To declare a new category class you must create a new class that extends [Common.Catalog.CatalogCategory](../api/classes/Common.Catalog.CatalogCategory.md) and implement all of the abstract fields.
The categories provided by Lens itself have the following names:
- `KubernetesClusters`
- `WebLinks`
- `General`
To register a category, call the `Main.Catalog.catalogCategories.add()` and `Renderer.Catalog.catalogCategories.add()` with instances of your class.
## Entities
An entity is the data within the catalog.
All entities are typed and the class instances will be recreated on the renderer side by the catalog and the category registrations.

View File

@ -16,11 +16,11 @@ import { Main } from "@k8slens/extensions";
export default class ExampleExtensionMain extends Main.LensExtension { export default class ExampleExtensionMain extends Main.LensExtension {
onActivate() { onActivate() {
console.log('custom main process extension code started'); console.log("custom main process extension code started");
} }
onDeactivate() { onDeactivate() {
console.log('custom main process extension de-activated'); console.log("custom main process extension de-activated");
} }
} }
``` ```
@ -33,21 +33,21 @@ Implementing `onDeactivate()` gives you the opportunity to clean up after your e
Disable extensions from the Lens Extensions page: Disable extensions from the Lens Extensions page:
1. Navigate to **File** > **Extensions** in the top menu bar. 1. Navigate to **File** > **Extensions** in the top menu bar.
(On Mac, it is **Lens** > **Extensions**.) (On Mac, it is **Lens** > **Extensions**.)
2. Click **Disable** on the extension you want to disable. 2. Click **Disable** on the extension you want to disable.
The example above logs messages when the extension is enabled and disabled. The example above logs messages when the extension is enabled and disabled.
To see standard output from the main process there must be a console connected to it. To see standard output from the main process there must be a console connected to it.
Achieve this by starting Lens from the command prompt. Achieve this by starting Lens from the command prompt.
For more details on accessing Lens state data, please see the [Stores](../stores) guide. For more details on accessing Lens state data, please see the [Stores](stores.md) guide.
### `appMenus` ### `appMenus`
The Main Extension API allows you to customize the UI application menu. The Main Extension API allows you to customize the UI application menu.
The following example demonstrates adding an item to the **Help** menu. The following example demonstrates adding an item to the **Help** menu.
``` typescript ```typescript
import { Main } from "@k8slens/extensions"; import { Main } from "@k8slens/extensions";
export default class SamplePageMainExtension extends Main.LensExtension { export default class SamplePageMainExtension extends Main.LensExtension {
@ -57,9 +57,9 @@ export default class SamplePageMainExtension extends Main.LensExtension {
label: "Sample", label: "Sample",
click() { click() {
console.log("Sample clicked"); console.log("Sample clicked");
} },
} },
] ];
} }
``` ```
@ -67,18 +67,18 @@ export default class SamplePageMainExtension extends Main.LensExtension {
`MenuRegistration` extends Electron's `MenuItemConstructorOptions` interface. `MenuRegistration` extends Electron's `MenuItemConstructorOptions` interface.
The properties of the appMenus array objects are defined as follows: The properties of the appMenus array objects are defined as follows:
* `parentId` is the name of the menu where your new menu item will be listed. - `parentId` is the name of the menu where your new menu item will be listed.
Valid values include: `"file"`, `"edit"`, `"view"`, and `"help"`. Valid values include: `"file"`, `"edit"`, `"view"`, and `"help"`.
`"lens"` is valid on Mac only. `"lens"` is valid on Mac only.
* `label` is the name of your menu item. - `label` is the name of your menu item.
* `click()` is called when the menu item is selected. - `click()` is called when the menu item is selected.
In this example, we simply log a message. In this example, we simply log a message.
However, you would typically have this navigate to a specific page or perform another operation. However, you would typically have this navigate to a specific page or perform another operation.
Note that pages are associated with the [`Renderer.LensExtension`](renderer-extension.md) class and can be defined in the process of extending it. Note that pages are associated with the [`Renderer.LensExtension`](renderer-extension.md) class and can be defined in the process of extending it.
The following example demonstrates how an application menu can be used to navigate to such a page: The following example demonstrates how an application menu can be used to navigate to such a page:
``` typescript ```typescript
import { Main } from "@k8slens/extensions"; import { Main } from "@k8slens/extensions";
export default class SamplePageMainExtension extends Main.LensExtension { export default class SamplePageMainExtension extends Main.LensExtension {
@ -86,9 +86,9 @@ export default class SamplePageMainExtension extends Main.LensExtension {
{ {
parentId: "help", parentId: "help",
label: "Sample", label: "Sample",
click: () => this.navigate("myGlobalPage") click: () => this.navigate("myGlobalPage"),
} },
] ];
} }
``` ```
@ -99,32 +99,36 @@ This page would be defined in your extension's `Renderer.LensExtension` implemen
`trayMenus` is an array of `TrayMenuRegistration` objects. Most importantly you can define a `label` and a `click` handler. Other properties are `submenu`, `enabled`, `toolTip`, `id` and `type`. `trayMenus` is an array of `TrayMenuRegistration` objects. Most importantly you can define a `label` and a `click` handler. Other properties are `submenu`, `enabled`, `toolTip`, `id` and `type`.
``` typescript ```typescript
interface TrayMenuRegistration { interface TrayMenuRegistration {
label?: string; label?: string;
click?: (menuItem: TrayMenuRegistration) => void; click?: (menuItem: TrayMenuRegistration) => void;
id?: string; id?: string;
type?: "normal" | "separator" | "submenu" type?: "normal" | "separator" | "submenu";
toolTip?: string; toolTip?: string;
enabled?: boolean; enabled?: boolean;
submenu?: TrayMenuRegistration[] submenu?: TrayMenuRegistration[];
} }
``` ```
The following example demonstrates how tray menus can be added from extension: The following example demonstrates how tray menus can be added from extension:
``` typescript ```typescript
import { Main } from "@k8slens/extensions"; import { Main } from "@k8slens/extensions";
export default class SampleTrayMenuMainExtension extends Main.LensExtension { export default class SampleTrayMenuMainExtension extends Main.LensExtension {
trayMenus = [{ trayMenus = [
label: "menu from the extension", {
click: () => { console.log("tray menu clicked!") } label: "menu from the extension",
}] click: () => {
console.log("tray menu clicked!");
},
},
];
} }
``` ```
### `addCatalogSource()` and `removeCatalogSource()` Methods ### `addCatalogSource()` and `removeCatalogSource()` Methods
The `Main.LensExtension` class also provides the `addCatalogSource()` and `removeCatalogSource()` methods, for managing custom catalog items (or entities). The `Main.LensExtension` class also provides the `addCatalogSource()` and `removeCatalogSource()` methods, for managing custom catalog items (or entities).
See the [`Catalog`](catalog.md) documentation for full details about the catalog. See the [`Catalog`](catalog.md) documentation for full details about the catalog.

View File

@ -84,35 +84,91 @@ export interface CatalogCategorySpec {
} }
/** /**
* If the filter returns true, the menu item is displayed * If the filter return a thruthy value, the menu item is displayed
*/ */
export type AddMenuFilter = (menu: CatalogEntityAddMenu) => any; export type AddMenuFilter = (menu: CatalogEntityAddMenu) => any;
export interface CatalogCategoryEvents { export interface CatalogCategoryEvents {
/**
* This event will be emitted when the category is loaded in the catalog
* view.
*/
load: () => void; load: () => void;
/**
* This event will be emitted when the catalog add menu is opened and is the
* way to added entries to that menu.
*/
catalogAddMenu: (context: CatalogEntityAddMenuContext) => void; catalogAddMenu: (context: CatalogEntityAddMenuContext) => void;
/**
* This event will be emitted when the context menu for an entity is declared
* by this category is opened.
*/
contextMenuOpen: (entity: CatalogEntity, context: CatalogEntityContextMenuContext) => void; contextMenuOpen: (entity: CatalogEntity, context: CatalogEntityContextMenuContext) => void;
} }
export abstract class CatalogCategory extends (EventEmitter as new () => TypedEmitter<CatalogCategoryEvents>) { export abstract class CatalogCategory extends (EventEmitter as new () => TypedEmitter<CatalogCategoryEvents>) {
/**
* The version of category that you are wanting to declare.
*
* Currently supported values:
*
* - `"catalog.k8slens.dev/v1alpha1"`
*/
abstract readonly apiVersion: string; abstract readonly apiVersion: string;
/**
* The kind of item you wish to declare.
*
* Currently supported values:
*
* - `"CatalogCategory"`
*/
abstract readonly kind: string; abstract readonly kind: string;
abstract metadata: {
/**
* The data about the category itself
*/
abstract readonly metadata: {
/**
* The name of your category. The category can be searched for by this
* value. This will also be used for the catalog menu.
*/
name: string; name: string;
/**
* Either an `<svg>` or the name of an icon from {@link IconProps}
*/
icon: string; icon: string;
}; };
/**
* The most important part of a category, as it is where entity versions are declared.
*/
abstract spec: CatalogCategorySpec; abstract spec: CatalogCategorySpec;
/**
* @internal
*/
protected filters = observable.set<AddMenuFilter>([], { protected filters = observable.set<AddMenuFilter>([], {
deep: false, deep: false,
}); });
static parseId(id = ""): { group?: string, kind?: string } { /**
* Parse a category ID into parts.
* @param id The id of a category is parse
* @returns The group and kind parts of the ID
*/
public static parseId(id: string): { group?: string, kind?: string } {
const [group, kind] = id.split("/") ?? []; const [group, kind] = id.split("/") ?? [];
return { group, kind }; return { group, kind };
} }
/**
* Get the ID of this category
*/
public getId(): string { public getId(): string {
return `${this.spec.group}/${this.spec.names.kind}`; return `${this.spec.group}/${this.spec.names.kind}`;
} }

View File

@ -4,16 +4,16 @@
*/ */
/** /**
* Get the value behind `key`. If it was not pressent, first insert `value` * Get the value behind `key`. If it was not present, first insert `value`
* @param map The map to interact with * @param map The map to interact with
* @param key The key to insert into the map with * @param key The key to insert into the map with
* @param value The value to optional add to the map * @param value The value to optional add to the map
* @returns The value in the map * @returns The value in the map
*/ */
export function getOrInsert<K, V>(map: Map<K, V>, key: K, value: V): V { export function getOrInsert<K, V>(map: Map<K, V>, key: K, value: V): V {
if (map.has(key)) { if (!map.has(key)) {
return map.get(key); map.set(key, value);
} }
return map.set(key, value).get(key); return map.get(key);
} }

View File

@ -31,6 +31,11 @@ export * from "../../renderer/components/input/input";
// command-overlay // command-overlay
export const CommandOverlay = asLegacyGlobalObjectForExtensionApi(commandOverlayInjectable); export const CommandOverlay = asLegacyGlobalObjectForExtensionApi(commandOverlayInjectable);
export type {
CategoryColumnRegistration,
AdditionalCategoryColumnRegistration,
} from "../../renderer/components/+catalog/custom-category-columns";
// other components // other components
export * from "../../renderer/components/icon"; export * from "../../renderer/components/icon";
export * from "../../renderer/components/tooltip"; export * from "../../renderer/components/tooltip";

View File

@ -14,9 +14,12 @@ import type { AdditionalCategoryColumnRegistration, CategoryColumnRegistration }
import getCategoryColumnsInjectable, { CategoryColumns, GetCategoryColumnsParams } from "../get-category-columns.injectable"; import getCategoryColumnsInjectable, { CategoryColumns, GetCategoryColumnsParams } from "../get-category-columns.injectable";
class TestCategory extends CatalogCategory { class TestCategory extends CatalogCategory {
apiVersion: string; apiVersion = "catalog.k8slens.dev/v1alpha1";
kind: string; kind = "CatalogCategory";
metadata: { name: string; icon: string; }; metadata: {
name: "Test";
icon: "question_mark";
};
spec: CatalogCategorySpec = { spec: CatalogCategorySpec = {
group: "foo.bar.bat", group: "foo.bar.bat",
names: { names: {

View File

@ -8,7 +8,7 @@
import "./markdown-viewer.scss"; import "./markdown-viewer.scss";
import React, { Component } from "react"; import React, { Component } from "react";
import { marked } from "marked"; import marked from "marked";
import DOMPurify from "dompurify"; import DOMPurify from "dompurify";
import { cssNames } from "../../utils"; import { cssNames } from "../../utils";