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

fix WizardStep and AddNamespaceDialog

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-04-25 11:26:03 -04:00
parent c89d63ad3e
commit 8499f26707
11 changed files with 102 additions and 106 deletions

View File

@ -601,20 +601,19 @@ export class KubeApi<
return parsed;
}
async create({ name, namespace }: Partial<ResourceDescriptor>, data?: PartialDeep<Object>): Promise<Object | null> {
async create({ name, namespace }: Partial<ResourceDescriptor>, partialData?: PartialDeep<Object>): Promise<Object | null> {
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)) {

View File

@ -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<boolean>;
}
@observer
@ -39,41 +40,51 @@ class NonInjectedAddNamespaceDialog extends React.Component<AddNamespaceDialogPr
constructor(props: AddNamespaceDialogProps & Dependencies) {
super(props);
makeObservable(this);
autoBind(this);
}
reset = () => {
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 = <h5>Create Namespace</h5>;
const isOpen = state.get();
return (
<Dialog
{...dialogProps}
className="AddNamespaceDialog"
isOpen={this.props.model.isOpen}
onOpen={this.reset}
close={this.props.model.close}
isOpen={isOpen}
onClose={this.reset}
close={this.close}
>
<Wizard header={header} done={this.props.model.close}>
<Wizard
header={<h5>Create Namespace</h5>}
done={this.close}
>
<WizardStep
contentClass="flex gaps column"
nextLabel="Create"
@ -96,15 +107,10 @@ class NonInjectedAddNamespaceDialog extends React.Component<AddNamespaceDialogPr
}
}
export const AddNamespaceDialog = withInjectables<Dependencies, AddNamespaceDialogProps>(
NonInjectedAddNamespaceDialog,
{
getProps: (di, props) => ({
namespaceStore: di.inject(namespaceStoreInjectable),
model: di.inject(addNamespaceDialogModelInjectable),
...props,
}),
},
);
export const AddNamespaceDialog = withInjectables<Dependencies, AddNamespaceDialogProps>(NonInjectedAddNamespaceDialog, {
getProps: (di, props) => ({
...props,
namespaceStore: di.inject(namespaceStoreInjectable),
state: di.inject(addNamespaceDialogStateInjectable),
}),
});

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;
};
}

View File

@ -4,4 +4,4 @@
*/
export * from "./namespace-details";
export * from "./add-namespace-dialog";
export * from "./add-dialog/dialog";

View File

@ -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<Dependencies>(NonInjectedNamespacesRoute, {
getProps: (di) => ({
namespaceStore: di.inject(namespaceStoreInjectable),
openAddNamespaceDialog: di.inject(addNamespaceDialogModelInjectable).open,
openAddNamespaceDialog: di.inject(openAddNamepaceDialogInjectable),
}),
});

View File

@ -28,7 +28,7 @@ export class Notifications extends React.Component {
}
static checkedError(message: unknown, fallback: string, customOpts?: Partial<Omit<Notification, "message">>) {
if (typeof message === "string" || message instanceof Error) {
if (typeof message === "string" || message instanceof Error || message instanceof JsonApiErrorParsed) {
return Notifications.error(message, customOpts);
}

View File

@ -210,47 +210,43 @@ export class WizardStep<D> extends React.Component<WizardStepProps<D>, 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 (
<form
className={className}
className={cssNames(`WizardStep step${step}`, className)}
onSubmit={prevDefault(this.submit)}
noValidate={noValidate}
onKeyDown={(evt) => this.keyDown(evt)}
ref={e => this.form = e}
>
{beforeContent}
<div className={contentClass}>
<div className={cssNames("step-content", { scrollable }, contentClass)}>
{loading ? this.renderLoading() : children}
</div>
{customButtons !== undefined ? customButtons : (
{customButtons ?? (
<div className="buttons flex gaps align-center">
{moreButtons}
<Button
className="back-btn"
plain
label={prevLabel}
label={prevLabel || (isFirst?.() ? "Cancel" : "Back")}
hidden={hideBackBtn}
onClick={this.prev}
/>
<Button
primary
type="submit"
label={nextLabel}
label={nextLabel || (isLast?.() ? "Submit" : "Next")}
hidden={hideNextBtn}
waiting={waiting}
waiting={waiting ?? this.state.waiting}
disabled={disabledNext}
onClick={this.next}
/>
</div>
)}