github.com/argoproj/argo-cd/v2@v2.10.9/ui/src/app/shared/components/yaml-editor/yaml-editor.tsx (about) 1 import {ErrorNotification, NotificationType} from 'argo-ui'; 2 import * as jsYaml from 'js-yaml'; 3 import * as monacoEditor from 'monaco-editor'; 4 import * as React from 'react'; 5 6 import {Consumer} from '../../context'; 7 import {MonacoEditor} from '../monaco-editor'; 8 9 const jsonMergePatch = require('json-merge-patch'); 10 require('./yaml-editor.scss'); 11 12 export class YamlEditor<T> extends React.Component< 13 { 14 input: T; 15 hideModeButtons?: boolean; 16 initialEditMode?: boolean; 17 vScrollbar?: boolean; 18 onSave?: (patch: string, patchType: string) => Promise<any>; 19 onCancel?: () => any; 20 minHeight?: number; 21 }, 22 { 23 editing: boolean; 24 } 25 > { 26 private model: monacoEditor.editor.ITextModel; 27 28 constructor(props: any) { 29 super(props); 30 this.state = {editing: props.initialEditMode}; 31 } 32 33 public render() { 34 const props = this.props; 35 const yaml = props.input ? jsYaml.safeDump(props.input) : ''; 36 37 return ( 38 <div className='yaml-editor'> 39 {!props.hideModeButtons && ( 40 <div className='yaml-editor__buttons'> 41 {(this.state.editing && ( 42 <Consumer> 43 {ctx => ( 44 <React.Fragment> 45 <button 46 onClick={async () => { 47 try { 48 const updated = jsYaml.load(this.model.getLinesContent().join('\n')); 49 const patch = jsonMergePatch.generate(props.input, updated); 50 try { 51 const unmounted = await this.props.onSave(JSON.stringify(patch || {}), 'application/merge-patch+json'); 52 if (unmounted !== true) { 53 this.setState({editing: false}); 54 } 55 } catch (e) { 56 ctx.notifications.show({ 57 content: ( 58 <div className='yaml-editor__error'> 59 <ErrorNotification title='Unable to save changes' e={e} /> 60 </div> 61 ), 62 type: NotificationType.Error 63 }); 64 } 65 } catch (e) { 66 ctx.notifications.show({ 67 content: <ErrorNotification title='Unable to validate changes' e={e} />, 68 type: NotificationType.Error 69 }); 70 } 71 }} 72 className='argo-button argo-button--base'> 73 Save 74 </button>{' '} 75 <button 76 onClick={() => { 77 this.model.setValue(jsYaml.safeDump(props.input)); 78 this.setState({editing: !this.state.editing}); 79 if (props.onCancel) { 80 props.onCancel(); 81 } 82 }} 83 className='argo-button argo-button--base-o'> 84 Cancel 85 </button> 86 </React.Fragment> 87 )} 88 </Consumer> 89 )) || ( 90 <button onClick={() => this.setState({editing: true})} className='argo-button argo-button--base'> 91 Edit 92 </button> 93 )} 94 </div> 95 )} 96 <MonacoEditor 97 minHeight={props.minHeight} 98 vScrollBar={props.vScrollbar} 99 editor={{ 100 input: {text: yaml, language: 'yaml'}, 101 options: {readOnly: !this.state.editing, minimap: {enabled: false}}, 102 getApi: api => { 103 this.model = api.getModel() as monacoEditor.editor.ITextModel; 104 } 105 }} 106 /> 107 </div> 108 ); 109 } 110 }