1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

dock: don't use kube-object-store while editing resources

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman 2021-10-20 18:37:22 +03:00
parent c22609ee0c
commit 05552fefab
3 changed files with 47 additions and 69 deletions

View File

@ -246,18 +246,16 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
}
@action
async load(params: { name: string; namespace?: string, save?: boolean }): Promise<T> {
const { name, namespace, save = true } = params;
async load(params: { name: string; namespace?: string }): Promise<T> {
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<T extends KubeObject> extends ItemStore<T>
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<T>): Promise<T> {

View File

@ -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<EditingResource> {
constructor() {
super({ storageKey: "edit_resource_store" });
makeObservable(this);
autoBind(this);
}
async init() {
super.init();
async getResource(tabId: TabId): Promise<KubeObject> {
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<KubeObject> | 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 {

View File

@ -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<Props> {
@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<Props> {
{resource.kind} version <b>{resource.getName()}</b> is updated on the server while editing.
</p>
<p>
Please backup your changes and <a onClick={() => this.saveDraft(resource)}>refresh resource</a> to the editor.
Please backup your changes and{" "}
<a onClick={() => this.saveDraft(resource.toPlainObject())}>refresh resource</a> to the editor.
</p>
</div>
);
}
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 (
<p>
{updatedResource.kind} <b>{updatedResource.getName()}</b> updated.
{updatedResource.kind} <b>{updatedResource.metadata.name}</b> updated.
</p>
);
};