diff --git a/src/renderer/components/dock/create-resource.tsx b/src/renderer/components/dock/create-resource.tsx index faba70ff7c..135118dcd8 100644 --- a/src/renderer/components/dock/create-resource.tsx +++ b/src/renderer/components/dock/create-resource.tsx @@ -25,18 +25,17 @@ import { GroupSelectOption, Select, SelectOption } from "../select"; import jsYaml from "js-yaml"; import { computed, makeObservable, observable } from "mobx"; import { observer } from "mobx-react"; -import { cssNames } from "../../utils"; import { createResourceStore } from "./create-resource.store"; -import type { DockTab } from "./dock.store"; -import { MonacoEditor } from "../monaco-editor"; import { InfoPanel } from "./info-panel"; import { resourceApplierApi } from "../../../common/k8s-api/endpoints/resource-applier.api"; import type { JsonApiErrorParsed } from "../../../common/k8s-api/json-api"; import { Notifications } from "../notifications"; +import { DockTabContent, DockTabContentProps } from "./dock-tab-content"; +import { TabKind } from "./dock.store"; +import { dockViewsManager } from "./dock.views-manager"; +import { MonacoEditor } from "../monaco-editor"; -interface Props { - className?: string; - tab: DockTab; +interface Props extends DockTabContentProps { } type SelectOptionTemplate = SelectOption; @@ -146,11 +145,10 @@ export class CreateResource extends React.Component { }; render() { - const { tabId, draft, error, create } = this; - const { className } = this.props; + const { tabId, draft, error, create, onChange, onError } = this; return ( -
+ { -
+ ); } } + +dockViewsManager.register(TabKind.CREATE_RESOURCE, { + tabContent: CreateResource, +}); diff --git a/src/renderer/components/dock/dock-tab-content.tsx b/src/renderer/components/dock/dock-tab-content.tsx new file mode 100644 index 0000000000..fe877fb832 --- /dev/null +++ b/src/renderer/components/dock/dock-tab-content.tsx @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +import React from "react"; +import type { DockTab } from "./dock.store"; +import { cssNames } from "../../utils"; + +export interface DockTabContentProps { + className?: string; + tab: DockTab; + bindElemRef?(container: HTMLElement): void; +} + +export class DockTabContent extends React.Component { + render() { + const { children: tabContent, bindElemRef, className } = this.props; + + return ( +
+ {tabContent} +
+ ); + } +} diff --git a/src/renderer/components/dock/dock.tsx b/src/renderer/components/dock/dock.tsx index a8cea06d7b..2599b65de1 100644 --- a/src/renderer/components/dock/dock.tsx +++ b/src/renderer/components/dock/dock.tsx @@ -23,22 +23,16 @@ import "./dock.scss"; import React from "react"; import { observer } from "mobx-react"; - import { cssNames, prevDefault } from "../../utils"; import { Icon } from "../icon"; import { MenuItem } from "../menu"; import { MenuActions } from "../menu/menu-actions"; import { ResizeDirection, ResizingAnchor } from "../resizing-anchor"; -import { CreateResource } from "./create-resource"; import { createResourceTab } from "./create-resource.store"; import { DockTabs } from "./dock-tabs"; -import { dockStore, DockTab, TabKind } from "./dock.store"; -import { EditResource } from "./edit-resource"; -import { InstallChart } from "./install-chart"; -import { Logs } from "./logs"; -import { TerminalWindow } from "./terminal-window"; +import { dockStore, DockTab } from "./dock.store"; import { createTerminalTab } from "./terminal.store"; -import { UpgradeChart } from "./upgrade-chart"; +import { dockViewsManager } from "./dock.views-manager"; interface Props { className?: string; @@ -69,38 +63,10 @@ export class Dock extends React.Component { selectTab(tab.id); }; - renderTab(tab: DockTab) { - switch (tab.kind) { - case TabKind.CREATE_RESOURCE: - return ; - case TabKind.EDIT_RESOURCE: - return ; - case TabKind.INSTALL_CHART: - return ; - case TabKind.UPGRADE_CHART: - return ; - case TabKind.POD_LOGS: - return ; - case TabKind.TERMINAL: - return ; - } - } - - renderTabContent() { - const { isOpen, height, selectedTab } = dockStore; - - if (!isOpen || !selectedTab) return null; - - return ( -
- {this.renderTab(selectedTab)} -
- ); - } - render() { const { className } = this.props; - const { isOpen, toggle, tabs, toggleFillSize, selectedTab, hasTabs, fullSize } = dockStore; + const { isOpen, toggle, tabs, toggleFillSize, selectedTab, hasTabs, fullSize, height } = dockStore; + const TabContent = dockViewsManager.get(selectedTab?.kind)?.tabContent ?? React.Fragment; return (
{
createTerminalTab()}> - + Terminal session createResourceTab()}> - + Create resource @@ -155,7 +121,9 @@ export class Dock extends React.Component { )}
- {this.renderTabContent()} +
+ +
); } diff --git a/src/renderer/components/dock/dock.views-manager.ts b/src/renderer/components/dock/dock.views-manager.ts new file mode 100644 index 0000000000..8ac91168b2 --- /dev/null +++ b/src/renderer/components/dock/dock.views-manager.ts @@ -0,0 +1,45 @@ +/** + * Copyright (c) 2021 OpenLens Authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +import type React from "react"; +import { observable } from "mobx"; +import type { TabKind } from "./dock.store"; +import type { DockTabContentProps } from "./dock-tab-content"; + +export interface DockViews { + tabContent?: React.ComponentType; +} + +const dockViews = observable.map([], { + deep: false, // mobx: don't try to modify react components +}); + +export const dockViewsManager = { + get(tabKind: TabKind): DockViews { + return dockViews.get(tabKind) ?? {}; + }, + + register(tabKind: TabKind, views: DockViews) { + const currentViews = this.get(tabKind); + + dockViews.set(tabKind, { ...currentViews, ...views }); + } +}; diff --git a/src/renderer/components/dock/edit-resource.tsx b/src/renderer/components/dock/edit-resource.tsx index 62ff0ce368..cdecbfca9d 100644 --- a/src/renderer/components/dock/edit-resource.tsx +++ b/src/renderer/components/dock/edit-resource.tsx @@ -25,18 +25,18 @@ import React from "react"; import { action, autorun, makeObservable, observable } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; import jsYaml from "js-yaml"; -import type { DockTab } from "./dock.store"; -import { cssNames } from "../../utils"; import { editResourceStore } from "./edit-resource.store"; import { InfoPanel } from "./info-panel"; import { Badge } from "../badge"; -import { MonacoEditor } from "../monaco-editor"; import { Spinner } from "../spinner"; import type { KubeObject } from "../../../common/k8s-api/kube-object"; +import type { DockTabContentProps } from "./dock-tab-content"; +import { DockTabContent } from "./dock-tab-content"; +import { TabKind } from "./dock.store"; +import { dockViewsManager } from "./dock.views-manager"; +import { MonacoEditor } from "../monaco-editor"; -interface Props { - className?: string; - tab: DockTab; +interface Props extends DockTabContentProps { } @observer @@ -104,10 +104,10 @@ export class EditResource extends React.Component { return ; } - const { tabId, error, draft, resource } = this; + const { tabId, error, draft, resource, onChange, onError } = this; return ( -
+ { -
+ ); } } + +dockViewsManager.register(TabKind.EDIT_RESOURCE, { + tabContent: EditResource, +}); diff --git a/src/renderer/components/dock/index.ts b/src/renderer/components/dock/index.ts index a4cb5982f7..67a0d7e5b3 100644 --- a/src/renderer/components/dock/index.ts +++ b/src/renderer/components/dock/index.ts @@ -20,3 +20,11 @@ */ export * from "./dock"; + +// registered dock-tab view components +export * from "./terminal-window"; +export * from "./create-resource"; +export * from "./edit-resource"; +export * from "./install-chart"; +export * from "./upgrade-chart"; +export * from "./logs"; diff --git a/src/renderer/components/dock/install-chart.tsx b/src/renderer/components/dock/install-chart.tsx index 5e3060bc62..154077109b 100644 --- a/src/renderer/components/dock/install-chart.tsx +++ b/src/renderer/components/dock/install-chart.tsx @@ -24,7 +24,7 @@ import "./install-chart.scss"; import React, { Component } from "react"; import { autorun, computed, makeObservable, observable } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; -import { dockStore, DockTab } from "./dock.store"; +import { dockStore, TabKind } from "./dock.store"; import { InfoPanel } from "./info-panel"; import { Badge } from "../badge"; import { NamespaceSelect } from "../+namespaces/namespace-select"; @@ -37,12 +37,13 @@ import { releaseStore } from "../+apps-releases/release.store"; import { LogsDialog } from "../dialog/logs-dialog"; import { Select, SelectOption } from "../select"; import { Input } from "../input"; -import { MonacoEditor } from "../monaco-editor"; import { navigate } from "../../navigation"; import { releaseURL } from "../../../common/routes"; +import { DockTabContent, DockTabContentProps } from "./dock-tab-content"; +import { dockViewsManager } from "./dock.views-manager"; +import { MonacoEditor } from "../monaco-editor"; -interface Props { - tab: DockTab; +interface Props extends DockTabContentProps { } @observer @@ -108,6 +109,10 @@ export class InstallChart extends Component { this.save({ values }); }; + onValuesError = (error: string) => { + this.error = error; + }; + onNamespaceChange = (opt: SelectOption) => { this.save({ namespace: opt.value }); }; @@ -203,7 +208,7 @@ export class InstallChart extends Component { ); return ( -
+ { id={tabId} value={chartData.values} onChange={this.onValuesChange} - onError={error => this.error = error} + onError={this.onValuesError} /> -
+ ); } } + +dockViewsManager.register(TabKind.INSTALL_CHART, { + tabContent: InstallChart, +}); diff --git a/src/renderer/components/dock/logs.tsx b/src/renderer/components/dock/logs.tsx index 6c5c8d115f..e57ccf0a7e 100644 --- a/src/renderer/components/dock/logs.tsx +++ b/src/renderer/components/dock/logs.tsx @@ -20,12 +20,11 @@ */ import React from "react"; -import { observable, reaction, makeObservable } from "mobx"; +import { makeObservable, observable, reaction } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; import { searchStore } from "../../../common/search-store"; import { boundMethod } from "../../utils"; -import type { DockTab } from "./dock.store"; import { InfoPanel } from "./info-panel"; import { LogResourceSelector } from "./log-resource-selector"; import { LogList } from "./log-list"; @@ -33,10 +32,11 @@ import { logStore } from "./log.store"; import { LogSearch } from "./log-search"; import { LogControls } from "./log-controls"; import { LogTabData, logTabStore } from "./log-tab.store"; +import { DockTabContent, DockTabContentProps } from "./dock-tab-content"; +import { TabKind } from "./dock.store"; +import { dockViewsManager } from "./dock.views-manager"; -interface Props { - className?: string - tab: DockTab +interface Props extends DockTabContentProps { } @observer @@ -143,7 +143,7 @@ export class Logs extends React.Component { } return ( -
+ {this.renderResourceSelector(data)} { save={newData => logTabStore.setData(this.tabId, { ...data, ...newData })} reload={this.reload} /> -
+ ); } } + +dockViewsManager.register(TabKind.POD_LOGS, { + tabContent: Logs, +}); diff --git a/src/renderer/components/dock/terminal-window.tsx b/src/renderer/components/dock/terminal-window.tsx index 652086d811..e07d9d800c 100644 --- a/src/renderer/components/dock/terminal-window.tsx +++ b/src/renderer/components/dock/terminal-window.tsx @@ -25,14 +25,14 @@ import React from "react"; import { reaction } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; import { cssNames } from "../../utils"; -import type { DockTab } from "./dock.store"; import type { Terminal } from "./terminal"; import { terminalStore } from "./terminal.store"; import { ThemeStore } from "../../theme.store"; +import { DockTabContent, DockTabContentProps } from "./dock-tab-content"; +import { TabKind } from "./dock.store"; +import { dockViewsManager } from "./dock.views-manager"; -interface Props { - className?: string; - tab: DockTab; +interface Props extends DockTabContentProps { } @observer @@ -55,13 +55,16 @@ export class TerminalWindow extends React.Component { } render() { - const { className } = this.props; - return ( -
this.elem = e} + this.elem = elem} /> ); } } + +dockViewsManager.register(TabKind.TERMINAL, { + tabContent: TerminalWindow, +}); diff --git a/src/renderer/components/dock/upgrade-chart.tsx b/src/renderer/components/dock/upgrade-chart.tsx index 85cd8ccbe9..6e43caf41b 100644 --- a/src/renderer/components/dock/upgrade-chart.tsx +++ b/src/renderer/components/dock/upgrade-chart.tsx @@ -24,21 +24,20 @@ import "./upgrade-chart.scss"; import React from "react"; import { autorun, computed, makeObservable, observable } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; -import { cssNames } from "../../utils"; -import type { DockTab } from "./dock.store"; import { InfoPanel } from "./info-panel"; import { upgradeChartStore } from "./upgrade-chart.store"; import { Spinner } from "../spinner"; import { releaseStore } from "../+apps-releases/release.store"; import { Badge } from "../badge"; -import { MonacoEditor } from "../monaco-editor"; import { Select, SelectOption } from "../select"; import type { IChartVersion } from "../+apps-helm-charts/helm-chart.store"; import type { HelmRelease } from "../../../common/k8s-api/endpoints/helm-releases.api"; +import { DockTabContent, DockTabContentProps } from "./dock-tab-content"; +import { TabKind } from "./dock.store"; +import { dockViewsManager } from "./dock.views-manager"; +import { MonacoEditor } from "../monaco-editor"; -interface Props { - className?: string; - tab: DockTab; +interface Props extends DockTabContentProps { } @observer @@ -63,7 +62,7 @@ export class UpgradeChart extends React.Component { return upgradeChartStore.getRelease(this.tabId); } - get isReady(){ + get isReady() { return [ upgradeChartStore.dataReady, this.release, @@ -118,8 +117,7 @@ export class UpgradeChart extends React.Component { return ; } - const { className } = this.props; - const { tabId, release, value, error, versionOptions, selectedVersion } = this; + const { tabId, release, value, error, versionOptions, selectedVersion, onChange, onError } = this; const currentVersion = release.getVersion(); const controlsAndInfo = ( @@ -141,7 +139,7 @@ export class UpgradeChart extends React.Component { ); return ( -
+ { -
+
); } } + +dockViewsManager.register(TabKind.UPGRADE_CHART, { + tabContent: UpgradeChart, +});