diff --git a/src/extensions/registries/command-registry.ts b/src/extensions/registries/command-registry.ts index 258f856b9c..2637cf49eb 100644 --- a/src/extensions/registries/command-registry.ts +++ b/src/extensions/registries/command-registry.ts @@ -3,6 +3,8 @@ import type { Cluster } from "../../main/cluster"; import type { Workspace } from "../../common/workspace-store"; import { BaseRegistry } from "./base-registry"; +import { action } from "mobx"; +import { LensExtension } from "../lens-extension"; export type CommandContext = { cluster?: Cluster; @@ -18,6 +20,18 @@ export interface CommandRegistration { } export class CommandRegistry extends BaseRegistry { + @action + add(items: CommandRegistration | CommandRegistration[], extension?: LensExtension) { + const itemArray = [items].flat() as CommandRegistration[]; + + const newIds = itemArray.map((item) => item.id); + const currentIds = this.getItems().map((item) => item.id); + + const filteredIds = newIds.filter((id) => !currentIds.includes(id)); + const filteredItems = itemArray.filter((item) => filteredIds.includes(item.id)); + + return super.add(filteredItems, extension); + } } export const commandRegistry = new CommandRegistry(); diff --git a/src/main/index.ts b/src/main/index.ts index 265c91f6d4..2b7817f093 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -26,6 +26,7 @@ import { InstalledExtension, extensionDiscovery } from "../extensions/extension- import type { LensExtensionId } from "../extensions/lens-extension"; import { installDeveloperTools } from "./developer-tools"; import { filesystemProvisionerStore } from "./extension-filesystem"; +import { bindBroadcastHandlers } from "../common/ipc"; const workingDir = path.join(app.getPath("appData"), appName); let proxyPort: number; @@ -63,6 +64,8 @@ app.on("ready", async () => { logger.info(`🚀 Starting Lens from "${workingDir}"`); await shellSync(); + bindBroadcastHandlers(); + powerMonitor.on("shutdown", () => { app.exit(); }); diff --git a/src/renderer/components/+cluster-settings/components/cluster-workspace-setting.tsx b/src/renderer/components/+cluster-settings/components/cluster-workspace-setting.tsx index ea4ee5a571..fa76dde806 100644 --- a/src/renderer/components/+cluster-settings/components/cluster-workspace-setting.tsx +++ b/src/renderer/components/+cluster-settings/components/cluster-workspace-setting.tsx @@ -1,7 +1,5 @@ import React from "react"; import { observer } from "mobx-react"; -import { Link } from "react-router-dom"; -import { workspacesURL } from "../../+workspaces"; import { workspaceStore } from "../../../../common/workspace-store"; import { Cluster } from "../../../../main/cluster"; import { Select } from "../../../components/select"; @@ -18,10 +16,7 @@ export class ClusterWorkspaceSetting extends React.Component { <>

- Define cluster{" "} - - workspace - . + Define cluster workspace.

this.onChange(v.value)} + components={{ DropdownIndicator: null, IndicatorSeparator: null }} + menuIsOpen={true} + options={this.options} + autoFocus={true} + escapeClearsValue={false} + placeholder="Switch to cluster" /> + ); + } +} + + +commandRegistry.add({ + id: "workspace.chooseCluster", + title: "Workspace: Switch to cluster ...", + scope: "global", + action: () => openCommandDialog() +}); diff --git a/src/renderer/components/command-palette/command-container.tsx b/src/renderer/components/command-palette/command-container.tsx index 8b1c6a3851..701170d79b 100644 --- a/src/renderer/components/command-palette/command-container.tsx +++ b/src/renderer/components/command-palette/command-container.tsx @@ -7,6 +7,10 @@ import { Dialog } from "../dialog"; import { EventEmitter } from "../../../common/event-emitter"; import { subscribeToBroadcast } from "../../../common/ipc"; import { CommandDialog } from "./command-dialog"; +import { CommandRegistration, commandRegistry } from "../../../extensions/registries/command-registry"; +import { clusterStore } from "../../../common/cluster-store"; +import { workspaceStore } from "../../../common/workspace-store"; +import { Cluster } from "../../../main/cluster"; export type CommandDialogEvent = { component: React.ReactElement @@ -23,7 +27,7 @@ export function closeCommandDialog() { } @observer -export class CommandContainer extends React.Component<{listenPaletteOpen: boolean}> { +export class CommandContainer extends React.Component<{cluster?: Cluster}> { @observable visible = false; @observable commandComponent: React.ReactElement; @@ -39,22 +43,49 @@ export class CommandContainer extends React.Component<{listenPaletteOpen: boolea this.commandComponent = null; } + private findCommandById(commandId: string) { + return commandRegistry.getItems().find((command) => command.id === commandId); + } + + private runCommand(command: CommandRegistration) { + command.action({ + cluster: clusterStore.active, + workspace: workspaceStore.currentWorkspace + }); + } + + onClusterAction(commandId: string) { + const command = this.findCommandById(commandId); + + if (command) { + this.runCommand(command); + } + } + componentDidMount() { - if (this.props.listenPaletteOpen) { + if (this.props.cluster) { + subscribeToBroadcast(`command-palette:run-action:${this.props.cluster.id}`, (event, commandId: string) => { + console.log("run-action", commandId); + const command = this.findCommandById(commandId); + + if (command) { + this.runCommand(command); + } + }); + } else { subscribeToBroadcast("command-palette:open", () => { openCommandDialog(); }); } window.addEventListener("keyup", (e) => this.escHandler(e), true); commandDialogBus.addListener((event) => { - console.log(event); this.commandComponent = event.component; }); } render() { return ( - + this.commandComponent = null}>
{this.commandComponent}
diff --git a/src/renderer/components/command-palette/command-dialog.tsx b/src/renderer/components/command-palette/command-dialog.tsx index 865bc9d0f5..b377442d56 100644 --- a/src/renderer/components/command-palette/command-dialog.tsx +++ b/src/renderer/components/command-palette/command-dialog.tsx @@ -7,15 +7,37 @@ import { commandRegistry } from "../../../extensions/registries/command-registry import { clusterStore } from "../../../common/cluster-store"; import { workspaceStore } from "../../../common/workspace-store"; import { closeCommandDialog } from "./command-container"; +import { broadcastMessage } from "../../../common/ipc"; @observer export class CommandDialog extends React.Component { @observable menuIsOpen = true; @computed get options() { - return commandRegistry.getItems().map((command) => { + const context = { + cluster: clusterStore.active, + workspace: workspaceStore.currentWorkspace + }; + + return commandRegistry.getItems().filter((command) => { + if (command.scope === "cluster" && !clusterStore.active) { + return false; + } + + if (!command.isActive) { + return true; + } + + try { + return command.isActive(context); + } catch(e) { + console.error(e); + + return false; + } + }).map((command) => { return { value: command.id, label: command.title }; - }); + }).sort((a, b) => a.label > b.label ? 1 : -1); } private onChange(value: string) { @@ -29,10 +51,15 @@ export class CommandDialog extends React.Component { try { closeCommandDialog(); - action({ - cluster: clusterStore.active, - workspace: workspaceStore.currentWorkspace - }); + + if (command.scope === "global") { + action({ + cluster: clusterStore.active, + workspace: workspaceStore.currentWorkspace + }); + } else if(clusterStore.active) { + broadcastMessage(`command-palette:run-action:${clusterStore.active.id}`, command.id); + } } catch(error) { console.error("failed to execute command", command.id, error); } diff --git a/src/renderer/components/dock/dock.tsx b/src/renderer/components/dock/dock.tsx index c8adf82992..34559302a4 100644 --- a/src/renderer/components/dock/dock.tsx +++ b/src/renderer/components/dock/dock.tsx @@ -22,6 +22,7 @@ import { TerminalWindow } from "./terminal-window"; import { createTerminalTab, isTerminalTab } from "./terminal.store"; import { UpgradeChart } from "./upgrade-chart"; import { isUpgradeChartTab } from "./upgrade-chart.store"; +import { commandRegistry } from "../../../extensions/registries/command-registry"; interface Props { className?: string; @@ -131,3 +132,11 @@ export class Dock extends React.Component { ); } } + +commandRegistry.add({ + id: "cluster.openTerminal", + title: "Cluster: Open terminal", + scope: "cluster", + action: () => createTerminalTab(), + isActive: (context) => !!context.cluster +}); diff --git a/src/renderer/lens-app.tsx b/src/renderer/lens-app.tsx index 9c5f0f1041..8bf188cdbf 100644 --- a/src/renderer/lens-app.tsx +++ b/src/renderer/lens-app.tsx @@ -38,7 +38,7 @@ export class LensApp extends React.Component { - + ); }