mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
master-merge fixes, fine-tuning
Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
parent
d6b7001f72
commit
59357d0a69
@ -30,6 +30,7 @@ import * as resourceApplierApi from "../../../common/k8s-api/endpoints/resource-
|
||||
import { Notifications } from "../notifications";
|
||||
import { TabKind } from "./dock.store";
|
||||
import { dockViewsManager } from "./dock.views-manager";
|
||||
import logger from "../../../common/logger";
|
||||
|
||||
interface Props extends InfoPanelProps {
|
||||
}
|
||||
@ -58,13 +59,13 @@ export class CreateResourceInfoPanel extends React.Component<Props> {
|
||||
}
|
||||
|
||||
create = async (): Promise<undefined> => {
|
||||
if (this.error || !this.data.trim()) {
|
||||
if (!this.draft) {
|
||||
// do not save when field is empty or there is an error
|
||||
return null;
|
||||
}
|
||||
|
||||
// skip empty documents
|
||||
const resources = yaml.loadAll(this.data).filter(Boolean);
|
||||
const resources = yaml.loadAll(this.draft).filter(Boolean);
|
||||
const createdResources: string[] = [];
|
||||
|
||||
if (resources.length === 0) {
|
||||
|
||||
@ -26,7 +26,7 @@ import { dockStore, DockTab, DockTabCreateSpecific, TabId, TabKind } from "./doc
|
||||
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 jsYaml from "js-yaml";
|
||||
import yaml from "js-yaml";
|
||||
|
||||
export interface EditingResource {
|
||||
resource: string; // resource path, e.g. /api/v1/namespaces/default
|
||||
@ -61,7 +61,7 @@ export class EditResourceStore extends DockTabStore<EditingResource> {
|
||||
let resource = this.getResource(tabId);
|
||||
|
||||
resource ??= await store.loadFromPath(data.resource);
|
||||
data.draft ||= jsYaml.safeDump(resource.toPlainObject()); // dump resource if empty
|
||||
data.draft ||= yaml.dump(resource.toPlainObject()); // dump resource if empty
|
||||
} catch (error) {
|
||||
console.error(`[DOCK]: dumping '${data.resource}' has failed: ${error}`, { store, data });
|
||||
}
|
||||
|
||||
@ -21,13 +21,14 @@
|
||||
|
||||
import React from "react";
|
||||
import { observer } from "mobx-react";
|
||||
import jsYaml from "js-yaml";
|
||||
import yaml from "js-yaml";
|
||||
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 {
|
||||
}
|
||||
@ -42,50 +43,43 @@ export class EditResourceInfoPanel extends React.Component<Props> {
|
||||
return editResourceStore.getResource(this.tabId);
|
||||
}
|
||||
|
||||
@computed get draft(): string {
|
||||
if (!this.isReadyForEditing) {
|
||||
return ""; // wait until tab's data and kube-object resource are loaded
|
||||
}
|
||||
|
||||
const { draft } = editResourceStore.getData(this.tabId);
|
||||
|
||||
if (typeof draft === "string") {
|
||||
return draft;
|
||||
}
|
||||
|
||||
return yaml.dump(this.resource.toPlainObject()); // dump resource first time
|
||||
get draft(): string {
|
||||
return editResourceStore.getData(this.tabId)?.draft;
|
||||
}
|
||||
|
||||
@action
|
||||
saveDraft(draft: string | object) {
|
||||
private saveDraft(draft: string | KubeObject) {
|
||||
if (typeof draft === "object") {
|
||||
draft = draft ? yaml.dump(draft) : undefined;
|
||||
draft = draft ? yaml.dump(draft.toPlainObject()) : undefined;
|
||||
}
|
||||
|
||||
editResourceStore.setData(this.tabId, {
|
||||
firstDraft: draft, // this must be before the next line
|
||||
...editResourceStore.getData(this.tabId),
|
||||
draft,
|
||||
});
|
||||
editResourceStore.getData(this.tabId).draft = draft;
|
||||
}
|
||||
|
||||
onChange = (draft: string, error?: string) => {
|
||||
this.error = error;
|
||||
this.saveDraft(draft);
|
||||
};
|
||||
|
||||
save = async () => {
|
||||
if (this.error) {
|
||||
return null;
|
||||
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 editedVersion = yaml.load(draft) as KubeObject;
|
||||
const patches = createPatch(currentVersion, editedVersion);
|
||||
const editingVersion = editedVersion.metadata.resourceVersion;
|
||||
|
||||
if (editingVersion != resource.getResourceVersion()) {
|
||||
throw (
|
||||
<div className="resource-outdated flex column gaps">
|
||||
<p>
|
||||
{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.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const store = editResourceStore.getStore(this.tabId);
|
||||
const currentVersion = yaml.load(this.draft);
|
||||
const firstVersion = yaml.load(editResourceStore.getData(this.tabId).firstDraft ?? this.draft);
|
||||
const patches = createPatch(firstVersion, currentVersion);
|
||||
const updatedResource = await store.patch(this.resource, patches);
|
||||
|
||||
editResourceStore.clearInitialDraft(this.tabId);
|
||||
this.saveDraft(updatedResource); // dump latest resource version for editing
|
||||
|
||||
return (
|
||||
<p>
|
||||
|
||||
@ -23,7 +23,7 @@ import "./info-panel.scss";
|
||||
import React, { Component, ReactNode } from "react";
|
||||
import { makeObservable, observable, reaction } from "mobx";
|
||||
import { disposeOnUnmount, observer } from "mobx-react";
|
||||
import { cssNames } from "../../utils";
|
||||
import { cssNames, isReactNode } from "../../utils";
|
||||
import { Button } from "../button";
|
||||
import { Icon } from "../icon";
|
||||
import { Spinner } from "../spinner";
|
||||
@ -85,7 +85,9 @@ export class InfoPanel extends Component<InfoPanelProps> {
|
||||
|
||||
if (showNotifications) Notifications.ok(result);
|
||||
} catch (error) {
|
||||
if (showNotifications) Notifications.error(error.toString());
|
||||
const errorMessage = isReactNode(error) ? error : String(error);
|
||||
|
||||
if (showNotifications) Notifications.error(errorMessage);
|
||||
} finally {
|
||||
this.waiting = false;
|
||||
}
|
||||
@ -126,12 +128,12 @@ export class InfoPanel extends Component<InfoPanelProps> {
|
||||
</div>
|
||||
{showStatusPanel && (
|
||||
<div className="flex gaps align-center">
|
||||
{waiting ? <><Spinner /> {submittingMessage}</> : this.renderErrorIcon()}
|
||||
{waiting ? <><Spinner/> {submittingMessage}</> : this.renderErrorIcon()}
|
||||
</div>
|
||||
)}
|
||||
{showButtons && (
|
||||
<>
|
||||
<Button plain label="Cancel" onClick={close} />
|
||||
<Button plain label="Cancel" onClick={close}/>
|
||||
<Button
|
||||
active
|
||||
outlined={showSubmitClose}
|
||||
|
||||
@ -35,7 +35,7 @@ registerCustomThemes(); // setup
|
||||
|
||||
export interface MonacoEditorProps {
|
||||
id?: string; // associating editor's ID with created model.uri
|
||||
value?: string; // initial text value for editor
|
||||
value?: string;
|
||||
className?: string;
|
||||
autoFocus?: boolean;
|
||||
readOnly?: boolean;
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
// Helper for working with storages (e.g. window.localStorage, NodeJS/file-system, etc.)
|
||||
import { action, comparer, IReactionDisposer, IReactionOptions, makeObservable, observable, reaction, toJS, when, } from "mobx";
|
||||
import produce, { Draft, isDraft } from "immer";
|
||||
import { isEqual } from "lodash";
|
||||
import { isEqual, isPlainObject } from "lodash";
|
||||
import logger from "../../main/logger";
|
||||
import { disposer } from "../../common/utils";
|
||||
|
||||
@ -166,7 +166,7 @@ export class StorageHelper<T> {
|
||||
if (newValue && !isDraft(newValue)) {
|
||||
Object.assign(draft, newValue);
|
||||
}
|
||||
} else {
|
||||
} else if (isPlainObject(value)) {
|
||||
Object.assign(draft, value);
|
||||
}
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user