/** * Copyright (c) OpenLens Authors. All rights reserved. * Licensed under MIT License. See LICENSE in root directory for more information. */ import "./info-panel.scss"; import type { ReactNode } from "react"; import React, { Component } from "react"; import { computed, observable, reaction, makeObservable } from "mobx"; import { disposeOnUnmount, observer } from "mobx-react"; import { cssNames } from "../../utils"; import { Button } from "../button"; import { Icon } from "../icon"; import { Spinner } from "../spinner"; import type { DockStore, TabId } from "./dock/store"; import type { ShowNotification } from "../notifications"; import { withInjectables } from "@ogre-tools/injectable-react"; import dockStoreInjectable from "./dock/store.injectable"; import type { ShowCheckedErrorNotification } from "../notifications/show-checked-error.injectable"; import showSuccessNotificationInjectable from "../notifications/show-success-notification.injectable"; import showCheckedErrorNotificationInjectable from "../notifications/show-checked-error.injectable"; export interface InfoPanelProps extends OptionalProps { tabId: TabId; submit?: () => Promise; } export interface OptionalProps { className?: string; error?: string; controls?: ReactNode; submitLabel?: ReactNode; submittingMessage?: ReactNode; disableSubmit?: boolean; showButtons?: boolean; showSubmitClose?: boolean; showInlineInfo?: boolean; showNotifications?: boolean; showStatusPanel?: boolean; submitTestId?: string; submitAndCloseTestId?: string; cancelTestId?: string; submittingTestId?: string; } interface Dependencies { dockStore: DockStore; showSuccessNotification: ShowNotification; showCheckedErrorNotification: ShowCheckedErrorNotification; } @observer class NonInjectedInfoPanel extends Component { static defaultProps: OptionalProps = { submitLabel: "Submit", submittingMessage: "Submitting..", showButtons: true, showSubmitClose: true, showInlineInfo: true, showNotifications: true, showStatusPanel: true, }; @observable error = ""; @observable waiting = false; constructor(props: InfoPanelProps & Dependencies) { super(props); makeObservable(this); } componentDidMount() { disposeOnUnmount(this, [ reaction(() => this.props.tabId, () => { this.waiting = false; }), ]); } @computed get errorInfo() { return this.props.error; } submit = async () => { const { showNotifications } = this.props; this.waiting = true; try { const result = await this.props.submit?.(); if (showNotifications && result) { this.props.showSuccessNotification(result); } } catch (error) { if (showNotifications) { this.props.showCheckedErrorNotification(error, "Unknown error while submitting"); } } finally { this.waiting = false; } }; submitAndClose = async () => { await this.submit(); this.close(); }; close = () => { this.props.dockStore.closeTab(this.props.tabId); }; renderErrorIcon() { if (!this.props.showInlineInfo || !this.errorInfo) { return null; } return (
); } render() { const { className, controls, submitLabel, disableSubmit, error, submittingMessage, showButtons, showSubmitClose, showStatusPanel } = this.props; const { submit, close, submitAndClose, waiting } = this; const isDisabled = !!(disableSubmit || waiting || error); return (
{controls}
{showStatusPanel && (
{waiting ? ( <> {" "} {submittingMessage} ) : this.renderErrorIcon()}
)} {showButtons && ( <>
); } } export const InfoPanel = withInjectables( NonInjectedInfoPanel, { getProps: (di, props) => ({ dockStore: di.inject(dockStoreInjectable), showSuccessNotification: di.inject(showSuccessNotificationInjectable), showCheckedErrorNotification: di.inject(showCheckedErrorNotificationInjectable), ...props, }), }, );