mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
more DRY, remove DrawerSection, DrawerSubSection, and DrawerSubTitle
Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
2b2395d4dd
commit
3c530ab0ed
@ -6,29 +6,29 @@ The Renderer Extension API allows you to access, configure, and customize Lens d
|
|||||||
|
|
||||||
The custom Lens UI elements that you can add include:
|
The custom Lens UI elements that you can add include:
|
||||||
|
|
||||||
* [Cluster pages](#clusterpages)
|
- [Cluster pages](#clusterpages)
|
||||||
* [Cluster page menus](#clusterpagemenus)
|
- [Cluster page menus](#clusterpagemenus)
|
||||||
* [Global pages](#globalpages)
|
- [Global pages](#globalpages)
|
||||||
* [Welcome menus](#welcomemenus)
|
- [Welcome menus](#welcomemenus)
|
||||||
* [App preferences](#apppreferences)
|
- [App preferences](#apppreferences)
|
||||||
* [Top bar items](#topbaritems)
|
- [Top bar items](#topbaritems)
|
||||||
* [Status bar items](#statusbaritems)
|
- [Status bar items](#statusbaritems)
|
||||||
* [KubeObject menu items](#kubeobjectmenuitems)
|
- [KubeObject menu items](#kubeobjectmenuitems)
|
||||||
* [KubeObject detail items](#kubeobjectdetailitems)
|
- [KubeObject detail items](#kubeobjectdetailitems)
|
||||||
* [KubeObject status texts](#kubeobjectstatustexts)
|
- [KubeObject status texts](#kubeobjectstatustexts)
|
||||||
* [Kube workloads overview items](#kubeworkloadsoverviewitems)
|
- [Kube workloads overview items](#kubeworkloadsoverviewitems)
|
||||||
|
|
||||||
as well as catalog-related UI elements:
|
as well as catalog-related UI elements:
|
||||||
|
|
||||||
* [Entity settings](#entitysettings)
|
- [Entity settings](#entitysettings)
|
||||||
* [Catalog entity detail items](#catalogentitydetailitems)
|
- [Catalog entity detail items](#catalogentitydetailitems)
|
||||||
|
|
||||||
All UI elements are based on React components.
|
All UI elements are based on React components.
|
||||||
|
|
||||||
Finally, you can also add commands and protocol handlers:
|
Finally, you can also add commands and protocol handlers:
|
||||||
|
|
||||||
* [Command palette commands](#commandpalettecommands)
|
- [Command palette commands](#commandpalettecommands)
|
||||||
* [protocol handlers](protocol-handlers.md)
|
- [protocol handlers](protocol-handlers.md)
|
||||||
|
|
||||||
## `Renderer.LensExtension` Class
|
## `Renderer.LensExtension` Class
|
||||||
|
|
||||||
@ -41,11 +41,11 @@ import { Renderer } from "@k8slens/extensions";
|
|||||||
|
|
||||||
export default class ExampleExtensionMain extends Renderer.LensExtension {
|
export default class ExampleExtensionMain extends Renderer.LensExtension {
|
||||||
onActivate() {
|
onActivate() {
|
||||||
console.log('custom renderer process extension code started');
|
console.log("custom renderer process extension code started");
|
||||||
}
|
}
|
||||||
|
|
||||||
onDeactivate() {
|
onDeactivate() {
|
||||||
console.log('custom renderer process extension de-activated');
|
console.log("custom renderer process extension de-activated");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -56,7 +56,7 @@ You can initiate custom code by implementing `onActivate()`.
|
|||||||
Implementing `onDeactivate()` gives you the opportunity to clean up after your extension.
|
Implementing `onDeactivate()` gives you the opportunity to clean up after your extension.
|
||||||
|
|
||||||
!!! info
|
!!! info
|
||||||
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**.)
|
||||||
@ -75,17 +75,17 @@ Add a cluster page definition to a `Renderer.LensExtension` subclass with the fo
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import { ExampleIcon, ExamplePage } from "./page"
|
import { ExampleIcon, ExamplePage } from "./page";
|
||||||
import React from "react"
|
import React from "react";
|
||||||
|
|
||||||
export default class ExampleExtension extends Renderer.LensExtension {
|
export default class ExampleExtension extends Renderer.LensExtension {
|
||||||
clusterPages = [
|
clusterPages = [
|
||||||
{
|
{
|
||||||
id: "hello",
|
id: "hello",
|
||||||
components: {
|
components: {
|
||||||
Page: () => <ExamplePage extension={this}/>,
|
Page: () => <ExamplePage extension={this} />,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -93,24 +93,26 @@ export default class ExampleExtension extends Renderer.LensExtension {
|
|||||||
`clusterPages` is an array of objects that satisfy the `PageRegistration` interface.
|
`clusterPages` is an array of objects that satisfy the `PageRegistration` interface.
|
||||||
The properties of the `clusterPages` array objects are defined as follows:
|
The properties of the `clusterPages` array objects are defined as follows:
|
||||||
|
|
||||||
* `id` is a string that identifies the page.
|
- `id` is a string that identifies the page.
|
||||||
* `components` matches the `PageComponents` interface for which there is one field, `Page`.
|
- `components` matches the `PageComponents` interface for which there is one field, `Page`.
|
||||||
* `Page` is of type ` React.ComponentType<any>`.
|
- `Page` is of type ` React.ComponentType<any>`.
|
||||||
It offers flexibility in defining the appearance and behavior of your page.
|
It offers flexibility in defining the appearance and behavior of your page.
|
||||||
|
|
||||||
`ExamplePage` in the example above can be defined in `page.tsx`:
|
`ExamplePage` in the example above can be defined in `page.tsx`:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import React from "react"
|
import React from "react";
|
||||||
|
|
||||||
export class ExamplePage extends React.Component<{ extension: LensRendererExtension }> {
|
export class ExamplePage extends React.Component<{
|
||||||
|
extension: LensRendererExtension;
|
||||||
|
}> {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p>Hello world!</p>
|
<p>Hello world!</p>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -130,17 +132,17 @@ By expanding on the above example, you can add a cluster page menu item to the `
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import { ExampleIcon, ExamplePage } from "./page"
|
import { ExampleIcon, ExamplePage } from "./page";
|
||||||
import React from "react"
|
import React from "react";
|
||||||
|
|
||||||
export default class ExampleExtension extends Renderer.LensExtension {
|
export default class ExampleExtension extends Renderer.LensExtension {
|
||||||
clusterPages = [
|
clusterPages = [
|
||||||
{
|
{
|
||||||
id: "hello",
|
id: "hello",
|
||||||
components: {
|
components: {
|
||||||
Page: () => <ExamplePage extension={this}/>,
|
Page: () => <ExamplePage extension={this} />,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
clusterPageMenus = [
|
clusterPageMenus = [
|
||||||
@ -149,7 +151,7 @@ export default class ExampleExtension extends Renderer.LensExtension {
|
|||||||
title: "Hello World",
|
title: "Hello World",
|
||||||
components: {
|
components: {
|
||||||
Icon: ExampleIcon,
|
Icon: ExampleIcon,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -159,10 +161,10 @@ export default class ExampleExtension extends Renderer.LensExtension {
|
|||||||
This element defines how the cluster page menu item will appear and what it will do when you click it.
|
This element defines how the cluster page menu item will appear and what it will do when you click it.
|
||||||
The properties of the `clusterPageMenus` array objects are defined as follows:
|
The properties of the `clusterPageMenus` array objects are defined as follows:
|
||||||
|
|
||||||
* `target` links to the relevant cluster page using `pageId`.
|
- `target` links to the relevant cluster page using `pageId`.
|
||||||
* `pageId` takes the value of the relevant cluster page's `id` property.
|
- `pageId` takes the value of the relevant cluster page's `id` property.
|
||||||
* `title` sets the name of the cluster page menu item that will appear in the left side menu.
|
- `title` sets the name of the cluster page menu item that will appear in the left side menu.
|
||||||
* `components` is used to set an icon that appears to the left of the `title` text in the left side menu.
|
- `components` is used to set an icon that appears to the left of the `title` text in the left side menu.
|
||||||
|
|
||||||
The above example creates a menu item that reads **Hello World**.
|
The above example creates a menu item that reads **Hello World**.
|
||||||
When users click **Hello World**, the cluster dashboard will show the contents of `Example Page`.
|
When users click **Hello World**, the cluster dashboard will show the contents of `Example Page`.
|
||||||
@ -171,7 +173,7 @@ This example requires the definition of another React-based component, `ExampleI
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import React from "react"
|
import React from "react";
|
||||||
|
|
||||||
type IconProps = Renderer.Component.IconProps;
|
type IconProps = Renderer.Component.IconProps;
|
||||||
|
|
||||||
@ -180,16 +182,18 @@ const {
|
|||||||
} = Renderer;
|
} = Renderer;
|
||||||
|
|
||||||
export function ExampleIcon(props: IconProps) {
|
export function ExampleIcon(props: IconProps) {
|
||||||
return <Icon {...props} material="pages" tooltip={"Hi!"}/>
|
return <Icon {...props} material="pages" tooltip={"Hi!"} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ExamplePage extends React.Component<{ extension: Renderer.LensExtension }> {
|
export class ExamplePage extends React.Component<{
|
||||||
|
extension: Renderer.LensExtension;
|
||||||
|
}> {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p>Hello world!</p>
|
<p>Hello world!</p>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -198,32 +202,31 @@ Lens includes various built-in components available for extension developers to
|
|||||||
One of these is the `Renderer.Component.Icon`, introduced in `ExampleIcon`, which you can use to access any of the [icons](https://material.io/resources/icons/) available at [Material Design](https://material.io).
|
One of these is the `Renderer.Component.Icon`, introduced in `ExampleIcon`, which you can use to access any of the [icons](https://material.io/resources/icons/) available at [Material Design](https://material.io).
|
||||||
The properties that `Renderer.Component.Icon` uses are defined as follows:
|
The properties that `Renderer.Component.Icon` uses are defined as follows:
|
||||||
|
|
||||||
* `material` takes the name of the icon you want to use.
|
- `material` takes the name of the icon you want to use.
|
||||||
* `tooltip` sets the text you want to appear when a user hovers over the icon.
|
- `tooltip` sets the text you want to appear when a user hovers over the icon.
|
||||||
|
|
||||||
`clusterPageMenus` can also be used to define sub menu items, so that you can create groups of cluster pages.
|
`clusterPageMenus` can also be used to define sub menu items, so that you can create groups of cluster pages.
|
||||||
The following example groups two sub menu items under one parent menu item:
|
The following example groups two sub menu items under one parent menu item:
|
||||||
|
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import { ExampleIcon, ExamplePage } from "./page"
|
import { ExampleIcon, ExamplePage } from "./page";
|
||||||
import React from "react"
|
import React from "react";
|
||||||
|
|
||||||
export default class ExampleExtension extends Renderer.LensExtension {
|
export default class ExampleExtension extends Renderer.LensExtension {
|
||||||
clusterPages = [
|
clusterPages = [
|
||||||
{
|
{
|
||||||
id: "hello",
|
id: "hello",
|
||||||
components: {
|
components: {
|
||||||
Page: () => <ExamplePage extension={this}/>,
|
Page: () => <ExamplePage extension={this} />,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "bonjour",
|
id: "bonjour",
|
||||||
components: {
|
components: {
|
||||||
Page: () => <ExemplePage extension={this}/>,
|
Page: () => <ExemplePage extension={this} />,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
clusterPageMenus = [
|
clusterPageMenus = [
|
||||||
@ -232,7 +235,7 @@ export default class ExampleExtension extends Renderer.LensExtension {
|
|||||||
title: "Greetings",
|
title: "Greetings",
|
||||||
components: {
|
components: {
|
||||||
Icon: ExampleIcon,
|
Icon: ExampleIcon,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
parentId: "example",
|
parentId: "example",
|
||||||
@ -240,7 +243,7 @@ export default class ExampleExtension extends Renderer.LensExtension {
|
|||||||
title: "Hello World",
|
title: "Hello World",
|
||||||
components: {
|
components: {
|
||||||
Icon: ExampleIcon,
|
Icon: ExampleIcon,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
parentId: "example",
|
parentId: "example",
|
||||||
@ -248,8 +251,8 @@ export default class ExampleExtension extends Renderer.LensExtension {
|
|||||||
title: "Bonjour le monde",
|
title: "Bonjour le monde",
|
||||||
components: {
|
components: {
|
||||||
Icon: ExempleIcon,
|
Icon: ExempleIcon,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -280,18 +283,18 @@ Unlike cluster pages, users can trigger global pages even when there is no activ
|
|||||||
The following example defines a `Renderer.LensExtension` subclass with a single global page definition:
|
The following example defines a `Renderer.LensExtension` subclass with a single global page definition:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer } from '@k8slens/extensions';
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import { HelpPage } from './page';
|
import { HelpPage } from "./page";
|
||||||
import React from 'react';
|
import React from "react";
|
||||||
|
|
||||||
export default class HelpExtension extends Renderer.LensExtension {
|
export default class HelpExtension extends Renderer.LensExtension {
|
||||||
globalPages = [
|
globalPages = [
|
||||||
{
|
{
|
||||||
id: "help",
|
id: "help",
|
||||||
components: {
|
components: {
|
||||||
Page: () => <HelpPage extension={this}/>,
|
Page: () => <HelpPage extension={this} />,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -299,24 +302,26 @@ export default class HelpExtension extends Renderer.LensExtension {
|
|||||||
`globalPages` is an array of objects that satisfy the `PageRegistration` interface.
|
`globalPages` is an array of objects that satisfy the `PageRegistration` interface.
|
||||||
The properties of the `globalPages` array objects are defined as follows:
|
The properties of the `globalPages` array objects are defined as follows:
|
||||||
|
|
||||||
* `id` is a string that identifies the page.
|
- `id` is a string that identifies the page.
|
||||||
* `components` matches the `PageComponents` interface for which there is one field, `Page`.
|
- `components` matches the `PageComponents` interface for which there is one field, `Page`.
|
||||||
* `Page` is of type `React.ComponentType<any>`.
|
- `Page` is of type `React.ComponentType<any>`.
|
||||||
It offers flexibility in defining the appearance and behavior of your page.
|
It offers flexibility in defining the appearance and behavior of your page.
|
||||||
|
|
||||||
`HelpPage` in the example above can be defined in `page.tsx`:
|
`HelpPage` in the example above can be defined in `page.tsx`:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import React from "react"
|
import React from "react";
|
||||||
|
|
||||||
export class HelpPage extends React.Component<{ extension: LensRendererExtension }> {
|
export class HelpPage extends React.Component<{
|
||||||
|
extension: LensRendererExtension;
|
||||||
|
}> {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<p>Help yourself</p>
|
<p>Help yourself</p>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -328,11 +333,12 @@ This way, `HelpPage` can access all `HelpExtension` subclass data.
|
|||||||
This example code shows how to create a global page, but not how to make that page available to the Lens user.
|
This example code shows how to create a global page, but not how to make that page available to the Lens user.
|
||||||
Global pages are typically made available in the following ways:
|
Global pages are typically made available in the following ways:
|
||||||
|
|
||||||
* To add global pages to the top menu bar, see [`appMenus`](../main-extension#appmenus) in the Main Extension guide.
|
- To add global pages to the top menu bar, see [`appMenus`](../main-extension#appmenus) in the Main Extension guide.
|
||||||
* To add global pages as an interactive element in the blue status bar along the bottom of the Lens UI, see [`statusBarItems`](#statusbaritems).
|
- To add global pages as an interactive element in the blue status bar along the bottom of the Lens UI, see [`statusBarItems`](#statusbaritems).
|
||||||
* To add global pages to the Welcome Page, see [`welcomeMenus`](#welcomemenus).
|
- To add global pages to the Welcome Page, see [`welcomeMenus`](#welcomemenus).
|
||||||
|
|
||||||
### `welcomeMenus`
|
### `welcomeMenus`
|
||||||
|
|
||||||
### `appPreferences`
|
### `appPreferences`
|
||||||
|
|
||||||
The Lens **Preferences** page is a built-in global page.
|
The Lens **Preferences** page is a built-in global page.
|
||||||
@ -342,22 +348,24 @@ The following example demonstrates adding a custom preference:
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import { ExamplePreferenceHint, ExamplePreferenceInput } from "./src/example-preference";
|
import {
|
||||||
|
ExamplePreferenceHint,
|
||||||
|
ExamplePreferenceInput,
|
||||||
|
} from "./src/example-preference";
|
||||||
import { observable } from "mobx";
|
import { observable } from "mobx";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export default class ExampleRendererExtension extends Renderer.LensExtension {
|
export default class ExampleRendererExtension extends Renderer.LensExtension {
|
||||||
|
|
||||||
@observable preference = { enabled: false };
|
@observable preference = { enabled: false };
|
||||||
|
|
||||||
appPreferences = [
|
appPreferences = [
|
||||||
{
|
{
|
||||||
title: "Example Preferences",
|
title: "Example Preferences",
|
||||||
components: {
|
components: {
|
||||||
Input: () => <ExamplePreferenceInput preference={this.preference}/>,
|
Input: () => <ExamplePreferenceInput preference={this.preference} />,
|
||||||
Hint: () => <ExamplePreferenceHint/>
|
Hint: () => <ExamplePreferenceHint />,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -365,13 +373,13 @@ export default class ExampleRendererExtension extends Renderer.LensExtension {
|
|||||||
`appPreferences` is an array of objects that satisfies the `AppPreferenceRegistration` interface.
|
`appPreferences` is an array of objects that satisfies the `AppPreferenceRegistration` interface.
|
||||||
The properties of the `appPreferences` array objects are defined as follows:
|
The properties of the `appPreferences` array objects are defined as follows:
|
||||||
|
|
||||||
* `title` sets the heading text displayed on the Preferences page.
|
- `title` sets the heading text displayed on the Preferences page.
|
||||||
* `components` specifies two `React.Component` objects that define the interface for the preference.
|
- `components` specifies two `React.Component` objects that define the interface for the preference.
|
||||||
* `Input` specifies an interactive input element for the preference.
|
- `Input` specifies an interactive input element for the preference.
|
||||||
* `Hint` provides descriptive information for the preference, shown below the `Input` element.
|
- `Hint` provides descriptive information for the preference, shown below the `Input` element.
|
||||||
|
|
||||||
!!! note
|
!!! note
|
||||||
Note that the input and the hint can be comprised of more sophisticated elements, according to the needs of the extension.
|
Note that the input and the hint can be comprised of more sophisticated elements, according to the needs of the extension.
|
||||||
|
|
||||||
`ExamplePreferenceInput` expects its React props to be set to an `ExamplePreferenceProps` instance.
|
`ExamplePreferenceInput` expects its React props to be set to an `ExamplePreferenceProps` instance.
|
||||||
This is how `ExampleRendererExtension` handles the state of the preference input.
|
This is how `ExampleRendererExtension` handles the state of the preference input.
|
||||||
@ -386,22 +394,19 @@ import { observer } from "mobx-react";
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
Component: {
|
Component: { Checkbox },
|
||||||
Checkbox,
|
|
||||||
},
|
|
||||||
} = Renderer;
|
} = Renderer;
|
||||||
|
|
||||||
export class ExamplePreferenceProps {
|
export class ExamplePreferenceProps {
|
||||||
preference: {
|
preference: {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class ExamplePreferenceInput extends React.Component<ExamplePreferenceProps> {
|
export class ExamplePreferenceInput extends React.Component<ExamplePreferenceProps> {
|
||||||
|
|
||||||
public constructor() {
|
public constructor() {
|
||||||
super({preference: { enabled: false}});
|
super({ preference: { enabled: false } });
|
||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,7 +416,9 @@ export class ExamplePreferenceInput extends React.Component<ExamplePreferencePro
|
|||||||
<Checkbox
|
<Checkbox
|
||||||
label="I understand appPreferences"
|
label="I understand appPreferences"
|
||||||
value={preference.enabled}
|
value={preference.enabled}
|
||||||
onChange={v => { preference.enabled = v; }}
|
onChange={(v) => {
|
||||||
|
preference.enabled = v;
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -419,18 +426,16 @@ export class ExamplePreferenceInput extends React.Component<ExamplePreferencePro
|
|||||||
|
|
||||||
export class ExamplePreferenceHint extends React.Component {
|
export class ExamplePreferenceHint extends React.Component {
|
||||||
render() {
|
render() {
|
||||||
return (
|
return <span>This is an example of an appPreference for extensions.</span>;
|
||||||
<span>This is an example of an appPreference for extensions.</span>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`ExamplePreferenceInput` implements a simple checkbox using Lens's `Renderer.Component.Checkbox` using the following properties:
|
`ExamplePreferenceInput` implements a simple checkbox using Lens's `Renderer.Component.Checkbox` using the following properties:
|
||||||
|
|
||||||
* `label` sets the text that displays next to the checkbox.
|
- `label` sets the text that displays next to the checkbox.
|
||||||
* `value` is initially set to `preference.enabled`.
|
- `value` is initially set to `preference.enabled`.
|
||||||
* `onChange` is a function that responds when the state of the checkbox changes.
|
- `onChange` is a function that responds when the state of the checkbox changes.
|
||||||
|
|
||||||
`ExamplePreferenceInput` is defined with the `ExamplePreferenceProps` React props.
|
`ExamplePreferenceInput` is defined with the `ExamplePreferenceProps` React props.
|
||||||
This is an object with the single `enabled` property.
|
This is an object with the single `enabled` property.
|
||||||
@ -461,18 +466,18 @@ The following example adds a `statusBarItems` definition and a `globalPages` def
|
|||||||
It configures the status bar item to navigate to the global page upon activation (normally a mouse click):
|
It configures the status bar item to navigate to the global page upon activation (normally a mouse click):
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer } from '@k8slens/extensions';
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import { HelpIcon, HelpPage } from "./page"
|
import { HelpIcon, HelpPage } from "./page";
|
||||||
import React from 'react';
|
import React from "react";
|
||||||
|
|
||||||
export default class HelpExtension extends Renderer.LensExtension {
|
export default class HelpExtension extends Renderer.LensExtension {
|
||||||
globalPages = [
|
globalPages = [
|
||||||
{
|
{
|
||||||
id: "help",
|
id: "help",
|
||||||
components: {
|
components: {
|
||||||
Page: () => <HelpPage extension={this}/>,
|
Page: () => <HelpPage extension={this} />,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
statusBarItems = [
|
statusBarItems = [
|
||||||
@ -486,7 +491,7 @@ export default class HelpExtension extends Renderer.LensExtension {
|
|||||||
<HelpIcon />
|
<HelpIcon />
|
||||||
My Status Bar Item
|
My Status Bar Item
|
||||||
</div>
|
</div>
|
||||||
)
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -495,14 +500,14 @@ export default class HelpExtension extends Renderer.LensExtension {
|
|||||||
|
|
||||||
The properties of the `statusBarItems` array objects are defined as follows:
|
The properties of the `statusBarItems` array objects are defined as follows:
|
||||||
|
|
||||||
* `Item` specifies the `React.Component` that will be shown on the status bar.
|
- `Item` specifies the `React.Component` that will be shown on the status bar.
|
||||||
By default, items are added starting from the right side of the status bar.
|
By default, items are added starting from the right side of the status bar.
|
||||||
Due to limited space in the status bar, `Item` will typically specify only an icon or a short string of text.
|
Due to limited space in the status bar, `Item` will typically specify only an icon or a short string of text.
|
||||||
The example above reuses the `HelpIcon` from the [`globalPageMenus` guide](#globalpagemenus).
|
The example above reuses the `HelpIcon` from the [`globalPageMenus` guide](#globalpagemenus).
|
||||||
* `onClick` determines what the `statusBarItem` does when it is clicked.
|
- `onClick` determines what the `statusBarItem` does when it is clicked.
|
||||||
In the example, `onClick` is set to a function that calls the `LensRendererExtension` `navigate()` method.
|
In the example, `onClick` is set to a function that calls the `LensRendererExtension` `navigate()` method.
|
||||||
`navigate` takes the `id` of the associated global page as a parameter.
|
`navigate` takes the `id` of the associated global page as a parameter.
|
||||||
Thus, clicking the status bar item activates the associated global pages.
|
Thus, clicking the status bar item activates the associated global pages.
|
||||||
|
|
||||||
### `kubeObjectMenuItems`
|
### `kubeObjectMenuItems`
|
||||||
|
|
||||||
@ -518,9 +523,9 @@ They also appear on the title bar of the details page for specific resources:
|
|||||||
The following example shows how to add a `kubeObjectMenuItems` for namespace resources with an associated action:
|
The following example shows how to add a `kubeObjectMenuItems` for namespace resources with an associated action:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import React from "react"
|
import React from "react";
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import { NamespaceMenuItem } from "./src/namespace-menu-item"
|
import { NamespaceMenuItem } from "./src/namespace-menu-item";
|
||||||
|
|
||||||
type KubeObjectMenuProps = Renderer.Component.KubeObjectMenuProps;
|
type KubeObjectMenuProps = Renderer.Component.KubeObjectMenuProps;
|
||||||
type Namespace = Renderer.K8sApi.Namespace;
|
type Namespace = Renderer.K8sApi.Namespace;
|
||||||
@ -531,23 +536,24 @@ export default class ExampleExtension extends Renderer.LensExtension {
|
|||||||
kind: "Namespace",
|
kind: "Namespace",
|
||||||
apiVersions: ["v1"],
|
apiVersions: ["v1"],
|
||||||
components: {
|
components: {
|
||||||
MenuItem: (props: KubeObjectMenuProps<Namespace>) => <NamespaceMenuItem {...props} />
|
MenuItem: (props: KubeObjectMenuProps<Namespace>) => (
|
||||||
}
|
<NamespaceMenuItem {...props} />
|
||||||
}
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
`kubeObjectMenuItems` is an array of objects matching the `KubeObjectMenuRegistration` interface.
|
`kubeObjectMenuItems` is an array of objects matching the `KubeObjectMenuRegistration` interface.
|
||||||
The example above adds a menu item for namespaces in the cluster dashboard.
|
The example above adds a menu item for namespaces in the cluster dashboard.
|
||||||
The properties of the `kubeObjectMenuItems` array objects are defined as follows:
|
The properties of the `kubeObjectMenuItems` array objects are defined as follows:
|
||||||
|
|
||||||
* `kind` specifies the Kubernetes resource type the menu item will apply to.
|
- `kind` specifies the Kubernetes resource type the menu item will apply to.
|
||||||
* `apiVersion` specifies the Kubernetes API version number to use with the resource type.
|
- `apiVersion` specifies the Kubernetes API version number to use with the resource type.
|
||||||
* `components` defines the menu item's appearance and behavior.
|
- `components` defines the menu item's appearance and behavior.
|
||||||
* `MenuItem` provides a function that returns a `React.Component` given a set of menu item properties.
|
- `MenuItem` provides a function that returns a `React.Component` given a set of menu item properties.
|
||||||
In this example a `NamespaceMenuItem` object is returned.
|
In this example a `NamespaceMenuItem` object is returned.
|
||||||
|
|
||||||
`NamespaceMenuItem` is defined in `./src/namespace-menu-item.tsx`:
|
`NamespaceMenuItem` is defined in `./src/namespace-menu-item.tsx`:
|
||||||
|
|
||||||
@ -556,11 +562,7 @@ import React from "react";
|
|||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
Component: {
|
Component: { terminalStore, MenuItem, Icon },
|
||||||
terminalStore,
|
|
||||||
MenuItem,
|
|
||||||
Icon,
|
|
||||||
},
|
|
||||||
Navigation,
|
Navigation,
|
||||||
} = Renderer;
|
} = Renderer;
|
||||||
|
|
||||||
@ -587,12 +589,15 @@ export function NamespaceMenuItem(props: KubeObjectMenuProps<Namespace>) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<MenuItem onClick={getPods}>
|
<MenuItem onClick={getPods}>
|
||||||
<Icon material="speaker_group" interactive={toolbar} title="Get pods in terminal"/>
|
<Icon
|
||||||
|
material="speaker_group"
|
||||||
|
interactive={toolbar}
|
||||||
|
title="Get pods in terminal"
|
||||||
|
/>
|
||||||
<span className="title">Get Pods</span>
|
<span className="title">Get Pods</span>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
`NamespaceMenuItem` returns a `Renderer.Component.MenuItem` which defines the menu item's appearance and its behavior when activated via the `onClick` property.
|
`NamespaceMenuItem` returns a `Renderer.Component.MenuItem` which defines the menu item's appearance and its behavior when activated via the `onClick` property.
|
||||||
@ -629,9 +634,11 @@ export default class ExampleExtension extends Renderer.LensExtension {
|
|||||||
apiVersions: ["v1"],
|
apiVersions: ["v1"],
|
||||||
priority: 10,
|
priority: 10,
|
||||||
components: {
|
components: {
|
||||||
Details: (props: KubeObjectDetailsProps<Namespace>) => <NamespaceDetailsItem {...props} />
|
Details: (props: KubeObjectDetailsProps<Namespace>) => (
|
||||||
}
|
<NamespaceDetailsItem {...props} />
|
||||||
}
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -640,15 +647,15 @@ export default class ExampleExtension extends Renderer.LensExtension {
|
|||||||
This example above adds a detail item for namespaces in the cluster dashboard.
|
This example above adds a detail item for namespaces in the cluster dashboard.
|
||||||
The properties of the `kubeObjectDetailItems` array objects are defined as follows:
|
The properties of the `kubeObjectDetailItems` array objects are defined as follows:
|
||||||
|
|
||||||
* `kind` specifies the Kubernetes resource type the detail item will apply to.
|
- `kind` specifies the Kubernetes resource type the detail item will apply to.
|
||||||
* `apiVersion` specifies the Kubernetes API version number to use with the resource type.
|
- `apiVersion` specifies the Kubernetes API version number to use with the resource type.
|
||||||
* `components` defines the detail item's appearance and behavior.
|
- `components` defines the detail item's appearance and behavior.
|
||||||
* `Details` provides a function that returns a `React.Component` given a set of detail item properties.
|
- `Details` provides a function that returns a `React.Component` given a set of detail item properties.
|
||||||
In this example a `NamespaceDetailsItem` object is returned.
|
In this example a `NamespaceDetailsItem` object is returned.
|
||||||
|
|
||||||
`NamespaceDetailsItem` is defined in `./src/namespace-details-item.tsx`:
|
`NamespaceDetailsItem` is defined in `./src/namespace-details-item.tsx`:
|
||||||
|
|
||||||
``` typescript
|
```typescript
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
import { PodsDetailsList } from "./pods-details-list";
|
import { PodsDetailsList } from "./pods-details-list";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
@ -656,12 +663,8 @@ import { observable } from "mobx";
|
|||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
K8sApi: {
|
K8sApi: { podsApi },
|
||||||
podsApi,
|
Component: { DrawerTitle },
|
||||||
},
|
|
||||||
Component: {
|
|
||||||
DrawerTitle,
|
|
||||||
},
|
|
||||||
} = Renderer;
|
} = Renderer;
|
||||||
|
|
||||||
type KubeObjectMenuProps = Renderer.Component.KubeObjectMenuProps;
|
type KubeObjectMenuProps = Renderer.Component.KubeObjectMenuProps;
|
||||||
@ -669,7 +672,9 @@ type Namespace = Renderer.K8sApi.Namespace;
|
|||||||
type Pod = Renderer.K8sApi.Pod;
|
type Pod = Renderer.K8sApi.Pod;
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class NamespaceDetailsItem extends React.Component<KubeObjectDetailsProps<Namespace>> {
|
export class NamespaceDetailsItem extends React.Component<
|
||||||
|
KubeObjectDetailsProps<Namespace>
|
||||||
|
> {
|
||||||
@observable private pods: Pod[];
|
@observable private pods: Pod[];
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
@ -681,10 +686,10 @@ export class NamespaceDetailsItem extends React.Component<KubeObjectDetailsProps
|
|||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<DrawerTitle title="Pods" />
|
<DrawerTitle>Pods</DrawerTitle>
|
||||||
<PodsDetailsList pods={this.pods}/>
|
<PodsDetailsList pods={this.pods} />
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@ -709,17 +714,12 @@ Details are placed in drawers, and using `Renderer.Component.DrawerTitle` provid
|
|||||||
Multiple details in a drawer can be placed in `<Renderer.Component.DrawerItem>` elements for further separation, if desired.
|
Multiple details in a drawer can be placed in `<Renderer.Component.DrawerItem>` elements for further separation, if desired.
|
||||||
The rest of this example's details are defined in `PodsDetailsList`, found in `./pods-details-list.tsx`:
|
The rest of this example's details are defined in `PodsDetailsList`, found in `./pods-details-list.tsx`:
|
||||||
|
|
||||||
``` typescript
|
```typescript
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
|
|
||||||
const {
|
const {
|
||||||
Component: {
|
Component: { TableHead, TableRow, TableCell, Table },
|
||||||
TableHead,
|
|
||||||
TableRow,
|
|
||||||
TableCell,
|
|
||||||
Table,
|
|
||||||
},
|
|
||||||
} = Renderer;
|
} = Renderer;
|
||||||
|
|
||||||
type Pod = Renderer.K8sApi.Pod;
|
type Pod = Renderer.K8sApi.Pod;
|
||||||
@ -736,11 +736,11 @@ export class PodsDetailsList extends React.Component<PodsDetailsListProps> {
|
|||||||
<TableCell className="podAge">{pods[index].getAge()}</TableCell>
|
<TableCell className="podAge">{pods[index].getAge()}</TableCell>
|
||||||
<TableCell className="podStatus">{pods[index].getStatus()}</TableCell>
|
<TableCell className="podStatus">{pods[index].getStatus()}</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
)
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { pods } = this.props
|
const { pods } = this.props;
|
||||||
|
|
||||||
if (!pods?.length) {
|
if (!pods?.length) {
|
||||||
return null;
|
return null;
|
||||||
@ -754,7 +754,7 @@ export class PodsDetailsList extends React.Component<PodsDetailsListProps> {
|
|||||||
<TableCell className="podAge">Age</TableCell>
|
<TableCell className="podAge">Age</TableCell>
|
||||||
<TableCell className="podStatus">Status</TableCell>
|
<TableCell className="podStatus">Status</TableCell>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
{ pods.map(this.getTableRow) }
|
{pods.map(this.getTableRow)}
|
||||||
</Table>
|
</Table>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -134,7 +134,7 @@ export class HpaDetails extends React.Component<HpaDetailsProps> {
|
|||||||
})}
|
})}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
|
|
||||||
<DrawerTitle title="Metrics"/>
|
<DrawerTitle>Metrics</DrawerTitle>
|
||||||
<div className="metrics">
|
<div className="metrics">
|
||||||
{this.renderMetrics()}
|
{this.renderMetrics()}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -85,7 +85,7 @@ export class ConfigMapDetails extends React.Component<ConfigMapDetailsProps> {
|
|||||||
{
|
{
|
||||||
data.length > 0 && (
|
data.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Data"/>
|
<DrawerTitle>Data</DrawerTitle>
|
||||||
{
|
{
|
||||||
data.map(([name, value]) => (
|
data.map(([name, value]) => (
|
||||||
<div key={name} className="data">
|
<div key={name} className="data">
|
||||||
|
|||||||
@ -82,7 +82,7 @@ export class ResourceQuotaDetails extends React.Component<ResourceQuotaDetailsPr
|
|||||||
|
|
||||||
{quota.getScopeSelector().length > 0 && (
|
{quota.getScopeSelector().length > 0 && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Scope Selector"/>
|
<DrawerTitle>Scope Selector</DrawerTitle>
|
||||||
<Table className="paths">
|
<Table className="paths">
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableCell>Operator</TableCell>
|
<TableCell>Operator</TableCell>
|
||||||
|
|||||||
@ -116,7 +116,7 @@ export class SecretDetails extends React.Component<SecretDetailsProps> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Data" />
|
<DrawerTitle>Data</DrawerTitle>
|
||||||
{secrets.map(this.renderSecret)}
|
{secrets.map(this.renderSecret)}
|
||||||
<Button
|
<Button
|
||||||
primary
|
primary
|
||||||
|
|||||||
@ -92,7 +92,7 @@ export class CRDDetails extends React.Component<CRDDetailsProps> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
<DrawerTitle title="Names"/>
|
<DrawerTitle>Names</DrawerTitle>
|
||||||
<Table selectable className="names box grow">
|
<Table selectable className="names box grow">
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableCell>plural</TableCell>
|
<TableCell>plural</TableCell>
|
||||||
@ -109,7 +109,7 @@ export class CRDDetails extends React.Component<CRDDetailsProps> {
|
|||||||
</Table>
|
</Table>
|
||||||
{printerColumns.length > 0 &&
|
{printerColumns.length > 0 &&
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Additional Printer Columns"/>
|
<DrawerTitle>Additional Printer Columns</DrawerTitle>
|
||||||
<Table selectable className="printer-columns box grow">
|
<Table selectable className="printer-columns box grow">
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableCell className="name">Name</TableCell>
|
<TableCell className="name">Name</TableCell>
|
||||||
@ -136,7 +136,7 @@ export class CRDDetails extends React.Component<CRDDetailsProps> {
|
|||||||
}
|
}
|
||||||
{validation &&
|
{validation &&
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Validation"/>
|
<DrawerTitle>Validation</DrawerTitle>
|
||||||
<MonacoEditor
|
<MonacoEditor
|
||||||
readOnly
|
readOnly
|
||||||
value={validation}
|
value={validation}
|
||||||
|
|||||||
@ -71,7 +71,7 @@ export class EventDetails extends React.Component<EventDetailsProps> {
|
|||||||
<span className={kebabCase(type)}>{type}</span>
|
<span className={kebabCase(type)}>{type}</span>
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
|
|
||||||
<DrawerTitle title="Involved object"/>
|
<DrawerTitle>Involved object</DrawerTitle>
|
||||||
<Table>
|
<Table>
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableCell>Name</TableCell>
|
<TableCell>Name</TableCell>
|
||||||
|
|||||||
@ -113,7 +113,7 @@ class NonInjectedReleaseDetails extends Component<ReleaseDetailsProps & Dependen
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="values">
|
<div className="values">
|
||||||
<DrawerTitle title="Values" />
|
<DrawerTitle>Values</DrawerTitle>
|
||||||
<div className="flex column gaps">
|
<div className="flex column gaps">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
label="User-supplied values only"
|
label="User-supplied values only"
|
||||||
@ -238,9 +238,9 @@ class NonInjectedReleaseDetails extends Component<ReleaseDetailsProps & Dependen
|
|||||||
/>
|
/>
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
{this.renderValues()}
|
{this.renderValues()}
|
||||||
<DrawerTitle title="Notes"/>
|
<DrawerTitle>Notes</DrawerTitle>
|
||||||
{this.renderNotes()}
|
{this.renderNotes()}
|
||||||
<DrawerTitle title="Resources"/>
|
<DrawerTitle>Resources</DrawerTitle>
|
||||||
{resources && this.renderResources(resources)}
|
{resources && this.renderResources(resources)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -35,7 +35,7 @@ export class EndpointDetails extends React.Component<EndpointDetailsProps> {
|
|||||||
return (
|
return (
|
||||||
<div className="EndpointDetails">
|
<div className="EndpointDetails">
|
||||||
<KubeObjectMeta object={endpoint}/>
|
<KubeObjectMeta object={endpoint}/>
|
||||||
<DrawerTitle title="Subsets"/>
|
<DrawerTitle>Subsets</DrawerTitle>
|
||||||
{
|
{
|
||||||
endpoint.getEndpointSubsets().map((subset) => (
|
endpoint.getEndpointSubsets().map((subset) => (
|
||||||
<EndpointSubsetList key={subset.toString()} subset={subset} endpoint={endpoint} />
|
<EndpointSubsetList key={subset.toString()} subset={subset} endpoint={endpoint} />
|
||||||
|
|||||||
@ -160,10 +160,10 @@ export class IngressDetails extends React.Component<IngressDetailsProps> {
|
|||||||
{serviceName}:{servicePort}
|
{serviceName}:{servicePort}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
}
|
}
|
||||||
<DrawerTitle title="Rules"/>
|
<DrawerTitle>Rules</DrawerTitle>
|
||||||
{this.renderPaths(ingress)}
|
{this.renderPaths(ingress)}
|
||||||
|
|
||||||
<DrawerTitle title="Load-Balancer Ingress Points"/>
|
<DrawerTitle>Load-Balancer Ingress Points</DrawerTitle>
|
||||||
{this.renderIngressPoints(ingressPoints)}
|
{this.renderIngressPoints(ingressPoints)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -170,7 +170,7 @@ export class NetworkPolicyDetails extends React.Component<NetworkPolicyDetailsPr
|
|||||||
|
|
||||||
{ingress && (
|
{ingress && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Ingress"/>
|
<DrawerTitle>Ingress</DrawerTitle>
|
||||||
{ingress.map((ingress, i) => (
|
{ingress.map((ingress, i) => (
|
||||||
<div key={i} data-testid={`ingress-${i}`}>
|
<div key={i} data-testid={`ingress-${i}`}>
|
||||||
{this.renderNetworkPolicyPorts(ingress.ports)}
|
{this.renderNetworkPolicyPorts(ingress.ports)}
|
||||||
@ -182,7 +182,7 @@ export class NetworkPolicyDetails extends React.Component<NetworkPolicyDetailsPr
|
|||||||
|
|
||||||
{egress && (
|
{egress && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Egress"/>
|
<DrawerTitle>Egress</DrawerTitle>
|
||||||
{egress.map((egress, i) => (
|
{egress.map((egress, i) => (
|
||||||
<div key={i} data-testid={`egress-${i}`}>
|
<div key={i} data-testid={`egress-${i}`}>
|
||||||
{this.renderNetworkPolicyPorts(egress.ports)}
|
{this.renderNetworkPolicyPorts(egress.ports)}
|
||||||
|
|||||||
@ -86,7 +86,7 @@ class NonInjectedServiceDetails extends React.Component<ServiceDetailsProps & De
|
|||||||
{spec.sessionAffinity}
|
{spec.sessionAffinity}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
|
|
||||||
<DrawerTitle title="Connection"/>
|
<DrawerTitle>Connection</DrawerTitle>
|
||||||
|
|
||||||
<DrawerItem name="Cluster IP">
|
<DrawerItem name="Cluster IP">
|
||||||
{spec.clusterIP}
|
{spec.clusterIP}
|
||||||
@ -129,7 +129,7 @@ class NonInjectedServiceDetails extends React.Component<ServiceDetailsProps & De
|
|||||||
{spec.loadBalancerIP}
|
{spec.loadBalancerIP}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
)}
|
)}
|
||||||
<DrawerTitle title="Endpoint"/>
|
<DrawerTitle>Endpoint</DrawerTitle>
|
||||||
|
|
||||||
<ServiceDetailsEndpoint endpoint={endpoint}/>
|
<ServiceDetailsEndpoint endpoint={endpoint}/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -169,9 +169,9 @@ class NonInjectedNodeDetails extends React.Component<NodeDetailsProps & Dependen
|
|||||||
}
|
}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
}
|
}
|
||||||
<DrawerTitle title="Capacity"/>
|
<DrawerTitle>Capacity</DrawerTitle>
|
||||||
<NodeDetailsResources node={node} type={"capacity"}/>
|
<NodeDetailsResources node={node} type={"capacity"}/>
|
||||||
<DrawerTitle title="Allocatable"/>
|
<DrawerTitle>Allocatable</DrawerTitle>
|
||||||
<NodeDetailsResources node={node} type={"allocatable"}/>
|
<NodeDetailsResources node={node} type={"allocatable"}/>
|
||||||
<PodDetailsList
|
<PodDetailsList
|
||||||
pods={childPods}
|
pods={childPods}
|
||||||
|
|||||||
@ -161,7 +161,7 @@ export class PodSecurityPolicyDetails extends React.Component<PodSecurityPolicyD
|
|||||||
|
|
||||||
{allowedHostPaths && (
|
{allowedHostPaths && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Allowed Host Paths"/>
|
<DrawerTitle>Allowed Host Paths</DrawerTitle>
|
||||||
<Table>
|
<Table>
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableCell>Path Prefix</TableCell>
|
<TableCell>Path Prefix</TableCell>
|
||||||
@ -186,7 +186,7 @@ export class PodSecurityPolicyDetails extends React.Component<PodSecurityPolicyD
|
|||||||
|
|
||||||
{runtimeClass && (
|
{runtimeClass && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Runtime Class"/>
|
<DrawerTitle>Runtime Class</DrawerTitle>
|
||||||
<DrawerItem name="Allowed Runtime Class Names">
|
<DrawerItem name="Allowed Runtime Class Names">
|
||||||
{runtimeClass.allowedRuntimeClassNames?.join(", ") || "-"}
|
{runtimeClass.allowedRuntimeClassNames?.join(", ") || "-"}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
@ -198,7 +198,7 @@ export class PodSecurityPolicyDetails extends React.Component<PodSecurityPolicyD
|
|||||||
|
|
||||||
{seLinux && (
|
{seLinux && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Se Linux"/>
|
<DrawerTitle>Se Linux</DrawerTitle>
|
||||||
<DrawerItem name="Rule">
|
<DrawerItem name="Rule">
|
||||||
{seLinux.rule}
|
{seLinux.rule}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
|
|||||||
@ -80,7 +80,7 @@ class NonInjectedStorageClassDetails extends React.Component<StorageClassDetails
|
|||||||
)}
|
)}
|
||||||
{parameters && (
|
{parameters && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Parameters"/>
|
<DrawerTitle>Parameters</DrawerTitle>
|
||||||
{
|
{
|
||||||
Object.entries(parameters).map(([name, value]) => (
|
Object.entries(parameters).map(([name, value]) => (
|
||||||
<DrawerItem key={name + value} name={startCase(name)}>
|
<DrawerItem key={name + value} name={startCase(name)}>
|
||||||
|
|||||||
@ -102,7 +102,7 @@ export class PersistentVolumeClaimDetails extends React.Component<PersistentVolu
|
|||||||
{volumeClaim.getStatus()}
|
{volumeClaim.getStatus()}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
|
|
||||||
<DrawerTitle title="Selector"/>
|
<DrawerTitle>Selector</DrawerTitle>
|
||||||
|
|
||||||
<DrawerItem name="Match Labels" labelsOnly>
|
<DrawerItem name="Match Labels" labelsOnly>
|
||||||
{volumeClaim.getMatchLabels().map(label => <Badge key={label} label={label}/>)}
|
{volumeClaim.getMatchLabels().map(label => <Badge key={label} label={label}/>)}
|
||||||
|
|||||||
@ -67,7 +67,7 @@ export class VolumeDetailsList extends React.Component<VolumeDetailsListProps> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="VolumeDetailsList flex column">
|
<div className="VolumeDetailsList flex column">
|
||||||
<DrawerTitle title="Persistent Volumes"/>
|
<DrawerTitle>Persistent Volumes</DrawerTitle>
|
||||||
<Table
|
<Table
|
||||||
tableId="storage_volume_details_list"
|
tableId="storage_volume_details_list"
|
||||||
items={persistentVolumes}
|
items={persistentVolumes}
|
||||||
|
|||||||
@ -65,7 +65,7 @@ export class PersistentVolumeDetails extends React.Component<PersistentVolumeDet
|
|||||||
|
|
||||||
{nfs && (
|
{nfs && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Network File System"/>
|
<DrawerTitle>Network File System</DrawerTitle>
|
||||||
{
|
{
|
||||||
Object.entries(nfs).map(([name, value]) => (
|
Object.entries(nfs).map(([name, value]) => (
|
||||||
<DrawerItem key={name} name={startCase(name)}>
|
<DrawerItem key={name} name={startCase(name)}>
|
||||||
@ -78,7 +78,7 @@ export class PersistentVolumeDetails extends React.Component<PersistentVolumeDet
|
|||||||
|
|
||||||
{flexVolume && (
|
{flexVolume && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="FlexVolume"/>
|
<DrawerTitle>FlexVolume</DrawerTitle>
|
||||||
<DrawerItem name="Driver">
|
<DrawerItem name="Driver">
|
||||||
{flexVolume.driver}
|
{flexVolume.driver}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
@ -94,7 +94,7 @@ export class PersistentVolumeDetails extends React.Component<PersistentVolumeDet
|
|||||||
|
|
||||||
{claimRef && (
|
{claimRef && (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Claim"/>
|
<DrawerTitle>Claim</DrawerTitle>
|
||||||
<DrawerItem name="Type">
|
<DrawerItem name="Type">
|
||||||
{claimRef.kind}
|
{claimRef.kind}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
|
|||||||
@ -68,7 +68,7 @@ export class ClusterRoleBindingDetails extends React.Component<ClusterRoleBindin
|
|||||||
<div className="ClusterRoleBindingDetails">
|
<div className="ClusterRoleBindingDetails">
|
||||||
<KubeObjectMeta object={clusterRoleBinding} />
|
<KubeObjectMeta object={clusterRoleBinding} />
|
||||||
|
|
||||||
<DrawerTitle title="Reference" />
|
<DrawerTitle>Reference</DrawerTitle>
|
||||||
<Table>
|
<Table>
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableCell>Kind</TableCell>
|
<TableCell>Kind</TableCell>
|
||||||
@ -82,7 +82,7 @@ export class ClusterRoleBindingDetails extends React.Component<ClusterRoleBindin
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
</Table>
|
</Table>
|
||||||
|
|
||||||
<DrawerTitle title="Bindings" />
|
<DrawerTitle>Bindings</DrawerTitle>
|
||||||
{subjects.length > 0 && (
|
{subjects.length > 0 && (
|
||||||
<Table selectable className="bindings box grow">
|
<Table selectable className="bindings box grow">
|
||||||
<TableHead>
|
<TableHead>
|
||||||
|
|||||||
@ -28,7 +28,7 @@ export class ClusterRoleDetails extends React.Component<ClusterRoleDetailsProps>
|
|||||||
<div className="ClusterRoleDetails">
|
<div className="ClusterRoleDetails">
|
||||||
<KubeObjectMeta object={clusterRole}/>
|
<KubeObjectMeta object={clusterRole}/>
|
||||||
|
|
||||||
<DrawerTitle title="Rules"/>
|
<DrawerTitle>Rules</DrawerTitle>
|
||||||
{rules.map(({ resourceNames, apiGroups, resources, verbs }, index) => {
|
{rules.map(({ resourceNames, apiGroups, resources, verbs }, index) => {
|
||||||
return (
|
return (
|
||||||
<div className="rule" key={index}>
|
<div className="rule" key={index}>
|
||||||
|
|||||||
@ -64,7 +64,7 @@ export class RoleBindingDetails extends React.Component<RoleBindingDetailsProps>
|
|||||||
<div className="RoleBindingDetails">
|
<div className="RoleBindingDetails">
|
||||||
<KubeObjectMeta object={roleBinding} />
|
<KubeObjectMeta object={roleBinding} />
|
||||||
|
|
||||||
<DrawerTitle title="Reference" />
|
<DrawerTitle>Reference</DrawerTitle>
|
||||||
<Table>
|
<Table>
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableCell>Kind</TableCell>
|
<TableCell>Kind</TableCell>
|
||||||
@ -78,7 +78,7 @@ export class RoleBindingDetails extends React.Component<RoleBindingDetailsProps>
|
|||||||
</TableRow>
|
</TableRow>
|
||||||
</Table>
|
</Table>
|
||||||
|
|
||||||
<DrawerTitle title="Bindings" />
|
<DrawerTitle>Bindings</DrawerTitle>
|
||||||
{subjects.length > 0 && (
|
{subjects.length > 0 && (
|
||||||
<Table selectable className="bindings box grow">
|
<Table selectable className="bindings box grow">
|
||||||
<TableHead>
|
<TableHead>
|
||||||
|
|||||||
@ -27,7 +27,7 @@ export class RoleDetails extends React.Component<RoleDetailsProps> {
|
|||||||
return (
|
return (
|
||||||
<div className="RoleDetails">
|
<div className="RoleDetails">
|
||||||
<KubeObjectMeta object={role}/>
|
<KubeObjectMeta object={role}/>
|
||||||
<DrawerTitle title="Rules"/>
|
<DrawerTitle>Rules</DrawerTitle>
|
||||||
{rules.map(({ resourceNames, apiGroups, resources, verbs }, index) => {
|
{rules.map(({ resourceNames, apiGroups, resources, verbs }, index) => {
|
||||||
return (
|
return (
|
||||||
<div className="rule" key={index}>
|
<div className="rule" key={index}>
|
||||||
|
|||||||
@ -143,7 +143,7 @@ export class ServiceAccountsDetails extends React.Component<ServiceAccountsDetai
|
|||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
}
|
}
|
||||||
|
|
||||||
<DrawerTitle title="Mountable secrets"/>
|
<DrawerTitle>Mountable secrets</DrawerTitle>
|
||||||
<div className="secrets">
|
<div className="secrets">
|
||||||
{this.renderSecrets()}
|
{this.renderSecrets()}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -78,7 +78,7 @@ class NonInjectedCronJobDetails extends React.Component<CronJobDetailsProps & De
|
|||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
{childJobs.length > 0 &&
|
{childJobs.length > 0 &&
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Jobs"/>
|
<DrawerTitle>Jobs</DrawerTitle>
|
||||||
{childJobs.map((job: Job) => {
|
{childJobs.map((job: Job) => {
|
||||||
const selectors = job.getSelectors();
|
const selectors = job.getSelectors();
|
||||||
const condition = job.getCondition();
|
const condition = job.getCondition();
|
||||||
|
|||||||
@ -53,7 +53,7 @@ export class DeploymentReplicaSets extends React.Component<DeploymentReplicaSets
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ReplicaSets flex column">
|
<div className="ReplicaSets flex column">
|
||||||
<DrawerTitle title="Deploy Revisions"/>
|
<DrawerTitle>Deploy Revisions</DrawerTitle>
|
||||||
<Table
|
<Table
|
||||||
selectable
|
selectable
|
||||||
tableId="deployment_replica_sets_view"
|
tableId="deployment_replica_sets_view"
|
||||||
|
|||||||
@ -131,7 +131,7 @@ export class PodDetailsList extends React.Component<PodDetailsListProps> {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="PodDetailsList flex column">
|
<div className="PodDetailsList flex column">
|
||||||
<DrawerTitle title="Pods" />
|
<DrawerTitle>Pods</DrawerTitle>
|
||||||
<Table
|
<Table
|
||||||
tableId="workloads_pod_details_list"
|
tableId="workloads_pod_details_list"
|
||||||
items={pods}
|
items={pods}
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import { Link } from "react-router-dom";
|
|||||||
import { configMapApi, Pod, PodVolume, PodVolumeKind, PodVolumeVariants, pvcApi, SecretReference, secretsApi } from "../../../common/k8s-api/endpoints";
|
import { configMapApi, Pod, PodVolume, PodVolumeKind, PodVolumeVariants, pvcApi, SecretReference, secretsApi } from "../../../common/k8s-api/endpoints";
|
||||||
import type { KubeApi } from "../../../common/k8s-api/kube-api";
|
import type { KubeApi } from "../../../common/k8s-api/kube-api";
|
||||||
import type { KubeObject, LocalObjectReference } from "../../../common/k8s-api/kube-object";
|
import type { KubeObject, LocalObjectReference } from "../../../common/k8s-api/kube-object";
|
||||||
import { DrawerItem, DrawerItemLabels, DrawerSection, DrawerSubSection } from "../drawer";
|
import { DrawerItem, DrawerItemLabels, DrawerTitle } from "../drawer";
|
||||||
import { Icon } from "../icon";
|
import { Icon } from "../icon";
|
||||||
import { getDetailsUrl } from "../kube-detail-params";
|
import { getDetailsUrl } from "../kube-detail-params";
|
||||||
|
|
||||||
@ -341,7 +341,8 @@ const volumeRenderers: PodVolumeVariantRenderers = {
|
|||||||
sources.map(({ secret, downwardAPI, configMap, serviceAccountToken }, index) => (
|
sources.map(({ secret, downwardAPI, configMap, serviceAccountToken }, index) => (
|
||||||
<React.Fragment key={index}>
|
<React.Fragment key={index}>
|
||||||
{secret && (
|
{secret && (
|
||||||
<DrawerSubSection title="Secret">
|
<>
|
||||||
|
<DrawerTitle size="sub-title">Secret</DrawerTitle>
|
||||||
<DrawerItem name="Name">
|
<DrawerItem name="Name">
|
||||||
{secret.name}
|
{secret.name}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
@ -352,10 +353,11 @@ const volumeRenderers: PodVolumeVariantRenderers = {
|
|||||||
</ul>
|
</ul>
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
)}
|
)}
|
||||||
</DrawerSubSection>
|
</>
|
||||||
)}
|
)}
|
||||||
{downwardAPI && (
|
{downwardAPI && (
|
||||||
<DrawerSubSection title="Downward API">
|
<>
|
||||||
|
<DrawerTitle size="sub-title">Downward API</DrawerTitle>
|
||||||
{downwardAPI.items && (
|
{downwardAPI.items && (
|
||||||
<DrawerItem name="Items">
|
<DrawerItem name="Items">
|
||||||
<ul>
|
<ul>
|
||||||
@ -363,10 +365,11 @@ const volumeRenderers: PodVolumeVariantRenderers = {
|
|||||||
</ul>
|
</ul>
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
)}
|
)}
|
||||||
</DrawerSubSection>
|
</>
|
||||||
)}
|
)}
|
||||||
{configMap && (
|
{configMap && (
|
||||||
<DrawerSubSection title="Config Map">
|
<>
|
||||||
|
<DrawerTitle size="sub-title">Config Map</DrawerTitle>
|
||||||
<DrawerItem name="Name">
|
<DrawerItem name="Name">
|
||||||
{configMap.name}
|
{configMap.name}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
@ -377,10 +380,11 @@ const volumeRenderers: PodVolumeVariantRenderers = {
|
|||||||
</ul>
|
</ul>
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
)}
|
)}
|
||||||
</DrawerSubSection>
|
</>
|
||||||
)}
|
)}
|
||||||
{serviceAccountToken && (
|
{serviceAccountToken && (
|
||||||
<DrawerSubSection title="Service Account Token">
|
<>
|
||||||
|
<DrawerTitle size="sub-title">Service Account Token</DrawerTitle>
|
||||||
<DrawerItem name="Audience" hidden={!serviceAccountToken.audience}>
|
<DrawerItem name="Audience" hidden={!serviceAccountToken.audience}>
|
||||||
{serviceAccountToken.audience}
|
{serviceAccountToken.audience}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
@ -390,7 +394,7 @@ const volumeRenderers: PodVolumeVariantRenderers = {
|
|||||||
<DrawerItem name="Path">
|
<DrawerItem name="Path">
|
||||||
{serviceAccountToken.path}
|
{serviceAccountToken.path}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
</DrawerSubSection>
|
</>
|
||||||
)}
|
)}
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
))
|
))
|
||||||
@ -639,9 +643,14 @@ export const PodVolumes = observer(({ pod }: PodVolumesProps) => {
|
|||||||
|
|
||||||
const volumes = pod.getVolumes();
|
const volumes = pod.getVolumes();
|
||||||
|
|
||||||
|
if (volumes.length === 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DrawerSection title="Volumes" hidden={volumes.length === 0}>
|
<>
|
||||||
|
<DrawerTitle>Volumes</DrawerTitle>
|
||||||
{volumes.map(renderVolume)}
|
{volumes.map(renderVolume)}
|
||||||
</DrawerSection>
|
</>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,47 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) OpenLens Authors. All rights reserved.
|
|
||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from "react";
|
|
||||||
import { DrawerTitle, DrawerSubTitle } from "./drawer-title";
|
|
||||||
|
|
||||||
export interface DrawerSectionProps {
|
|
||||||
className?: string;
|
|
||||||
title?: React.ReactNode;
|
|
||||||
hidden?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DrawerSection extends React.Component<DrawerSectionProps> {
|
|
||||||
render() {
|
|
||||||
const { title, children, className, hidden } = this.props;
|
|
||||||
|
|
||||||
if (hidden) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<DrawerTitle className={className} title={title} />
|
|
||||||
{children}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class DrawerSubSection extends React.Component<DrawerSectionProps> {
|
|
||||||
render() {
|
|
||||||
const { title, children, className, hidden } = this.props;
|
|
||||||
|
|
||||||
if (hidden) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<DrawerSubTitle className={className} title={title} />
|
|
||||||
{children}
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -4,12 +4,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
.DrawerTitle {
|
.DrawerTitle {
|
||||||
padding: $padding * 1.5 $padding * 3;
|
|
||||||
margin: $margin * 3 (-$margin * 3);
|
margin: $margin * 3 (-$margin * 3);
|
||||||
background: var(--drawerSubtitleBackground);
|
background: var(--drawerSubtitleBackground);
|
||||||
}
|
}
|
||||||
|
|
||||||
.DrawerSubTitle {
|
.DrawerTitle.title {
|
||||||
padding: $padding $padding * 2;
|
padding: $padding * 1.5 $padding * 3;
|
||||||
background: var(--drawerSubtitleBackground);
|
}
|
||||||
|
|
||||||
|
.DrawerTitle.sub-title {
|
||||||
|
padding: $padding $padding * 2;
|
||||||
}
|
}
|
||||||
@ -3,34 +3,29 @@
|
|||||||
* Licensed under MIT License. See LICENSE in root directory for more information.
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import "./drawer-title.scss";
|
import styles from "./drawer-title.module.css";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { cssNames } from "../../utils";
|
import { cssNames } from "../../utils";
|
||||||
|
|
||||||
export interface DrawerTitleProps {
|
export interface DrawerTitleProps {
|
||||||
className?: string;
|
className?: string;
|
||||||
title?: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies how large this title is
|
||||||
|
*
|
||||||
|
* @default "title"
|
||||||
|
*/
|
||||||
|
size?: "sub-title" | "title";
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DrawerTitle extends React.Component<DrawerTitleProps> {
|
export function DrawerTitle({ className, children, size = "title" }: DrawerTitleProps) {
|
||||||
render() {
|
return (
|
||||||
const { title, children, className } = this.props;
|
<div className={cssNames(styles.DrawerTitle, className, {
|
||||||
|
[styles.title]: size === "title",
|
||||||
return (
|
[styles["sub-title"]]: size === "sub-title",
|
||||||
<div className={cssNames("DrawerTitle", className)}>
|
})}>
|
||||||
{title || children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
export class DrawerSubTitle extends React.Component<DrawerTitleProps> {
|
|
||||||
render() {
|
|
||||||
const { title, children, className } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={cssNames("DrawerSubTitle", className)}>
|
|
||||||
{title || children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@ export function initCatalogEntityDetailRegistry() {
|
|||||||
components: {
|
components: {
|
||||||
Details: ({ entity }: CatalogEntityDetailsProps<KubernetesCluster>) => (
|
Details: ({ entity }: CatalogEntityDetailsProps<KubernetesCluster>) => (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="Kubernetes Information" />
|
<DrawerTitle>Kubernetes Information</DrawerTitle>
|
||||||
<div className="box grow EntityMetadata">
|
<div className="box grow EntityMetadata">
|
||||||
<DrawerItem name="Distribution">
|
<DrawerItem name="Distribution">
|
||||||
{entity.metadata.distro || "unknown"}
|
{entity.metadata.distro || "unknown"}
|
||||||
@ -36,7 +36,7 @@ export function initCatalogEntityDetailRegistry() {
|
|||||||
components: {
|
components: {
|
||||||
Details: ({ entity }: CatalogEntityDetailsProps<WebLink>) => (
|
Details: ({ entity }: CatalogEntityDetailsProps<WebLink>) => (
|
||||||
<>
|
<>
|
||||||
<DrawerTitle title="More Information" />
|
<DrawerTitle>More Information</DrawerTitle>
|
||||||
<DrawerItem name="URL">
|
<DrawerItem name="URL">
|
||||||
{entity.spec.url}
|
{entity.spec.url}
|
||||||
</DrawerItem>
|
</DrawerItem>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user