github.com/argoproj/argo-cd@v1.8.7/ui/src/app/settings/components/cluster-details/cluster-details.tsx (about)

     1  import * as classNames from 'classnames';
     2  import * as moment from 'moment';
     3  import * as React from 'react';
     4  import {FieldApi, FormField as ReactFormField, Text} from 'react-form';
     5  import {RouteComponentProps} from 'react-router-dom';
     6  import {Observable} from 'rxjs';
     7  
     8  import {FormField, Ticker} from 'argo-ui';
     9  import {ConnectionStateIcon, DataLoader, EditablePanel, Page, Timestamp} from '../../../shared/components';
    10  import {Cluster} from '../../../shared/models';
    11  import {services} from '../../../shared/services';
    12  
    13  function isRefreshRequested(cluster: Cluster): boolean {
    14      return cluster.info.connectionState.attemptedAt && cluster.refreshRequestedAt && moment(cluster.info.connectionState.attemptedAt).isBefore(moment(cluster.refreshRequestedAt));
    15  }
    16  
    17  export const NamespacesEditor = ReactFormField((props: {fieldApi: FieldApi; className: string}) => {
    18      const val = (props.fieldApi.getValue() || []).join(',');
    19      return <input className={props.className} value={val} onChange={event => props.fieldApi.setValue(event.target.value.split(','))} />;
    20  });
    21  
    22  export const ClusterDetails = (props: RouteComponentProps<{server: string}>) => {
    23      const server = decodeURIComponent(props.match.params.server);
    24      const loaderRef = React.useRef<DataLoader>();
    25      const [updating, setUpdating] = React.useState(false);
    26      return (
    27          <DataLoader ref={loaderRef} input={server} load={(url: string) => Observable.timer(0, 1000).flatMap(() => Observable.fromPromise(services.clusters.get(url, '')))}>
    28              {(cluster: Cluster) => (
    29                  <Page
    30                      title={server}
    31                      toolbar={{
    32                          breadcrumbs: [{title: 'Settings', path: '/settings'}, {title: 'Cluster', path: '/settings/clusters'}, {title: server}],
    33                          actionMenu: {
    34                              items: [
    35                                  {
    36                                      iconClassName: classNames('fa fa-redo', {'status-icon--spin': isRefreshRequested(cluster)}),
    37                                      title: 'Invalidate Cache',
    38                                      disabled: isRefreshRequested(cluster) || updating,
    39                                      action: async () => {
    40                                          setUpdating(true);
    41                                          try {
    42                                              const updated = await services.clusters.invalidateCache(props.match.params.server);
    43                                              loaderRef.current.setData(updated);
    44                                          } finally {
    45                                              setUpdating(false);
    46                                          }
    47                                      }
    48                                  }
    49                              ]
    50                          }
    51                      }}>
    52                      <p />
    53  
    54                      <div className='argo-container'>
    55                          <EditablePanel
    56                              values={cluster}
    57                              save={async updated => {
    58                                  const item = await services.clusters.get(updated.server, '');
    59                                  item.name = updated.name;
    60                                  item.namespaces = updated.namespaces;
    61                                  loaderRef.current.setData(await services.clusters.update(item, 'name', 'namespaces'));
    62                              }}
    63                              title='GENERAL'
    64                              items={[
    65                                  {
    66                                      title: 'SERVER',
    67                                      view: cluster.server
    68                                  },
    69                                  {
    70                                      title: 'CREDENTIALS TYPE',
    71                                      view:
    72                                          (cluster.config.awsAuthConfig && `IAM AUTH (cluster name: ${cluster.config.awsAuthConfig.clusterName})`) ||
    73                                          (cluster.config.execProviderConfig && `External provider (command: ${cluster.config.execProviderConfig.command})`) ||
    74                                          'Token/Basic Auth'
    75                                  },
    76                                  {
    77                                      title: 'NAME',
    78                                      view: cluster.name,
    79                                      edit: formApi => <FormField formApi={formApi} field='name' component={Text} />
    80                                  },
    81                                  {
    82                                      title: 'NAMESPACES',
    83                                      view: ((cluster.namespaces || []).length === 0 && 'All namespaces') || cluster.namespaces.join(', '),
    84                                      edit: formApi => <FormField formApi={formApi} field='namespaces' component={NamespacesEditor} />
    85                                  }
    86                              ]}
    87                          />
    88                          <div className='white-box'>
    89                              <p>CONNECTION STATE</p>
    90                              <div className='white-box__details'>
    91                                  <div className='row white-box__details-row'>
    92                                      <div className='columns small-3'>STATUS:</div>
    93                                      <div className='columns small-9'>
    94                                          <ConnectionStateIcon state={cluster.info.connectionState} /> {cluster.info.connectionState.status}
    95                                      </div>
    96                                  </div>
    97                                  <div className='row white-box__details-row'>
    98                                      <div className='columns small-3'>VERSION:</div>
    99                                      <div className='columns small-9'> {cluster.info.serverVersion}</div>
   100                                  </div>
   101                                  <div className='row white-box__details-row'>
   102                                      <div className='columns small-3'>DETAILS:</div>
   103                                      <div className='columns small-9'> {cluster.info.connectionState.message} </div>
   104                                  </div>
   105                                  <div className='row white-box__details-row'>
   106                                      <div className='columns small-3'>MODIFIED AT:</div>
   107                                      <div className='columns small-9'>
   108                                          <Ticker>
   109                                              {now => {
   110                                                  if (!cluster.info.connectionState.attemptedAt) {
   111                                                      return <span>Never (next refresh in few seconds)</span>;
   112                                                  }
   113                                                  const secondsBeforeRefresh = Math.round(Math.max(10 - now.diff(moment(cluster.info.connectionState.attemptedAt)) / 1000, 1));
   114                                                  return (
   115                                                      <React.Fragment>
   116                                                          <Timestamp date={cluster.info.connectionState.attemptedAt} /> (next refresh in {secondsBeforeRefresh} seconds)
   117                                                      </React.Fragment>
   118                                                  );
   119                                              }}
   120                                          </Ticker>
   121                                      </div>
   122                                  </div>
   123                              </div>
   124                          </div>
   125  
   126                          <div className='white-box'>
   127                              <p>CACHE INFO</p>
   128                              <div className='white-box__details'>
   129                                  <Ticker>
   130                                      {() => (
   131                                          <div className='row white-box__details-row'>
   132                                              <div className='columns small-3'>RE-SYNCHRONIZED:</div>
   133                                              <div className='columns small-9'>
   134                                                  <Timestamp date={cluster.info.cacheInfo.lastCacheSyncTime} />
   135                                              </div>
   136                                          </div>
   137                                      )}
   138                                  </Ticker>
   139                                  <div className='row white-box__details-row'>
   140                                      <div className='columns small-3'>APIs COUNT:</div>
   141                                      <div className='columns small-9'> {cluster.info.cacheInfo.apisCount} </div>
   142                                  </div>
   143                                  <div className='row white-box__details-row'>
   144                                      <div className='columns small-3'>RESOURCES COUNT:</div>
   145                                      <div className='columns small-9'> {cluster.info.cacheInfo.resourcesCount} </div>
   146                                  </div>
   147                                  <div className='row white-box__details-row'>
   148                                      <div className='columns small-3'>APPLICATIONS COUNT:</div>
   149                                      <div className='columns small-9'> {cluster.info.applicationsCount} </div>
   150                                  </div>
   151                              </div>
   152                          </div>
   153                      </div>
   154                  </Page>
   155              )}
   156          </DataLoader>
   157      );
   158  };