From c4ddb7c5098a39f3089b52d25dc161ad99f4a5b5 Mon Sep 17 00:00:00 2001 From: Bat-Zion Rotman Date: Wed, 29 Nov 2023 20:03:25 +0200 Subject: [PATCH] chore(orchestrator): implement the WorkflowViewerFormatter (#41) * chore: implement the WorkflowViewerFormatter: utility for converting WorkflowOverview backend data to data UI can display * removed redundant export and removed redundant 'Interface' suffix from DataFormatter interface name * Update plugins/orchestrator/src/dataFormatters/DataFormatter.ts Co-authored-by: Guilherme Caponetto <638737+caponetto@users.noreply.github.com> --------- Co-authored-by: Guilherme Caponetto <638737+caponetto@users.noreply.github.com> --- .../src/dataFormatters/DataFormatter.ts | 5 ++ .../WorkflowOverviewFormatter.test.ts | 51 ++++++++++++++ .../WorkflowOverviewFormatter.ts | 70 +++++++++++++++++++ 3 files changed, 126 insertions(+) create mode 100644 plugins/orchestrator/src/dataFormatters/DataFormatter.ts create mode 100644 plugins/orchestrator/src/dataFormatters/WorkflowOverviewFormatter.test.ts create mode 100644 plugins/orchestrator/src/dataFormatters/WorkflowOverviewFormatter.ts diff --git a/plugins/orchestrator/src/dataFormatters/DataFormatter.ts b/plugins/orchestrator/src/dataFormatters/DataFormatter.ts new file mode 100644 index 0000000000..71c39fe58a --- /dev/null +++ b/plugins/orchestrator/src/dataFormatters/DataFormatter.ts @@ -0,0 +1,5 @@ +interface DataFormatter { + format(data: Data): FormattedData; +} + +export default DataFormatter; diff --git a/plugins/orchestrator/src/dataFormatters/WorkflowOverviewFormatter.test.ts b/plugins/orchestrator/src/dataFormatters/WorkflowOverviewFormatter.test.ts new file mode 100644 index 0000000000..ac9bc75880 --- /dev/null +++ b/plugins/orchestrator/src/dataFormatters/WorkflowOverviewFormatter.test.ts @@ -0,0 +1,51 @@ +import { WorkflowOverview } from '@janus-idp/backstage-plugin-orchestrator-common'; + +import WorkflowOverviewFormatter, { + FormattedWorkflowOverview, +} from './WorkflowOverviewFormatter'; + +describe('WorkflowOverviewAdapter', () => { + it('should adapt WorkflowOverview to AdaptedWorkflowOverview', () => { + // Mock data for testing + const mockWorkflowOverview: WorkflowOverview = { + workflowId: '123', + name: 'Sample Workflow', + lastTriggeredMs: 1697276096000, + lastRunStatus: 'Success', + type: 'Sample Type', + avgDurationMs: 150000, + description: 'Sample description', + uri: 'sample.workflow.sw.yaml', + }; + + const adaptedData: FormattedWorkflowOverview = + WorkflowOverviewFormatter.format(mockWorkflowOverview); + + expect(adaptedData.id).toBe(mockWorkflowOverview.workflowId); + expect(adaptedData.name).toBe(mockWorkflowOverview.name); + expect(adaptedData.lastTriggered).toBe('14/10/23 09:34:56'); + expect(adaptedData.lastRunStatus).toBe(mockWorkflowOverview.lastRunStatus); + expect(adaptedData.type).toBe(mockWorkflowOverview.type); + expect(adaptedData.avgDuration).toBe('2 min'); + expect(adaptedData.description).toBe(mockWorkflowOverview.description); + expect(adaptedData.format).toBe('yaml'); // Adjust based on your expected value + }); + + it('should have --- for undefined data', () => { + // Mock data for testing + const mockWorkflowOverview: WorkflowOverview = { + workflowId: '123', + }; + const adaptedData: FormattedWorkflowOverview = + WorkflowOverviewFormatter.format(mockWorkflowOverview); + + expect(adaptedData.id).toBe(mockWorkflowOverview.workflowId); + expect(adaptedData.name).toBe('---'); + expect(adaptedData.lastTriggered).toBe('---'); + expect(adaptedData.lastRunStatus).toBe('---'); + expect(adaptedData.type).toBe('---'); + expect(adaptedData.avgDuration).toBe('---'); + expect(adaptedData.description).toBe('---'); + expect(adaptedData.format).toBe('yaml'); + }); +}); diff --git a/plugins/orchestrator/src/dataFormatters/WorkflowOverviewFormatter.ts b/plugins/orchestrator/src/dataFormatters/WorkflowOverviewFormatter.ts new file mode 100644 index 0000000000..c65b650764 --- /dev/null +++ b/plugins/orchestrator/src/dataFormatters/WorkflowOverviewFormatter.ts @@ -0,0 +1,70 @@ +import moment from 'moment'; + +import { + extractWorkflowFormatFromUri, + WorkflowFormat, + WorkflowOverview, +} from '@janus-idp/backstage-plugin-orchestrator-common'; + +import DataFormatter from './DataFormatter'; + +const UNAVAILABLE = '---'; + +export interface FormattedWorkflowOverview { + id: string; + name: string; + lastTriggered: string; + lastRunStatus: string; + type: string; + avgDuration: string; + description: string; + format: WorkflowFormat; +} + +const formatDuration = (milliseconds: number): string => { + let sec = Math.round(milliseconds / 1000); + let min = 0; + let hr = 0; + if (sec >= 60) { + min = Math.floor(sec / 60); + sec %= 60; + } + if (min >= 60) { + hr = Math.floor(min / 60); + min %= 60; + } + if (hr > 0) { + return `${hr} h`; + } + if (min > 0) { + return `${min} min`; + } + if (sec > 0) { + return `${sec} sec`; + } + return 'less than a sec'; +}; + +const WorkflowOverviewFormatter: DataFormatter< + WorkflowOverview, + FormattedWorkflowOverview +> = { + format: (data: WorkflowOverview): FormattedWorkflowOverview => { + return { + id: data.workflowId, + name: data.name || UNAVAILABLE, + lastTriggered: data.lastTriggeredMs + ? moment(data.lastTriggeredMs).format('DD/MM/YY HH:mm:ss') + : UNAVAILABLE, + lastRunStatus: data.lastRunStatus || UNAVAILABLE, + type: data.type || UNAVAILABLE, + avgDuration: data.avgDurationMs + ? formatDuration(data.avgDurationMs) + : UNAVAILABLE, + description: data.description || UNAVAILABLE, + format: data.uri ? extractWorkflowFormatFromUri(data.uri) : 'yaml', + }; + }, +}; + +export default WorkflowOverviewFormatter;