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  }