github.com/argoproj/argo-cd/v3@v3.2.1/ui/src/app/applications/components/application-deployment-history/application-deployment-history-details.tsx (about) 1 import * as moment from 'moment'; 2 import * as React from 'react'; 3 import * as classNames from 'classnames'; 4 import * as models from '../../../shared/models'; 5 import './application-deployment-history.scss'; 6 import '../../../shared/components/editable-panel/editable-panel.scss'; 7 import {DataLoader} from 'argo-ui'; 8 import {Repo, Revision} from '../../../shared/components'; 9 import {services} from '../../../shared/services'; 10 import {ApplicationParameters} from '../application-parameters/application-parameters'; 11 import {RevisionMetadataRows} from './revision-metadata-rows'; 12 13 type props = { 14 app: models.Application; 15 info: models.RevisionHistory; 16 index: number; 17 }; 18 19 export const ApplicationDeploymentHistoryDetails = ({app, info, index}: props) => { 20 const deployments = (app.status.history || []).slice().reverse(); 21 const recentDeployments = deployments.map((info, i) => { 22 const nextDeployedAt = i === 0 ? null : deployments[i - 1].deployedAt; 23 const runEnd = nextDeployedAt ? moment(nextDeployedAt) : moment(); 24 return {...info, nextDeployedAt, durationMs: runEnd.diff(moment(info.deployedAt)) / 1000}; 25 }); 26 27 const [showParameterDetails, setShowParameterDetails] = React.useState(Boolean); 28 const [showSourceDetails, setShowSourceDetails] = React.useState([]); 29 const updateMap = (i: number) => { 30 if (i === null || i === undefined) { 31 return; 32 } 33 if (showSourceDetails.includes(i)) { 34 setShowSourceDetails(showSourceDetails.filter(item => item !== i)); 35 } else { 36 setShowSourceDetails([...showSourceDetails, i]); 37 } 38 }; 39 40 const getCollapsedSection = (i: number, repoURL: string): React.ReactFragment => { 41 return ( 42 <div 43 id={i ? `'hide-parameters-'${i}` : 'hide-parameters'} 44 key={i ? `'hide-parameters-'${i}` : 'hide-parameters'} 45 className='settings-overview__redirect-panel collapsible-section' 46 onClick={() => { 47 setShowParameterDetails(!showParameterDetails); 48 updateMap(i); 49 }}> 50 <div className='editable-panel__collapsible-button'> 51 <i className={`fa fa-angle-down filter__collapse editable-panel__collapsible-button__override`} /> 52 </div> 53 54 <div style={{textAlign: 'center'}}> 55 <div className='settings-overview__redirect-panel__title'>{i != null ? 'Source ' + (i + 1) + ' Parameters' : 'Source Parameters'}</div> 56 <div className='settings-overview__redirect-panel__description'>URL: {repoURL}</div> 57 </div> 58 </div> 59 ); 60 }; 61 62 const getExpandedSection = (index?: number): React.ReactFragment => { 63 return ( 64 <div id={index ? `'show-parameters-'${index}` : 'show-parameters'} className='editable-panel__collapsible-button' style={{zIndex: 1001}}> 65 <i 66 className={`fa fa-angle-up filter__collapse editable-panel__collapsible-button__override`} 67 onClick={() => { 68 setShowParameterDetails(!showParameterDetails); 69 updateMap(index); 70 }} 71 /> 72 </div> 73 ); 74 }; 75 76 const getErrorSection = (err: React.ReactNode): React.ReactFragment => { 77 return ( 78 <div style={{padding: '1.7em'}}> 79 <p style={{textAlign: 'center'}}>{err}</p> 80 </div> 81 ); 82 }; 83 84 return ( 85 <> 86 {info.sources === undefined ? ( 87 <React.Fragment> 88 <div> 89 <div className='row'> 90 <div className='columns small-3'>Revision:</div> 91 <div className='columns small-9'> 92 <Revision repoUrl={info.source.repoURL} revision={info.revision} /> 93 </div> 94 </div> 95 </div> 96 <RevisionMetadataRows 97 applicationName={app.metadata.name} 98 applicationNamespace={app.metadata.namespace} 99 source={{...recentDeployments[index].source, targetRevision: recentDeployments[index].revision}} 100 index={0} 101 versionId={recentDeployments[index].id} 102 /> 103 104 {showParameterDetails ? ( 105 <div id={`'history-expanded'`} key={`'history-expanded'`} className={classNames('white-box', 'collapsible-section')}> 106 {getExpandedSection()} 107 <DataLoader 108 errorRenderer={err => { 109 return getErrorSection(err); 110 }} 111 input={{...recentDeployments[index].source, targetRevision: recentDeployments[index].revision, appName: app.metadata.name}} 112 load={src => services.repos.appDetails(src, src.appName, app.spec.project, 0, recentDeployments[index].id)}> 113 {(details: models.RepoAppDetails) => ( 114 <div> 115 <ApplicationParameters 116 application={{ 117 ...app, 118 spec: {...app.spec, source: recentDeployments[index].source} 119 }} 120 details={details} 121 tempSource={{...recentDeployments[index].source, targetRevision: recentDeployments[index].revision}} 122 /> 123 </div> 124 )} 125 </DataLoader> 126 </div> 127 ) : ( 128 getCollapsedSection(null, recentDeployments[index].source.repoURL) 129 )} 130 </React.Fragment> 131 ) : ( 132 info.sources.map((source, i) => ( 133 <React.Fragment key={`${index}_${i}`}> 134 {i > 0 ? <div className='separator' /> : null} 135 <div> 136 <div className='row'> 137 <div className='columns small-3'>Repo URL:</div> 138 <div className='columns small-9'> 139 <Repo url={source.repoURL} /> 140 </div> 141 </div> 142 <div className='row'> 143 <div className='columns small-3'>Revision:</div> 144 <div className='columns small-9'> 145 <Revision repoUrl={source.repoURL} revision={info.revisions[i]} /> 146 </div> 147 </div> 148 </div> 149 <RevisionMetadataRows 150 applicationName={app.metadata.name} 151 applicationNamespace={app.metadata.namespace} 152 source={{...source, targetRevision: recentDeployments[index].revisions[i]}} 153 index={i} 154 versionId={recentDeployments[index].id} 155 /> 156 {showSourceDetails.includes(i) ? ( 157 <div id={`'history-expanded-'${i}`} key={`'history-expanded-'${i}`} className={classNames('white-box', 'collapsible-section')}> 158 <div id={`'history-expanded-'${i}`} key={`'history-expanded-'${i}`} className='white-box__details'> 159 {getExpandedSection(i)} 160 <DataLoader 161 errorRenderer={err => { 162 return getErrorSection(err); 163 }} 164 input={{ 165 ...source, 166 targetRevision: recentDeployments[index].revisions[i], 167 index: i, 168 versionId: recentDeployments[index].id, 169 appName: app.metadata.name 170 }} 171 load={src => services.repos.appDetails(src, src.appName, app.spec.project, i, recentDeployments[index].id)}> 172 {(details: models.RepoAppDetails) => ( 173 <React.Fragment> 174 <div id={'floating_title_' + i} className='editable-panel__sticky-title'> 175 <div style={{marginTop: '0px'}}> 176 <div>Source {i + 1} Parameters</div> 177 <div>Repo URL: {source.repoURL}</div> 178 <div>{source.path ? 'Path: ' + source.path : ''}</div> 179 <span> 180 Revision: <Revision repoUrl={''} revision={info.revisions[i]}></Revision> 181 </span> 182 </div> 183 </div> 184 <ApplicationParameters 185 application={{ 186 ...app, 187 spec: {...app.spec, source} 188 }} 189 details={details} 190 tempSource={{...source, targetRevision: recentDeployments[index].revisions[i]}} 191 /> 192 </React.Fragment> 193 )} 194 </DataLoader> 195 </div> 196 </div> 197 ) : ( 198 getCollapsedSection(i, source.repoURL) 199 )} 200 </React.Fragment> 201 )) 202 )} 203 </> 204 ); 205 };