mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Merge branch 'master' into cleaning-settings-page-view
This commit is contained in:
commit
95dc20d3e8
1
.github/release-drafter.yml
vendored
1
.github/release-drafter.yml
vendored
@ -10,6 +10,7 @@ categories:
|
|||||||
- title: '🧰 Maintenance'
|
- title: '🧰 Maintenance'
|
||||||
labels:
|
labels:
|
||||||
- 'chore'
|
- 'chore'
|
||||||
|
- 'area/documentation'
|
||||||
- 'area/ci'
|
- 'area/ci'
|
||||||
- 'area/tests'
|
- 'area/tests'
|
||||||
- 'dependencies'
|
- 'dependencies'
|
||||||
|
|||||||
2
Makefile
2
Makefile
@ -44,7 +44,7 @@ release-version:
|
|||||||
|
|
||||||
.PHONY: tag-release
|
.PHONY: tag-release
|
||||||
tag-release:
|
tag-release:
|
||||||
scripts/tag-release.sh
|
scripts/tag-release.sh $(CMD_ARGS)
|
||||||
|
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
test: binaries/client
|
test: binaries/client
|
||||||
|
|||||||
@ -33,6 +33,7 @@ function getBuildChannel(): string {
|
|||||||
* Note: it is by design that we don't use `rc` as a build channel for these versions
|
* Note: it is by design that we don't use `rc` as a build channel for these versions
|
||||||
*/
|
*/
|
||||||
switch (versionInfo.prerelease?.[0]) {
|
switch (versionInfo.prerelease?.[0]) {
|
||||||
|
case "rc":
|
||||||
case "beta":
|
case "beta":
|
||||||
return "beta";
|
return "beta";
|
||||||
case undefined:
|
case undefined:
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 251 KiB After Width: | Height: | Size: 712 KiB |
@ -60,7 +60,7 @@ Implementing `onDeactivate()` gives you the opportunity to clean up after your e
|
|||||||
|
|
||||||
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. For the extension you want to disable, open the context menu (click on the three vertical dots) and choose **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.
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ Use cluster pages to display information about or add functionality to the activ
|
|||||||
It is also possible to include custom details from other clusters.
|
It is also possible to include custom details from other clusters.
|
||||||
Use your extension to access Kubernetes resources in the active cluster with [`ClusterStore.getInstance()`](../stores#Clusterstore).
|
Use your extension to access Kubernetes resources in the active cluster with [`ClusterStore.getInstance()`](../stores#Clusterstore).
|
||||||
|
|
||||||
Add a cluster page definition to a `LensRendererExtension` subclass with the following example:
|
Add a cluster page definition to a `Renderer.LensExtension` subclass with the following example:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
@ -124,7 +124,7 @@ Use `clusterPageMenus`, covered in the next section, to add cluster pages to the
|
|||||||
|
|
||||||
### `clusterPageMenus`
|
### `clusterPageMenus`
|
||||||
|
|
||||||
`clusterPageMenus` allows you to add cluster page menu items to the secondary left nav.
|
`clusterPageMenus` allows you to add cluster page menu items to the secondary left nav, below Lens's standard cluster menus like **Workloads**, **Custom Resources**, etc.
|
||||||
|
|
||||||
By expanding on the above example, you can add a cluster page menu item to the `ExampleExtension` definition:
|
By expanding on the above example, you can add a cluster page menu item to the `ExampleExtension` definition:
|
||||||
|
|
||||||
@ -266,18 +266,18 @@ Activating this menu item toggles on and off the appearance of the submenu below
|
|||||||
The remaining two cluster page menu objects define the contents of the submenu.
|
The remaining two cluster page menu objects define the contents of the submenu.
|
||||||
A cluster page menu object is defined to be a submenu item by setting the `parentId` field to the id of the parent of a foldout submenu, `"example"` in this case.
|
A cluster page menu object is defined to be a submenu item by setting the `parentId` field to the id of the parent of a foldout submenu, `"example"` in this case.
|
||||||
|
|
||||||
This is what the example will look like, including how the menu item will appear in the secondary left nav:
|
This is what the example could look like, including how the menu item will appear in the secondary left nav:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
### `globalPages`
|
### `globalPages`
|
||||||
|
|
||||||
Global pages are independent of the cluster dashboard and can fill the entire Lens UI.
|
Global pages are independent of the cluster dashboard and can fill the entire Lens UI.
|
||||||
Their primary use is to display information and provide functionality across clusters, including customized data and functionality unique to your extension.
|
Their primary use is to display information and provide functionality across clusters (or catalog entities), including customized data and functionality unique to your extension.
|
||||||
|
|
||||||
Typically, you would use a [global page menu](#globalpagemenus) located in the left nav to trigger a global page.
|
Unlike cluster pages, users can trigger global pages even when there is no active cluster (or catalog entity).
|
||||||
You can also trigger a global page with a [custom app menu selection](../main-extension#appmenus) from a Main Extension or a [custom status bar item](#statusbaritems).
|
|
||||||
Unlike cluster pages, users can trigger global pages even when there is no active cluster.
|
|
||||||
|
|
||||||
The following example defines a `LensRendererExtension` 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';
|
||||||
@ -326,11 +326,11 @@ This allows the `HelpExtension` object to be passed in the global page definitio
|
|||||||
This way, `HelpPage` can access all `HelpExtension` subclass data.
|
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 can be 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 left side menu, see [`globalPageMenus`](#globalpagemenus).
|
* To add global pages to the Welcome Page, see [`welcomeMenus`](#welcomemenus).
|
||||||
|
|
||||||
### `welcomeMenus`
|
### `welcomeMenus`
|
||||||
### `appPreferences`
|
### `appPreferences`
|
||||||
@ -381,6 +381,7 @@ In this example `ExamplePreferenceInput`, `ExamplePreferenceHint`, and `ExampleP
|
|||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Renderer } from "@k8slens/extensions";
|
import { Renderer } from "@k8slens/extensions";
|
||||||
|
import { makeObservable } from "mobx";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
@ -399,6 +400,11 @@ export class ExamplePreferenceProps {
|
|||||||
@observer
|
@observer
|
||||||
export class ExamplePreferenceInput extends React.Component<ExamplePreferenceProps> {
|
export class ExamplePreferenceInput extends React.Component<ExamplePreferenceProps> {
|
||||||
|
|
||||||
|
public constructor() {
|
||||||
|
super({preference: { enabled: false}});
|
||||||
|
makeObservable(this);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { preference } = this.props;
|
const { preference } = this.props;
|
||||||
return (
|
return (
|
||||||
@ -432,7 +438,7 @@ It is used to indicate the state of the preference, and it is bound to the check
|
|||||||
|
|
||||||
`ExamplePreferenceHint` is a simple text span.
|
`ExamplePreferenceHint` is a simple text span.
|
||||||
|
|
||||||
The above example introduces the decorators `observable` and `observer` from the [`mobx`](https://mobx.js.org/README.html) and [`mobx-react`](https://github.com/mobxjs/mobx-react#mobx-react) packages.
|
The above example introduces the decorators `makeObservable` and `observer` from the [`mobx`](https://mobx.js.org/README.html) and [`mobx-react`](https://github.com/mobxjs/mobx-react#mobx-react) packages.
|
||||||
`mobx` simplifies state management.
|
`mobx` simplifies state management.
|
||||||
Without it, this example would not visually update the checkbox properly when the user activates it.
|
Without it, this example would not visually update the checkbox properly when the user activates it.
|
||||||
[Lens uses `mobx`](../working-with-mobx) extensively for state management of its own UI elements.
|
[Lens uses `mobx`](../working-with-mobx) extensively for state management of its own UI elements.
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
"productName": "OpenLens",
|
"productName": "OpenLens",
|
||||||
"description": "OpenLens - Open Source IDE for Kubernetes",
|
"description": "OpenLens - Open Source IDE for Kubernetes",
|
||||||
"homepage": "https://github.com/lensapp/lens",
|
"homepage": "https://github.com/lensapp/lens",
|
||||||
"version": "5.0.0-beta.11",
|
"version": "5.0.0-beta.10",
|
||||||
"main": "static/build/main.js",
|
"main": "static/build/main.js",
|
||||||
"copyright": "© 2021 OpenLens Authors",
|
"copyright": "© 2021 OpenLens Authors",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@ -1,10 +1,21 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
key="$1"
|
||||||
|
|
||||||
|
case $key in
|
||||||
|
-f|--force)
|
||||||
|
FORCE="--force"
|
||||||
|
shift # past argument
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
if [[ `git branch --show-current` =~ ^release/v ]]
|
if [[ `git branch --show-current` =~ ^release/v ]]
|
||||||
then
|
then
|
||||||
VERSION_STRING=$(cat package.json | jq '.version' -r | xargs printf "v%s")
|
VERSION_STRING=$(cat package.json | jq '.version' -r | xargs printf "v%s")
|
||||||
git tag ${VERSION_STRING}
|
git tag ${VERSION_STRING} ${FORCE}
|
||||||
git push ${GIT_REMOTE:-origin} ${VERSION_STRING}
|
git push ${GIT_REMOTE:-origin} ${VERSION_STRING} ${FORCE}
|
||||||
else
|
else
|
||||||
echo "You must be in a release branch"
|
echo "You must be in a release branch"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@ -38,9 +38,6 @@ export interface KubernetesClusterPrometheusMetrics {
|
|||||||
prefix: string;
|
prefix: string;
|
||||||
};
|
};
|
||||||
type?: string;
|
type?: string;
|
||||||
icon?: {
|
|
||||||
src?: string;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface KubernetesClusterSpec extends CatalogEntitySpec {
|
export interface KubernetesClusterSpec extends CatalogEntitySpec {
|
||||||
@ -49,7 +46,13 @@ export interface KubernetesClusterSpec extends CatalogEntitySpec {
|
|||||||
metrics?: {
|
metrics?: {
|
||||||
source: string;
|
source: string;
|
||||||
prometheus?: KubernetesClusterPrometheusMetrics;
|
prometheus?: KubernetesClusterPrometheusMetrics;
|
||||||
}
|
};
|
||||||
|
icon?: {
|
||||||
|
// TODO: move to CatalogEntitySpec once any-entity icons are supported
|
||||||
|
src?: string;
|
||||||
|
material?: string;
|
||||||
|
background?: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface KubernetesClusterStatus extends CatalogEntityStatus {
|
export interface KubernetesClusterStatus extends CatalogEntityStatus {
|
||||||
|
|||||||
@ -187,7 +187,7 @@ export abstract class LensProtocolRouter extends Singleton {
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ExtensionsStore.getInstance().isEnabled(extension.id)) {
|
if (!extension.isBundled && !ExtensionsStore.getInstance().isEnabled(extension.id)) {
|
||||||
logger.info(`${LensProtocolRouter.LoggingPrefix}: Extension ${name} matched, but not enabled`);
|
logger.info(`${LensProtocolRouter.LoggingPrefix}: Extension ${name} matched, but not enabled`);
|
||||||
|
|
||||||
return name;
|
return name;
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"@types/react-select": "*",
|
"@types/react-select": "*",
|
||||||
"@material-ui/core": "*",
|
"@material-ui/core": "*",
|
||||||
"conf": "^7.0.1"
|
"conf": "^7.0.1",
|
||||||
|
"typed-emitter": "^1.3.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -102,7 +102,7 @@ export class ClusterManager extends Singleton {
|
|||||||
const entity = catalogEntityRegistry.items[index] as KubernetesCluster;
|
const entity = catalogEntityRegistry.items[index] as KubernetesCluster;
|
||||||
|
|
||||||
this.updateEntityStatus(entity, cluster);
|
this.updateEntityStatus(entity, cluster);
|
||||||
|
|
||||||
entity.metadata.labels = Object.assign({}, cluster.labels, entity.metadata.labels);
|
entity.metadata.labels = Object.assign({}, cluster.labels, entity.metadata.labels);
|
||||||
|
|
||||||
if (cluster.preferences?.clusterName) {
|
if (cluster.preferences?.clusterName) {
|
||||||
@ -119,7 +119,12 @@ export class ClusterManager extends Singleton {
|
|||||||
entity.spec.metrics.prometheus = prometheus;
|
entity.spec.metrics.prometheus = prometheus;
|
||||||
}
|
}
|
||||||
|
|
||||||
entity.spec.icon.src = cluster.preferences.icon;
|
if (cluster.preferences.icon) {
|
||||||
|
entity.spec.icon ??= {};
|
||||||
|
entity.spec.icon.src = cluster.preferences.icon;
|
||||||
|
} else {
|
||||||
|
entity.spec.icon = null;
|
||||||
|
}
|
||||||
|
|
||||||
catalogEntityRegistry.items.splice(index, 1, entity);
|
catalogEntityRegistry.items.splice(index, 1, entity);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -82,10 +82,10 @@ export class LensProtocolRouterMain extends proto.LensProtocolRouter {
|
|||||||
throw new proto.RoutingError(proto.RoutingErrorType.INVALID_PROTOCOL, url);
|
throw new proto.RoutingError(proto.RoutingErrorType.INVALID_PROTOCOL, url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WindowManager.getInstance(false)?.ensureMainWindow().catch(noop);
|
||||||
const routeInternally = checkHost(url);
|
const routeInternally = checkHost(url);
|
||||||
|
|
||||||
logger.info(`${proto.LensProtocolRouter.LoggingPrefix}: routing ${url.toString()}`);
|
logger.info(`${proto.LensProtocolRouter.LoggingPrefix}: routing ${url.toString()}`);
|
||||||
WindowManager.getInstance(false)?.ensureMainWindow().catch(noop);
|
|
||||||
|
|
||||||
if (routeInternally) {
|
if (routeInternally) {
|
||||||
this._routeToInternal(url);
|
this._routeToInternal(url);
|
||||||
|
|||||||
@ -35,7 +35,7 @@ interface Pre500WorkspaceStoreModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
version: "5.0.0-beta.11",
|
version: "5.0.0-beta.10",
|
||||||
run(store) {
|
run(store) {
|
||||||
const hotbars: Hotbar[] = store.get("hotbars");
|
const hotbars: Hotbar[] = store.get("hotbars");
|
||||||
const userDataPath = app.getPath("userData");
|
const userDataPath = app.getPath("userData");
|
||||||
@ -26,11 +26,11 @@ import { joinMigrations } from "../helpers";
|
|||||||
import version500alpha0 from "./5.0.0-alpha.0";
|
import version500alpha0 from "./5.0.0-alpha.0";
|
||||||
import version500alpha2 from "./5.0.0-alpha.2";
|
import version500alpha2 from "./5.0.0-alpha.2";
|
||||||
import version500beta5 from "./5.0.0-beta.5";
|
import version500beta5 from "./5.0.0-beta.5";
|
||||||
import version500beta11 from "./5.0.0-beta.11";
|
import version500beta10 from "./5.0.0-beta.10";
|
||||||
|
|
||||||
export default joinMigrations(
|
export default joinMigrations(
|
||||||
version500alpha0,
|
version500alpha0,
|
||||||
version500alpha2,
|
version500alpha2,
|
||||||
version500beta5,
|
version500beta5,
|
||||||
version500beta11,
|
version500beta10,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -208,7 +208,7 @@ export class ReleaseDetails extends Component<Props> {
|
|||||||
{items.map(item => {
|
{items.map(item => {
|
||||||
const name = item.getName();
|
const name = item.getName();
|
||||||
const namespace = item.getNs();
|
const namespace = item.getNs();
|
||||||
const api = apiManager.getApi(item.metadata.selfLink);
|
const api = apiManager.getApi(api => api.kind === kind && api.apiVersionWithGroup == item.apiVersion);
|
||||||
const detailsUrl = api ? getDetailsUrl(api.getUrl({ name, namespace })) : "";
|
const detailsUrl = api ? getDetailsUrl(api.getUrl({ name, namespace })) : "";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -72,9 +72,21 @@ function getIconString(title: string) {
|
|||||||
export function Avatar(props: Props) {
|
export function Avatar(props: Props) {
|
||||||
const { title, width = 32, height = 32, colorHash, children, background, ...settings } = props;
|
const { title, width = 32, height = 32, colorHash, children, background, ...settings } = props;
|
||||||
|
|
||||||
|
const getBackgroundColor = () => {
|
||||||
|
if (background) {
|
||||||
|
return background;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.src) {
|
||||||
|
return "transparent";
|
||||||
|
}
|
||||||
|
|
||||||
|
return randomColor({ seed: colorHash, luminosity: "dark" });
|
||||||
|
};
|
||||||
|
|
||||||
const generateAvatarStyle = (): React.CSSProperties => {
|
const generateAvatarStyle = (): React.CSSProperties => {
|
||||||
return {
|
return {
|
||||||
backgroundColor: background || randomColor({ seed: colorHash, luminosity: "dark" }),
|
backgroundColor: getBackgroundColor(),
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
textTransform: "uppercase"
|
textTransform: "uppercase"
|
||||||
|
|||||||
@ -59,8 +59,8 @@ function UpdateAvailableHandler(event: IpcRendererEvent, ...[backchannel, update
|
|||||||
(
|
(
|
||||||
<div className="flex column gaps">
|
<div className="flex column gaps">
|
||||||
<b>Update Available</b>
|
<b>Update Available</b>
|
||||||
<p>Version {updateInfo.version} of Lens IDE is now available. Would you like to update?</p>
|
<p>Version {updateInfo.version} of Lens IDE is available and ready to be installed. Would you like to update now?</p>
|
||||||
<p>Manual restart required!</p>
|
<p>Lens should restart automatically, if it doesn't please restart manually. Installed extensions might require updating.</p>
|
||||||
<div className="flex gaps row align-left box grow">
|
<div className="flex gaps row align-left box grow">
|
||||||
<RenderYesButtons backchannel={backchannel} notificationId={notificationId} />
|
<RenderYesButtons backchannel={backchannel} notificationId={notificationId} />
|
||||||
<Button active outlined label="No" onClick={() => sendToBackchannel(backchannel, notificationId, { doUpdate: false })} />
|
<Button active outlined label="No" onClick={() => sendToBackchannel(backchannel, notificationId, { doUpdate: false })} />
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user