github.com/argoproj/argo-cd/v3@v3.2.1/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 enableWordWrap?: boolean; 19 onSave?: (patch: string, patchType: string) => Promise<any>; 20 onCancel?: () => any; 21 minHeight?: number; 22 }, 23 { 24 editing: boolean; 25 } 26 > { 27 private model: monacoEditor.editor.ITextModel; 28 29 constructor(props: any) { 30 super(props); 31 this.state = {editing: props.initialEditMode}; 32 } 33 34 public render() { 35 const props = this.props; 36 const yaml = props.input ? jsYaml.dump(props.input) : ''; 37 38 return ( 39 <div className='yaml-editor'> 40 {!props.hideModeButtons && ( 41 <div className='yaml-editor__buttons'> 42 {(this.state.editing && ( 43 <Consumer> 44 {ctx => ( 45 <React.Fragment> 46 <button 47 onClick={async () => { 48 try { 49 const updated = jsYaml.load(this.model.getLinesContent().join('\n')); 50 const patch = jsonMergePatch.generate(props.input, updated); 51 try { 52 const unmounted = await this.props.onSave(JSON.stringify(patch || {}), 'application/merge-patch+json'); 53 if (unmounted !== true) { 54 this.setState({editing: false}); 55 } 56 } catch (e) { 57 ctx.notifications.show({ 58 content: ( 59 <div className='yaml-editor__error'> 60 <ErrorNotification title='Unable to save changes' e={e} /> 61 </div> 62 ), 63 type: NotificationType.Error 64 }); 65 } 66 } catch (e) { 67 ctx.notifications.show({ 68 content: <ErrorNotification title='Unable to validate changes' e={e} />, 69 type: NotificationType.Error 70 }); 71 } 72 }} 73 className='argo-button argo-button--base'> 74 Save 75 </button>{' '} 76 <button 77 onClick={() => { 78 this.model.setValue(jsYaml.dump(props.input)); 79 this.setState({editing: !this.state.editing}); 80 if (props.onCancel) { 81 props.onCancel(); 82 } 83 }} 84 className='argo-button argo-button--base-o'> 85 Cancel 86 </button> 87 </React.Fragment> 88 )} 89 </Consumer> 90 )) || ( 91 <button onClick={() => this.setState({editing: true})} className='argo-button argo-button--base'> 92 Edit 93 </button> 94 )} 95 </div> 96 )} 97 <MonacoEditor 98 minHeight={props.minHeight} 99 vScrollBar={props.vScrollbar} 100 editor={{ 101 input: {text: yaml, language: 'yaml'}, 102 options: { 103 readOnly: !this.state.editing, 104 minimap: {enabled: false}, 105 wordWrap: props.enableWordWrap ? 'on' : 'off' 106 }, 107 getApi: api => { 108 this.model = api.getModel() as monacoEditor.editor.ITextModel; 109 } 110 }} 111 /> 112 </div> 113 ); 114 } 115 }