1
0
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:
Alex Andreev 2021-06-23 09:50:11 +03:00
commit 95dc20d3e8
17 changed files with 72 additions and 32 deletions

View File

@ -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'

View File

@ -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

View File

@ -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

View File

@ -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:
![Cluster Page Menus](images/clusterpagemenus.png)
### `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.

View File

@ -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",

View File

@ -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

View File

@ -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 {

View File

@ -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;

View File

@ -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"
} }
} }

View File

@ -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);
} }

View File

@ -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);

View File

@ -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");

View File

@ -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,
); );

View File

@ -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 (

View File

@ -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"

View File

@ -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&apos;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 })} />