/** * 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 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"; import type { KubeObject } from "../../../common/k8s-api/kube-object"; import { TabKind } from "./dock.store"; import { dockViewsManager } from "./dock.views-manager"; import { createPatch } from "rfc6902"; 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; } private saveDraft(draft: string | object, tabId = this.tabId) { if (typeof draft === "object") { draft = yaml.dump(draft); } editResourceStore.getData(tabId).draft = draft; } save = async () => { 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; if (editingVersion != resource.getResourceVersion()) { throw (

{resource.kind} version {resource.getName()} is updated on the server while editing.

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

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

{updatedResource.kind} {updatedResource.metadata.name} updated.

); }; render() { const { resource } = this; if (!resource) return null; return ( Kind: Name: Namespace: )} /> ); } } dockViewsManager.register(TabKind.EDIT_RESOURCE, { InfoPanel: EditResourceInfoPanel, editor: { getValue(tabId) { return editResourceStore.getData(tabId)?.draft ?? ""; }, setValue(tabId, value) { editResourceStore.getData(tabId).draft = value; }, } });