Improves the "Sync Apps" panel UI. Closes #2698 (#2699)

This commit is contained in:
Alex Collins 2019-12-09 11:04:31 -08:00 committed by GitHub
parent 3a7f6d06b1
commit adc2e9ba54
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 275 additions and 5 deletions

View file

@ -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>

View file

@ -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';

View file

@ -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>
`;

View 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>
);
};

View file

@ -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();
});

View 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>
);
};