From 0faf364006efec9affff996ec45482e289c46c84 Mon Sep 17 00:00:00 2001 From: linghaoSu Date: Thu, 31 Oct 2024 20:24:52 +0800 Subject: [PATCH] feat(ui): support display sync wave Signed-off-by: linghaoSu --- .../application-operation-state.tsx | 211 ++++++++++++------ ui/src/app/shared/models.ts | 1 + .../services/view-preferences-service.ts | 8 +- 3 files changed, 148 insertions(+), 72 deletions(-) diff --git a/ui/src/app/applications/components/application-operation-state/application-operation-state.tsx b/ui/src/app/applications/components/application-operation-state/application-operation-state.tsx index 37c22cfed267c..6cf6735104c0e 100644 --- a/ui/src/app/applications/components/application-operation-state/application-operation-state.tsx +++ b/ui/src/app/applications/components/application-operation-state/application-operation-state.tsx @@ -1,4 +1,4 @@ -import {Checkbox, DropDown, Duration, NotificationType, Ticker, HelpIcon} from 'argo-ui'; +import {Checkbox, DropDown, Duration, NotificationType, Ticker, HelpIcon, DataLoader} from 'argo-ui'; import * as moment from 'moment'; import * as PropTypes from 'prop-types'; import * as React from 'react'; @@ -15,7 +15,8 @@ interface Props { application: models.Application; operationState: models.OperationState; } -const buildResourceUniqueId = (res: Omit) => `${res.group}-${res.kind}-${res.version}-${res.namespace}-${res.name}`; +const buildResourceUniqueId = (res: Omit) => + `${res.group || ''}-${res.kind || ''}-${res.version || ''}-${res.kind === 'Namespace' ? res.name : res.kind}-${res.name}`; const Filter = (props: {filters: string[]; setFilters: (f: string[]) => void; options: string[]; title: string; style?: React.CSSProperties}) => { const {filters, setFilters, options, title, style} = props; @@ -138,13 +139,19 @@ export const ApplicationOperationState: React.StatelessComponent = ({appl // const hookPhases = ['Running', 'Terminating', 'Failed', 'Error', 'Succeeded']; const resourceHealth = application.status.resources.reduce( (acc, res) => { - if (res.health) { - acc[buildResourceUniqueId(res)] = res.health; - } - + acc[buildResourceUniqueId(res)] = { + health: res.health, + syncWave: res.syncWave + }; return acc; }, - {} as Record + {} as Record< + string, + { + health: models.HealthStatus; + syncWave: number; + } + > ); const combinedHealthSyncResult: models.SyncResourceResult[] = syncResult?.resources?.map(syncResultItem => { @@ -156,10 +163,12 @@ export const ApplicationOperationState: React.StatelessComponent = ({appl ...syncResultItem }; - if (healthStatus) { - syncResultWithHealth.health = healthStatus; + if (healthStatus?.health) { + syncResultWithHealth.health = healthStatus.health; } + syncResultWithHealth.syncWave = healthStatus?.syncWave; + return syncResultWithHealth; }); let filtered: models.SyncResourceResult[] = []; @@ -195,72 +204,132 @@ export const ApplicationOperationState: React.StatelessComponent = ({appl ))} - {syncResult && syncResult.resources && syncResult.resources.length > 0 && ( - -
- -
- - - -
-
-
-
-
-
KIND
-
NAMESPACE
-
NAME
-
STATUS
-
HEALTH
-
HOOK
-
MESSAGE
-
-
- {filtered.length > 0 ? ( - filtered.map((resource, i) => ( -
-
-
-
- {resource.hookType && } -
- {getKind(resource)} -
-
- {resource.namespace} -
-
- {resource.name} + services.viewPreferences.getPreferences()}> + {pref => { + const showSyncWave = pref.appDetails?.syncResult?.showSyncWave ?? false; + + return ( + <> + {syncResult && syncResult.resources && syncResult.resources.length > 0 && ( + +
+ +
+ + + services.viewPreferences.updatePreferences({ + ...pref, + appDetails: { + ...pref.appDetails, + syncResult: { + ...pref.appDetails.syncResult, + showSyncWave: !showSyncWave + } + } + }) + }> + + + + +
-
- {getStatus(resource)} +
+
+
+
+ {showSyncWave ? ( + <> +
SYNC WAVE
+
KIND
+
NAMESPACE
+ + ) : ( + <> +
KIND
+
NAMESPACE
+ + )} + +
NAME
+
STATUS
+
HEALTH
+
HOOK
+
MESSAGE
+
-
- {resource.health ? ( -
- {resource.health?.status} - {resource.health.message && } + {filtered.length > 0 ? ( + filtered.map((resource, i) => ( +
+
+ {showSyncWave ? ( + <> +
+ {resource.syncWave || '0'} +
+
+
+ {resource.hookType && } +
+ {getKind(resource)} +
+
+ {resource.namespace} +
+ + ) : ( + <> +
+
+ {resource.hookType && } +
+ {getKind(resource)} +
+
+ {resource.namespace} +
+ + )} +
+ {resource.name} +
+
+ {getStatus(resource)} +
+
+ {resource.health ? ( +
+ {resource.health?.status} + {resource.health.message && } +
+ ) : ( + <>{'-'} + )} +
+
+ {resource.hookType} +
+
+
{resource.message}
+
+
- ) : ( - <>{'-'} - )} -
-
- {resource.hookType} -
-
-
{resource.message}
-
+ )) + ) : ( +
No Sync Results match filter
+ )}
-
- )) - ) : ( -
No Sync Results match filter
- )} -
-
- )} + + )} + + ); + }} +
); }; diff --git a/ui/src/app/shared/models.ts b/ui/src/app/shared/models.ts index c9d37184539d3..ef405fb6bb3dd 100644 --- a/ui/src/app/shared/models.ts +++ b/ui/src/app/shared/models.ts @@ -129,6 +129,7 @@ export interface ResourceResult { export type SyncResourceResult = ResourceResult & { health?: HealthStatus; + syncWave?: number; }; export const AnnotationRefreshKey = 'argocd.argoproj.io/refresh'; diff --git a/ui/src/app/shared/services/view-preferences-service.ts b/ui/src/app/shared/services/view-preferences-service.ts index 575c4b734d416..a89852aecc2ba 100644 --- a/ui/src/app/shared/services/view-preferences-service.ts +++ b/ui/src/app/shared/services/view-preferences-service.ts @@ -31,6 +31,9 @@ export interface AppDetailsPreferences { zoom: number; podGroupCount: number; userHelpTipMsgs: UserMessages[]; + syncResult?: { + showSyncWave?: boolean; + }; } export interface PodViewPreferences { @@ -126,7 +129,10 @@ const DEFAULT_PREFERENCES: ViewPreferences = { wrapLines: false, zoom: 1.0, podGroupCount: 15.0, - userHelpTipMsgs: [] + userHelpTipMsgs: [], + syncResult: { + showSyncWave: false + } }, appList: { view: 'tiles' as AppsListViewType,