Skip to content

Commit

Permalink
feat(ui): add health status and message in sync status list (#19875)
Browse files Browse the repository at this point in the history
Signed-off-by: linghaoSu <linghao.su@daocloud.io>
Co-authored-by: Alexander Matyushentsev <AMatyushentsev@gmail.com>
  • Loading branch information
linghaoSu and alexmt committed Sep 12, 2024
1 parent ddab959 commit 20e7f8e
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {Checkbox, DropDown, Duration, NotificationType, Ticker} from 'argo-ui';
import {Checkbox, DropDown, Duration, NotificationType, Ticker, HelpIcon} from 'argo-ui';
import * as moment from 'moment';
import * as PropTypes from 'prop-types';
import * as React from 'react';
Expand All @@ -15,6 +15,7 @@ interface Props {
application: models.Application;
operationState: models.OperationState;
}
const buildResourceUniqueId = (res: Omit<models.ResourceRef, 'uid'>) => `${res.group}-${res.kind}-${res.version}-${res.namespace}-${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;
Expand Down Expand Up @@ -126,18 +127,60 @@ export const ApplicationOperationState: React.StatelessComponent<Props> = ({appl
}
}
const [filters, setFilters] = React.useState([]);
const [healthFilters, setHealthFilters] = React.useState([]);

const Healths = Object.keys(models.HealthStatuses);
const Statuses = Object.keys(models.ResultCodes);
const OperationPhases = Object.keys(models.OperationPhases);
// const syncPhases = ['PreSync', 'Sync', 'PostSync', 'SyncFail'];
// const hookPhases = ['Running', 'Terminating', 'Failed', 'Error', 'Succeeded'];
const resourceHealth = application.status.resources.reduce(
(acc, res) => {
if (res.health) {
acc[buildResourceUniqueId(res)] = res.health;
}

let filtered: models.ResourceResult[] = [];
if (syncResult) {
if (syncResult.resources && syncResult.resources.length > 0) {
filtered = syncResult.resources.filter(r => filters.length === 0 || filters.includes(getStatus(r)));
return acc;
},
{} as Record<string, models.HealthStatus>
);

const combinedHealthSyncResult: models.SyncResourceResult[] = syncResult?.resources?.map(syncResultItem => {
const uniqueResourceName = buildResourceUniqueId(syncResultItem);

const healthStatus = resourceHealth[uniqueResourceName];

const syncResultWithHealth: models.SyncResourceResult = {
...syncResultItem
};

if (healthStatus) {
syncResultWithHealth.health = healthStatus;
}

return syncResultWithHealth;
});
let filtered: models.SyncResourceResult[] = [];

if (combinedHealthSyncResult && combinedHealthSyncResult.length > 0) {
filtered = combinedHealthSyncResult.filter(r => {
if (filters.length === 0 && healthFilters.length === 0) {
return true;
}

let pass = true;
if (filters.length !== 0 && !filters.includes(getStatus(r))) {
pass = false;
}

if (pass && healthFilters.length !== 0 && !healthFilters.includes(r.health?.status)) {
pass = false;
}

return pass;
});
}

return (
<div>
<div className='white-box'>
Expand All @@ -155,6 +198,7 @@ export const ApplicationOperationState: React.StatelessComponent<Props> = ({appl
<div style={{display: 'flex'}}>
<label style={{display: 'block', marginBottom: '1em'}}>RESULT</label>
<div style={{marginLeft: 'auto'}}>
<Filter options={Healths} filters={healthFilters} setFilters={setHealthFilters} title='HEALTH' style={{marginRight: '5px'}} />
<Filter options={Statuses} filters={filters} setFilters={setFilters} title='STATUS' style={{marginRight: '5px'}} />
<Filter options={OperationPhases} filters={filters} setFilters={setFilters} title='HOOK' />
</div>
Expand All @@ -166,6 +210,7 @@ export const ApplicationOperationState: React.StatelessComponent<Props> = ({appl
<div className='columns large-2 show-for-large'>NAMESPACE</div>
<div className='columns large-2 small-2'>NAME</div>
<div className='columns large-1 small-2'>STATUS</div>
<div className='columns large-1 small-2'>HEALTH</div>
<div className='columns large-1 show-for-large'>HOOK</div>
<div className='columns large-4 small-8'>MESSAGE</div>
</div>
Expand All @@ -189,6 +234,16 @@ export const ApplicationOperationState: React.StatelessComponent<Props> = ({appl
<div className='columns large-1 small-2' title={getStatus(resource)}>
<utils.ResourceResultIcon resource={resource} /> {getStatus(resource)}
</div>
<div className='columns large-1 small-2'>
{resource.health ? (
<div>
<utils.HealthStatusIcon state={resource?.health} /> {resource.health?.status}
{resource.health.message && <HelpIcon title={resource.health.message} />}
</div>
) : (
<>{'-'}</>
)}
</div>
<div className='columns large-1 show-for-large' title={resource.hookType}>
{resource.hookType}
</div>
Expand Down
4 changes: 4 additions & 0 deletions ui/src/app/shared/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ export interface ResourceResult {
hookPhase: OperationPhase;
}

export type SyncResourceResult = ResourceResult & {
health?: HealthStatus;
};

export const AnnotationRefreshKey = 'argocd.argoproj.io/refresh';
export const AnnotationHookKey = 'argocd.argoproj.io/hook';
export const AnnotationSyncWaveKey = 'argocd.argoproj.io/sync-wave';
Expand Down

0 comments on commit 20e7f8e

Please # to comment.