From 4c80d6bc345f0b7b192b68fb385f8587d8b188dc Mon Sep 17 00:00:00 2001 From: Alexander Matyushentsev Date: Thu, 12 Jul 2018 15:37:56 -0700 Subject: [PATCH 1/3] Set cascade to true in app delete popup --- src/app/applications/components/utils.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/applications/components/utils.tsx b/src/app/applications/components/utils.tsx index d14005205393f..063066d24c48a 100644 --- a/src/app/applications/components/utils.tsx +++ b/src/app/applications/components/utils.tsx @@ -22,7 +22,7 @@ export async function deleteApplication(appName: string, context: AppContext) { const confirmationForm = class extends React.Component<{}, { cascade: boolean } > { constructor(props: any) { super(props); - this.state = {cascade: false}; + this.state = {cascade: true}; } public render() { return ( From 3a256973490e6652019f979892222e14efe82484 Mon Sep 17 00:00:00 2001 From: Alexander Matyushentsev Date: Thu, 12 Jul 2018 15:38:29 -0700 Subject: [PATCH 2/3] Add revision to app summary panel --- .../components/application-summary/application-summary.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/app/applications/components/application-summary/application-summary.tsx b/src/app/applications/components/application-summary/application-summary.tsx index ded8ad2a30687..e6450967d6e29 100644 --- a/src/app/applications/components/application-summary/application-summary.tsx +++ b/src/app/applications/components/application-summary/application-summary.tsx @@ -11,6 +11,7 @@ export const ApplicationSummary = ({app}: {app: models.Application}) => { event.stopPropagation()}> {app.spec.source.repoURL} )}, + {title: 'REVISION', value: app.spec.source.targetRevision || 'HEAD'}, {title: 'PATH', value: app.spec.source.path}, {title: 'ENVIRONMENT', value: app.spec.source.environment}, {title: 'STATUS', value: ( From 1db0fbdedc4ebcc24b3a72238ba3f5cd1f4d05e6 Mon Sep 17 00:00:00 2001 From: Alexander Matyushentsev Date: Thu, 12 Jul 2018 15:38:56 -0700 Subject: [PATCH 3/3] Render sync hooks and operation status message --- .../application-operation-state.tsx | 68 ++++++++++++++++--- src/app/shared/components/index.ts | 1 + src/app/shared/components/ticket.tsx | 25 +++++++ src/app/shared/models.ts | 30 ++++++++ 4 files changed, 114 insertions(+), 10 deletions(-) create mode 100644 src/app/shared/components/ticket.tsx diff --git a/src/app/applications/components/application-operation-state/application-operation-state.tsx b/src/app/applications/components/application-operation-state/application-operation-state.tsx index 22b166e8b4c16..423462e3d414b 100644 --- a/src/app/applications/components/application-operation-state/application-operation-state.tsx +++ b/src/app/applications/components/application-operation-state/application-operation-state.tsx @@ -2,28 +2,28 @@ import { Duration } from 'argo-ui'; import * as moment from 'moment'; import * as React from 'react'; +import { Ticker } from '../../../shared/components'; import * as models from '../../../shared/models'; import * as utils from '../utils'; export const ApplicationOperationState = ({operationState}: { operationState: models.OperationState }) => { - const durationMs = operationState.finishedAt ? - moment(operationState.finishedAt).diff(moment(operationState.startedAt)) / 1000 : - null; const operationAttributes = [ {title: 'OPERATION', value: utils.getOperationType(operationState)}, {title: 'PHASE', value: operationState.phase}, + ...(operationState.message ? [{title: 'MESSAGE', value: operationState.message}] : []), {title: 'STARTED AT', value: operationState.startedAt}, - {title: 'FINISHED AT', value: operationState.finishedAt}, - ...(durationMs ? [{title: 'DURATION', value: }] : []), + {title: 'DURATION', value: ( + + {(time) => } + + )}, + ...(operationState.finishedAt ? [{title: 'FINISHED AT', value: operationState.finishedAt}] : []), ]; const resultAttributes: {title: string, value: string}[] = []; + const syncResult = operationState.syncResult || operationState.rollbackResult; if (operationState.finishedAt) { - if (operationState.message) { - resultAttributes.push({title: 'MESSAGE', value: operationState.message}); - } - const syncResult = operationState.syncResult || operationState.rollbackResult; if (syncResult) { (syncResult.resources || []).forEach((res) => { resultAttributes.push({ @@ -33,6 +33,7 @@ export const ApplicationOperationState = ({operationState}: { operationState: mo }); } } + return (
@@ -47,7 +48,54 @@ export const ApplicationOperationState = ({operationState}: { operationState: mo ))}
- { resultAttributes.length > 0 && ( + {syncResult && syncResult.hooks && syncResult.hooks.length > 0 && ( + +

Hooks:

+
+
+
+
+ KIND +
+
+ NAME +
+
+ STATUS +
+
+ TYPE +
+
+ MESSAGE +
+
+
+ {syncResult.hooks.map((hook, i) => ( +
+
+
+ {hook.kind} +
+
+ {hook.name} +
+
+ {hook.status} +
+
+ {hook.type} +
+
+ {hook.message} +
+
+
+ ))} +
+
+ )} + {resultAttributes.length > 0 && (

Result details:

)} { resultAttributes.length > 0 && ( diff --git a/src/app/shared/components/index.ts b/src/app/shared/components/index.ts index 5877953c98c2f..cf09fb6d61bbc 100644 --- a/src/app/shared/components/index.ts +++ b/src/app/shared/components/index.ts @@ -3,3 +3,4 @@ export * from './form-field'; export * from './colors'; export * from './connection-state-icon'; export * from './error-notification'; +export * from './ticket'; diff --git a/src/app/shared/components/ticket.tsx b/src/app/shared/components/ticket.tsx new file mode 100644 index 0000000000000..512428e3c7ecf --- /dev/null +++ b/src/app/shared/components/ticket.tsx @@ -0,0 +1,25 @@ +import * as moment from 'moment'; +import * as React from 'react'; +import {Observable, Subscription} from 'rxjs'; + +export class Ticker extends React.Component<{intervalMs?: number, children?: ((time: moment.Moment) => React.ReactNode)}, {time: moment.Moment}> { + + private subscription: Subscription; + + constructor(props: {intervalMs?: number, children?: ((time: moment.Moment) => React.ReactNode)}) { + super(props); + this.state = { time: moment() }; + this.subscription = Observable.interval(props.intervalMs || 1000).subscribe(() => this.setState({ time: moment() })); + } + + public render() { + return this.props.children(this.state.time); + } + + public componentWillUnmount() { + if (this.subscription != null) { + this.subscription.unsubscribe(); + this.subscription = null; + } + } +} diff --git a/src/app/shared/models.ts b/src/app/shared/models.ts index e64c322025816..7012611a08e88 100644 --- a/src/app/shared/models.ts +++ b/src/app/shared/models.ts @@ -49,8 +49,38 @@ export interface OperationState { finishedAt: models.Time; } +export type HookType = 'PreSync' | 'Sync' | 'PostSync' | 'Skip'; + +export interface HookStatus { + /** + * Name is the resource name + */ + name: string; + /** + * Name is the resource name + */ + kind: string; + /** + * Name is the resource name + */ + apiVersion: string; + /** + * Type is the type of hook (e.g. PreSync, Sync, PostSync, Skip) + */ + type: HookType; + /** + * Status a simple, high-level summary of where the resource is in its lifecycle + */ + status: OperationPhase; + /** + * A human readable message indicating details about why the resource is in this condition. + */ + message: string; +} + export interface SyncOperationResult { resources: ResourceDetails[]; + hooks?: HookStatus[]; } export interface ResourceDetails {