github.com/argoproj/argo-cd@v1.8.7/ui/src/app/shared/components/editable-panel/editable-panel.tsx (about)

     1  import {ErrorNotification, NotificationType} from 'argo-ui';
     2  import * as classNames from 'classnames';
     3  import * as React from 'react';
     4  import {Form, FormApi} from 'react-form';
     5  
     6  import {Consumer} from '../../context';
     7  import {Spinner} from '../spinner';
     8  
     9  export interface EditablePanelItem {
    10      title: string;
    11      key?: string;
    12      before?: React.ReactNode;
    13      view: string | React.ReactNode;
    14      edit?: (formApi: FormApi) => React.ReactNode;
    15      titleEdit?: (formApi: FormApi) => React.ReactNode;
    16  }
    17  
    18  export interface EditablePanelProps<T> {
    19      title?: string | React.ReactNode;
    20      values: T;
    21      validate?: (values: T) => any;
    22      save?: (input: T) => Promise<any>;
    23      items: EditablePanelItem[];
    24      onModeSwitch?: () => any;
    25      noReadonlyMode?: boolean;
    26      view?: string | React.ReactNode;
    27      edit?: (formApi: FormApi) => React.ReactNode;
    28  }
    29  
    30  interface EditablePanelState {
    31      edit: boolean;
    32      saving: boolean;
    33  }
    34  
    35  require('./editable-panel.scss');
    36  
    37  export class EditablePanel<T = {}> extends React.Component<EditablePanelProps<T>, EditablePanelState> {
    38      private formApi: FormApi;
    39  
    40      constructor(props: EditablePanelProps<T>) {
    41          super(props);
    42          this.state = {edit: !!props.noReadonlyMode, saving: false};
    43      }
    44  
    45      public UNSAFE_componentWillReceiveProps(nextProps: EditablePanelProps<T>) {
    46          if (this.formApi && JSON.stringify(this.props.values) !== JSON.stringify(nextProps.values)) {
    47              if (!!nextProps.noReadonlyMode) {
    48                  this.formApi.setAllValues(nextProps.values);
    49              }
    50          }
    51      }
    52  
    53      public render() {
    54          return (
    55              <Consumer>
    56                  {ctx => (
    57                      <div className={classNames('white-box editable-panel', {'editable-panel--disabled': this.state.saving})}>
    58                          <div className='white-box__details'>
    59                              {!this.props.noReadonlyMode && this.props.save && (
    60                                  <div className='editable-panel__buttons'>
    61                                      {!this.state.edit && (
    62                                          <button
    63                                              onClick={() => {
    64                                                  this.setState({edit: true});
    65                                                  this.onModeSwitch();
    66                                              }}
    67                                              className='argo-button argo-button--base'>
    68                                              Edit
    69                                          </button>
    70                                      )}
    71                                      {this.state.edit && (
    72                                          <React.Fragment>
    73                                              <button
    74                                                  disabled={this.state.saving}
    75                                                  onClick={() => !this.state.saving && this.formApi.submitForm(null)}
    76                                                  className='argo-button argo-button--base'>
    77                                                  <Spinner show={this.state.saving} style={{marginRight: '5px'}} />
    78                                                  Save
    79                                              </button>{' '}
    80                                              <button
    81                                                  onClick={() => {
    82                                                      this.setState({edit: false});
    83                                                      this.onModeSwitch();
    84                                                  }}
    85                                                  className='argo-button argo-button--base-o'>
    86                                                  Cancel
    87                                              </button>
    88                                          </React.Fragment>
    89                                      )}
    90                                  </div>
    91                              )}
    92                              {this.props.title && <p>{this.props.title}</p>}
    93                              {(!this.state.edit && (
    94                                  <React.Fragment>
    95                                      {this.props.view}
    96                                      {this.props.items.map(item => (
    97                                          <React.Fragment key={item.key || item.title}>
    98                                              {item.before}
    99                                              <div className='row white-box__details-row'>
   100                                                  <div className='columns small-3'>{item.title}</div>
   101                                                  <div className='columns small-9'>{item.view}</div>
   102                                              </div>
   103                                          </React.Fragment>
   104                                      ))}
   105                                  </React.Fragment>
   106                              )) || (
   107                                  <Form
   108                                      getApi={api => (this.formApi = api)}
   109                                      formDidUpdate={async form => {
   110                                          if (this.props.noReadonlyMode && this.props.save) {
   111                                              await this.props.save(form.values as any);
   112                                          }
   113                                      }}
   114                                      onSubmit={async input => {
   115                                          try {
   116                                              this.setState({saving: true});
   117                                              await this.props.save(input as any);
   118                                              this.setState({edit: false, saving: false});
   119                                              this.onModeSwitch();
   120                                          } catch (e) {
   121                                              ctx.notifications.show({
   122                                                  content: <ErrorNotification title='Unable to save changes' e={e} />,
   123                                                  type: NotificationType.Error
   124                                              });
   125                                          } finally {
   126                                              this.setState({saving: false});
   127                                          }
   128                                      }}
   129                                      defaultValues={this.props.values}
   130                                      validateError={this.props.validate}>
   131                                      {api => (
   132                                          <React.Fragment>
   133                                              {this.props.edit && this.props.edit(api)}
   134                                              {this.props.items.map(item => (
   135                                                  <React.Fragment key={item.key || item.title}>
   136                                                      {item.before}
   137                                                      <div className='row white-box__details-row'>
   138                                                          <div className='columns small-3'>{(item.titleEdit && item.titleEdit(api)) || item.title}</div>
   139                                                          <div className='columns small-9'>{(item.edit && item.edit(api)) || item.view}</div>
   140                                                      </div>
   141                                                  </React.Fragment>
   142                                              ))}
   143                                          </React.Fragment>
   144                                      )}
   145                                  </Form>
   146                              )}
   147                          </div>
   148                      </div>
   149                  )}
   150              </Consumer>
   151          );
   152      }
   153  
   154      private onModeSwitch() {
   155          if (this.props.onModeSwitch) {
   156              this.props.onModeSwitch();
   157          }
   158      }
   159  }