Skip to content

Commit

Permalink
initial refactoring
Browse files Browse the repository at this point in the history
Signed-off-by: reggie <[email protected]>
  • Loading branch information
reggie-k committed Sep 29, 2023
1 parent ab9c29c commit db3f2dd
Show file tree
Hide file tree
Showing 26 changed files with 1,805 additions and 1,018 deletions.
6 changes: 4 additions & 2 deletions ui/src/app/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as React from 'react';
import {Helmet} from 'react-helmet';
import {Redirect, Route, RouteComponentProps, Router, Switch} from 'react-router';
import applications from './applications';
// import applicationsets from './applicationsets';
import help from './help';
import login from './login';
import settings from './settings';
Expand All @@ -30,6 +31,7 @@ type Routes = {[path: string]: {component: React.ComponentType<RouteComponentPro
const routes: Routes = {
'/login': {component: login.component as any, noLayout: true},
'/applications': {component: applications.component},
'/applicationsets': {component: applications.component},
'/settings': {component: settings.component},
'/user-info': {component: userInfo.component},
'/help': {component: help.component}
Expand All @@ -49,9 +51,9 @@ const navItems: NavItem[] = [
path: '/applications',
iconClassName: 'argo-icon argo-icon-application'
},
{
{
title: 'Settings',
tooltip: 'Manage your repositories, projects, settings',
tooltip: 'Manage your repositories, projects, settings, application sets',
path: '/settings',
iconClassName: 'argo-icon argo-icon-settings'
},
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as React from 'react';
import {Checkbox} from 'argo-ui/v2';
import {ApplicationTree, HealthStatusCode, HealthStatuses, SyncStatusCode, SyncStatuses} from '../../../shared/models';
import {AppDetailsPreferences, services} from '../../../shared/services';
import {AppDetailsPreferences, AppSetDetailsPreferences, services} from '../../../shared/services';
import {Context} from '../../../shared/context';
import {Filter, FiltersGroup} from '../filter/filter';
import {ComparisonStatusIcon, HealthStatusIcon} from '../utils';
Expand All @@ -14,17 +14,25 @@ function toOption(label: string) {
return {label};
}

export interface FiltersProps {
export interface AbstractFiltersProps {
children?: React.ReactNode;
pref: AppDetailsPreferences;
pref: AppDetailsPreferences | AppSetDetailsPreferences;
tree: ApplicationTree;
resourceNodes: models.ResourceStatus[];
onSetFilter: (items: string[]) => void;
onClearFilter: () => void;
collapsed?: boolean;
}

export const Filters = (props: FiltersProps) => {
export interface FiltersProps extends AbstractFiltersProps{
pref: AppDetailsPreferences;
}

export interface AppSetFiltersProps extends AbstractFiltersProps{
pref: AppSetDetailsPreferences;
}

export const Filters = (props: AbstractFiltersProps) => {
const ctx = React.useContext(Context);

const {pref, tree, onSetFilter} = props;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const ApplicationResourceList = ({
return null;
}
const parentNode = ((resources || []).length > 0 && (getResNode(tree.nodes, nodeKey(resources[0])) as ResourceNode)?.parentRefs?.[0]) || ({} as ResourceRef);
// debugger;

return (
<div>
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import {HelpIcon} from 'argo-ui';
import { HelpIcon } from 'argo-ui';
import * as React from 'react';
import {ARGO_GRAY6_COLOR, DataLoader} from '../../../shared/components';
import {Revision} from '../../../shared/components/revision';
import {Timestamp} from '../../../shared/components/timestamp';
import { ARGO_GRAY6_COLOR, DataLoader } from '../../../shared/components';
import { Revision } from '../../../shared/components/revision';
import { Timestamp } from '../../../shared/components/timestamp';
import * as models from '../../../shared/models';
import {services} from '../../../shared/services';
import {ApplicationSyncWindowStatusIcon, ComparisonStatusIcon, getAppDefaultSource, getAppOperationState} from '../utils';
import {getConditionCategory, HealthStatusIcon, OperationState, syncStatusMessage, helpTip} from '../utils';
import {RevisionMetadataPanel} from './revision-metadata-panel';
import { services } from '../../../shared/services';
import { AppSetHealthStatusIcon, ApplicationSyncWindowStatusIcon, ComparisonStatusIcon, getAppDefaultSource, getAppOperationState, getAppSetHealthStatus, isApp } from '../utils';
import { getConditionCategory, HealthStatusIcon, OperationState, syncStatusMessage, helpTip } from '../utils';
import { RevisionMetadataPanel } from './revision-metadata-panel';

import './application-status-panel.scss';

interface Props {
application: models.Application;
application: models.AbstractApplication;
showDiff?: () => any;
showOperation?: () => any;
showConditions?: () => any;
Expand All @@ -25,15 +25,15 @@ interface SectionInfo {
}

const sectionLabel = (info: SectionInfo) => (
<label style={{fontSize: '12px', fontWeight: 600, color: ARGO_GRAY6_COLOR}}>
<label style={{ fontSize: '12px', fontWeight: 600, color: ARGO_GRAY6_COLOR }}>
{info.title}
{info.helpContent && <HelpIcon title={info.helpContent} />}
</label>
);

const sectionHeader = (info: SectionInfo, hasMultipleSources: boolean, onClick?: () => any) => {
return (
<div style={{display: 'flex', alignItems: 'center', marginBottom: '0.5em'}}>
<div style={{ display: 'flex', alignItems: 'center', marginBottom: '0.5em' }}>
{sectionLabel(info)}
{onClick && (
<button className='application-status-panel__more-button' onClick={onClick} disabled={hasMultipleSources}>
Expand All @@ -45,80 +45,98 @@ const sectionHeader = (info: SectionInfo, hasMultipleSources: boolean, onClick?:
);
};

export const ApplicationStatusPanel = ({application, showDiff, showOperation, showConditions, showMetadataInfo}: Props) => {
const today = new Date();

export const ApplicationStatusPanel = ({ application, showDiff, showOperation, showConditions, showMetadataInfo }: Props) => {
let cntByCategory;
let hasMultipleSources;
let source;
let appOperationState: models.OperationState;
let daysSinceLastSynchronized = 0;
const history = application.status.history || [];
if (history.length > 0) {
const deployDate = new Date(history[history.length - 1].deployedAt);
daysSinceLastSynchronized = Math.round(Math.abs((today.getTime() - deployDate.getTime()) / (24 * 60 * 60 * 1000)));

if (isApp) {
const today = new Date();

const history = application.status.history || [];
if (history.length > 0) {
const deployDate = new Date(history[history.length - 1].deployedAt);
daysSinceLastSynchronized = Math.round(Math.abs((today.getTime() - deployDate.getTime()) / (24 * 60 * 60 * 1000)));
}
cntByCategory = ((application as models.Application).status.conditions || []).reduce(
(map, next) => map.set(getConditionCategory(next), (map.get(getConditionCategory(next)) || 0) + 1),
new Map<string, number>()
);
appOperationState = getAppOperationState(application);
if (application.metadata.deletionTimestamp && !appOperationState) {
showOperation = null;
}
hasMultipleSources = (application as models.Application).spec.sources && (application as models.Application).spec.sources.length > 0;
source = getAppDefaultSource((application as models.Application));

}
const cntByCategory = (application.status.conditions || []).reduce(
(map, next) => map.set(getConditionCategory(next), (map.get(getConditionCategory(next)) || 0) + 1),
new Map<string, number>()
);
const appOperationState = getAppOperationState(application);
if (application.metadata.deletionTimestamp && !appOperationState) {
showOperation = null;
else {
cntByCategory = ((application as models.ApplicationSet).status.conditions || []).reduce(
(map, next) => map.set(getConditionCategory(next), (map.get(getConditionCategory(next)) || 0) + 1),
new Map<string, number>()
);
}

const infos = cntByCategory.get('info');
const warnings = cntByCategory.get('warning');
const errors = cntByCategory.get('error');
const source = getAppDefaultSource(application);
const hasMultipleSources = application.spec.sources && application.spec.sources.length > 0;


return (
<div className='application-status-panel row'>
<div className='application-status-panel__item'>
<div style={{lineHeight: '19.5px', marginBottom: '0.3em'}}>{sectionLabel({title: 'APP HEALTH', helpContent: 'The health status of your app'})}</div>
<div style={{ lineHeight: '19.5px', marginBottom: '0.3em' }}>{sectionLabel({ title: 'APP HEALTH', helpContent: 'The health status of your app' })}</div>
<div className='application-status-panel__item-value'>
<HealthStatusIcon state={application.status.health} />
{isApp(application) && <HealthStatusIcon state={(application as models.Application).status.health} />}
{!isApp(application) && <AppSetHealthStatusIcon state={(application as models.ApplicationSet).status} />}
&nbsp;
{application.status.health.status}
{isApp(application) ? (application as models.Application).status.health.status : getAppSetHealthStatus((application as models.ApplicationSet).status)}
</div>
{application.status.health.message && <div className='application-status-panel__item-name'>{application.status.health.message}</div>}
{isApp(application) && (application as models.Application).status.health.message && <div className='application-status-panel__item-name'>{(application as models.Application).status.health.message}</div>}
{!isApp(application) && (application as models.ApplicationSet).status.conditions[0].message && <div className='application-status-panel__item-name'>{(application as models.ApplicationSet).status.conditions[0].message}</div>}
</div>
<div className='application-status-panel__item'>
{isApp(application) && <div className='application-status-panel__item'>
<React.Fragment>
{sectionHeader(
{
title: 'SYNC STATUS',
helpContent: 'Whether or not the version of your app is up to date with your repo. You may wish to sync your app if it is out-of-sync.'
},
hasMultipleSources,
() => showMetadataInfo(application.status.sync ? application.status.sync.revision : '')
() => showMetadataInfo((application as models.Application).status.sync ? (application as models.Application).status.sync.revision : '')
)}
{appOperationState && (
<div className={`application-status-panel__item-value application-status-panel__item-value--${appOperationState.phase}`}>
<div>
{application.status.sync.status === models.SyncStatuses.OutOfSync ? (
{(application as models.Application).status.sync.status === models.SyncStatuses.OutOfSync ? (
<a onClick={() => showDiff && showDiff()}>
<ComparisonStatusIcon status={application.status.sync.status} label={true} />
<ComparisonStatusIcon status={(application as models.Application).status.sync.status} label={true} />
</a>
) : (
<ComparisonStatusIcon status={application.status.sync.status} label={true} />
<ComparisonStatusIcon status={(application as models.Application).status.sync.status} label={true} />
)}
</div>
<div className='application-status-panel__item-value__revision show-for-large'>{syncStatusMessage(application)}</div>
</div>
)}
<div className='application-status-panel__item-name' style={{marginBottom: '0.5em'}}>
{application.spec.syncPolicy?.automated ? 'Auto sync is enabled.' : 'Auto sync is not enabled.'}
<div className='application-status-panel__item-name' style={{ marginBottom: '0.5em' }}>
{(application as models.Application).spec.syncPolicy?.automated ? 'Auto sync is enabled.' : 'Auto sync is not enabled.'}
</div>
{application.status && application.status.sync && application.status.sync.revision && !application.spec.source.chart && (
{(application as models.Application).status && (application as models.Application).status.sync && (application as models.Application).status.sync.revision && !(application as models.Application).spec.source.chart && (
<div className='application-status-panel__item-name'>
<RevisionMetadataPanel
appName={application.metadata.name}
appNamespace={application.metadata.namespace}
type={source.chart && 'helm'}
revision={application.status.sync.revision}
type={source && source.chart && 'helm'}
revision={(application as models.Application).status.sync.revision}
/>
</div>
)}
</React.Fragment>
</div>
{appOperationState && (
</div> }
{isApp(application) && appOperationState && (
<div className='application-status-panel__item'>
<React.Fragment>
{sectionHeader(
Expand All @@ -143,7 +161,7 @@ export const ApplicationStatusPanel = ({application, showDiff, showOperation, sh
)}
</div>

<div className='application-status-panel__item-name' style={{marginBottom: '0.5em'}}>
<div className='application-status-panel__item-name' style={{ marginBottom: '0.5em' }}>
{appOperationState.phase} <Timestamp date={appOperationState.finishedAt || appOperationState.startedAt} />
</div>
{(appOperationState.syncResult && appOperationState.syncResult.revision && (
Expand All @@ -159,7 +177,7 @@ export const ApplicationStatusPanel = ({application, showDiff, showOperation, sh
)}
{application.status.conditions && (
<div className={`application-status-panel__item`}>
{sectionLabel({title: 'APP CONDITIONS'})}
{sectionLabel({ title: 'APP CONDITIONS' })}
<div className='application-status-panel__item-value application-status-panel__conditions' onClick={() => showConditions && showConditions()}>
{infos && (
<a className='info'>
Expand All @@ -179,7 +197,7 @@ export const ApplicationStatusPanel = ({application, showDiff, showOperation, sh
</div>
</div>
)}
<DataLoader
{isApp(application) && <DataLoader
noLoaderOnInputChange={true}
input={application}
load={async app => {
Expand All @@ -188,7 +206,7 @@ export const ApplicationStatusPanel = ({application, showDiff, showOperation, sh
{(data: models.ApplicationSyncWindowState) => (
<React.Fragment>
{data.assignedWindows && (
<div className='application-status-panel__item' style={{position: 'relative'}}>
<div className='application-status-panel__item' style={{ position: 'relative' }}>
{sectionLabel({
title: 'SYNC WINDOWS',
helpContent:
Expand All @@ -197,14 +215,14 @@ export const ApplicationStatusPanel = ({application, showDiff, showOperation, sh
'Yellow: manual syncs allowed. ' +
'Green: all syncs allowed'
})}
<div className='application-status-panel__item-value' style={{margin: 'auto 0'}}>
<div className='application-status-panel__item-value' style={{ margin: 'auto 0' }}>
<ApplicationSyncWindowStatusIcon project={application.spec.project} state={data} />
</div>
</div>
)}
</React.Fragment>
)}
</DataLoader>
</DataLoader> }
</div>
);
};
3 changes: 3 additions & 0 deletions ui/src/app/applications/components/applications-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {Route, RouteComponentProps, Switch} from 'react-router';
import {ApplicationDetails} from './application-details/application-details';
import {ApplicationFullscreenLogs} from './application-fullscreen-logs/application-fullscreen-logs';
import {ApplicationsList} from './applications-list/applications-list';
// import {ApplicationSetsList, ApplicationsList} from './applications-list/applications-list';

export const ApplicationsContainer = (props: RouteComponentProps<any>) => (
<Switch>
Expand All @@ -11,5 +12,7 @@ export const ApplicationsContainer = (props: RouteComponentProps<any>) => (
<Route exact={true} path={`${props.match.path}/:appnamespace/:name`} component={ApplicationDetails} />
<Route exact={true} path={`${props.match.path}/:name/:namespace/:container/logs`} component={ApplicationFullscreenLogs} />
<Route exact={true} path={`${props.match.path}/:appnamespace/:name/:namespace/:container/logs`} component={ApplicationFullscreenLogs} />

{/* <Route exact={true} path={`${props.match.path}`} component={ApplicationSetsList} /> */}
</Switch>
);
Loading

0 comments on commit db3f2dd

Please sign in to comment.