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

     1  import * as React from 'react';
     2  import * as ReactForm from 'react-form';
     3  
     4  /*
     5      This provide a way to may a form field to an array of items. It allows you to
     6  
     7      * Add a new (maybe duplicate) item.
     8      * Replace an item.
     9      * Remove an item.
    10  
    11      E.g.
    12      env:
    13      - name: FOO
    14        value: bar
    15      - name: BAZ
    16        value: qux
    17      # You can have dup items
    18      - name: FOO
    19        value: bar
    20  
    21      It does not allow re-ordering of elements (maybe in a v2).
    22   */
    23  
    24  export interface NameValue {
    25      name: string;
    26      value: string;
    27  }
    28  
    29  export const NameValueEditor = (item: NameValue, onChange: (item: NameValue) => any) => (
    30      <React.Fragment>
    31          <input
    32              // disable chrome autocomplete
    33              autoComplete='fake'
    34              className='argo-field'
    35              style={{width: '40%'}}
    36              placeholder='Name'
    37              value={item.name || ''}
    38              onChange={e => onChange({...item, name: e.target.value})}
    39              title='Name'
    40          />
    41          &nbsp; = &nbsp;
    42          <input
    43              // disable chrome autocomplete
    44              autoComplete='fake'
    45              className='argo-field'
    46              style={{width: '40%'}}
    47              placeholder='Value'
    48              value={item.value || ''}
    49              onChange={e => onChange({...item, value: e.target.value})}
    50              title='Value'
    51          />
    52          &nbsp;
    53      </React.Fragment>
    54  );
    55  
    56  interface Props<T> {
    57      items: T[];
    58      onChange: (items: T[]) => void;
    59      editor: (item: T, onChange: (updated: T) => any) => React.ReactNode;
    60  }
    61  
    62  export function ArrayInput<T>(props: Props<T>) {
    63      const addItem = (item: T) => {
    64          props.onChange([...props.items, item]);
    65      };
    66  
    67      const replaceItem = (item: T, i: number) => {
    68          const items = props.items.slice();
    69          items[i] = item;
    70          props.onChange(items);
    71      };
    72  
    73      const removeItem = (i: number) => {
    74          const items = props.items.slice();
    75          items.splice(i, 1);
    76          props.onChange(items);
    77      };
    78  
    79      return (
    80          <div className='argo-field' style={{border: 0, marginTop: '15px', zIndex: 1}}>
    81              {props.items.map((item, i) => (
    82                  <div key={`item-${i}`} style={{marginBottom: '5px'}}>
    83                      {props.editor(item, (updated: T) => replaceItem(updated, i))}
    84                      &nbsp;
    85                      <button>
    86                          <i className='fa fa-times' style={{cursor: 'pointer'}} onClick={() => removeItem(i)} />
    87                      </button>{' '}
    88                  </div>
    89              ))}
    90              {props.items.length === 0 && <label>No items</label>}
    91              <div>
    92                  <button className='argo-button argo-button--base argo-button--short' onClick={() => addItem({} as T)}>
    93                      <i style={{cursor: 'pointer'}} className='fa fa-plus' />
    94                  </button>
    95              </div>
    96          </div>
    97      );
    98  }
    99  
   100  export const ArrayInputField = ReactForm.FormField((props: {fieldApi: ReactForm.FieldApi}) => {
   101      const {
   102          fieldApi: {getValue, setValue}
   103      } = props;
   104      return <ArrayInput editor={NameValueEditor} items={getValue() || []} onChange={setValue} />;
   105  });
   106  
   107  export const MapInputField = ReactForm.FormField((props: {fieldApi: ReactForm.FieldApi}) => {
   108      const {
   109          fieldApi: {getValue, setValue}
   110      } = props;
   111      const items = new Array<NameValue>();
   112      const map = getValue() || {};
   113      Object.keys(map).forEach(key => items.push({name: key, value: map[key]}));
   114      return (
   115          <ArrayInput
   116              editor={NameValueEditor}
   117              items={items}
   118              onChange={array => {
   119                  const newMap = {} as any;
   120                  array.forEach(item => (newMap[item.name || ''] = item.value || ''));
   121                  setValue(newMap);
   122              }}
   123          />
   124      );
   125  });