diff --git a/ui/src/app/shared/components/links.test.ts b/ui/src/app/shared/components/links.test.ts index f33be645b827..384de4c21b71 100644 --- a/ui/src/app/shared/components/links.test.ts +++ b/ui/src/app/shared/components/links.test.ts @@ -1,4 +1,4 @@ -import {ProcessURL} from './links'; +import {processURL} from './links'; describe('process URL', () => { test('original timestamp', () => { @@ -8,7 +8,7 @@ describe('process URL', () => { finishedAt: '2021-01-01T10:30:00Z' } }; - expect(ProcessURL('https://logging?from=${status.startedAt}&to=${status.finishedAt}', object)).toBe('https://logging?from=2021-01-01T10:30:00Z&to=2021-01-01T10:30:00Z'); + expect(processURL('https://logging?from=${status.startedAt}&to=${status.finishedAt}', object)).toBe('https://logging?from=2021-01-01T10:30:00Z&to=2021-01-01T10:30:00Z'); }); test('epoch timestamp', () => { @@ -18,7 +18,7 @@ describe('process URL', () => { finishedAt: '2021-01-01T10:30:00Z' } }; - expect(ProcessURL('https://logging?from=${status.startedAtEpoch}&to=${status.finishedAtEpoch}', object)).toBe('https://logging?from=1609497000000&to=1609497000000'); + expect(processURL('https://logging?from=${status.startedAtEpoch}&to=${status.finishedAtEpoch}', object)).toBe('https://logging?from=1609497000000&to=1609497000000'); }); test('epoch timestamp with ongoing workflow', () => { @@ -31,7 +31,7 @@ describe('process URL', () => { const expectedDate = new Date('2021-03-01T10:30:00.00Z'); jest.spyOn(global.Date, 'now').mockImplementationOnce(() => expectedDate.valueOf()); - expect(ProcessURL('https://logging?from=${status.startedAtEpoch}&to=${status.finishedAtEpoch}', object)).toBe( + expect(processURL('https://logging?from=${status.startedAtEpoch}&to=${status.finishedAtEpoch}', object)).toBe( `https://logging?from=1609497000000&to=${expectedDate.getTime()}` ); }); @@ -41,7 +41,7 @@ describe('process URL', () => { status: {} }; - expect(ProcessURL('https://logging?from=${status.startedAtEpoch}&to=${status.finishedAtEpoch}', object)).toBe(`https://logging?from=null&to=null`); + expect(processURL('https://logging?from=${status.startedAtEpoch}&to=${status.finishedAtEpoch}', object)).toBe(`https://logging?from=null&to=null`); }); test('ignore missing workflow var', () => { @@ -54,6 +54,6 @@ describe('process URL', () => { } }; - expect(ProcessURL('https://logging?${workflow.annotations.logQuery}${workflow.annotations.additionalLogParams}', object)).toBe('https://logging?query=env:qa'); + expect(processURL('https://logging?${workflow.annotations.logQuery}${workflow.annotations.additionalLogParams}', object)).toBe('https://logging?query=env:qa'); }); }); diff --git a/ui/src/app/shared/components/links.tsx b/ui/src/app/shared/components/links.tsx index a2bc8216a2af..ed4ae6154a67 100644 --- a/ui/src/app/shared/components/links.tsx +++ b/ui/src/app/shared/components/links.tsx @@ -5,35 +5,44 @@ import {Link, Workflow} from '../../../models'; import {services} from '../services'; import {Button} from './button'; -const addEpochTimestamp = (jsonObject: {metadata: ObjectMeta; workflow?: Workflow; status?: any}) => { +function toEpoch(datetime: string) { + if (datetime) { + return new Date(datetime).getTime(); + } else { + return Date.now(); + } +} + +function addEpochTimestamp(jsonObject: {metadata: ObjectMeta; workflow?: Workflow; status?: any}) { if (jsonObject === undefined || jsonObject.status.startedAt === undefined) { return; } - const toEpoch = (datetime: string) => { - if (datetime) { - return new Date(datetime).getTime(); - } else { - return Date.now(); - } - }; jsonObject.status.startedAtEpoch = toEpoch(jsonObject.status.startedAt); jsonObject.status.finishedAtEpoch = toEpoch(jsonObject.status.finishedAt); -}; +} -export const ProcessURL = (url: string, jsonObject: any) => { +export function processURL(urlExpression: string, jsonObject: any) { addEpochTimestamp(jsonObject); /* replace ${} from input url with corresponding elements from object only return null for known variables, otherwise empty string*/ - return url.replace(/\${[^}]*}/g, x => { + return urlExpression.replace(/\${[^}]*}/g, x => { const parts = x.replace(/(\$%7B|%7D|\${|})/g, '').split('.'); const emptyVal = parts[0] === 'workflow' ? '' : null; const res = parts.reduce((p: any, c: string) => (p && p[c]) || emptyVal, jsonObject); return res; }); -}; +} + +export function openLinkWithKey(url: string) { + if ((window.event as MouseEvent).ctrlKey || (window.event as MouseEvent).metaKey) { + window.open(url, '_blank'); + } else { + document.location.href = url; + } +} -export const Links = ({scope, object, button}: {scope: string; object: {metadata: ObjectMeta; workflow?: Workflow; status?: any}; button?: boolean}) => { +export function Links({scope, object, button}: {scope: string; object: {metadata: ObjectMeta; workflow?: Workflow; status?: any}; button?: boolean}) { const [links, setLinks] = useState(); const [error, setError] = useState(); @@ -45,18 +54,6 @@ export const Links = ({scope, object, button}: {scope: string; object: {metadata .catch(setError); }, []); - const formatUrl = (url: string) => { - return ProcessURL(url, object); - }; - - const openLink = (url: string) => { - if ((window.event as MouseEvent).ctrlKey || (window.event as MouseEvent).metaKey) { - window.open(url, '_blank'); - } else { - document.location.href = url; - } - }; - return ( <> {error && error.message} @@ -64,17 +61,17 @@ export const Links = ({scope, object, button}: {scope: string; object: {metadata links.map(({url, name}) => { if (button) { return ( - ); } return ( - + {name} ); })} ); -}; +} diff --git a/ui/src/app/workflows/components/workflow-details/workflow-details.tsx b/ui/src/app/workflows/components/workflow-details/workflow-details.tsx index 57ddfc8e4495..a4b05885d414 100644 --- a/ui/src/app/workflows/components/workflow-details/workflow-details.tsx +++ b/ui/src/app/workflows/components/workflow-details/workflow-details.tsx @@ -9,7 +9,7 @@ import {artifactRepoHasLocation, findArtifact} from '../../../shared/artifacts'; import {uiUrl} from '../../../shared/base'; import {CostOptimisationNudge} from '../../../shared/components/cost-optimisation-nudge'; import {ErrorNotice} from '../../../shared/components/error-notice'; -import {ProcessURL} from '../../../shared/components/links'; +import {openLinkWithKey, processURL} from '../../../shared/components/links'; import {Loading} from '../../../shared/components/loading'; import {SecurityNudge} from '../../../shared/components/security-nudge'; import {useCollectEvent} from '../../../shared/components/use-collect-event'; @@ -440,13 +440,7 @@ export function WorkflowDetails({history, location, match}: RouteComponentProps< finishedAt: workflow.status.finishedAt } }; - const url = ProcessURL(link.url, object); - - if ((window.event as MouseEvent).ctrlKey || (window.event as MouseEvent).metaKey) { - window.open(url, '_blank'); - } else { - document.location.href = url; - } + openLinkWithKey(processURL(link.url, object)); } function setParameter(key: string, value: string) {