Skip to content

Commit

Permalink
feat(ui): Add start/end workflows ISO display switch (argoproj#13284)
Browse files Browse the repository at this point in the history
Signed-off-by: Adrien Delannoy <[email protected]>
  • Loading branch information
Adrien-D committed Sep 17, 2024
1 parent 464965c commit 22b2cb8
Show file tree
Hide file tree
Showing 16 changed files with 358 additions and 159 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ import {ErrorNotice} from '../../../shared/components/error-notice';
import {Loading} from '../../../shared/components/loading';
import {PaginationPanel} from '../../../shared/components/pagination-panel';
import {PhaseIcon} from '../../../shared/components/phase-icon';
import {Timestamp} from '../../../shared/components/timestamp';
import {Timestamp, TimestampSwitch} from '../../../shared/components/timestamp';
import {ZeroState} from '../../../shared/components/zero-state';
import {formatDuration, wfDuration} from '../../../shared/duration';
import {Pagination, parseLimit} from '../../../shared/pagination';
import {ScopedLocalStorage} from '../../../shared/scoped-local-storage';
import {services} from '../../../shared/services';
import {TIMESTAMP_KEYS} from '../../../shared/use-timestamp';
import {Utils} from '../../../shared/utils';
import {ArchivedWorkflowFilters} from '../archived-workflow-filters/archived-workflow-filters';

Expand All @@ -29,6 +30,8 @@ interface BrowserStorageOptions {
maxStartedAt?: Date;
error?: Error;
deep: boolean;
storedDisplayISOFormatStart: boolean;
storedDisplayISOFormatFinished: boolean;
}

interface State extends BrowserStorageOptions {
Expand All @@ -39,10 +42,12 @@ const defaultPaginationLimit = 10;

export class ArchivedWorkflowList extends BasePage<RouteComponentProps<any>, State> {
private storage: ScopedLocalStorage;
private timestampStorage: ScopedLocalStorage;

constructor(props: RouteComponentProps<any>, context: any) {
super(props, context);
this.storage = new ScopedLocalStorage('ArchiveListOptions');
this.timestampStorage = new ScopedLocalStorage('Timestamp');
const savedOptions = this.storage.getItem('options', {
pagination: {limit: defaultPaginationLimit},
selectedPhases: [],
Expand All @@ -59,7 +64,9 @@ export class ArchivedWorkflowList extends BasePage<RouteComponentProps<any>, Sta
selectedLabels: labelQueryParam.length > 0 ? labelQueryParam : savedOptions.selectedLabels,
minStartedAt: this.parseTime(this.queryParam('minStartedAt')) || this.lastMonth(),
maxStartedAt: this.parseTime(this.queryParam('maxStartedAt')) || this.nextDay(),
deep: this.queryParam('deep') === 'true'
deep: this.queryParam('deep') === 'true',
storedDisplayISOFormatStart: this.timestampStorage.getItem(`displayISOFormat-${TIMESTAMP_KEYS.WORKFLOWS_ARCHIVED_ROW_STARTED}`, false),
storedDisplayISOFormatFinished: this.timestampStorage.getItem(`displayISOFormat-${TIMESTAMP_KEYS.WORKFLOWS_ARCHIVED_ROW_FINISHED}`, false)
};
}

Expand Down Expand Up @@ -242,6 +249,16 @@ export class ArchivedWorkflowList extends BasePage<RouteComponentProps<any>, Sta
.catch(error => this.setState({error}));
}

private setStoredDisplayISOFormatStart = (value: boolean) => {
this.setState({storedDisplayISOFormatStart: value});
this.timestampStorage.setItem(`displayISOFormat-${TIMESTAMP_KEYS.WORKFLOWS_ARCHIVED_ROW_STARTED}`, value, false);
};

private setStoredDisplayISOFormatFinished = (value: boolean) => {
this.setState({storedDisplayISOFormatFinished: value});
this.timestampStorage.setItem(`displayISOFormat-${TIMESTAMP_KEYS.WORKFLOWS_ARCHIVED_ROW_FINISHED}`, value, false);
};

private renderWorkflows() {
if (this.state.error) {
return <ErrorNotice error={this.state.error} />;
Expand All @@ -266,8 +283,17 @@ export class ArchivedWorkflowList extends BasePage<RouteComponentProps<any>, Sta
<div className='columns small-1' />
<div className='columns small-3'>NAME</div>
<div className='columns small-2'>NAMESPACE</div>
<div className='columns small-2'>STARTED</div>
<div className='columns small-2'>FINISHED</div>
<div className='columns small-2'>
STARTED{' '}
<TimestampSwitch storedDisplayISOFormat={this.state.storedDisplayISOFormatStart} setStoredDisplayISOFormat={this.setStoredDisplayISOFormatStart} />
</div>
<div className='columns small-2'>
FINISHED{' '}
<TimestampSwitch
storedDisplayISOFormat={this.state.storedDisplayISOFormatFinished}
setStoredDisplayISOFormat={this.setStoredDisplayISOFormatFinished}
/>
</div>
<div className='columns small-2'>DURATION</div>
</div>
{this.state.workflows.map(w => (
Expand All @@ -278,10 +304,10 @@ export class ArchivedWorkflowList extends BasePage<RouteComponentProps<any>, Sta
<div className='columns small-3'>{w.metadata.name}</div>
<div className='columns small-2'>{w.metadata.namespace}</div>
<div className='columns small-2'>
<Timestamp date={w.status.startedAt} />
<Timestamp date={w.status.startedAt} displayISOFormat={this.state.storedDisplayISOFormatStart} />
</div>
<div className='columns small-2'>
<Timestamp date={w.status.finishedAt} />
<Timestamp date={w.status.finishedAt} displayISOFormat={this.state.storedDisplayISOFormatFinished} />
</div>
<div className='columns small-2'>{formatDuration(wfDuration(w.status))}</div>
</Link>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,18 @@ import {ExampleManifests} from '../../../shared/components/example-manifests';
import {InfoIcon} from '../../../shared/components/fa-icons';
import {Loading} from '../../../shared/components/loading';
import {Timestamp} from '../../../shared/components/timestamp';
import {TimestampSwitch} from '../../../shared/components/timestamp';
import {ZeroState} from '../../../shared/components/zero-state';
import {Context} from '../../../shared/context';
import {useQueryParams} from '../../../shared/use-query-params';

import {Footnote} from '../../../shared/footnote';
import {services} from '../../../shared/services';
import useTimestamp, {TIMESTAMP_KEYS} from '../../../shared/use-timestamp';
import {ClusterWorkflowTemplateCreator} from '../cluster-workflow-template-creator';
require('./cluster-workflow-template-list.scss');

export const ClusterWorkflowTemplateList = ({history, location}: RouteComponentProps<any>) => {
export function ClusterWorkflowTemplateList({history, location}: RouteComponentProps<any>) {
const {navigation} = useContext(Context);
const queryParams = new URLSearchParams(location.search);
const [templates, setTemplates] = useState<models.ClusterWorkflowTemplate[]>();
Expand All @@ -45,6 +47,8 @@ export const ClusterWorkflowTemplateList = ({history, location}: RouteComponentP
services.info.collectEvent('openedClusterWorkflowTemplateList').then();
}, []);

const [storedDisplayISOFormat, setStoredDisplayISOFormat] = useTimestamp(TIMESTAMP_KEYS.CLUSTER_WORKFLOW_TEMPLATE_LIST);

const renderTemplates = () => {
if (error) {
return <ErrorNotice error={error} />;
Expand All @@ -69,7 +73,9 @@ export const ClusterWorkflowTemplateList = ({history, location}: RouteComponentP
<div className='row argo-table-list__head'>
<div className='columns small-1' />
<div className='columns small-5'>NAME</div>
<div className='columns small-3'>CREATED</div>
<div className='columns small-3'>
CREATED <TimestampSwitch storedDisplayISOFormat={storedDisplayISOFormat} setStoredDisplayISOFormat={setStoredDisplayISOFormat} />
</div>
</div>
{templates.map(t => (
<Link className='row argo-table-list__row' key={t.metadata.uid} to={uiUrl(`cluster-workflow-templates/${t.metadata.name}`)}>
Expand All @@ -78,7 +84,7 @@ export const ClusterWorkflowTemplateList = ({history, location}: RouteComponentP
</div>
<div className='columns small-5'>{t.metadata.name}</div>
<div className='columns small-3'>
<Timestamp date={t.metadata.creationTimestamp} />
<Timestamp date={t.metadata.creationTimestamp} displayISOFormat={storedDisplayISOFormat} />
</div>
</Link>
))}
Expand Down Expand Up @@ -111,4 +117,4 @@ export const ClusterWorkflowTemplateList = ({history, location}: RouteComponentP
</SlidingPanel>
</Page>
);
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {ErrorNotice} from '../../../shared/components/error-notice';
import {ExampleManifests} from '../../../shared/components/example-manifests';
import {InfoIcon} from '../../../shared/components/fa-icons';
import {Loading} from '../../../shared/components/loading';
import {Timestamp} from '../../../shared/components/timestamp';
import {Timestamp, TimestampSwitch} from '../../../shared/components/timestamp';
import {useCollectEvent} from '../../../shared/components/use-collect-event';
import {ZeroState} from '../../../shared/components/zero-state';
import {Context} from '../../../shared/context';
Expand All @@ -17,6 +17,7 @@ import {Footnote} from '../../../shared/footnote';
import {historyUrl} from '../../../shared/history';
import {services} from '../../../shared/services';
import {useQueryParams} from '../../../shared/use-query-params';
import useTimestamp, {TIMESTAMP_KEYS} from '../../../shared/use-timestamp';
import {Utils} from '../../../shared/utils';
import {CronWorkflowCreator} from '../cron-workflow-creator';
import {CronWorkflowFilters} from '../cron-workflow-filters/cron-workflow-filters';
Expand All @@ -37,6 +38,9 @@ export const CronWorkflowList = ({match, location, history}: RouteComponentProps
const [labels, setLabels] = useState([]);
const [states, setStates] = useState(['Running', 'Suspended']); // check all by default

const [storedDisplayISOFormatCreation, setStoredDisplayISOFormatCreation] = useTimestamp(TIMESTAMP_KEYS.CRON_WORKFLOW_LIST_CREATION);
const [storedDisplayISOFormatNextScheduled, setStoredDisplayISOFormatNextScheduled] = useTimestamp(TIMESTAMP_KEYS.CRON_WORKFLOW_LIST_NEXT_SCHEDULED);

useEffect(
useQueryParams(history, p => {
setSidePanel(p.get('sidePanel') === 'true');
Expand Down Expand Up @@ -129,33 +133,49 @@ export const CronWorkflowList = ({match, location, history}: RouteComponentProps
<div className='argo-table-list'>
<div className='row argo-table-list__head'>
<div className='columns small-1' />
<div className='columns small-3'>NAME</div>
<div className='columns small-2'>NAME</div>
<div className='columns small-2'>NAMESPACE</div>
<div className='columns small-1'>SCHEDULE</div>
<div className='columns small-3' />
<div className='columns small-1'>CREATED</div>
<div className='columns small-1'>NEXT RUN</div>
<div className='columns small-1' />
<div className='columns small-2'>
CREATED{' '}
<TimestampSwitch storedDisplayISOFormat={storedDisplayISOFormatCreation} setStoredDisplayISOFormat={setStoredDisplayISOFormatCreation} />
</div>
<div className='columns small-2'>
NEXT RUN{' '}
<TimestampSwitch
storedDisplayISOFormat={storedDisplayISOFormatNextScheduled}
setStoredDisplayISOFormat={setStoredDisplayISOFormatNextScheduled}
/>
</div>
</div>
{cronWorkflows.map(w => (
<Link
className='row argo-table-list__row'
key={`${w.metadata.namespace}/${w.metadata.name}`}
to={uiUrl(`cron-workflows/${w.metadata.namespace}/${w.metadata.name}`)}>
<div className='columns small-1'>{w.spec.suspend ? <i className='fa fa-pause' /> : <i className='fa fa-clock' />}</div>
<div className='columns small-3'>{w.metadata.name}</div>
<div className='columns small-2'>{w.metadata.name}</div>
<div className='columns small-2'>{w.metadata.namespace}</div>
<div className='columns small-1'>{w.spec.schedule}</div>
<div className='columns small-3'>
<div className='columns small-1'>
<PrettySchedule schedule={w.spec.schedule} />
</div>
<div className='columns small-1'>
<Timestamp date={w.metadata.creationTimestamp} />
<div className='columns small-2'>
<Timestamp date={w.metadata.creationTimestamp} displayISOFormat={storedDisplayISOFormatCreation} />
</div>
<div className='columns small-1'>
<div className='columns small-2'>
{w.spec.suspend ? (
''
) : (
<Ticker intervalMs={1000}>{() => <Timestamp date={getNextScheduledTime(w.spec.schedule, w.spec.timezone)} />}</Ticker>
<Ticker intervalMs={1000}>
{() => (
<Timestamp
date={getNextScheduledTime(w.spec.schedule, w.spec.timezone)}
displayISOFormat={storedDisplayISOFormatNextScheduled}
/>
)}
</Ticker>
)}
</div>
</Link>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as React from 'react';
import {CronWorkflowSpec, CronWorkflowStatus} from '../../../models';
import {Timestamp} from '../../shared/components/timestamp';
import {ConditionsPanel} from '../../shared/conditions-panel';
import {TIMESTAMP_KEYS} from '../../shared/use-timestamp';
import {WorkflowLink} from '../../workflows/components/workflow-link';
import {PrettySchedule} from './pretty-schedule';

Expand All @@ -23,7 +24,7 @@ export const CronWorkflowStatusViewer = ({spec, status}: {spec: CronWorkflowSpec
</>
)
},
{title: 'Last Scheduled Time', value: <Timestamp date={status.lastScheduledTime} />},
{title: 'Last Scheduled Time', value: <Timestamp date={status.lastScheduledTime} timestampKey={TIMESTAMP_KEYS.CRON_WORKFLOW_STATUS_LAST_SCHEDULED} />},
{title: 'Conditions', value: <ConditionsPanel conditions={status.conditions} />}
].map(attr => (
<div className='row white-box__details-row' key={attr.title}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ import {ErrorNotice} from '../../../shared/components/error-notice';
import {Node} from '../../../shared/components/graph/types';
import {Loading} from '../../../shared/components/loading';
import {NamespaceFilter} from '../../../shared/components/namespace-filter';
import {Timestamp} from '../../../shared/components/timestamp';
import {Timestamp, TimestampSwitch} from '../../../shared/components/timestamp';
import {useCollectEvent} from '../../../shared/components/use-collect-event';
import {ZeroState} from '../../../shared/components/zero-state';
import {Context} from '../../../shared/context';
import {Footnote} from '../../../shared/footnote';
import {historyUrl} from '../../../shared/history';
import {services} from '../../../shared/services';
import {useQueryParams} from '../../../shared/use-query-params';
import useTimestamp, {TIMESTAMP_KEYS} from '../../../shared/use-timestamp';
import {Utils} from '../../../shared/utils';
import {EventsPanel} from '../../../workflows/components/events-panel';
import {EventSourceCreator} from '../event-source-creator';
Expand Down Expand Up @@ -85,6 +86,8 @@ export const EventSourceList = ({match, location, history}: RouteComponentProps<

useCollectEvent('openedEventSourceList');

const [storedDisplayISOFormat, setStoredDisplayISOFormat] = useTimestamp(TIMESTAMP_KEYS.EVENT_SOURCE_LIST_CREATION);

return (
<Page
title='EventSources'
Expand Down Expand Up @@ -123,7 +126,9 @@ export const EventSourceList = ({match, location, history}: RouteComponentProps<
<div className='columns small-1' />
<div className='columns small-4'>NAME</div>
<div className='columns small-3'>NAMESPACE</div>
<div className='columns small-2'>CREATED</div>
<div className='columns small-2'>
CREATED <TimestampSwitch storedDisplayISOFormat={storedDisplayISOFormat} setStoredDisplayISOFormat={setStoredDisplayISOFormat} />
</div>
<div className='columns small-2'>LOGS</div>
</div>
{eventSources.map(es => (
Expand All @@ -137,7 +142,7 @@ export const EventSourceList = ({match, location, history}: RouteComponentProps<
<div className='columns small-4'>{es.metadata.name}</div>
<div className='columns small-3'>{es.metadata.namespace}</div>
<div className='columns small-2'>
<Timestamp date={es.metadata.creationTimestamp} />
<Timestamp date={es.metadata.creationTimestamp} displayISOFormat={storedDisplayISOFormat} />
</div>
<div className='columns small-2'>
<div
Expand Down
Loading

0 comments on commit 22b2cb8

Please sign in to comment.