import classNames from 'classnames'; import React from 'react'; import { Modal } from 'react-bootstrap'; import type { IPipelineTemplateV2 } from '../../../../domain'; import { ModalClose } from '../../../../modal'; import type { IModalComponentProps } from '../../../../presentation'; import { JsonEditor } from '../../../../presentation'; import { CopyToClipboard, JsonUtils, noop } from '../../../../utils'; import { Spinner } from '../../../../widgets/spinners/Spinner'; import './ShowPipelineTemplateJsonModal.less'; export interface IShowPipelineTemplateJsonModalProps extends IModalComponentProps { template: IPipelineTemplateV2; editable?: boolean; modalHeading?: string; descriptionText?: string; saveTemplate?: (template: IPipelineTemplateV2) => PromiseLike; } export interface IShowPipelineTemplateJsonModalState { template: IPipelineTemplateV2; saveError: Error; saving: boolean; } export class ShowPipelineTemplateJsonModal extends React.Component< IShowPipelineTemplateJsonModalProps, IShowPipelineTemplateJsonModalState > { public static defaultProps: Partial = { dismissModal: noop, editable: true, modalHeading: 'Export as Pipeline Template', descriptionText: 'The JSON below is the templated version of your pipeline. Save it by copy/pasting to the Spin CLI tool.', }; constructor(props: IShowPipelineTemplateJsonModalProps) { super(props); this.state = { template: props.template, saveError: null, saving: false }; } private onChange = (e: React.ChangeEvent, property: string) => { if (!this.props.editable) { return; } this.setState({ template: { ...this.state.template, metadata: { ...this.state.template.metadata, [property]: e.target.value, }, }, }); }; private onTemplateSaved = (error?: Error) => { this.setState({ saveError: error, saving: false }); }; private saveTemplate = () => { this.setState({ saveError: null, saving: true }); this.props.saveTemplate(this.state.template).then( (shouldClose: boolean) => { if (shouldClose) { this.props.dismissModal(); } else { this.onTemplateSaved(); } }, (err: Error) => this.onTemplateSaved(err), ); }; public render() { const { dismissModal, editable, modalHeading, descriptionText, saveTemplate } = this.props; const { template, saveError, saving } = this.state; const sortedTemplate = JsonUtils.sortObject(template); const templateStr = JsonUtils.makeStringFromObject(sortedTemplate, 0); const templateStrWithSpacing = JsonUtils.makeStringFromObject(sortedTemplate); const disabled = !editable || !!saving; if (saving) { return ( <> {modalHeading}
); } return ( <> {modalHeading}

{descriptionText}

this.onChange(e, 'name')} disabled={disabled} />
this.onChange(e, 'description')} placeholder="Template Description" disabled={disabled} />
this.onChange(e, 'owner')} disabled={disabled} />
{!disabled && (
Copy the spin command for saving this template} text={`echo '${templateStr}' | spin pipeline-templates save`} />
)}
{saveError && {String(saveError)}} ); } } interface IShowPipelineTemplateJsonModalButtons { onSave: (e: React.SyntheticEvent) => void; onClose: (e: React.SyntheticEvent) => void; } const ShowPipelineTemplateJsonModalButtons = (props: IShowPipelineTemplateJsonModalButtons) => { const { onClose, onSave } = props; const closeClasses = classNames({ btn: true, 'btn-primary': !onSave }); const saveClasses = classNames({ btn: true, 'btn-primary': true }); return ( <> {onSave && ( )} ); };