diff --git a/src/common/k8s-api/kube-object.store.ts b/src/common/k8s-api/kube-object.store.ts index 42bf4e4285..6fd1209d4e 100644 --- a/src/common/k8s-api/kube-object.store.ts +++ b/src/common/k8s-api/kube-object.store.ts @@ -246,18 +246,16 @@ export abstract class KubeObjectStore extends ItemStore } @action - async load(params: { name: string; namespace?: string, save?: boolean }): Promise { - const { name, namespace, save = true } = params; + async load(params: { name: string; namespace?: string }): Promise { + const { name, namespace } = params; let item = this.getByName(name, namespace); if (!item) { item = await this.loadItem(params); - if (save) { - const newItems = this.sortItems([...this.items, item]); + const newItems = this.sortItems([...this.items, item]); - this.items.replace(newItems); - } + this.items.replace(newItems); } return item; @@ -267,10 +265,7 @@ export abstract class KubeObjectStore extends ItemStore async loadFromPath(resourcePath: string) { const { namespace, name } = parseKubeApi(resourcePath); - return this.load({ - name, namespace, - save: false, // don't save loaded resource to store - }); + return this.load({ name, namespace }); } protected async createItem(params: { name: string; namespace?: string }, data?: Partial): Promise { diff --git a/src/renderer/components/dock/edit-resource.store.ts b/src/renderer/components/dock/edit-resource.store.ts index d5120cabc0..8300a5d420 100644 --- a/src/renderer/components/dock/edit-resource.store.ts +++ b/src/renderer/components/dock/edit-resource.store.ts @@ -20,16 +20,14 @@ */ 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"; -import type { KubeObjectStore } from "../../../common/k8s-api/kube-object.store"; -import yaml from "js-yaml"; +import { parseKubeApi } from "../../../common/k8s-api/kube-api-parse"; +import type { KubeObject } from "../../../common/k8s-api/kube-object"; export interface EditingResource { - resource: string; // resource path, e.g. /api/v1/namespaces/default + resource: string; // resource path, e.g. "/api/v1/namespaces/default" draft?: string; // edited draft in yaml } @@ -37,43 +35,13 @@ export class EditResourceStore extends DockTabStore { constructor() { super({ storageKey: "edit_resource_store" }); makeObservable(this); - autoBind(this); } - async init() { - super.init(); + async getResource(tabId: TabId): Promise { + const resourcePath = this.getResourcePath(tabId); + const { name, namespace } = parseKubeApi(resourcePath); - this.dispose.push( - dockStore.onTabChange(({ tabId }) => this.editResource(tabId), { - tabKind: TabKind.EDIT_RESOURCE, - fireImmediately: true, - }) - ); - } - - async editResource(tabId: TabId) { - await this.whenReady; - const store = this.getStore(tabId); - const data = this.getData(tabId); - - if (data.resource && !data.draft) { - try { - let resource = this.getResource(tabId); - - resource ??= await store.loadFromPath(data.resource); - data.draft ||= yaml.dump(resource.toPlainObject()); // dump resource if empty - } catch (error) { - console.error(`[DOCK]: dumping '${data.resource}' has failed: ${error}`, { store, data }); - } - } - } - - getStore(tabId: TabId): KubeObjectStore | undefined { - return apiManager.getStore(this.getResourcePath(tabId)); - } - - getResource(tabId: TabId): KubeObject | undefined { - return this.getStore(tabId)?.getByPath(this.getResourcePath(tabId)); + return apiManager.getApi(resourcePath)?.get({ name, namespace }); } getResourcePath(tabId: TabId): string { diff --git a/src/renderer/components/dock/edit-resource.tsx b/src/renderer/components/dock/edit-resource.tsx index 667a9a4667..d3ee4bdb21 100644 --- a/src/renderer/components/dock/edit-resource.tsx +++ b/src/renderer/components/dock/edit-resource.tsx @@ -20,8 +20,9 @@ */ import React from "react"; -import { observer } from "mobx-react"; import yaml from "js-yaml"; +import { makeObservable, observable, reaction } from "mobx"; +import { disposeOnUnmount, observer } from "mobx-react"; import { editResourceStore } from "./edit-resource.store"; import { InfoPanel, InfoPanelProps } from "./info-panel"; import { Badge } from "../badge"; @@ -35,31 +36,44 @@ interface Props extends InfoPanelProps { @observer export class EditResourceInfoPanel extends React.Component { + @observable.ref resource?: KubeObject; + + constructor(props: Props) { + super(props); + makeObservable(this); + + disposeOnUnmount(this, [ + reaction(() => this.tabId, async (tabId) => { + this.resource = null; + this.resource = await editResourceStore.getResource(tabId); + + const { draft } = editResourceStore.getData(tabId); + + if (!draft) { + this.saveDraft(this.resource.toPlainObject(), tabId); + } + }, { + fireImmediately: true, + }), + ]); + } + get tabId() { return this.props.tabId; } - get resource(): KubeObject | undefined { - return editResourceStore.getResource(this.tabId); - } - - get draft(): string { - return editResourceStore.getData(this.tabId)?.draft; - } - - private saveDraft(draft: string | KubeObject) { + private saveDraft(draft: string | object, tabId = this.tabId) { if (typeof draft === "object") { - draft = draft ? yaml.dump(draft.toPlainObject()) : undefined; + draft = yaml.dump(draft); } - editResourceStore.getData(this.tabId).draft = draft; + editResourceStore.getData(tabId).draft = draft; } save = async () => { - const store = editResourceStore.getStore(this.tabId); - const { resource: resourcePath, draft } = editResourceStore.getData(this.tabId); - const resource = store.getByPath(resourcePath) ?? await store.loadFromPath(resourcePath); - const currentVersion = resource.toPlainObject(); + const resource = await editResourceStore.getResource(this.tabId); // get latest resource version + const { draft } = editResourceStore.getData(this.tabId); + const currentVersion = resource.toPlainObject() as KubeObject; const editedVersion = yaml.load(draft) as KubeObject; const patches = createPatch(currentVersion, editedVersion); const editingVersion = editedVersion.metadata.resourceVersion; @@ -71,19 +85,20 @@ export class EditResourceInfoPanel extends React.Component { {resource.kind} version {resource.getName()} is updated on the server while editing.

- Please backup your changes and this.saveDraft(resource)}>refresh resource to the editor. + Please backup your changes and{" "} + this.saveDraft(resource.toPlainObject())}>refresh resource to the editor.

); } - const updatedResource = await store.patch(this.resource, patches); + const updatedResource = await this.resource.patch(patches); - this.saveDraft(updatedResource); // dump latest resource version for editing + this.saveDraft(updatedResource); // dump latest version for editing return (

- {updatedResource.kind} {updatedResource.getName()} updated. + {updatedResource.kind} {updatedResource.metadata.name} updated.

); };