mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
refactoring dock-tab stores -- part 2
Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
parent
5c41b8612e
commit
5038267bbc
@ -23,10 +23,10 @@ import fs from "fs-extra";
|
||||
import path from "path";
|
||||
import os from "os";
|
||||
import { autoBind } from "../../utils";
|
||||
import { DockTabsStore } from "./dock-tabs.store";
|
||||
import { DockTabStore } from "./dock-tab.store";
|
||||
import { dockStore, DockTabCreateSpecific, TabKind } from "./dock.store";
|
||||
|
||||
export class CreateResourceStore extends DockTabsStore<string> {
|
||||
export class CreateResourceStore extends DockTabStore<string> {
|
||||
constructor() {
|
||||
super({
|
||||
storageKey: "create_resource"
|
||||
@ -43,8 +43,8 @@ export class CreateResourceStore extends DockTabsStore<string> {
|
||||
return path.resolve(os.homedir(), "~/.k8slens/templates");
|
||||
}
|
||||
|
||||
async getBundledTemplate(fileName: string, ext = "yaml") {
|
||||
return import(`../../../../templates/create-resource/${fileName}.${ext}`);
|
||||
async getTemplate(fileName: string, ext = "yaml") {
|
||||
return import(`../../../../templates/create-resource/${fileName}.${ext}?raw`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -51,7 +51,7 @@ export class CreateResource extends React.Component<Props> {
|
||||
}
|
||||
|
||||
// TODO
|
||||
@computed get selectTemplateOptions(): SelectOption<string>[] {
|
||||
@computed get templateOptions(): SelectOption<string>[] {
|
||||
return [];
|
||||
}
|
||||
|
||||
@ -127,7 +127,7 @@ export class CreateResource extends React.Component<Props> {
|
||||
autoConvertOptions={false}
|
||||
className="SelectResourceTemplate"
|
||||
placeholder="Select Template ..."
|
||||
options={this.selectTemplateOptions}
|
||||
options={this.templateOptions}
|
||||
menuPlacement="top"
|
||||
themeName="outlined"
|
||||
onChange={v => this.onSelectTemplate(v)}
|
||||
|
||||
@ -28,18 +28,20 @@ export interface DockTabStoreOptions {
|
||||
storageKey?: string; // save data to persistent storage under the key
|
||||
}
|
||||
|
||||
export class DockTabsStore<T extends {}> {
|
||||
export class DockTabStore<T extends {}> {
|
||||
@observable private _data: Record<TabId, T> = {};
|
||||
@observable.ref private storage?: StorageHelper<Record<TabId, T>>; // available only with `options.storageKey`
|
||||
@observable dataReady = false; // dock-tab's data ready to interact, e.g. start editing resource
|
||||
|
||||
protected watchers = observable.map<TabId, IReactionDisposer | Disposer>();
|
||||
protected dispose = disposer();
|
||||
|
||||
@computed get data() {
|
||||
if (this.options.storageKey) {
|
||||
return this.storage.get();
|
||||
} else {
|
||||
return this._data;
|
||||
}
|
||||
|
||||
return this._data;
|
||||
}
|
||||
|
||||
set data(value: Record<TabId, T>) {
|
||||
@ -60,7 +62,7 @@ export class DockTabsStore<T extends {}> {
|
||||
};
|
||||
|
||||
if (this.options.storageKey) {
|
||||
this.storage = createStorage(this.options.storageKey, {}); // starts preloading json file via Node.fs right away
|
||||
this.storage = createStorage(this.options.storageKey, this._data);
|
||||
}
|
||||
|
||||
if (this.options.autoInit) {
|
||||
@ -69,13 +71,15 @@ export class DockTabsStore<T extends {}> {
|
||||
}
|
||||
|
||||
get whenReady(): Promise<any> {
|
||||
return Promise.allSettled([
|
||||
return Promise.all([
|
||||
dockStore.whenReady,
|
||||
this.storage?.whenReady,
|
||||
]);
|
||||
}
|
||||
|
||||
protected init() {
|
||||
this.dataReady = true;
|
||||
|
||||
this.dispose.push(
|
||||
autorun(() => {
|
||||
const docTabIds = dockStore.tabs.map(tab => tab.id);
|
||||
@ -110,16 +114,12 @@ export class DockTabsStore<T extends {}> {
|
||||
return reaction(() => this.data[tabId], callback, opts);
|
||||
}
|
||||
|
||||
isReady(tabId: TabId): boolean {
|
||||
return Boolean(this.getData(tabId) !== undefined);
|
||||
}
|
||||
|
||||
getData(tabId: TabId) {
|
||||
return this.data[tabId];
|
||||
getData(tabId: TabId): T {
|
||||
return this.data[tabId] ?? {} as T;
|
||||
}
|
||||
|
||||
setData(tabId: TabId, data: T) {
|
||||
this.data[tabId] = data;
|
||||
this.data[tabId] = { ...data };
|
||||
}
|
||||
|
||||
clearData(tabId: TabId) {
|
||||
@ -131,6 +131,7 @@ export class DockTabsStore<T extends {}> {
|
||||
}
|
||||
|
||||
destroy() {
|
||||
this.dataReady = false;
|
||||
this.dispose();
|
||||
this.disposeWatchers();
|
||||
this.reset();
|
||||
@ -96,7 +96,7 @@ export interface DockTabChangeEvent {
|
||||
|
||||
export interface DockTabChangeEventOptions extends IReactionOptions {
|
||||
kind?: TabKind; // filter: matching by dockStore.selectedTab.kind
|
||||
isVisible?: boolean; // filter: dock and selected tab should be visible
|
||||
dockIsVisible?: boolean; // filter: dock and selected tab should be visible (default: true)
|
||||
}
|
||||
|
||||
export class DockStore implements DockStorageState {
|
||||
@ -190,11 +190,11 @@ export class DockStore implements DockStorageState {
|
||||
}
|
||||
|
||||
onTabChange(callback?: (evt: DockTabChangeEvent) => void, options: DockTabChangeEventOptions = {}) {
|
||||
const { kind, isVisible, ...reactionOpts } = options;
|
||||
const { kind, dockIsVisible = true, ...reactionOpts } = options;
|
||||
|
||||
return reaction(() => this.selectedTab, ((tab, prevTab) => {
|
||||
if (kind && kind !== tab.kind) return;
|
||||
if (isVisible && !dockStore.isOpen) return;
|
||||
if (dockIsVisible && !dockStore.isOpen) return;
|
||||
|
||||
callback({
|
||||
tab, prevTab,
|
||||
|
||||
@ -19,8 +19,9 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { autoBind, noop } from "../../utils";
|
||||
import { DockTabsStore } from "./dock-tabs.store";
|
||||
import { makeObservable } from "mobx";
|
||||
import { autoBind } from "../../utils";
|
||||
import { DockTabStore } from "./dock-tab.store";
|
||||
import { dockStore, DockTab, DockTabCreateSpecific, TabId, TabKind } from "./dock.store";
|
||||
import type { KubeObject } from "../../../common/k8s-api/kube-object";
|
||||
import { apiManager } from "../../../common/k8s-api/api-manager";
|
||||
@ -31,39 +32,23 @@ export interface EditingResource {
|
||||
draft?: string; // edited draft in yaml
|
||||
}
|
||||
|
||||
export class EditResourceStore extends DockTabsStore<EditingResource> {
|
||||
export class EditResourceStore extends DockTabStore<EditingResource> {
|
||||
constructor() {
|
||||
super({
|
||||
storageKey: "edit_resource_store",
|
||||
});
|
||||
autoBind(this);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
protected async init() {
|
||||
super.init();
|
||||
async loadResource(tabId: TabId) {
|
||||
const resource = this.getResource(tabId);
|
||||
const store = this.getStore(tabId);
|
||||
const data = this.getData(tabId);
|
||||
|
||||
this.dispose.push(
|
||||
dockStore.onTabChange(({ selectedTabId }) => {
|
||||
const { resource } = this.getData(selectedTabId);
|
||||
const store = apiManager.getStore(resource);
|
||||
|
||||
if (!store?.getByPath(resource)) {
|
||||
store?.loadFromPath(resource).catch(noop); // preload resource by uri
|
||||
}
|
||||
}, {
|
||||
fireImmediately: true,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
protected finalizeDataForSave({ draft, ...data }: EditingResource): EditingResource {
|
||||
return data; // skip saving draft to local-storage
|
||||
}
|
||||
|
||||
isReady(tabId: TabId) {
|
||||
const tabDataReady = super.isReady(tabId);
|
||||
|
||||
return Boolean(tabDataReady && this.getResource(tabId)); // ready to edit resource
|
||||
if (!resource && store && data) {
|
||||
await store.loadFromPath(data.resource); // preloading resource for the first time
|
||||
}
|
||||
}
|
||||
|
||||
getStore(tabId: TabId): KubeObjectStore<KubeObject> | undefined {
|
||||
@ -74,8 +59,8 @@ export class EditResourceStore extends DockTabsStore<EditingResource> {
|
||||
return this.getStore(tabId)?.getByPath(this.getResourcePath(tabId));
|
||||
}
|
||||
|
||||
getResourcePath(tabId: TabId): string | undefined {
|
||||
return this.getData(tabId)?.resource;
|
||||
getResourcePath(tabId: TabId): string {
|
||||
return this.getData(tabId)?.resource ?? "";
|
||||
}
|
||||
|
||||
getTabByResource(object: KubeObject): DockTab {
|
||||
|
||||
@ -22,8 +22,8 @@
|
||||
import "./edit-resource.scss";
|
||||
|
||||
import React from "react";
|
||||
import { action, computed, makeObservable, observable } from "mobx";
|
||||
import { observer } from "mobx-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";
|
||||
@ -46,32 +46,32 @@ export class EditResource extends React.Component<Props> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
|
||||
disposeOnUnmount(this, [
|
||||
autorun(() => editResourceStore.loadResource(this.tabId)),
|
||||
]);
|
||||
}
|
||||
|
||||
get tabId() {
|
||||
return this.props.tab.id;
|
||||
}
|
||||
|
||||
get isReadyForEditing() {
|
||||
return editResourceStore.isReady(this.tabId);
|
||||
}
|
||||
|
||||
get resource(): KubeObject | undefined {
|
||||
return editResourceStore.getResource(this.tabId);
|
||||
}
|
||||
|
||||
@computed get draft(): string {
|
||||
if (!this.isReadyForEditing) {
|
||||
return ""; // wait until tab's data and kube-object resource are loaded
|
||||
}
|
||||
|
||||
get draft(): string {
|
||||
const { draft } = editResourceStore.getData(this.tabId);
|
||||
|
||||
if (typeof draft === "string") {
|
||||
return draft;
|
||||
return draft; // get previously edited draft
|
||||
}
|
||||
|
||||
return jsYaml.safeDump(this.resource.toPlainObject()); // dump resource first time
|
||||
if (this.resource) {
|
||||
return jsYaml.safeDump(this.resource.toPlainObject()); // dump resource first time
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
@action
|
||||
@ -113,12 +113,12 @@ export class EditResource extends React.Component<Props> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { tabId, error, draft, isReadyForEditing, resource } = this;
|
||||
|
||||
if (!isReadyForEditing) {
|
||||
if (!editResourceStore.dataReady || !this.resource) {
|
||||
return <Spinner center/>;
|
||||
}
|
||||
|
||||
const { tabId, error, draft, resource } = this;
|
||||
|
||||
return (
|
||||
<div className={cssNames("EditResource flex column", this.props.className)}>
|
||||
<InfoPanel
|
||||
|
||||
@ -21,10 +21,9 @@
|
||||
|
||||
import { action, makeObservable, observable } from "mobx";
|
||||
import { dockStore, DockTabCreateSpecific, TabId, TabKind } from "./dock.store";
|
||||
import { DockTabsStore } from "./dock-tabs.store";
|
||||
import { DockTabStore } from "./dock-tab.store";
|
||||
import { getChartDetails, getChartValues, HelmChart } from "../../../common/k8s-api/endpoints/helm-charts.api";
|
||||
import type { IReleaseUpdateDetails } from "../../../common/k8s-api/endpoints/helm-releases.api";
|
||||
import { Notifications } from "../notifications";
|
||||
|
||||
export interface IChartInstallData {
|
||||
name: string;
|
||||
@ -37,7 +36,7 @@ export interface IChartInstallData {
|
||||
lastVersion?: boolean;
|
||||
}
|
||||
|
||||
export class InstallChartStore extends DockTabsStore<IChartInstallData> {
|
||||
export class InstallChartStore extends DockTabStore<IChartInstallData> {
|
||||
details = observable.map<TabId, IReleaseUpdateDetails>();
|
||||
versions = observable.map<TabId, string[]>();
|
||||
|
||||
@ -48,22 +47,8 @@ export class InstallChartStore extends DockTabsStore<IChartInstallData> {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
protected init() {
|
||||
super.init();
|
||||
|
||||
this.dispose.push(
|
||||
dockStore.onTabChange(({ selectedTabId }) => {
|
||||
this.loadData(selectedTabId).catch(err => Notifications.error(String(err)));
|
||||
}, {
|
||||
kind: TabKind.INSTALL_CHART,
|
||||
fireImmediately: true,
|
||||
isVisible: true,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
@action
|
||||
async loadData(tabId: string) {
|
||||
async loadData(tabId: TabId) {
|
||||
const promises = [];
|
||||
|
||||
if (!this.getData(tabId).values) {
|
||||
|
||||
@ -22,8 +22,8 @@
|
||||
import "./install-chart.scss";
|
||||
|
||||
import React, { Component } from "react";
|
||||
import { makeObservable, observable } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import { autorun, computed, makeObservable, observable } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { dockStore, DockTab } from "./dock.store";
|
||||
import { InfoPanel } from "./info-panel";
|
||||
import { Badge } from "../badge";
|
||||
@ -53,20 +53,20 @@ export class InstallChart extends Component<Props> {
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
get values() {
|
||||
return this.chartData.values;
|
||||
}
|
||||
|
||||
get chartData() {
|
||||
return installChartStore.getData(this.tabId);
|
||||
disposeOnUnmount(this, [
|
||||
autorun(() => installChartStore.loadData(this.tabId)),
|
||||
]);
|
||||
}
|
||||
|
||||
get tabId() {
|
||||
return this.props.tab.id;
|
||||
}
|
||||
|
||||
get chartData(): IChartInstallData | undefined {
|
||||
return installChartStore.getData(this.tabId);
|
||||
}
|
||||
|
||||
get versions() {
|
||||
return installChartStore.versions.get(this.tabId);
|
||||
}
|
||||
@ -75,6 +75,10 @@ export class InstallChart extends Component<Props> {
|
||||
return installChartStore.details.get(this.tabId);
|
||||
}
|
||||
|
||||
@computed get isReady() {
|
||||
return [installChartStore.dataReady, this.versions].every(Boolean);
|
||||
}
|
||||
|
||||
viewRelease = () => {
|
||||
const { release } = this.releaseDetails;
|
||||
|
||||
@ -127,42 +131,45 @@ export class InstallChart extends Component<Props> {
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const { tabId, chartData, values, versions, install } = this;
|
||||
renderReleaseDetails(): React.ReactNode {
|
||||
return (
|
||||
<div className="InstallChartDone flex column gaps align-center justify-center">
|
||||
<p>
|
||||
<Icon material="check" big sticker/>
|
||||
</p>
|
||||
<p>Installation complete!</p>
|
||||
<div className="flex gaps align-center">
|
||||
<Button
|
||||
autoFocus primary
|
||||
label="View Helm Release"
|
||||
onClick={prevDefault(this.viewRelease)}
|
||||
/>
|
||||
<Button
|
||||
plain active
|
||||
label="Show Notes"
|
||||
onClick={() => this.showNotes = true}
|
||||
/>
|
||||
</div>
|
||||
<LogsDialog
|
||||
title="Helm Chart Install"
|
||||
isOpen={this.showNotes}
|
||||
close={() => this.showNotes = false}
|
||||
logs={this.releaseDetails.log}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (chartData?.values === undefined || !versions) {
|
||||
render() {
|
||||
if (!this.isReady) {
|
||||
return <Spinner center/>;
|
||||
}
|
||||
|
||||
if (this.releaseDetails) {
|
||||
return (
|
||||
<div className="InstallChartDone flex column gaps align-center justify-center">
|
||||
<p>
|
||||
<Icon material="check" big sticker/>
|
||||
</p>
|
||||
<p>Installation complete!</p>
|
||||
<div className="flex gaps align-center">
|
||||
<Button
|
||||
autoFocus primary
|
||||
label="View Helm Release"
|
||||
onClick={prevDefault(this.viewRelease)}
|
||||
/>
|
||||
<Button
|
||||
plain active
|
||||
label="Show Notes"
|
||||
onClick={() => this.showNotes = true}
|
||||
/>
|
||||
</div>
|
||||
<LogsDialog
|
||||
title="Helm Chart Install"
|
||||
isOpen={this.showNotes}
|
||||
close={() => this.showNotes = false}
|
||||
logs={this.releaseDetails.log}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
return this.renderReleaseDetails();
|
||||
}
|
||||
|
||||
const { tabId, chartData, install, versions } = this;
|
||||
const { repo, name, version, namespace, releaseName } = chartData;
|
||||
const panelControls = (
|
||||
<div className="install-controls flex gaps align-center">
|
||||
@ -208,7 +215,7 @@ export class InstallChart extends Component<Props> {
|
||||
/>
|
||||
<MonacoEditor
|
||||
id={tabId}
|
||||
value={values}
|
||||
value={chartData.values}
|
||||
onChange={this.onValuesChange}
|
||||
onError={error => this.error = error}
|
||||
/>
|
||||
|
||||
@ -25,7 +25,7 @@ import { podsStore } from "../+workloads-pods/pods.store";
|
||||
|
||||
import { IPodContainer, Pod } from "../../../common/k8s-api/endpoints";
|
||||
import type { WorkloadKubeObject } from "../../../common/k8s-api/workload-kube-object";
|
||||
import { DockTabsStore } from "./dock-tabs.store";
|
||||
import { DockTabStore } from "./dock-tab.store";
|
||||
import { dockStore, DockTabCreateSpecific, TabKind } from "./dock.store";
|
||||
|
||||
export interface LogTabData {
|
||||
@ -45,7 +45,7 @@ interface WorkloadLogsTabData {
|
||||
workload: WorkloadKubeObject
|
||||
}
|
||||
|
||||
export class LogTabStore extends DockTabsStore<LogTabData> {
|
||||
export class LogTabStore extends DockTabStore<LogTabData> {
|
||||
constructor() {
|
||||
super({
|
||||
storageKey: "pod_logs"
|
||||
|
||||
@ -19,19 +19,22 @@
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
import { action, makeObservable, observable, when } from "mobx";
|
||||
import { action, makeObservable, observable } from "mobx";
|
||||
import { dockStore, DockTab, DockTabCreateSpecific, TabId, TabKind } from "./dock.store";
|
||||
import { DockTabsStore } from "./dock-tabs.store";
|
||||
import { DockTabStore } from "./dock-tab.store";
|
||||
import { getReleaseValues, HelmRelease } from "../../../common/k8s-api/endpoints/helm-releases.api";
|
||||
import { releaseStore } from "../+apps-releases/release.store";
|
||||
import type { IChartVersion } from "../+apps-helm-charts/helm-chart.store";
|
||||
import { helmChartStore } from "../+apps-helm-charts/helm-chart.store";
|
||||
|
||||
export interface IChartUpgradeData {
|
||||
releaseName: string;
|
||||
releaseNamespace: string;
|
||||
}
|
||||
|
||||
export class UpgradeChartStore extends DockTabsStore<IChartUpgradeData> {
|
||||
export class UpgradeChartStore extends DockTabStore<IChartUpgradeData> {
|
||||
public values = observable.map<TabId, string>();
|
||||
public versions = observable.array<IChartVersion>();
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
@ -41,64 +44,65 @@ export class UpgradeChartStore extends DockTabsStore<IChartUpgradeData> {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
get whenReady() {
|
||||
return Promise.all([
|
||||
super.whenReady,
|
||||
when(() => releaseStore.isLoaded),
|
||||
]);
|
||||
}
|
||||
|
||||
protected init() {
|
||||
super.init();
|
||||
|
||||
this.dispose.push(
|
||||
dockStore.onTabChange(({ selectedTabId }) => {
|
||||
if (!this.isLoaded(selectedTabId)) {
|
||||
this.loadData(selectedTabId); // preload just once
|
||||
}
|
||||
}, {
|
||||
kind: TabKind.UPGRADE_CHART,
|
||||
isVisible: true,
|
||||
fireImmediately: true,
|
||||
}),
|
||||
);
|
||||
releaseStore.loadFromContextNamespaces();
|
||||
}
|
||||
|
||||
isLoading(tabId = dockStore.selectedTabId) {
|
||||
const values = this.values.get(tabId);
|
||||
|
||||
return !releaseStore.isLoaded || values === undefined;
|
||||
}
|
||||
|
||||
isLoaded(tabId: TabId) {
|
||||
hasValues(tabId: TabId) {
|
||||
return this.values.has(tabId);
|
||||
}
|
||||
|
||||
@action
|
||||
private async loadData(tabId: TabId) {
|
||||
const values = this.values.get(tabId);
|
||||
|
||||
async loadData(tabId: TabId) {
|
||||
await Promise.all([
|
||||
!releaseStore.isLoaded && releaseStore.loadFromContextNamespaces(),
|
||||
!values && this.reloadValues(tabId)
|
||||
this.loadValues(tabId),
|
||||
this.loadVersions(tabId),
|
||||
]);
|
||||
}
|
||||
|
||||
@action
|
||||
private async reloadValues(tabId: TabId) {
|
||||
this.values.delete(tabId);
|
||||
const { releaseName, releaseNamespace } = this.getData(tabId);
|
||||
const values = await getReleaseValues(releaseName, releaseNamespace, true);
|
||||
getRelease(tabId: TabId) {
|
||||
const releaseName = this.getData(tabId)?.releaseName;
|
||||
|
||||
this.values.set(tabId, values);
|
||||
if (!releaseName) return null;
|
||||
|
||||
return releaseStore.getByName(releaseName);
|
||||
}
|
||||
|
||||
getTabByRelease(releaseName: string): DockTab {
|
||||
const entry = Object
|
||||
.entries(this.data)
|
||||
.find(([, data]) => data.releaseName === releaseName);
|
||||
@action
|
||||
async loadVersions(tabId: TabId) {
|
||||
try {
|
||||
const { releaseName } = this.getData(tabId);
|
||||
|
||||
return dockStore.getTabById(entry?.[0]);
|
||||
this.versions.clear();
|
||||
const versions = await helmChartStore.getVersions(releaseName);
|
||||
|
||||
this.versions.replace(versions);
|
||||
} catch (error) {
|
||||
console.error(`[UPGRADE-CHART]: loading versions has failed: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
@action
|
||||
async loadValues(tabId: TabId, { forceReload = false } = {}) {
|
||||
if (this.hasValues(tabId) && !forceReload) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.values.delete(tabId);
|
||||
const { releaseName, releaseNamespace } = this.getData(tabId);
|
||||
const values = await getReleaseValues(releaseName, releaseNamespace, true);
|
||||
|
||||
this.values.set(tabId, values);
|
||||
} catch (error) {
|
||||
console.error(`[UPGRADE-CHART]: loading values has failed: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
getTabByRelease(releaseName: string): DockTab | null {
|
||||
const entry = Object.entries(this.data).find(([, data]) => data.releaseName === releaseName);
|
||||
|
||||
return entry ? dockStore.getTabById(entry[0]) : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
import "./upgrade-chart.scss";
|
||||
|
||||
import React from "react";
|
||||
import { makeObservable, observable, reaction } from "mobx";
|
||||
import { autorun, computed, makeObservable, observable } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { cssNames } from "../../utils";
|
||||
import type { DockTab } from "./dock.store";
|
||||
@ -32,9 +32,9 @@ import { Spinner } from "../spinner";
|
||||
import { releaseStore } from "../+apps-releases/release.store";
|
||||
import { Badge } from "../badge";
|
||||
import { MonacoEditor } from "../monaco-editor";
|
||||
import { helmChartStore, IChartVersion } from "../+apps-helm-charts/helm-chart.store";
|
||||
import type { HelmRelease } from "../../../common/k8s-api/endpoints/helm-releases.api";
|
||||
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";
|
||||
|
||||
interface Props {
|
||||
className?: string;
|
||||
@ -44,19 +44,14 @@ interface Props {
|
||||
@observer
|
||||
export class UpgradeChart extends React.Component<Props> {
|
||||
@observable error: string;
|
||||
@observable versions = observable.array<IChartVersion>();
|
||||
@observable version: IChartVersion;
|
||||
@observable selectedVersion: IChartVersion;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.loadVersions();
|
||||
|
||||
disposeOnUnmount(this, [
|
||||
reaction(() => this.release, () => this.loadVersions())
|
||||
autorun(() => upgradeChartStore.loadData(this.tabId)),
|
||||
]);
|
||||
}
|
||||
|
||||
@ -64,28 +59,26 @@ export class UpgradeChart extends React.Component<Props> {
|
||||
return this.props.tab.id;
|
||||
}
|
||||
|
||||
get release(): HelmRelease {
|
||||
const tabData = upgradeChartStore.getData(this.tabId);
|
||||
get release(): HelmRelease | null {
|
||||
return upgradeChartStore.getRelease(this.tabId);
|
||||
}
|
||||
|
||||
if (!tabData) return null;
|
||||
get isReady(){
|
||||
return [
|
||||
upgradeChartStore.dataReady,
|
||||
this.release,
|
||||
this.selectedVersion,
|
||||
].every(Boolean);
|
||||
}
|
||||
|
||||
return releaseStore.getByName(tabData.releaseName);
|
||||
@computed get versionOptions(): SelectOption<IChartVersion>[] {
|
||||
return upgradeChartStore.versions.map(version => ({ value: version }));
|
||||
}
|
||||
|
||||
get value() {
|
||||
return upgradeChartStore.values.get(this.tabId);
|
||||
}
|
||||
|
||||
async loadVersions() {
|
||||
if (!this.release) return;
|
||||
this.version = null;
|
||||
this.versions.clear();
|
||||
const versions = await helmChartStore.getVersions(this.release.getChart());
|
||||
|
||||
this.versions.replace(versions);
|
||||
this.version = this.versions[0];
|
||||
}
|
||||
|
||||
onChange = (value: string) => {
|
||||
upgradeChartStore.values.set(this.tabId, value);
|
||||
};
|
||||
@ -96,7 +89,7 @@ export class UpgradeChart extends React.Component<Props> {
|
||||
|
||||
upgrade = async () => {
|
||||
if (this.error) return null;
|
||||
const { version, repo } = this.version;
|
||||
const { version, repo } = this.selectedVersion;
|
||||
const releaseName = this.release.getName();
|
||||
const releaseNs = this.release.getNs();
|
||||
|
||||
@ -121,13 +114,14 @@ export class UpgradeChart extends React.Component<Props> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { tabId, release, value, error, versions, version } = this;
|
||||
const { className } = this.props;
|
||||
|
||||
if (!release || upgradeChartStore.isLoading() || !version) {
|
||||
if (!this.isReady) {
|
||||
return <Spinner center/>;
|
||||
}
|
||||
|
||||
const { className } = this.props;
|
||||
const { tabId, release, value, error, versionOptions, selectedVersion } = this;
|
||||
const currentVersion = release.getVersion();
|
||||
|
||||
const controlsAndInfo = (
|
||||
<div className="upgrade flex gaps align-center">
|
||||
<span>Release</span> <Badge label={release.getName()}/>
|
||||
@ -138,10 +132,10 @@ export class UpgradeChart extends React.Component<Props> {
|
||||
className="chart-version"
|
||||
menuPlacement="top"
|
||||
themeName="outlined"
|
||||
value={version}
|
||||
options={versions}
|
||||
value={selectedVersion}
|
||||
options={versionOptions}
|
||||
formatOptionLabel={this.formatVersionLabel}
|
||||
onChange={({ value }: SelectOption) => this.version = value}
|
||||
onChange={({ value }: SelectOption) => this.selectedVersion = value}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
|
||||
import "./monaco-editor.scss";
|
||||
import React from "react";
|
||||
import { action, computed, makeObservable, observable, reaction, when } from "mobx";
|
||||
import { action, computed, makeObservable, observable, reaction } from "mobx";
|
||||
import { observer } from "mobx-react";
|
||||
import { editor, Uri } from "monaco-editor";
|
||||
import { ThemeStore } from "../../theme.store";
|
||||
@ -65,7 +65,6 @@ export const defaultEditorProps: Partial<MonacoEditorProps> = {
|
||||
}
|
||||
};
|
||||
|
||||
// FIXME: load resource templates via webpack's dynamic import for create-resource dock tab
|
||||
// FIXME: apply changes of props.options and globalOptions.editor to active editor
|
||||
|
||||
@observer
|
||||
@ -86,14 +85,6 @@ export class MonacoEditor extends React.Component<MonacoEditorProps> {
|
||||
makeObservable(this);
|
||||
}
|
||||
|
||||
get whenEditorReady() {
|
||||
return when(() => Boolean(this.containerElem && this.editor));
|
||||
}
|
||||
|
||||
get whenUnmounting() {
|
||||
return when(() => this.unmounting);
|
||||
}
|
||||
|
||||
/**
|
||||
* Monitor editor's dom container element box-size and sync with monaco's dimensions
|
||||
* @private
|
||||
@ -141,7 +132,7 @@ export class MonacoEditor extends React.Component<MonacoEditorProps> {
|
||||
}
|
||||
console.info(`[MONACO]: editor did mounted`);
|
||||
} catch (error) {
|
||||
console.error(`[MONACO]: mounting failed`, { error, editor: this });
|
||||
console.error(`[MONACO]: mounting failed`, { error, editor, component: this });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -88,6 +88,13 @@ export function webpackLensRenderer({ showVars = true } = {}): webpack.Configura
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
// Allow to load raw file contents with dynamic imports, e.g. import("../some-path.txt?raw")
|
||||
// See also: https://webpack.js.org/guides/asset-modules/
|
||||
use: "raw-loader",
|
||||
resourceQuery: /raw/,
|
||||
enforce: "post",
|
||||
},
|
||||
{
|
||||
test: /\.node$/,
|
||||
use: "node-loader"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user