diff --git a/packages/oss-console/src/components/Executions/ExecutionDetails/ExecutionLabels.tsx b/packages/oss-console/src/components/Executions/ExecutionDetails/ExecutionLabels.tsx new file mode 100644 index 000000000..3586909aa --- /dev/null +++ b/packages/oss-console/src/components/Executions/ExecutionDetails/ExecutionLabels.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import Chip from '@mui/material/Chip'; +import makeStyles from '@mui/styles/makeStyles'; + +type ValuesType = {[p: string]: string}; +interface Props { + values: ValuesType; +} + +const useStyles = makeStyles({ + chipContainer: { + display: 'flex', + flexWrap: 'wrap', + width: '100%', + maxWidth: '420px' + }, + chip: { + margin: '2px 2px 2px 0', + }, +}); + + +export const ExecutionLabels: React.FC = ({values}) => { + const classes = useStyles(); + return ( +
+ {Object.entries(values).map(([key, value]) => ( + + ))} +
+ ); +}; diff --git a/packages/oss-console/src/components/Executions/ExecutionDetails/ExecutionMetadata.tsx b/packages/oss-console/src/components/Executions/ExecutionDetails/ExecutionMetadata.tsx index 86c4db73d..1552677c6 100644 --- a/packages/oss-console/src/components/Executions/ExecutionDetails/ExecutionMetadata.tsx +++ b/packages/oss-console/src/components/Executions/ExecutionDetails/ExecutionMetadata.tsx @@ -14,6 +14,7 @@ import { ExecutionContext } from '../contexts'; import { ExpandableExecutionError } from '../Tables/ExpandableExecutionError'; import { ExecutionMetadataLabels } from './constants'; import { ExecutionMetadataExtra } from './ExecutionMetadataExtra'; +import { ExecutionLabels } from './ExecutionLabels'; const StyledContainer = styled('div')(({ theme }) => { return { @@ -69,6 +70,7 @@ export const ExecutionMetadata: React.FC<{}> = () => { const startedAt = execution?.closure?.startedAt; const workflowId = execution?.closure?.workflowId; + const { labels } = execution.spec; const { referenceExecution, systemMetadata , @@ -118,9 +120,19 @@ export const ExecutionMetadata: React.FC<{}> = () => { + > {parentNodeExecution.executionId.name} + ), + }); + } + + if (labels != null && labels.values != null) { + details.push({ + label: ExecutionMetadataLabels.labels, + value: ( + Object.entries(labels.values).length > 0 ? + : dashedValueString ) }) } diff --git a/packages/oss-console/src/components/Executions/ExecutionDetails/constants.ts b/packages/oss-console/src/components/Executions/ExecutionDetails/constants.ts index 42e00c893..d38a0b045 100644 --- a/packages/oss-console/src/components/Executions/ExecutionDetails/constants.ts +++ b/packages/oss-console/src/components/Executions/ExecutionDetails/constants.ts @@ -13,6 +13,7 @@ export enum ExecutionMetadataLabels { interruptible = 'Interruptible override', overwriteCache = 'Overwrite cached outputs', parent = 'Parent', + labels = 'Labels', } export const tabs = { diff --git a/packages/oss-console/src/components/Executions/ExecutionDetails/test/ExecutionLabels.test.tsx b/packages/oss-console/src/components/Executions/ExecutionDetails/test/ExecutionLabels.test.tsx new file mode 100644 index 000000000..0bc9f5d3e --- /dev/null +++ b/packages/oss-console/src/components/Executions/ExecutionDetails/test/ExecutionLabels.test.tsx @@ -0,0 +1,51 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import '@testing-library/jest-dom'; +import { ExecutionLabels } from '../ExecutionLabels'; + +jest.mock('@mui/material/Chip', () => (props: any) => ( +
{props.label}
+)); + +describe('ExecutionLabels', () => { + it('renders chips with key-value pairs correctly', () => { + const values = { + 'random/uuid': 'f8b9ff18-4811-4bcc-aefd-4f4ec4de469d', + 'bar': 'baz', + 'foo': '', + }; + + render(); + + expect(screen.getByText('random/uuid: f8b9ff18-4811-4bcc-aefd-4f4ec4de469d')).toBeInTheDocument(); + expect(screen.getByText('bar: baz')).toBeInTheDocument(); + expect(screen.getByText('foo')).toBeInTheDocument(); + }); + + it('applies correct styles to chip container', () => { + const values = { + 'key': 'value', + }; + + const { container } = render(); + const chipContainer = container.firstChild; + + expect(chipContainer).toHaveStyle('display: flex'); + expect(chipContainer).toHaveStyle('flex-wrap: wrap'); + expect(chipContainer).toHaveStyle('width: 100%'); + expect(chipContainer).toHaveStyle('max-width: 420px'); + }); + + it('renders correct number of chips', () => { + const values = { + 'key1': 'value1', + 'key2': 'value2', + 'key3': 'value3', + }; + + render(); + + const chips = screen.getAllByTestId('chip'); + expect(chips.length).toBe(3); + }); +}); diff --git a/packages/oss-console/src/components/Executions/ExecutionDetails/test/ExecutionMetadata.test.tsx b/packages/oss-console/src/components/Executions/ExecutionDetails/test/ExecutionMetadata.test.tsx index d20a94190..782ac2b35 100644 --- a/packages/oss-console/src/components/Executions/ExecutionDetails/test/ExecutionMetadata.test.tsx +++ b/packages/oss-console/src/components/Executions/ExecutionDetails/test/ExecutionMetadata.test.tsx @@ -16,6 +16,7 @@ const interruptibleTestId = `metadata-${ExecutionMetadataLabels.interruptible}`; const overwriteCacheTestId = `metadata-${ExecutionMetadataLabels.overwriteCache}`; const relatedToTestId = `metadata-${ExecutionMetadataLabels.relatedTo}`; const parentNodeExecutionTestId = `metadata-${ExecutionMetadataLabels.parent}` +const labelsTestId = `metadata-${ExecutionMetadataLabels.labels}`; jest.mock('../../../../models/Launch/api', () => ({ getLaunchPlan: jest.fn(() => Promise.resolve({ spec: {} })), @@ -118,4 +119,9 @@ describe('ExecutionMetadata', () => { const { getByTestId } = renderMetadata(); expect(getByTestId(parentNodeExecutionTestId)).toHaveTextContent('name'); }) + + it('shows labels if spec has them', () => { + const { getByTestId } = renderMetadata(); + expect(getByTestId(labelsTestId)).toHaveTextContent("key: value"); + }) }); diff --git a/packages/oss-console/src/models/__mocks__/executionsData.ts b/packages/oss-console/src/models/__mocks__/executionsData.ts index a7ee4af1f..90727193e 100644 --- a/packages/oss-console/src/models/__mocks__/executionsData.ts +++ b/packages/oss-console/src/models/__mocks__/executionsData.ts @@ -100,6 +100,11 @@ export const createMockExecutionSpec: () => ExecutionSpec = () => ({ launchPlan: { ...MOCK_LAUNCH_PLAN_ID }, notifications: { notifications: [] }, metadata: generateExecutionMetadata(), + labels: { + values: { + "key": "value" + } + } }); export const createMockExecution: (id?: string | number) => Execution = (id = 1) => {