github.com/argoproj/argo-cd/v2@v2.10.9/ui/src/app/applications/components/applications-refresh-panel/applications-refresh-panel.tsx (about) 1 import {ErrorNotification, NotificationType, SlidingPanel} from 'argo-ui'; 2 import * as React from 'react'; 3 import {Form, FormApi} from 'react-form'; 4 import {ProgressPopup} from '../../../shared/components'; 5 import {Consumer} from '../../../shared/context'; 6 import * as models from '../../../shared/models'; 7 import {services} from '../../../shared/services'; 8 import {ApplicationSelector} from '../../../shared/components'; 9 10 interface Progress { 11 percentage: number; 12 title: string; 13 } 14 15 const RefreshTypes = ['normal', 'hard']; 16 17 export const ApplicationsRefreshPanel = ({show, apps, hide}: {show: boolean; apps: models.Application[]; hide: () => void}) => { 18 const [form, setForm] = React.useState<FormApi>(null); 19 const [progress, setProgress] = React.useState<Progress>(null); 20 const getSelectedApps = (params: any) => apps.filter((_, i) => params['app/' + i]); 21 22 return ( 23 <Consumer> 24 {ctx => ( 25 <SlidingPanel 26 isMiddle={true} 27 isShown={show} 28 onClose={() => hide()} 29 header={ 30 <div> 31 <button className='argo-button argo-button--base' onClick={() => form.submitForm(null)}> 32 Refresh 33 </button>{' '} 34 <button onClick={() => hide()} className='argo-button argo-button--base-o'> 35 Cancel 36 </button> 37 </div> 38 }> 39 <Form 40 defaultValues={{refreshType: 'normal'}} 41 onSubmit={async (params: any) => { 42 const selectedApps = getSelectedApps(params); 43 if (selectedApps.length === 0) { 44 ctx.notifications.show({content: `No apps selected`, type: NotificationType.Error}); 45 return; 46 } 47 48 setProgress({percentage: 0, title: 'Refreshing applications'}); 49 let i = 0; 50 const refreshActions = []; 51 for (const app of selectedApps) { 52 const refreshAction = async () => { 53 await services.applications.get(app.metadata.name, app.metadata.namespace, params.refreshType).catch(e => { 54 ctx.notifications.show({ 55 content: <ErrorNotification title={`Unable to refresh ${app.metadata.name}`} e={e} />, 56 type: NotificationType.Error 57 }); 58 }); 59 i++; 60 setProgress({ 61 percentage: i / selectedApps.length, 62 title: `Refreshed ${i} of ${selectedApps.length} applications` 63 }); 64 }; 65 refreshActions.push(refreshAction()); 66 67 if (refreshActions.length >= 20) { 68 await Promise.all(refreshActions); 69 refreshActions.length = 0; 70 } 71 } 72 await Promise.all(refreshActions); 73 setProgress({percentage: 100, title: 'Complete'}); 74 }} 75 getApi={setForm}> 76 {formApi => ( 77 <React.Fragment> 78 <div className='argo-form-row' style={{marginTop: 0}}> 79 <h4>Refresh app(s)</h4> 80 {progress !== null && <ProgressPopup onClose={() => setProgress(null)} percentage={progress.percentage} title={progress.title} />} 81 <div style={{marginBottom: '1em'}}> 82 <label>Refresh Type</label> 83 <div className='row application-sync-options'> 84 {RefreshTypes.map(refreshType => ( 85 <label key={refreshType} style={{paddingRight: '1.5em', marginTop: '0.4em'}}> 86 <input 87 type='radio' 88 value={refreshType} 89 checked={formApi.values.refreshType === refreshType} 90 onChange={() => formApi.setValue('refreshType', refreshType)} 91 style={{marginRight: '5px', transform: 'translateY(2px)'}} 92 /> 93 {refreshType} 94 </label> 95 ))} 96 </div> 97 </div> 98 <ApplicationSelector apps={apps} formApi={formApi} /> 99 </div> 100 </React.Fragment> 101 )} 102 </Form> 103 </SlidingPanel> 104 )} 105 </Consumer> 106 ); 107 };