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  }