mirror of
https://github.com/argoproj/argo-cd
synced 2026-05-24 01:38:43 +00:00
parent
3a7f6d06b1
commit
adc2e9ba54
6 changed files with 275 additions and 5 deletions
|
|
@ -1,13 +1,20 @@
|
|||
import {ErrorNotification, NotificationType, SlidingPanel} from 'argo-ui';
|
||||
import * as React from 'react';
|
||||
import {Checkbox, Form, FormApi} from 'react-form';
|
||||
import {ProgressPopup} from '../../../shared/components';
|
||||
import {Consumer} from '../../../shared/context';
|
||||
import * as models from '../../../shared/models';
|
||||
import {services} from '../../../shared/services';
|
||||
import {ComparisonStatusIcon, HealthStatusIcon, OperationPhaseIcon} from '../utils';
|
||||
|
||||
interface Progress {
|
||||
percentage: number;
|
||||
title: string;
|
||||
}
|
||||
|
||||
export const ApplicationsSyncPanel = ({show, apps, hide}: {show: boolean; apps: models.Application[]; hide: () => void}) => {
|
||||
const [form, setForm] = React.useState<FormApi>(null);
|
||||
const [progress, setProgress] = React.useState<Progress>(null);
|
||||
const getSelectedApps = (params: any) => apps.filter(app => params['app/' + app.metadata.name]);
|
||||
return (
|
||||
<Consumer>
|
||||
|
|
@ -33,11 +40,9 @@ export const ApplicationsSyncPanel = ({show, apps, hide}: {show: boolean; apps:
|
|||
ctx.notifications.show({content: `No apps selected`, type: NotificationType.Error});
|
||||
return;
|
||||
}
|
||||
ctx.notifications.show({
|
||||
content: `Syncing ${selectedApps.length} app(s)`,
|
||||
type: NotificationType.Success
|
||||
});
|
||||
const syncStrategy = (params.applyOnly ? {apply: {force: params.force}} : {hook: {force: params.force}}) as models.SyncStrategy;
|
||||
setProgress({percentage: 0, title: 'Starting...'});
|
||||
let i = 0;
|
||||
for (const app of selectedApps) {
|
||||
await services.applications.sync(app.metadata.name, app.spec.source.targetRevision, params.prune, params.dryRun, syncStrategy, null).catch(e => {
|
||||
ctx.notifications.show({
|
||||
|
|
@ -45,14 +50,20 @@ export const ApplicationsSyncPanel = ({show, apps, hide}: {show: boolean; apps:
|
|||
type: NotificationType.Error
|
||||
});
|
||||
});
|
||||
i++;
|
||||
setProgress({
|
||||
percentage: i / selectedApps.length,
|
||||
title: `${i} of ${selectedApps.length} apps synced`
|
||||
});
|
||||
}
|
||||
hide();
|
||||
setProgress({percentage: 100, title: 'Complete'});
|
||||
}}
|
||||
getApi={setForm}>
|
||||
{formApi => (
|
||||
<React.Fragment>
|
||||
<div className='argo-form-row'>
|
||||
<h4>Sync app(s)</h4>
|
||||
{progress !== null && <ProgressPopup onClose={() => setProgress(null)} percentage={progress.percentage} title={progress.title} />}
|
||||
<label>Options:</label>
|
||||
<div style={{paddingLeft: '1em'}}>
|
||||
<label>
|
||||
|
|
|
|||
|
|
@ -19,5 +19,6 @@ export * from './autocomplete/autocomplete';
|
|||
export * from './autocomplete/autocomplete-field';
|
||||
export * from './monaco-editor';
|
||||
export * from './yaml-editor/yaml-editor';
|
||||
export * from './progress/progress-popup';
|
||||
export * from './repo';
|
||||
export * from './revision';
|
||||
|
|
|
|||
|
|
@ -0,0 +1,182 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`ProgressPopup.0% 1`] = `
|
||||
<div
|
||||
className="popup-overlay"
|
||||
>
|
||||
<div
|
||||
className="popup-container"
|
||||
>
|
||||
<div
|
||||
className="row popup-container__header"
|
||||
>
|
||||
|
||||
</div>
|
||||
<div
|
||||
className="row popup-container__body"
|
||||
>
|
||||
<div
|
||||
className="columns large-12"
|
||||
>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"background": "#CCD6DD",
|
||||
"borderRadius": "5px",
|
||||
"height": "10px",
|
||||
"margin": "15px auto",
|
||||
"width": "90%",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"background": "#18BE94",
|
||||
"borderRadius": "inherit",
|
||||
"height": "100%",
|
||||
"transition": "width 0.1s ease-in",
|
||||
"width": "0%",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="row popup-container__footer"
|
||||
>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"textAlign": "right",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`ProgressPopup.50% 1`] = `
|
||||
<div
|
||||
className="popup-overlay"
|
||||
>
|
||||
<div
|
||||
className="popup-container"
|
||||
>
|
||||
<div
|
||||
className="row popup-container__header"
|
||||
>
|
||||
My Title
|
||||
</div>
|
||||
<div
|
||||
className="row popup-container__body"
|
||||
>
|
||||
<div
|
||||
className="columns large-12"
|
||||
>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"background": "#CCD6DD",
|
||||
"borderRadius": "5px",
|
||||
"height": "10px",
|
||||
"margin": "15px auto",
|
||||
"width": "90%",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"background": "#18BE94",
|
||||
"borderRadius": "inherit",
|
||||
"height": "100%",
|
||||
"transition": "width 0.1s ease-in",
|
||||
"width": "100%",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="row popup-container__footer"
|
||||
>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"textAlign": "right",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`ProgressPopup.100% 1`] = `
|
||||
<div
|
||||
className="popup-overlay"
|
||||
>
|
||||
<div
|
||||
className="popup-container"
|
||||
>
|
||||
<div
|
||||
className="row popup-container__header"
|
||||
>
|
||||
|
||||
</div>
|
||||
<div
|
||||
className="row popup-container__body"
|
||||
>
|
||||
<div
|
||||
className="columns large-12"
|
||||
>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"background": "#CCD6DD",
|
||||
"borderRadius": "5px",
|
||||
"height": "10px",
|
||||
"margin": "15px auto",
|
||||
"width": "90%",
|
||||
}
|
||||
}
|
||||
>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"background": "#18BE94",
|
||||
"borderRadius": "inherit",
|
||||
"height": "100%",
|
||||
"transition": "width 0.1s ease-in",
|
||||
"width": "100%",
|
||||
}
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="row popup-container__footer"
|
||||
>
|
||||
<div
|
||||
style={
|
||||
Object {
|
||||
"textAlign": "right",
|
||||
}
|
||||
}
|
||||
>
|
||||
<button
|
||||
className="argo-button argo-button--base-o"
|
||||
onClick={[Function]}
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
25
ui/src/app/shared/components/progress/progress-bar.tsx
Normal file
25
ui/src/app/shared/components/progress/progress-bar.tsx
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
import * as React from 'react';
|
||||
import {COLORS} from '../colors';
|
||||
|
||||
export const ProgressBar = (props: {percentage: number}) => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: '90%',
|
||||
height: '10px',
|
||||
margin: '15px auto',
|
||||
background: COLORS.sync.unknown,
|
||||
borderRadius: '5px'
|
||||
}}>
|
||||
<div
|
||||
style={{
|
||||
background: COLORS.sync.synced,
|
||||
height: '100%',
|
||||
width: Math.min(100, 100 * props.percentage) + '%',
|
||||
borderRadius: 'inherit',
|
||||
transition: 'width 0.1s ease-in'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import * as renderer from 'react-test-renderer';
|
||||
import * as React from 'react';
|
||||
import {ProgressPopup} from './progress-popup';
|
||||
|
||||
test('ProgressPopup.0%', () => {
|
||||
const state = renderer.create(<ProgressPopup onClose={() => {
|
||||
}} percentage={0} title={''}/>);
|
||||
|
||||
expect(state).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('ProgressPopup.50%', () => {
|
||||
const state = renderer.create(<ProgressPopup onClose={() => {
|
||||
}} percentage={50} title={'My Title'}/>);
|
||||
|
||||
expect(state).toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('ProgressPopup.100%', () => {
|
||||
const state = renderer.create(<ProgressPopup onClose={() => {
|
||||
}} percentage={100} title={''}/>);
|
||||
|
||||
expect(state).toMatchSnapshot();
|
||||
});
|
||||
27
ui/src/app/shared/components/progress/progress-popup.tsx
Normal file
27
ui/src/app/shared/components/progress/progress-popup.tsx
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import {Popup} from 'argo-ui/src/app/shared/components/popup/popup';
|
||||
import * as React from 'react';
|
||||
import {ProgressBar} from './progress-bar';
|
||||
|
||||
const Title = ({title}: {title: string}) => {
|
||||
return <React.Fragment>{title}</React.Fragment>;
|
||||
};
|
||||
|
||||
const Footer = ({percentage, onClose}: {percentage: number; onClose: () => void}) => {
|
||||
return (
|
||||
<div style={{textAlign: 'right'}}>
|
||||
{percentage >= 100 && (
|
||||
<button className='argo-button argo-button--base-o' onClick={() => onClose()}>
|
||||
Close
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const ProgressPopup = ({title, percentage, onClose}: {title: string; percentage: number; onClose: () => void}) => {
|
||||
return (
|
||||
<Popup title={<Title title={title} />} footer={<Footer percentage={percentage} onClose={onClose} />}>
|
||||
<ProgressBar percentage={percentage} />
|
||||
</Popup>
|
||||
);
|
||||
};
|
||||
Loading…
Reference in a new issue