github.com/argoproj/argo-cd@v1.8.7/ui/src/app/applications/components/application-node-info/application-node-info.tsx (about) 1 import {DataLoader, Tab, Tabs} from 'argo-ui'; 2 import * as moment from 'moment'; 3 import * as React from 'react'; 4 5 import {YamlEditor} from '../../../shared/components'; 6 import * as models from '../../../shared/models'; 7 import {services} from '../../../shared/services'; 8 import {ApplicationResourcesDiff} from '../application-resources-diff/application-resources-diff'; 9 import {ComparisonStatusIcon, getPodStateReason, HealthStatusIcon} from '../utils'; 10 11 require('./application-node-info.scss'); 12 13 export const ApplicationNodeInfo = (props: { 14 application: models.Application; 15 node: models.ResourceNode; 16 live: models.State; 17 controlled: {summary: models.ResourceStatus; state: models.ResourceDiff}; 18 }) => { 19 const attributes: {title: string; value: any}[] = [ 20 {title: 'KIND', value: props.node.kind}, 21 {title: 'NAME', value: props.node.name}, 22 {title: 'NAMESPACE', value: props.node.namespace} 23 ]; 24 if (props.node.createdAt) { 25 attributes.push({ 26 title: 'CREATED_AT', 27 value: moment 28 .utc(props.node.createdAt) 29 .local() 30 .format('MM/DD/YYYY HH:mm:ss') 31 }); 32 } 33 if ((props.node.images || []).length) { 34 attributes.push({ 35 title: 'IMAGES', 36 value: ( 37 <div className='application-node-info__labels'> 38 {(props.node.images || []).sort().map(image => ( 39 <span className='application-node-info__label' key={image}> 40 {image} 41 </span> 42 ))} 43 </div> 44 ) 45 }); 46 } 47 if (props.live) { 48 if (props.node.kind === 'Pod') { 49 const {reason, message} = getPodStateReason(props.live); 50 attributes.push({title: 'STATE', value: reason}); 51 if (message) { 52 attributes.push({title: 'STATE DETAILS', value: message}); 53 } 54 } else if (props.node.kind === 'Service') { 55 attributes.push({title: 'TYPE', value: props.live.spec.type}); 56 let hostNames = ''; 57 const status = props.live.status; 58 if (status && status.loadBalancer && status.loadBalancer.ingress) { 59 hostNames = (status.loadBalancer.ingress || []).map((item: any) => item.hostname || item.ip).join(', '); 60 } 61 attributes.push({title: 'HOSTNAMES', value: hostNames}); 62 } 63 } 64 65 if (props.controlled) { 66 if (!props.controlled.summary.hook) { 67 attributes.push({ 68 title: 'STATUS', 69 value: ( 70 <span> 71 <ComparisonStatusIcon status={props.controlled.summary.status} resource={props.controlled.summary} label={true} /> 72 </span> 73 ) 74 } as any); 75 } 76 if (props.controlled.summary.health !== undefined) { 77 attributes.push({ 78 title: 'HEALTH', 79 value: ( 80 <span> 81 <HealthStatusIcon state={props.controlled.summary.health} /> {props.controlled.summary.health.status} 82 </span> 83 ) 84 } as any); 85 if (props.controlled.summary.health.message) { 86 attributes.push({title: 'HEALTH DETAILS', value: props.controlled.summary.health.message}); 87 } 88 } 89 } 90 91 const tabs: Tab[] = [ 92 { 93 key: 'manifest', 94 title: 'Live Manifest', 95 content: ( 96 <YamlEditor 97 input={props.live} 98 hideModeButtons={!props.live} 99 onSave={(patch, patchType) => services.applications.patchResource(props.application.metadata.name, props.node, patch, patchType)} 100 /> 101 ) 102 } 103 ]; 104 if (props.controlled && !props.controlled.summary.hook) { 105 tabs.push({ 106 key: 'diff', 107 icon: 'fa fa-file-medical', 108 title: 'Diff', 109 content: <ApplicationResourcesDiff states={[props.controlled.state]} /> 110 }); 111 tabs.push({ 112 key: 'desiredManifest', 113 title: 'Desired Manifest', 114 content: <YamlEditor input={props.controlled.state.targetState} hideModeButtons={true} /> 115 }); 116 } 117 118 return ( 119 <div> 120 <div className='white-box'> 121 <div className='white-box__details'> 122 {attributes.map(attr => ( 123 <div className='row white-box__details-row' key={attr.title}> 124 <div className='columns small-3'>{attr.title}</div> 125 <div className='columns small-9'>{attr.value}</div> 126 </div> 127 ))} 128 </div> 129 </div> 130 131 <div className='application-node-info__manifest'> 132 <DataLoader load={() => services.viewPreferences.getPreferences()}> 133 {pref => ( 134 <Tabs 135 selectedTabKey={(tabs.length > 1 && pref.appDetails.resourceView) || 'manifest'} 136 tabs={tabs} 137 onTabSelected={selected => { 138 services.viewPreferences.updatePreferences({appDetails: {...pref.appDetails, resourceView: selected as any}}); 139 }} 140 /> 141 )} 142 </DataLoader> 143 </div> 144 </div> 145 ); 146 };