diff --git a/src/common/k8s-api/kube-api.ts b/src/common/k8s-api/kube-api.ts index f45b503bf4..9de6366e90 100644 --- a/src/common/k8s-api/kube-api.ts +++ b/src/common/k8s-api/kube-api.ts @@ -601,20 +601,19 @@ export class KubeApi< return parsed; } - async create({ name, namespace }: Partial, data?: PartialDeep): Promise { + async create({ name, namespace }: Partial, partialData?: PartialDeep): Promise { await this.checkPreferredVersion(); const apiUrl = this.getUrl({ namespace }); - const res = await this.request.post(apiUrl, { - data: merge(data, { - kind: this.kind, - apiVersion: this.apiVersionWithGroup, - metadata: { - name, - namespace, - }, - }), + const data = merge(partialData, { + kind: this.kind, + apiVersion: this.apiVersionWithGroup, + metadata: { + name, + namespace, + }, }); + const res = await this.request.post(apiUrl, { data }); const parsed = this.parseResponse(res); if (Array.isArray(parsed)) { diff --git a/src/renderer/components/+namespaces/add-namespace-dialog.scss b/src/renderer/components/+namespaces/add-dialog/dialog.scss similarity index 100% rename from src/renderer/components/+namespaces/add-namespace-dialog.scss rename to src/renderer/components/+namespaces/add-dialog/dialog.scss diff --git a/src/renderer/components/+namespaces/add-namespace-dialog.tsx b/src/renderer/components/+namespaces/add-dialog/dialog.tsx similarity index 52% rename from src/renderer/components/+namespaces/add-namespace-dialog.tsx rename to src/renderer/components/+namespaces/add-dialog/dialog.tsx index 8969c08027..0f6a2d184a 100644 --- a/src/renderer/components/+namespaces/add-namespace-dialog.tsx +++ b/src/renderer/components/+namespaces/add-dialog/dialog.tsx @@ -3,24 +3,25 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ -import "./add-namespace-dialog.scss"; +import "./dialog.scss"; import React from "react"; -import { observable, makeObservable } from "mobx"; +import type { IObservableValue } from "mobx"; +import { action, observable, makeObservable } from "mobx"; import { observer } from "mobx-react"; -import type { DialogProps } from "../dialog"; -import { Dialog } from "../dialog"; -import { Wizard, WizardStep } from "../wizard"; -import type { Namespace } from "../../../common/k8s-api/endpoints"; -import { Input } from "../input"; -import { systemName } from "../input/input_validators"; -import { Notifications } from "../notifications"; +import type { DialogProps } from "../../dialog"; +import { Dialog } from "../../dialog"; +import { Wizard, WizardStep } from "../../wizard"; +import type { Namespace } from "../../../../common/k8s-api/endpoints"; +import { Input } from "../../input"; +import { systemName } from "../../input/input_validators"; +import { Notifications } from "../../notifications"; import { withInjectables } from "@ogre-tools/injectable-react"; -import namespaceStoreInjectable from "./store.injectable"; -import type { AddNamespaceDialogModel } from "./add-namespace-dialog-model/add-namespace-dialog-model"; -import addNamespaceDialogModelInjectable - from "./add-namespace-dialog-model/add-namespace-dialog-model.injectable"; -import type { NamespaceStore } from "./store"; +import namespaceStoreInjectable from "../store.injectable"; +import addNamespaceDialogStateInjectable + from "./state.injectable"; +import type { NamespaceStore } from "../store"; +import { autoBind } from "../../../utils"; export interface AddNamespaceDialogProps extends DialogProps { onSuccess?(ns: Namespace): void; @@ -29,7 +30,7 @@ export interface AddNamespaceDialogProps extends DialogProps { interface Dependencies { namespaceStore: NamespaceStore; - model: AddNamespaceDialogModel; + state: IObservableValue; } @observer @@ -39,41 +40,51 @@ class NonInjectedAddNamespaceDialog extends React.Component { - this.namespace = ""; - }; + @action + close() { + this.props.state.set(false); + } - addNamespace = async () => { + @action + reset() { + this.namespace = ""; + } + + async addNamespace() { const { namespace } = this; - const { onSuccess, onError } = this.props; + const { onSuccess, onError, namespaceStore } = this.props; try { - const created = await this.props.namespaceStore.create({ name: namespace }); + const created = await namespaceStore.create({ name: namespace }); onSuccess?.(created); - this.props.model.close(); + this.close(); } catch (err) { Notifications.checkedError(err, "Unknown error occured while creating the namespace"); onError?.(err); } - }; + } render() { - const { model, namespaceStore, ...dialogProps } = this.props; + const { state, namespaceStore, ...dialogProps } = this.props; const { namespace } = this; - const header =
Create Namespace
; + const isOpen = state.get(); return ( - + Create Namespace} + done={this.close} + > ( - NonInjectedAddNamespaceDialog, - - { - getProps: (di, props) => ({ - namespaceStore: di.inject(namespaceStoreInjectable), - model: di.inject(addNamespaceDialogModelInjectable), - - ...props, - }), - }, -); +export const AddNamespaceDialog = withInjectables(NonInjectedAddNamespaceDialog, { + getProps: (di, props) => ({ + ...props, + namespaceStore: di.inject(namespaceStoreInjectable), + state: di.inject(addNamespaceDialogStateInjectable), + }), +}); diff --git a/src/renderer/components/+namespaces/add-dialog/open.injectable.ts b/src/renderer/components/+namespaces/add-dialog/open.injectable.ts new file mode 100644 index 0000000000..7c88cd6660 --- /dev/null +++ b/src/renderer/components/+namespaces/add-dialog/open.injectable.ts @@ -0,0 +1,20 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { action } from "mobx"; +import addNamespaceDialogStateInjectable from "./state.injectable"; + +const openAddNamepaceDialogInjectable = getInjectable({ + id: "open-add-namepace-dialog", + instantiate: (di) => { + const state = di.inject(addNamespaceDialogStateInjectable); + + return action(() => { + state.set(true); + }); + }, +}); + +export default openAddNamepaceDialogInjectable; diff --git a/src/renderer/components/+namespaces/add-dialog/state.injectable.ts b/src/renderer/components/+namespaces/add-dialog/state.injectable.ts new file mode 100644 index 0000000000..043b7db3bb --- /dev/null +++ b/src/renderer/components/+namespaces/add-dialog/state.injectable.ts @@ -0,0 +1,13 @@ +/** + * Copyright (c) OpenLens Authors. All rights reserved. + * Licensed under MIT License. See LICENSE in root directory for more information. + */ +import { getInjectable } from "@ogre-tools/injectable"; +import { observable } from "mobx"; + +const addNamespaceDialogStateInjectable = getInjectable({ + id: "add-namespace-dialog-state", + instantiate: () => observable.box(false), +}); + +export default addNamespaceDialogStateInjectable; diff --git a/src/renderer/components/+namespaces/add-namespace-dialog-model/add-namespace-dialog-model.injectable.ts b/src/renderer/components/+namespaces/add-namespace-dialog-model/add-namespace-dialog-model.injectable.ts deleted file mode 100644 index 844c3912c0..0000000000 --- a/src/renderer/components/+namespaces/add-namespace-dialog-model/add-namespace-dialog-model.injectable.ts +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { getInjectable } from "@ogre-tools/injectable"; -import { AddNamespaceDialogModel } from "./add-namespace-dialog-model"; - -const addNamespaceDialogModelInjectable = getInjectable({ - id: "add-namespace-dialog-model", - instantiate: () => new AddNamespaceDialogModel(), -}); - -export default addNamespaceDialogModelInjectable; diff --git a/src/renderer/components/+namespaces/add-namespace-dialog-model/add-namespace-dialog-model.ts b/src/renderer/components/+namespaces/add-namespace-dialog-model/add-namespace-dialog-model.ts deleted file mode 100644 index 439a9b8ef9..0000000000 --- a/src/renderer/components/+namespaces/add-namespace-dialog-model/add-namespace-dialog-model.ts +++ /dev/null @@ -1,25 +0,0 @@ -/** - * Copyright (c) OpenLens Authors. All rights reserved. - * Licensed under MIT License. See LICENSE in root directory for more information. - */ -import { observable, makeObservable, action } from "mobx"; - -export class AddNamespaceDialogModel { - isOpen = false; - - constructor() { - makeObservable(this, { - isOpen: observable, - open: action, - close: action, - }); - } - - open = () => { - this.isOpen = true; - }; - - close = () => { - this.isOpen = false; - }; -} diff --git a/src/renderer/components/+namespaces/index.ts b/src/renderer/components/+namespaces/index.ts index 1ce2e35264..5542f4ebdb 100644 --- a/src/renderer/components/+namespaces/index.ts +++ b/src/renderer/components/+namespaces/index.ts @@ -4,4 +4,4 @@ */ export * from "./namespace-details"; -export * from "./add-namespace-dialog"; +export * from "./add-dialog/dialog"; diff --git a/src/renderer/components/+namespaces/route.tsx b/src/renderer/components/+namespaces/route.tsx index 4c110fee7f..4bcc59041b 100644 --- a/src/renderer/components/+namespaces/route.tsx +++ b/src/renderer/components/+namespaces/route.tsx @@ -7,7 +7,7 @@ import "./namespaces.scss"; import React from "react"; import { NamespaceStatusKind } from "../../../common/k8s-api/endpoints"; -import { AddNamespaceDialog } from "./add-namespace-dialog"; +import { AddNamespaceDialog } from "./add-dialog/dialog"; import { TabLayout } from "../layout/tab-layout-2"; import { Badge } from "../badge"; import { KubeObjectListLayout } from "../kube-object-list-layout"; @@ -15,8 +15,8 @@ import type { NamespaceStore } from "./store"; import { KubeObjectStatusIcon } from "../kube-object-status-icon"; import { withInjectables } from "@ogre-tools/injectable-react"; import namespaceStoreInjectable from "./store.injectable"; -import addNamespaceDialogModelInjectable from "./add-namespace-dialog-model/add-namespace-dialog-model.injectable"; import { KubeObjectAge } from "../kube-object/age"; +import openAddNamepaceDialogInjectable from "./add-dialog/open.injectable"; enum columnId { name = "name", @@ -84,6 +84,6 @@ export const NonInjectedNamespacesRoute = ({ namespaceStore, openAddNamespaceDia export const NamespacesRoute = withInjectables(NonInjectedNamespacesRoute, { getProps: (di) => ({ namespaceStore: di.inject(namespaceStoreInjectable), - openAddNamespaceDialog: di.inject(addNamespaceDialogModelInjectable).open, + openAddNamespaceDialog: di.inject(openAddNamepaceDialogInjectable), }), }); diff --git a/src/renderer/components/notifications/notifications.tsx b/src/renderer/components/notifications/notifications.tsx index 11dc44de89..521a61e638 100644 --- a/src/renderer/components/notifications/notifications.tsx +++ b/src/renderer/components/notifications/notifications.tsx @@ -28,7 +28,7 @@ export class Notifications extends React.Component { } static checkedError(message: unknown, fallback: string, customOpts?: Partial>) { - if (typeof message === "string" || message instanceof Error) { + if (typeof message === "string" || message instanceof Error || message instanceof JsonApiErrorParsed) { return Notifications.error(message, customOpts); } diff --git a/src/renderer/components/wizard/wizard.tsx b/src/renderer/components/wizard/wizard.tsx index 4d7b471754..68a75d539e 100755 --- a/src/renderer/components/wizard/wizard.tsx +++ b/src/renderer/components/wizard/wizard.tsx @@ -210,47 +210,43 @@ export class WizardStep extends React.Component, WizardSte step, isFirst, isLast, children, loading, customButtons, disabledNext, scrollable, hideNextBtn, hideBackBtn, beforeContent, afterContent, noValidate, skip, moreButtons, + waiting, className, contentClass, prevLabel, nextLabel, } = this.props; - let { className, contentClass, nextLabel, prevLabel, waiting } = this.props; if (skip) { return null; } - waiting = (waiting !== undefined) ? waiting : this.state.waiting; - className = cssNames(`WizardStep step${step}`, className); - contentClass = cssNames("step-content", { scrollable }, contentClass); - prevLabel = prevLabel || (isFirst?.() ? "Cancel" : "Back"); - nextLabel = nextLabel || (isLast?.() ? "Submit" : "Next"); return (
this.keyDown(evt)} ref={e => this.form = e} > {beforeContent} -
+
{loading ? this.renderLoading() : children}
- {customButtons !== undefined ? customButtons : ( + {customButtons ?? (
{moreButtons}
)}