From 0063754ef3420593cf923951895608902418d0ab Mon Sep 17 00:00:00 2001 From: Yasser Elsayed Date: Wed, 7 Nov 2018 00:28:31 -0800 Subject: [PATCH] refactor run list to reuse DisplayRun computation code, tests --- frontend/src/pages/RunList.test.tsx | 349 +- frontend/src/pages/RunList.tsx | 245 +- .../pages/__snapshots__/RunList.test.tsx.snap | 6961 ++++++++++++++++- 3 files changed, 7328 insertions(+), 227 deletions(-) diff --git a/frontend/src/pages/RunList.test.tsx b/frontend/src/pages/RunList.test.tsx index 35593b6949c..6a853097bfe 100644 --- a/frontend/src/pages/RunList.test.tsx +++ b/frontend/src/pages/RunList.test.tsx @@ -16,13 +16,22 @@ import * as React from 'react'; import RunList, { RunListProps } from './RunList'; -import { Apis } from '../lib/Apis'; +import TestUtils from '../TestUtils'; +import produce from 'immer'; +import { ApiRun, ApiRunDetail, ApiResourceType, ApiRunMetric, RunMetricFormat } from '../apis/run'; +import { Apis, RunSortKeys } from '../lib/Apis'; +import { MetricMetadata } from 'src/lib/RunUtils'; +import { NodePhase } from './Status'; +import { range } from 'lodash'; import { shallow } from 'enzyme'; -import { ApiRun, ApiRunDetail, ApiResourceType } from '../apis/run'; -jest.mock('../lib/Apis'); describe('RunList', () => { const onErrorSpy = jest.fn(); + const listRunsMock = jest.spyOn(Apis.runServiceApi, 'listRuns'); + const getRunMock = jest.spyOn(Apis.runServiceApi, 'getRun'); + const getPipelineMock = jest.spyOn(Apis.pipelineServiceApi, 'getPipeline'); + const getExperimentMock = jest.spyOn(Apis.experimentServiceApi, 'getExperiment'); + function generateProps(): RunListProps { return { history: {} as any, @@ -32,27 +41,41 @@ describe('RunList', () => { }; } + function mockNRuns(n: number, runTemplate: Partial) { + getRunMock.mockImplementation(id => Promise.resolve( + produce(runTemplate, draft => { + draft.pipeline_runtime = draft.pipeline_runtime || { workflow_manifest: '' }; + draft.run = draft.run || {}; + draft.run.id = id; + draft.run.name = 'run with id: ' + id; + }) + )); + + listRunsMock.mockImplementation(() => Promise.resolve({ + runs: range(1, n + 1).map(i => ({ + id: 'testrun' + i, + name: 'run with id: testrun' + i, + } as ApiRun)), + })); + + getPipelineMock.mockImplementation(() => ({ name: 'some pipeline' })); + getExperimentMock.mockImplementation(() => ({ name: 'some experiment' })); + } + beforeEach(() => { onErrorSpy.mockClear(); + listRunsMock.mockClear(); + getRunMock.mockClear(); + getPipelineMock.mockClear(); + getExperimentMock.mockClear(); }); it('renders the empty experience', () => { expect(shallow()).toMatchSnapshot(); }); - it('loads all runs', async () => { - (Apis as any).runServiceApi = { - getRun: () => Promise.resolve({ - pipeline_runtime: { workflow_manifest: '' }, - run: {}, - } as ApiRunDetail), - listRuns: jest.fn(() => Promise.resolve({ - runs: [{ - id: 'testrun1', - name: 'test run1', - } as ApiRun], - })), - }; + it('loads one run', async () => { + mockNRuns(1, {}); const props = generateProps(); const tree = shallow(); await (tree.instance() as any)._loadRuns({}); @@ -61,32 +84,59 @@ describe('RunList', () => { expect(tree).toMatchSnapshot(); }); - it('calls error callback when loading runs fails', async () => { - (Apis as any).runServiceApi = { - getRun: jest.fn(), - listRuns: () => Promise.reject('bad stuff'), - }; + it('reloads the run when refresh is called', async () => { + mockNRuns(0, {}); + const props = generateProps(); + const tree = TestUtils.mountWithRouter(); + await (tree.instance() as RunList).refresh(); + expect(Apis.runServiceApi.listRuns).toHaveBeenLastCalledWith('', 10, RunSortKeys.CREATED_AT + ' desc', undefined, undefined); + expect(props.onError).not.toHaveBeenCalled(); + expect(tree).toMatchSnapshot(); + }); + + it('loads multiple run', async () => { + mockNRuns(5, {}); const props = generateProps(); const tree = shallow(); await (tree.instance() as any)._loadRuns({}); - expect(props.onError).toHaveBeenLastCalledWith('Error: failed to fetch runs.', 'bad stuff'); + expect(props.onError).not.toHaveBeenCalled(); + expect(tree).toMatchSnapshot(); }); - // TODO: Add tests for displaying associated Pipeline. + it('calls error callback when loading runs fails', async () => { + TestUtils.makeErrorResponseOnce(jest.spyOn(Apis.runServiceApi, 'listRuns'), 'bad stuff happened'); + const props = generateProps(); + const tree = shallow(); + await (tree.instance() as any)._loadRuns({}); + expect(props.onError).toHaveBeenLastCalledWith('Error: failed to fetch runs.', new Error('bad stuff happened')); + }); it('displays error in run row if it failed to parse', async () => { - (Apis as any).runServiceApi = { - getRun: jest.fn(() => Promise.resolve({ - pipeline_runtime: { workflow_manifest: 'bad json' }, - run: {}, - })), - listRuns: () => Promise.resolve({ - runs: [{ - id: 'testrun1', - name: 'test run1', - } as ApiRun], - }), - }; + mockNRuns(1, { pipeline_runtime: { workflow_manifest: 'bad json' } }); + const props = generateProps(); + const tree = shallow(); + await (tree.instance() as any)._loadRuns({}); + expect(tree).toMatchSnapshot(); + }); + + it('displays error in run row if pipeline could not be fetched', async () => { + mockNRuns(1, { run: { pipeline_spec: { pipeline_id: 'test-pipeline-id' } } }); + TestUtils.makeErrorResponseOnce(getPipelineMock, 'bad stuff happened'); + const props = generateProps(); + const tree = shallow(); + await (tree.instance() as any)._loadRuns({}); + expect(tree).toMatchSnapshot(); + }); + + it('displays error in run row if experiment could not be fetched', async () => { + mockNRuns(1, { + run: { + resource_references: [{ + key: { id: 'test-experiment-id', type: ApiResourceType.EXPERIMENT } + }] + } + }); + TestUtils.makeErrorResponseOnce(getExperimentMock, 'bad stuff happened'); const props = generateProps(); const tree = shallow(); await (tree.instance() as any)._loadRuns({}); @@ -94,43 +144,26 @@ describe('RunList', () => { }); it('displays error in run row if it failed to parse (run list mask)', async () => { - const listRunsSpy = jest.fn(); - const getRunSpy = jest.fn(() => Promise.resolve({ - pipeline_runtime: { workflow_manifest: '' }, - run: {}, - } as ApiRunDetail)); - (Apis as any).runServiceApi = { - getRun: getRunSpy, - listRuns: listRunsSpy, - }; + mockNRuns(2, { pipeline_runtime: { workflow_manifest: 'bad json' } }); const props = generateProps(); - props.runIdListMask = ['run1', 'run2']; + props.runIdListMask = ['testrun1', 'testrun2']; const tree = shallow(); await (tree.instance() as any)._loadRuns({}); expect(tree).toMatchSnapshot(); }); it('shows run time for each run', async () => { - (Apis as any).runServiceApi = { - getRun: () => Promise.resolve({ - pipeline_runtime: { - workflow_manifest: JSON.stringify({ - status: { - finishedAt: new Date(2018, 10, 10, 11, 11, 11), - phase: 'Succeeded', - startedAt: new Date(2018, 10, 10, 10, 10, 10), - } - }), - }, - run: {}, - } as ApiRunDetail), - listRuns: () => Promise.resolve({ - runs: [{ - id: 'testrun1', - name: 'test run1', - } as ApiRun], - }), - }; + mockNRuns(1, { + pipeline_runtime: { + workflow_manifest: JSON.stringify({ + status: { + finishedAt: new Date(2018, 10, 10, 11, 11, 11), + phase: 'Succeeded', + startedAt: new Date(2018, 10, 10, 10, 10, 10), + } + }), + }, + }); const props = generateProps(); const tree = shallow(); await (tree.instance() as any)._loadRuns({}); @@ -139,43 +172,181 @@ describe('RunList', () => { }); it('loads runs for a given experiment id', async () => { - (Apis as any).runServiceApi = { - getRun: () => Promise.resolve({ - pipeline_runtime: { workflow_manifest: '' }, - run: {}, - } as ApiRunDetail), - listRuns: jest.fn(() => Promise.resolve({ - runs: [{ id: 'testRun1' }], - })), - }; + mockNRuns(1, {}); const props = generateProps(); props.experimentIdMask = 'experiment1'; const tree = shallow(); - await (tree.instance() as any)._loadRuns({ pageSize: 10, pageToken: '', orderAscending: true }); + await (tree.instance() as any)._loadRuns({}); expect(props.onError).not.toHaveBeenCalled(); expect(Apis.runServiceApi.listRuns).toHaveBeenLastCalledWith( - '', 10, undefined, ApiResourceType.EXPERIMENT.toString(), 'experiment1'); - expect(tree).toMatchSnapshot(); + undefined, undefined, undefined, ApiResourceType.EXPERIMENT.toString(), 'experiment1'); }); it('loads given list of runs only', async () => { - const listRunsSpy = jest.fn(); - const getRunSpy = jest.fn(() => Promise.resolve({ - pipeline_runtime: { workflow_manifest: '' }, - run: {}, - } as ApiRunDetail)); - (Apis as any).runServiceApi = { - getRun: getRunSpy, - listRuns: listRunsSpy, - }; + mockNRuns(5, {}); const props = generateProps(); props.runIdListMask = ['run1', 'run2']; const tree = shallow(); await (tree.instance() as any)._loadRuns({}); expect(props.onError).not.toHaveBeenCalled(); - expect(listRunsSpy).not.toHaveBeenCalled(); - expect(getRunSpy).toHaveBeenCalledWith('run1'); - expect(getRunSpy).toHaveBeenCalledWith('run2'); + expect(Apis.runServiceApi.listRuns).not.toHaveBeenCalled(); + expect(Apis.runServiceApi.getRun).toHaveBeenCalledTimes(2); + expect(Apis.runServiceApi.getRun).toHaveBeenCalledWith('run1'); + expect(Apis.runServiceApi.getRun).toHaveBeenCalledWith('run2'); + }); + + it('adds metrics columns', async () => { + mockNRuns(2, { + pipeline_runtime: { + workflow_manifest: JSON.stringify({ + status: { + phase: 'Succeeded', + } + }), + }, + run: { + metrics: [ + { name: 'metric1', number_value: 5 }, + { name: 'metric2', number_value: 10 }, + ], + } + }); + const props = generateProps(); + const tree = shallow(); + await (tree.instance() as any)._loadRuns({}); + expect(props.onError).not.toHaveBeenCalled(); + expect(tree).toMatchSnapshot(); + }); + + it('shows pipeline name', async () => { + mockNRuns(1, { run: { pipeline_spec: { pipeline_id: 'test-pipeline-id' } } }); + getPipelineMock.mockImplementationOnce(() => ({ name: 'test pipeline' })); + const props = generateProps(); + const tree = shallow(); + await (tree.instance() as any)._loadRuns({}); + expect(props.onError).not.toHaveBeenCalled(); + expect(tree).toMatchSnapshot(); + }); + + it('shows experiment name', async () => { + mockNRuns(1, { + run: { + resource_references: [{ + key: { id: 'test-experiment-id', type: ApiResourceType.EXPERIMENT } + }] + } + }); + getExperimentMock.mockImplementationOnce(() => { + return ({ name: 'test experiment' }); + }); + const props = generateProps(); + const tree = shallow(); + await (tree.instance() as any)._loadRuns({}); + expect(props.onError).not.toHaveBeenCalled(); + expect(tree).toMatchSnapshot(); + }); + + it('renders run name as link to its details page', () => { + const tree = TestUtils.mountWithRouter((RunList.prototype as any) + ._nameCustomRenderer('test run', 'run-id')); + expect(tree).toMatchSnapshot(); + }); + + it('renders pipeline name as link to its details page', () => { + const tree = TestUtils.mountWithRouter((RunList.prototype as any) + ._pipelineCustomRenderer({ displayName: 'test pipeline', id: 'pipeline-id' })); + expect(tree).toMatchSnapshot(); + }); + + it('renders no pipeline name', () => { + const tree = TestUtils.mountWithRouter((RunList.prototype as any) + ._pipelineCustomRenderer()); + expect(tree).toMatchSnapshot(); + }); + + it('renders experiment name as link to its details page', () => { + const tree = TestUtils.mountWithRouter((RunList.prototype as any) + ._experimentCustomRenderer({ displayName: 'test experiment', id: 'experiment-id' })); + expect(tree).toMatchSnapshot(); + }); + + it('renders no experiment name', () => { + const tree = TestUtils.mountWithRouter((RunList.prototype as any) + ._experimentCustomRenderer()); + expect(tree).toMatchSnapshot(); + }); + + it('renders status as icon', () => { + const tree = shallow((RunList.prototype as any)._statusCustomRenderer(NodePhase.SUCCEEDED)); + expect(tree).toMatchSnapshot(); + }); + + it('renders metric buffer', () => { + const tree = shallow((RunList.prototype as any)._metricBufferCustomRenderer()); + expect(tree).toMatchSnapshot(); + }); + + it('renders an empty metric when there is no data', () => { + const noMetricTree = shallow((RunList.prototype as any)._metricCustomRenderer()); + expect(noMetricTree).toMatchSnapshot(); + + const emptyMetricTree = shallow((RunList.prototype as any)._metricCustomRenderer({})); + expect(emptyMetricTree).toMatchSnapshot(); + + const noMetricValueTree = shallow((RunList.prototype as any)._metricCustomRenderer({ metric: {} })); + expect(noMetricValueTree).toMatchSnapshot(); + }); + + it('renders a empty metric container when a metric has value of zero', () => { + const noMetricTree = shallow((RunList.prototype as any)._metricCustomRenderer( + { metric: { number_value: 0 } })); + expect(noMetricTree).toMatchSnapshot(); + }); + + it('renders percentage metric', () => { + const tree = shallow((RunList.prototype as any)._metricCustomRenderer( + { metric: { number_value: 0.3, format: RunMetricFormat.PERCENTAGE } as ApiRunMetric })); + expect(tree).toMatchSnapshot(); + }); + + it('renders raw metric', () => { + const tree = shallow((RunList.prototype as any)._metricCustomRenderer( + { + metadata: { count: 1, maxValue: 100, minValue: 10 } as MetricMetadata, + metric: { number_value: 55 } as ApiRunMetric, + })); + expect(tree).toMatchSnapshot(); + }); + + it('renders raw metric with zero max/min values', () => { + const tree = shallow((RunList.prototype as any)._metricCustomRenderer( + { + metadata: { count: 1, maxValue: 0, minValue: 0 } as MetricMetadata, + metric: { number_value: 15 } as ApiRunMetric, + })); + expect(tree).toMatchSnapshot(); + }); + + it('renders raw metric that is less than its min value', () => { + const consoleSpy = jest.spyOn(console, 'error').mockImplementation(); + const tree = shallow((RunList.prototype as any)._metricCustomRenderer( + { + metadata: { count: 1, maxValue: 100, minValue: 10 } as MetricMetadata, + metric: { number_value: 5 } as ApiRunMetric, + })); + expect(tree).toMatchSnapshot(); + expect(consoleSpy).toHaveBeenCalled(); + }); + + it('renders raw metric that is greater than its max value', () => { + const consoleSpy = jest.spyOn(console, 'error').mockImplementation(); + const tree = shallow((RunList.prototype as any)._metricCustomRenderer( + { + metadata: { count: 1, maxValue: 100, minValue: 10 } as MetricMetadata, + metric: { number_value: 105 } as ApiRunMetric, + })); + expect(tree).toMatchSnapshot(); + expect(consoleSpy).toHaveBeenCalled(); }); }); diff --git a/frontend/src/pages/RunList.tsx b/frontend/src/pages/RunList.tsx index 8bf0d9f82c8..8e369f7e22d 100644 --- a/frontend/src/pages/RunList.tsx +++ b/frontend/src/pages/RunList.tsx @@ -17,7 +17,7 @@ import * as React from 'react'; import CustomTable, { Column, Row } from '../components/CustomTable'; import RunUtils, { MetricMetadata } from '../../src/lib/RunUtils'; -import { ApiListRunsResponse, ApiRunDetail, ApiRun, ApiResourceType, RunMetricFormat, ApiRunMetric } from '../../src/apis/run'; +import { ApiRunDetail, ApiRun, ApiResourceType, RunMetricFormat, ApiRunMetric } from '../../src/apis/run'; import { Apis, RunSortKeys, ListRequest } from '../lib/Apis'; import { Link, RouteComponentProps } from 'react-router-dom'; import { NodePhase, statusToIcon } from './Status'; @@ -30,6 +30,7 @@ import { stylesheet } from 'typestyle'; const css = stylesheet({ metricContainer: { background: '#f6f7f9', + marginLeft: 6, marginRight: 10, }, metricFill: { @@ -38,6 +39,7 @@ const css = stylesheet({ color: '#202124', fontFamily: 'Roboto', fontSize: 13, + textIndent: 6, }, }); @@ -174,126 +176,62 @@ class RunList extends React.Component { } } - private _metricBufferCustomRenderer(): JSX.Element { - return
; - } - - private _metricCustomRenderer(displayMetric: DisplayMetric): JSX.Element { - if (!displayMetric.metric || !displayMetric.metric.number_value) { - return
; - } + private async _loadRuns(request: ListRequest): Promise { + let displayRuns: DisplayRun[] = []; + let nextPageToken = ''; - const leftSpace = 6; - let displayString = ''; - let width = ''; - - if (displayMetric.metric.format === RunMetricFormat.PERCENTAGE) { - displayString = (displayMetric.metric.number_value * 100).toFixed(3) + '%'; - width = `calc(${displayString})`; + if (Array.isArray(this.props.runIdListMask)) { + displayRuns = this.props.runIdListMask.map(id => ({ metadata: { id } })); } else { - displayString = displayMetric.metric.number_value.toFixed(3); - - if (displayMetric.metadata.maxValue === 0 && displayMetric.metadata.minValue === 0) { - return
{displayString}
; - } - - if (displayMetric.metric.number_value - displayMetric.metadata.minValue < 0) { - logger.error(`Run ${arguments[1]}'s metric ${displayMetric.metadata.name}'s value:` - + ` ${displayMetric.metric.number_value}) was lower than the supposed minimum of` - + ` ${displayMetric.metadata.minValue})`); - return
{displayString}
; - } - - if (displayMetric.metadata.maxValue - displayMetric.metric.number_value < 0) { - logger.error(`Run ${arguments[1]}'s metric ${displayMetric.metadata.name}'s value:` - + ` ${displayMetric.metric.number_value}) was greater than the supposed maximum of` - + ` ${displayMetric.metadata.maxValue})`); - return
{displayString}
; + // Load all runs + try { + const response = await Apis.runServiceApi.listRuns( + request.pageToken, + request.pageSize, + request.sortBy, + this.props.experimentIdMask ? ApiResourceType.EXPERIMENT.toString() : undefined, + this.props.experimentIdMask, + ); + + displayRuns = (response.runs || []).map(r => ({ metadata: r })); + nextPageToken = response.next_page_token || ''; + } catch (err) { + const error = new Error(await errorToMessage(err)); + this.props.onError('Error: failed to fetch runs.', error); + // No point in continuing if we couldn't retrieve any runs. + return ''; } - - const barWidth = - (displayMetric.metric.number_value - displayMetric.metadata.minValue) - / (displayMetric.metadata.maxValue - displayMetric.metadata.minValue) - * 100; - - width = `calc(${barWidth}%)`; } - return ( -
-
- {displayString} -
-
- ); - } - private async _loadRuns(loadRequest: ListRequest): Promise { - if (Array.isArray(this.props.runIdListMask)) { - return await this._loadSpecificRuns(this.props.runIdListMask); - } - return await this._loadAllRuns(loadRequest); - } + await this._getAndSetMetadataAndWorkflows(displayRuns); + await this._getAndSetPipelineNames(displayRuns); + await this._getAndSetExperimentNames(displayRuns); - private async _loadSpecificRuns(runIdListMask: string[]): Promise { - await Promise.all(runIdListMask.map(async id => await Apis.runServiceApi.getRun(id))) - .then(async (result) => { - const displayRuns: DisplayRun[] = result.map(r => ({ - metadata: r.run!, - workflow: JSON.parse(r.pipeline_runtime!.workflow_manifest || '{}'), - })); - - await this._getAndSetPipelineNames(displayRuns); - await this._getAndSetExperimentNames(displayRuns); - - this.setState({ - metrics: RunUtils.extractMetricMetadata(displayRuns), - runs: displayRuns, - }); - }) - .catch((err) => this.props.onError('Error: failed to fetch runs.', err)); - return ''; + this.setState({ + metrics: RunUtils.extractMetricMetadata(displayRuns.map(r => r.metadata)), + runs: displayRuns, + }); + return nextPageToken; } - private async _loadAllRuns(request: ListRequest): Promise { - let response: ApiListRunsResponse; - try { - response = await Apis.runServiceApi.listRuns( - request.pageToken, - request.pageSize, - request.sortBy, - this.props.experimentIdMask ? ApiResourceType.EXPERIMENT.toString() : undefined, - this.props.experimentIdMask, - ); - } catch (err) { - this.props.onError('Error: failed to fetch runs.', err); - // No point in continuing if we couldn't retrieve any runs. - return ''; - } - - const displayRuns: DisplayRun[] = (response.runs || []).map(r => ({ metadata: r })); - + /** + * For each DisplayRun, get its workflow spec and parse it into an object + */ + private _getAndSetMetadataAndWorkflows(displayRuns: DisplayRun[]): Promise { // Fetch and set the workflow details - await Promise.all(displayRuns.map(async displayRun => { + return Promise.all(displayRuns.map(async displayRun => { let getRunResponse: ApiRunDetail; try { getRunResponse = await Apis.runServiceApi.getRun(displayRun.metadata!.id!); + displayRun.metadata = getRunResponse.run!; displayRun.workflow = JSON.parse(getRunResponse.pipeline_runtime!.workflow_manifest || '{}'); } catch (err) { // This could be an API exception, or a JSON parse exception. displayRun.error = await errorToMessage(err); } + return displayRun; })); - - await this._getAndSetPipelineNames(displayRuns); - await this._getAndSetExperimentNames(displayRuns); - - this.setState({ - metrics: RunUtils.extractMetricMetadata(displayRuns), - runs: displayRuns, - }); - - return response.next_page_token || ''; } /** @@ -301,8 +239,8 @@ class RunList extends React.Component { * use that Pipeline ID to fetch its associated Pipeline and attach that Pipeline's name to the * DisplayRun. If the ApiRun has no Pipeline ID, then the corresponding DisplayRun will show '-'. */ - private async _getAndSetPipelineNames(displayRuns: DisplayRun[]): Promise { - return await Promise.all( + private _getAndSetPipelineNames(displayRuns: DisplayRun[]): Promise { + return Promise.all( displayRuns.map(async (displayRun) => { const pipelineId = RunUtils.getPipelineId(displayRun.metadata); if (pipelineId) { @@ -311,7 +249,7 @@ class RunList extends React.Component { displayRun.pipeline = { displayName: pipeline.name || '', id: pipelineId }; } catch (err) { // This could be an API exception, or a JSON parse exception. - displayRun.error = await errorToMessage(err); + displayRun.error = 'Failed to get associated pipeline: ' + await errorToMessage(err); } } return displayRun; @@ -319,27 +257,14 @@ class RunList extends React.Component { ); } - private _pipelineCustomRenderer(pipelineInfo?: PipelineInfo): JSX.Element { - // If the getPipeline call failed or a run has no pipeline, we display a placeholder. - if (!pipelineInfo || !pipelineInfo.id) { - return
-
; - } - return ( - e.stopPropagation()} - to={RoutePage.PIPELINE_DETAILS.replace(':' + RouteParams.pipelineId, pipelineInfo.id)}> - {pipelineInfo.displayName} - - ); - } - /** * For each DisplayRun, get its ApiRun and retrieve that ApiRun's Experiment ID if it has one, * then use that Experiment ID to fetch its associated Experiment and attach that Experiment's * name to the DisplayRun. If the ApiRun has no Experiment ID, then the corresponding DisplayRun * will show '-'. */ - private async _getAndSetExperimentNames(displayRuns: DisplayRun[]): Promise { - return await Promise.all( + private _getAndSetExperimentNames(displayRuns: DisplayRun[]): Promise { + return Promise.all( displayRuns.map(async (displayRun) => { const experimentId = RunUtils.getFirstExperimentReferenceId(displayRun.metadata); if (experimentId) { @@ -351,7 +276,7 @@ class RunList extends React.Component { displayRun.experiment = { displayName: experiment.name || '', id: experimentId }; } catch (err) { // This could be an API exception, or a JSON parse exception. - displayRun.error = await errorToMessage(err); + displayRun.error = 'Failed to get associated experiment: ' + await errorToMessage(err); } } return displayRun; @@ -359,6 +284,24 @@ class RunList extends React.Component { ); } + private _nameCustomRenderer(value: string, id: string): JSX.Element { + return e.stopPropagation()} + to={RoutePage.RUN_DETAILS.replace(':' + RouteParams.runId, id)}>{value}; + } + + private _pipelineCustomRenderer(pipelineInfo?: PipelineInfo): JSX.Element { + // If the getPipeline call failed or a run has no pipeline, we display a placeholder. + if (!pipelineInfo || !pipelineInfo.id) { + return
-
; + } + return ( + e.stopPropagation()} + to={RoutePage.PIPELINE_DETAILS.replace(':' + RouteParams.pipelineId, pipelineInfo.id)}> + {pipelineInfo.displayName} + + ); + } + private _experimentCustomRenderer(experimentInfo?: ExperimentInfo): JSX.Element { // If the getExperiment call failed or a run has no experiment, we display a placeholder. if (!experimentInfo || !experimentInfo.id) { @@ -372,14 +315,64 @@ class RunList extends React.Component { ); } - private _nameCustomRenderer(value: string, id: string): JSX.Element { - return e.stopPropagation()} - to={RoutePage.RUN_DETAILS.replace(':' + RouteParams.runId, id)}>{value}; - } - private _statusCustomRenderer(status: NodePhase): JSX.Element { return statusToIcon(status); } + + private _metricBufferCustomRenderer(): JSX.Element { + return
; + } + + private _metricCustomRenderer(displayMetric: DisplayMetric): JSX.Element { + if (!displayMetric || !displayMetric.metric || + displayMetric.metric.number_value === undefined || + (displayMetric.metric.format !== RunMetricFormat.PERCENTAGE && !displayMetric.metadata)) { + return
; + } + + const leftSpace = 6; + let displayString = ''; + let width = ''; + + if (displayMetric.metric.format === RunMetricFormat.PERCENTAGE) { + displayString = (displayMetric.metric.number_value * 100).toFixed(3) + '%'; + width = `calc(${displayString})`; + } else { + displayString = displayMetric.metric.number_value.toFixed(3); + + if (displayMetric.metadata.maxValue === 0 && displayMetric.metadata.minValue === 0) { + return
{displayString}
; + } + + if (displayMetric.metric.number_value - displayMetric.metadata.minValue < 0) { + logger.error(`Run ${arguments[1]}'s metric ${displayMetric.metadata.name}'s value:` + + ` (${displayMetric.metric.number_value}) was lower than the supposed minimum of` + + ` (${displayMetric.metadata.minValue})`); + return
{displayString}
; + } + + if (displayMetric.metadata.maxValue - displayMetric.metric.number_value < 0) { + logger.error(`Run ${arguments[1]}'s metric ${displayMetric.metadata.name}'s value:` + + ` (${displayMetric.metric.number_value}) was greater than the supposed maximum of` + + ` (${displayMetric.metadata.maxValue})`); + return
{displayString}
; + } + + const barWidth = + (displayMetric.metric.number_value - displayMetric.metadata.minValue) + / (displayMetric.metadata.maxValue - displayMetric.metadata.minValue) + * 100; + + width = `calc(${barWidth}%)`; + } + return ( +
+
+ {displayString} +
+
+ ); + } } export default RunList; diff --git a/frontend/src/pages/__snapshots__/RunList.test.tsx.snap b/frontend/src/pages/__snapshots__/RunList.test.tsx.snap index e2ee6cb1fac..c273d9f5abd 100644 --- a/frontend/src/pages/__snapshots__/RunList.test.tsx.snap +++ b/frontend/src/pages/__snapshots__/RunList.test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`RunList displays error in run row if it failed to parse (run list mask) 1`] = ` +exports[`RunList adds metrics columns 1`] = `
+
+`; + +exports[`RunList displays error in run row if experiment could not be fetched 1`] = ` +
+ +
+`; + +exports[`RunList displays error in run row if it failed to parse (run list mask) 1`] = ` +
+ `; -exports[`RunList loads all runs 1`] = ` +exports[`RunList displays error in run row if pipeline could not be fetched 1`] = `
`; -exports[`RunList loads runs for a given experiment id 1`] = ` +exports[`RunList loads multiple run 1`] = `
+
+`; + +exports[`RunList loads one run 1`] = ` +
+ `; +exports[`RunList reloads the run when refresh is called 1`] = ` + +
+ +
+
+
+ + } + classes={ + Object { + "checked": "MuiCheckbox-checked-2", + "colorPrimary": "MuiCheckbox-colorPrimary-5", + "colorSecondary": "MuiCheckbox-colorSecondary-6", + "disabled": "MuiCheckbox-disabled-3", + "indeterminate": "MuiCheckbox-indeterminate-4", + "root": "MuiCheckbox-root-1", + } + } + color="primary" + icon={} + indeterminate={false} + indeterminateIcon={} + onChange={[Function]} + > + } + className="" + classes={ + Object { + "checked": "MuiCheckbox-checked-2", + "disabled": "MuiCheckbox-disabled-3", + "root": "MuiCheckbox-root-1 MuiCheckbox-colorPrimary-5", + } + } + icon={} + inputProps={ + Object { + "data-indeterminate": false, + } + } + onChange={[Function]} + type="checkbox" + > + } + className="" + classes={ + Object { + "checked": "MuiSwitchBase-checked-8 MuiCheckbox-checked-2", + "disabled": "MuiSwitchBase-disabled-9 MuiCheckbox-disabled-3", + "input": "MuiSwitchBase-input-10", + "root": "MuiSwitchBase-root-7 MuiCheckbox-root-1 MuiCheckbox-colorPrimary-5", + } + } + icon={} + inputProps={ + Object { + "data-indeterminate": false, + } + } + onChange={[Function]} + type="checkbox" + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + Run name + + + + + + + + + + + + + + + + + Run name + + + } + className="MuiTooltip-popper-36" + id={null} + open={false} + placement="bottom" + transition={true} + > + + Run name + + + } + className="MuiTooltip-popper-36" + disablePortal={false} + id={null} + open={false} + placement="bottom" + theme={ + Object { + "breakpoints": Object { + "between": [Function], + "down": [Function], + "keys": Array [ + "xs", + "sm", + "md", + "lg", + "xl", + ], + "only": [Function], + "up": [Function], + "values": Object { + "lg": 1280, + "md": 960, + "sm": 600, + "xl": 1920, + "xs": 0, + }, + "width": [Function], + }, + "direction": "ltr", + "mixins": Object { + "gutters": [Function], + "toolbar": Object { + "@media (min-width:0px) and (orientation: landscape)": Object { + "minHeight": 48, + }, + "@media (min-width:600px)": Object { + "minHeight": 64, + }, + "minHeight": 56, + }, + }, + "overrides": Object {}, + "palette": Object { + "action": Object { + "active": "rgba(0, 0, 0, 0.54)", + "disabled": "rgba(0, 0, 0, 0.26)", + "disabledBackground": "rgba(0, 0, 0, 0.12)", + "hover": "rgba(0, 0, 0, 0.08)", + "hoverOpacity": 0.08, + "selected": "rgba(0, 0, 0, 0.14)", + }, + "augmentColor": [Function], + "background": Object { + "default": "#fafafa", + "paper": "#fff", + }, + "common": Object { + "black": "#000", + "white": "#fff", + }, + "contrastThreshold": 3, + "divider": "rgba(0, 0, 0, 0.12)", + "error": Object { + "contrastText": "#fff", + "dark": "#d32f2f", + "light": "#e57373", + "main": "#f44336", + }, + "getContrastText": [Function], + "grey": Object { + "100": "#f5f5f5", + "200": "#eeeeee", + "300": "#e0e0e0", + "400": "#bdbdbd", + "50": "#fafafa", + "500": "#9e9e9e", + "600": "#757575", + "700": "#616161", + "800": "#424242", + "900": "#212121", + "A100": "#d5d5d5", + "A200": "#aaaaaa", + "A400": "#303030", + "A700": "#616161", + }, + "primary": Object { + "contrastText": "#fff", + "dark": "#303f9f", + "light": "#7986cb", + "main": "#3f51b5", + }, + "secondary": Object { + "contrastText": "#fff", + "dark": "#c51162", + "light": "#ff4081", + "main": "#f50057", + }, + "text": Object { + "disabled": "rgba(0, 0, 0, 0.38)", + "hint": "rgba(0, 0, 0, 0.38)", + "primary": "rgba(0, 0, 0, 0.87)", + "secondary": "rgba(0, 0, 0, 0.54)", + }, + "tonalOffset": 0.2, + "type": "light", + }, + "props": Object {}, + "shadows": Array [ + "none", + "0px 1px 3px 0px rgba(0, 0, 0, 0.2),0px 1px 1px 0px rgba(0, 0, 0, 0.14),0px 2px 1px -1px rgba(0, 0, 0, 0.12)", + "0px 1px 5px 0px rgba(0, 0, 0, 0.2),0px 2px 2px 0px rgba(0, 0, 0, 0.14),0px 3px 1px -2px rgba(0, 0, 0, 0.12)", + "0px 1px 8px 0px rgba(0, 0, 0, 0.2),0px 3px 4px 0px rgba(0, 0, 0, 0.14),0px 3px 3px -2px rgba(0, 0, 0, 0.12)", + "0px 2px 4px -1px rgba(0, 0, 0, 0.2),0px 4px 5px 0px rgba(0, 0, 0, 0.14),0px 1px 10px 0px rgba(0, 0, 0, 0.12)", + "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 5px 8px 0px rgba(0, 0, 0, 0.14),0px 1px 14px 0px rgba(0, 0, 0, 0.12)", + "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 6px 10px 0px rgba(0, 0, 0, 0.14),0px 1px 18px 0px rgba(0, 0, 0, 0.12)", + "0px 4px 5px -2px rgba(0, 0, 0, 0.2),0px 7px 10px 1px rgba(0, 0, 0, 0.14),0px 2px 16px 1px rgba(0, 0, 0, 0.12)", + "0px 5px 5px -3px rgba(0, 0, 0, 0.2),0px 8px 10px 1px rgba(0, 0, 0, 0.14),0px 3px 14px 2px rgba(0, 0, 0, 0.12)", + "0px 5px 6px -3px rgba(0, 0, 0, 0.2),0px 9px 12px 1px rgba(0, 0, 0, 0.14),0px 3px 16px 2px rgba(0, 0, 0, 0.12)", + "0px 6px 6px -3px rgba(0, 0, 0, 0.2),0px 10px 14px 1px rgba(0, 0, 0, 0.14),0px 4px 18px 3px rgba(0, 0, 0, 0.12)", + "0px 6px 7px -4px rgba(0, 0, 0, 0.2),0px 11px 15px 1px rgba(0, 0, 0, 0.14),0px 4px 20px 3px rgba(0, 0, 0, 0.12)", + "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 12px 17px 2px rgba(0, 0, 0, 0.14),0px 5px 22px 4px rgba(0, 0, 0, 0.12)", + "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 13px 19px 2px rgba(0, 0, 0, 0.14),0px 5px 24px 4px rgba(0, 0, 0, 0.12)", + "0px 7px 9px -4px rgba(0, 0, 0, 0.2),0px 14px 21px 2px rgba(0, 0, 0, 0.14),0px 5px 26px 4px rgba(0, 0, 0, 0.12)", + "0px 8px 9px -5px rgba(0, 0, 0, 0.2),0px 15px 22px 2px rgba(0, 0, 0, 0.14),0px 6px 28px 5px rgba(0, 0, 0, 0.12)", + "0px 8px 10px -5px rgba(0, 0, 0, 0.2),0px 16px 24px 2px rgba(0, 0, 0, 0.14),0px 6px 30px 5px rgba(0, 0, 0, 0.12)", + "0px 8px 11px -5px rgba(0, 0, 0, 0.2),0px 17px 26px 2px rgba(0, 0, 0, 0.14),0px 6px 32px 5px rgba(0, 0, 0, 0.12)", + "0px 9px 11px -5px rgba(0, 0, 0, 0.2),0px 18px 28px 2px rgba(0, 0, 0, 0.14),0px 7px 34px 6px rgba(0, 0, 0, 0.12)", + "0px 9px 12px -6px rgba(0, 0, 0, 0.2),0px 19px 29px 2px rgba(0, 0, 0, 0.14),0px 7px 36px 6px rgba(0, 0, 0, 0.12)", + "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 20px 31px 3px rgba(0, 0, 0, 0.14),0px 8px 38px 7px rgba(0, 0, 0, 0.12)", + "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 21px 33px 3px rgba(0, 0, 0, 0.14),0px 8px 40px 7px rgba(0, 0, 0, 0.12)", + "0px 10px 14px -6px rgba(0, 0, 0, 0.2),0px 22px 35px 3px rgba(0, 0, 0, 0.14),0px 8px 42px 7px rgba(0, 0, 0, 0.12)", + "0px 11px 14px -7px rgba(0, 0, 0, 0.2),0px 23px 36px 3px rgba(0, 0, 0, 0.14),0px 9px 44px 8px rgba(0, 0, 0, 0.12)", + "0px 11px 15px -7px rgba(0, 0, 0, 0.2),0px 24px 38px 3px rgba(0, 0, 0, 0.14),0px 9px 46px 8px rgba(0, 0, 0, 0.12)", + ], + "shape": Object { + "borderRadius": 4, + }, + "spacing": Object { + "unit": 8, + }, + "transitions": Object { + "create": [Function], + "duration": Object { + "complex": 375, + "enteringScreen": 225, + "leavingScreen": 195, + "short": 250, + "shorter": 200, + "shortest": 150, + "standard": 300, + }, + "easing": Object { + "easeIn": "cubic-bezier(0.4, 0, 1, 1)", + "easeInOut": "cubic-bezier(0.4, 0, 0.2, 1)", + "easeOut": "cubic-bezier(0.0, 0, 0.2, 1)", + "sharp": "cubic-bezier(0.4, 0, 0.6, 1)", + }, + "getAutoHeightDuration": [Function], + }, + "typography": Object { + "body1": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 400, + "lineHeight": "1.46429em", + }, + "body2": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 500, + "lineHeight": "1.71429em", + }, + "button": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 500, + "textTransform": "uppercase", + }, + "caption": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.75rem", + "fontWeight": 400, + "lineHeight": "1.375em", + }, + "display1": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "2.125rem", + "fontWeight": 400, + "lineHeight": "1.20588em", + }, + "display2": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "2.8125rem", + "fontWeight": 400, + "lineHeight": "1.13333em", + "marginLeft": "-.02em", + }, + "display3": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "3.5rem", + "fontWeight": 400, + "letterSpacing": "-.02em", + "lineHeight": "1.30357em", + "marginLeft": "-.02em", + }, + "display4": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "7rem", + "fontWeight": 300, + "letterSpacing": "-.04em", + "lineHeight": "1.14286em", + "marginLeft": "-.04em", + }, + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": 14, + "fontWeightLight": 300, + "fontWeightMedium": 500, + "fontWeightRegular": 400, + "headline": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1.5rem", + "fontWeight": 400, + "lineHeight": "1.35417em", + }, + "pxToRem": [Function], + "round": [Function], + "subheading": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1rem", + "fontWeight": 400, + "lineHeight": "1.5em", + }, + "title": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1.3125rem", + "fontWeight": 500, + "lineHeight": "1.16667em", + }, + }, + "zIndex": Object { + "appBar": 1100, + "drawer": 1200, + "mobileStepper": 1000, + "modal": 1300, + "snackbar": 1400, + "tooltip": 1500, + }, + } + } + transition={true} + /> + + + +
+
+ + + + + + + + + Status + + + + + + + + + + + + + + + + + Status + + + } + className="MuiTooltip-popper-36" + id={null} + open={false} + placement="bottom" + transition={true} + > + + Status + + + } + className="MuiTooltip-popper-36" + disablePortal={false} + id={null} + open={false} + placement="bottom" + theme={ + Object { + "breakpoints": Object { + "between": [Function], + "down": [Function], + "keys": Array [ + "xs", + "sm", + "md", + "lg", + "xl", + ], + "only": [Function], + "up": [Function], + "values": Object { + "lg": 1280, + "md": 960, + "sm": 600, + "xl": 1920, + "xs": 0, + }, + "width": [Function], + }, + "direction": "ltr", + "mixins": Object { + "gutters": [Function], + "toolbar": Object { + "@media (min-width:0px) and (orientation: landscape)": Object { + "minHeight": 48, + }, + "@media (min-width:600px)": Object { + "minHeight": 64, + }, + "minHeight": 56, + }, + }, + "overrides": Object {}, + "palette": Object { + "action": Object { + "active": "rgba(0, 0, 0, 0.54)", + "disabled": "rgba(0, 0, 0, 0.26)", + "disabledBackground": "rgba(0, 0, 0, 0.12)", + "hover": "rgba(0, 0, 0, 0.08)", + "hoverOpacity": 0.08, + "selected": "rgba(0, 0, 0, 0.14)", + }, + "augmentColor": [Function], + "background": Object { + "default": "#fafafa", + "paper": "#fff", + }, + "common": Object { + "black": "#000", + "white": "#fff", + }, + "contrastThreshold": 3, + "divider": "rgba(0, 0, 0, 0.12)", + "error": Object { + "contrastText": "#fff", + "dark": "#d32f2f", + "light": "#e57373", + "main": "#f44336", + }, + "getContrastText": [Function], + "grey": Object { + "100": "#f5f5f5", + "200": "#eeeeee", + "300": "#e0e0e0", + "400": "#bdbdbd", + "50": "#fafafa", + "500": "#9e9e9e", + "600": "#757575", + "700": "#616161", + "800": "#424242", + "900": "#212121", + "A100": "#d5d5d5", + "A200": "#aaaaaa", + "A400": "#303030", + "A700": "#616161", + }, + "primary": Object { + "contrastText": "#fff", + "dark": "#303f9f", + "light": "#7986cb", + "main": "#3f51b5", + }, + "secondary": Object { + "contrastText": "#fff", + "dark": "#c51162", + "light": "#ff4081", + "main": "#f50057", + }, + "text": Object { + "disabled": "rgba(0, 0, 0, 0.38)", + "hint": "rgba(0, 0, 0, 0.38)", + "primary": "rgba(0, 0, 0, 0.87)", + "secondary": "rgba(0, 0, 0, 0.54)", + }, + "tonalOffset": 0.2, + "type": "light", + }, + "props": Object {}, + "shadows": Array [ + "none", + "0px 1px 3px 0px rgba(0, 0, 0, 0.2),0px 1px 1px 0px rgba(0, 0, 0, 0.14),0px 2px 1px -1px rgba(0, 0, 0, 0.12)", + "0px 1px 5px 0px rgba(0, 0, 0, 0.2),0px 2px 2px 0px rgba(0, 0, 0, 0.14),0px 3px 1px -2px rgba(0, 0, 0, 0.12)", + "0px 1px 8px 0px rgba(0, 0, 0, 0.2),0px 3px 4px 0px rgba(0, 0, 0, 0.14),0px 3px 3px -2px rgba(0, 0, 0, 0.12)", + "0px 2px 4px -1px rgba(0, 0, 0, 0.2),0px 4px 5px 0px rgba(0, 0, 0, 0.14),0px 1px 10px 0px rgba(0, 0, 0, 0.12)", + "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 5px 8px 0px rgba(0, 0, 0, 0.14),0px 1px 14px 0px rgba(0, 0, 0, 0.12)", + "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 6px 10px 0px rgba(0, 0, 0, 0.14),0px 1px 18px 0px rgba(0, 0, 0, 0.12)", + "0px 4px 5px -2px rgba(0, 0, 0, 0.2),0px 7px 10px 1px rgba(0, 0, 0, 0.14),0px 2px 16px 1px rgba(0, 0, 0, 0.12)", + "0px 5px 5px -3px rgba(0, 0, 0, 0.2),0px 8px 10px 1px rgba(0, 0, 0, 0.14),0px 3px 14px 2px rgba(0, 0, 0, 0.12)", + "0px 5px 6px -3px rgba(0, 0, 0, 0.2),0px 9px 12px 1px rgba(0, 0, 0, 0.14),0px 3px 16px 2px rgba(0, 0, 0, 0.12)", + "0px 6px 6px -3px rgba(0, 0, 0, 0.2),0px 10px 14px 1px rgba(0, 0, 0, 0.14),0px 4px 18px 3px rgba(0, 0, 0, 0.12)", + "0px 6px 7px -4px rgba(0, 0, 0, 0.2),0px 11px 15px 1px rgba(0, 0, 0, 0.14),0px 4px 20px 3px rgba(0, 0, 0, 0.12)", + "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 12px 17px 2px rgba(0, 0, 0, 0.14),0px 5px 22px 4px rgba(0, 0, 0, 0.12)", + "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 13px 19px 2px rgba(0, 0, 0, 0.14),0px 5px 24px 4px rgba(0, 0, 0, 0.12)", + "0px 7px 9px -4px rgba(0, 0, 0, 0.2),0px 14px 21px 2px rgba(0, 0, 0, 0.14),0px 5px 26px 4px rgba(0, 0, 0, 0.12)", + "0px 8px 9px -5px rgba(0, 0, 0, 0.2),0px 15px 22px 2px rgba(0, 0, 0, 0.14),0px 6px 28px 5px rgba(0, 0, 0, 0.12)", + "0px 8px 10px -5px rgba(0, 0, 0, 0.2),0px 16px 24px 2px rgba(0, 0, 0, 0.14),0px 6px 30px 5px rgba(0, 0, 0, 0.12)", + "0px 8px 11px -5px rgba(0, 0, 0, 0.2),0px 17px 26px 2px rgba(0, 0, 0, 0.14),0px 6px 32px 5px rgba(0, 0, 0, 0.12)", + "0px 9px 11px -5px rgba(0, 0, 0, 0.2),0px 18px 28px 2px rgba(0, 0, 0, 0.14),0px 7px 34px 6px rgba(0, 0, 0, 0.12)", + "0px 9px 12px -6px rgba(0, 0, 0, 0.2),0px 19px 29px 2px rgba(0, 0, 0, 0.14),0px 7px 36px 6px rgba(0, 0, 0, 0.12)", + "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 20px 31px 3px rgba(0, 0, 0, 0.14),0px 8px 38px 7px rgba(0, 0, 0, 0.12)", + "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 21px 33px 3px rgba(0, 0, 0, 0.14),0px 8px 40px 7px rgba(0, 0, 0, 0.12)", + "0px 10px 14px -6px rgba(0, 0, 0, 0.2),0px 22px 35px 3px rgba(0, 0, 0, 0.14),0px 8px 42px 7px rgba(0, 0, 0, 0.12)", + "0px 11px 14px -7px rgba(0, 0, 0, 0.2),0px 23px 36px 3px rgba(0, 0, 0, 0.14),0px 9px 44px 8px rgba(0, 0, 0, 0.12)", + "0px 11px 15px -7px rgba(0, 0, 0, 0.2),0px 24px 38px 3px rgba(0, 0, 0, 0.14),0px 9px 46px 8px rgba(0, 0, 0, 0.12)", + ], + "shape": Object { + "borderRadius": 4, + }, + "spacing": Object { + "unit": 8, + }, + "transitions": Object { + "create": [Function], + "duration": Object { + "complex": 375, + "enteringScreen": 225, + "leavingScreen": 195, + "short": 250, + "shorter": 200, + "shortest": 150, + "standard": 300, + }, + "easing": Object { + "easeIn": "cubic-bezier(0.4, 0, 1, 1)", + "easeInOut": "cubic-bezier(0.4, 0, 0.2, 1)", + "easeOut": "cubic-bezier(0.0, 0, 0.2, 1)", + "sharp": "cubic-bezier(0.4, 0, 0.6, 1)", + }, + "getAutoHeightDuration": [Function], + }, + "typography": Object { + "body1": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 400, + "lineHeight": "1.46429em", + }, + "body2": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 500, + "lineHeight": "1.71429em", + }, + "button": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 500, + "textTransform": "uppercase", + }, + "caption": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.75rem", + "fontWeight": 400, + "lineHeight": "1.375em", + }, + "display1": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "2.125rem", + "fontWeight": 400, + "lineHeight": "1.20588em", + }, + "display2": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "2.8125rem", + "fontWeight": 400, + "lineHeight": "1.13333em", + "marginLeft": "-.02em", + }, + "display3": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "3.5rem", + "fontWeight": 400, + "letterSpacing": "-.02em", + "lineHeight": "1.30357em", + "marginLeft": "-.02em", + }, + "display4": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "7rem", + "fontWeight": 300, + "letterSpacing": "-.04em", + "lineHeight": "1.14286em", + "marginLeft": "-.04em", + }, + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": 14, + "fontWeightLight": 300, + "fontWeightMedium": 500, + "fontWeightRegular": 400, + "headline": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1.5rem", + "fontWeight": 400, + "lineHeight": "1.35417em", + }, + "pxToRem": [Function], + "round": [Function], + "subheading": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1rem", + "fontWeight": 400, + "lineHeight": "1.5em", + }, + "title": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1.3125rem", + "fontWeight": 500, + "lineHeight": "1.16667em", + }, + }, + "zIndex": Object { + "appBar": 1100, + "drawer": 1200, + "mobileStepper": 1000, + "modal": 1300, + "snackbar": 1400, + "tooltip": 1500, + }, + } + } + transition={true} + /> + + + +
+
+ + + + + + + + + Duration + + + + + + + + + + + + + + + + + Duration + + + } + className="MuiTooltip-popper-36" + id={null} + open={false} + placement="bottom" + transition={true} + > + + Duration + + + } + className="MuiTooltip-popper-36" + disablePortal={false} + id={null} + open={false} + placement="bottom" + theme={ + Object { + "breakpoints": Object { + "between": [Function], + "down": [Function], + "keys": Array [ + "xs", + "sm", + "md", + "lg", + "xl", + ], + "only": [Function], + "up": [Function], + "values": Object { + "lg": 1280, + "md": 960, + "sm": 600, + "xl": 1920, + "xs": 0, + }, + "width": [Function], + }, + "direction": "ltr", + "mixins": Object { + "gutters": [Function], + "toolbar": Object { + "@media (min-width:0px) and (orientation: landscape)": Object { + "minHeight": 48, + }, + "@media (min-width:600px)": Object { + "minHeight": 64, + }, + "minHeight": 56, + }, + }, + "overrides": Object {}, + "palette": Object { + "action": Object { + "active": "rgba(0, 0, 0, 0.54)", + "disabled": "rgba(0, 0, 0, 0.26)", + "disabledBackground": "rgba(0, 0, 0, 0.12)", + "hover": "rgba(0, 0, 0, 0.08)", + "hoverOpacity": 0.08, + "selected": "rgba(0, 0, 0, 0.14)", + }, + "augmentColor": [Function], + "background": Object { + "default": "#fafafa", + "paper": "#fff", + }, + "common": Object { + "black": "#000", + "white": "#fff", + }, + "contrastThreshold": 3, + "divider": "rgba(0, 0, 0, 0.12)", + "error": Object { + "contrastText": "#fff", + "dark": "#d32f2f", + "light": "#e57373", + "main": "#f44336", + }, + "getContrastText": [Function], + "grey": Object { + "100": "#f5f5f5", + "200": "#eeeeee", + "300": "#e0e0e0", + "400": "#bdbdbd", + "50": "#fafafa", + "500": "#9e9e9e", + "600": "#757575", + "700": "#616161", + "800": "#424242", + "900": "#212121", + "A100": "#d5d5d5", + "A200": "#aaaaaa", + "A400": "#303030", + "A700": "#616161", + }, + "primary": Object { + "contrastText": "#fff", + "dark": "#303f9f", + "light": "#7986cb", + "main": "#3f51b5", + }, + "secondary": Object { + "contrastText": "#fff", + "dark": "#c51162", + "light": "#ff4081", + "main": "#f50057", + }, + "text": Object { + "disabled": "rgba(0, 0, 0, 0.38)", + "hint": "rgba(0, 0, 0, 0.38)", + "primary": "rgba(0, 0, 0, 0.87)", + "secondary": "rgba(0, 0, 0, 0.54)", + }, + "tonalOffset": 0.2, + "type": "light", + }, + "props": Object {}, + "shadows": Array [ + "none", + "0px 1px 3px 0px rgba(0, 0, 0, 0.2),0px 1px 1px 0px rgba(0, 0, 0, 0.14),0px 2px 1px -1px rgba(0, 0, 0, 0.12)", + "0px 1px 5px 0px rgba(0, 0, 0, 0.2),0px 2px 2px 0px rgba(0, 0, 0, 0.14),0px 3px 1px -2px rgba(0, 0, 0, 0.12)", + "0px 1px 8px 0px rgba(0, 0, 0, 0.2),0px 3px 4px 0px rgba(0, 0, 0, 0.14),0px 3px 3px -2px rgba(0, 0, 0, 0.12)", + "0px 2px 4px -1px rgba(0, 0, 0, 0.2),0px 4px 5px 0px rgba(0, 0, 0, 0.14),0px 1px 10px 0px rgba(0, 0, 0, 0.12)", + "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 5px 8px 0px rgba(0, 0, 0, 0.14),0px 1px 14px 0px rgba(0, 0, 0, 0.12)", + "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 6px 10px 0px rgba(0, 0, 0, 0.14),0px 1px 18px 0px rgba(0, 0, 0, 0.12)", + "0px 4px 5px -2px rgba(0, 0, 0, 0.2),0px 7px 10px 1px rgba(0, 0, 0, 0.14),0px 2px 16px 1px rgba(0, 0, 0, 0.12)", + "0px 5px 5px -3px rgba(0, 0, 0, 0.2),0px 8px 10px 1px rgba(0, 0, 0, 0.14),0px 3px 14px 2px rgba(0, 0, 0, 0.12)", + "0px 5px 6px -3px rgba(0, 0, 0, 0.2),0px 9px 12px 1px rgba(0, 0, 0, 0.14),0px 3px 16px 2px rgba(0, 0, 0, 0.12)", + "0px 6px 6px -3px rgba(0, 0, 0, 0.2),0px 10px 14px 1px rgba(0, 0, 0, 0.14),0px 4px 18px 3px rgba(0, 0, 0, 0.12)", + "0px 6px 7px -4px rgba(0, 0, 0, 0.2),0px 11px 15px 1px rgba(0, 0, 0, 0.14),0px 4px 20px 3px rgba(0, 0, 0, 0.12)", + "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 12px 17px 2px rgba(0, 0, 0, 0.14),0px 5px 22px 4px rgba(0, 0, 0, 0.12)", + "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 13px 19px 2px rgba(0, 0, 0, 0.14),0px 5px 24px 4px rgba(0, 0, 0, 0.12)", + "0px 7px 9px -4px rgba(0, 0, 0, 0.2),0px 14px 21px 2px rgba(0, 0, 0, 0.14),0px 5px 26px 4px rgba(0, 0, 0, 0.12)", + "0px 8px 9px -5px rgba(0, 0, 0, 0.2),0px 15px 22px 2px rgba(0, 0, 0, 0.14),0px 6px 28px 5px rgba(0, 0, 0, 0.12)", + "0px 8px 10px -5px rgba(0, 0, 0, 0.2),0px 16px 24px 2px rgba(0, 0, 0, 0.14),0px 6px 30px 5px rgba(0, 0, 0, 0.12)", + "0px 8px 11px -5px rgba(0, 0, 0, 0.2),0px 17px 26px 2px rgba(0, 0, 0, 0.14),0px 6px 32px 5px rgba(0, 0, 0, 0.12)", + "0px 9px 11px -5px rgba(0, 0, 0, 0.2),0px 18px 28px 2px rgba(0, 0, 0, 0.14),0px 7px 34px 6px rgba(0, 0, 0, 0.12)", + "0px 9px 12px -6px rgba(0, 0, 0, 0.2),0px 19px 29px 2px rgba(0, 0, 0, 0.14),0px 7px 36px 6px rgba(0, 0, 0, 0.12)", + "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 20px 31px 3px rgba(0, 0, 0, 0.14),0px 8px 38px 7px rgba(0, 0, 0, 0.12)", + "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 21px 33px 3px rgba(0, 0, 0, 0.14),0px 8px 40px 7px rgba(0, 0, 0, 0.12)", + "0px 10px 14px -6px rgba(0, 0, 0, 0.2),0px 22px 35px 3px rgba(0, 0, 0, 0.14),0px 8px 42px 7px rgba(0, 0, 0, 0.12)", + "0px 11px 14px -7px rgba(0, 0, 0, 0.2),0px 23px 36px 3px rgba(0, 0, 0, 0.14),0px 9px 44px 8px rgba(0, 0, 0, 0.12)", + "0px 11px 15px -7px rgba(0, 0, 0, 0.2),0px 24px 38px 3px rgba(0, 0, 0, 0.14),0px 9px 46px 8px rgba(0, 0, 0, 0.12)", + ], + "shape": Object { + "borderRadius": 4, + }, + "spacing": Object { + "unit": 8, + }, + "transitions": Object { + "create": [Function], + "duration": Object { + "complex": 375, + "enteringScreen": 225, + "leavingScreen": 195, + "short": 250, + "shorter": 200, + "shortest": 150, + "standard": 300, + }, + "easing": Object { + "easeIn": "cubic-bezier(0.4, 0, 1, 1)", + "easeInOut": "cubic-bezier(0.4, 0, 0.2, 1)", + "easeOut": "cubic-bezier(0.0, 0, 0.2, 1)", + "sharp": "cubic-bezier(0.4, 0, 0.6, 1)", + }, + "getAutoHeightDuration": [Function], + }, + "typography": Object { + "body1": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 400, + "lineHeight": "1.46429em", + }, + "body2": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 500, + "lineHeight": "1.71429em", + }, + "button": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 500, + "textTransform": "uppercase", + }, + "caption": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.75rem", + "fontWeight": 400, + "lineHeight": "1.375em", + }, + "display1": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "2.125rem", + "fontWeight": 400, + "lineHeight": "1.20588em", + }, + "display2": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "2.8125rem", + "fontWeight": 400, + "lineHeight": "1.13333em", + "marginLeft": "-.02em", + }, + "display3": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "3.5rem", + "fontWeight": 400, + "letterSpacing": "-.02em", + "lineHeight": "1.30357em", + "marginLeft": "-.02em", + }, + "display4": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "7rem", + "fontWeight": 300, + "letterSpacing": "-.04em", + "lineHeight": "1.14286em", + "marginLeft": "-.04em", + }, + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": 14, + "fontWeightLight": 300, + "fontWeightMedium": 500, + "fontWeightRegular": 400, + "headline": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1.5rem", + "fontWeight": 400, + "lineHeight": "1.35417em", + }, + "pxToRem": [Function], + "round": [Function], + "subheading": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1rem", + "fontWeight": 400, + "lineHeight": "1.5em", + }, + "title": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1.3125rem", + "fontWeight": 500, + "lineHeight": "1.16667em", + }, + }, + "zIndex": Object { + "appBar": 1100, + "drawer": 1200, + "mobileStepper": 1000, + "modal": 1300, + "snackbar": 1400, + "tooltip": 1500, + }, + } + } + transition={true} + /> + + + +
+
+ + + + + + + + + Experiment + + + + + + + + + + + + + + + + + Experiment + + + } + className="MuiTooltip-popper-36" + id={null} + open={false} + placement="bottom" + transition={true} + > + + Experiment + + + } + className="MuiTooltip-popper-36" + disablePortal={false} + id={null} + open={false} + placement="bottom" + theme={ + Object { + "breakpoints": Object { + "between": [Function], + "down": [Function], + "keys": Array [ + "xs", + "sm", + "md", + "lg", + "xl", + ], + "only": [Function], + "up": [Function], + "values": Object { + "lg": 1280, + "md": 960, + "sm": 600, + "xl": 1920, + "xs": 0, + }, + "width": [Function], + }, + "direction": "ltr", + "mixins": Object { + "gutters": [Function], + "toolbar": Object { + "@media (min-width:0px) and (orientation: landscape)": Object { + "minHeight": 48, + }, + "@media (min-width:600px)": Object { + "minHeight": 64, + }, + "minHeight": 56, + }, + }, + "overrides": Object {}, + "palette": Object { + "action": Object { + "active": "rgba(0, 0, 0, 0.54)", + "disabled": "rgba(0, 0, 0, 0.26)", + "disabledBackground": "rgba(0, 0, 0, 0.12)", + "hover": "rgba(0, 0, 0, 0.08)", + "hoverOpacity": 0.08, + "selected": "rgba(0, 0, 0, 0.14)", + }, + "augmentColor": [Function], + "background": Object { + "default": "#fafafa", + "paper": "#fff", + }, + "common": Object { + "black": "#000", + "white": "#fff", + }, + "contrastThreshold": 3, + "divider": "rgba(0, 0, 0, 0.12)", + "error": Object { + "contrastText": "#fff", + "dark": "#d32f2f", + "light": "#e57373", + "main": "#f44336", + }, + "getContrastText": [Function], + "grey": Object { + "100": "#f5f5f5", + "200": "#eeeeee", + "300": "#e0e0e0", + "400": "#bdbdbd", + "50": "#fafafa", + "500": "#9e9e9e", + "600": "#757575", + "700": "#616161", + "800": "#424242", + "900": "#212121", + "A100": "#d5d5d5", + "A200": "#aaaaaa", + "A400": "#303030", + "A700": "#616161", + }, + "primary": Object { + "contrastText": "#fff", + "dark": "#303f9f", + "light": "#7986cb", + "main": "#3f51b5", + }, + "secondary": Object { + "contrastText": "#fff", + "dark": "#c51162", + "light": "#ff4081", + "main": "#f50057", + }, + "text": Object { + "disabled": "rgba(0, 0, 0, 0.38)", + "hint": "rgba(0, 0, 0, 0.38)", + "primary": "rgba(0, 0, 0, 0.87)", + "secondary": "rgba(0, 0, 0, 0.54)", + }, + "tonalOffset": 0.2, + "type": "light", + }, + "props": Object {}, + "shadows": Array [ + "none", + "0px 1px 3px 0px rgba(0, 0, 0, 0.2),0px 1px 1px 0px rgba(0, 0, 0, 0.14),0px 2px 1px -1px rgba(0, 0, 0, 0.12)", + "0px 1px 5px 0px rgba(0, 0, 0, 0.2),0px 2px 2px 0px rgba(0, 0, 0, 0.14),0px 3px 1px -2px rgba(0, 0, 0, 0.12)", + "0px 1px 8px 0px rgba(0, 0, 0, 0.2),0px 3px 4px 0px rgba(0, 0, 0, 0.14),0px 3px 3px -2px rgba(0, 0, 0, 0.12)", + "0px 2px 4px -1px rgba(0, 0, 0, 0.2),0px 4px 5px 0px rgba(0, 0, 0, 0.14),0px 1px 10px 0px rgba(0, 0, 0, 0.12)", + "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 5px 8px 0px rgba(0, 0, 0, 0.14),0px 1px 14px 0px rgba(0, 0, 0, 0.12)", + "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 6px 10px 0px rgba(0, 0, 0, 0.14),0px 1px 18px 0px rgba(0, 0, 0, 0.12)", + "0px 4px 5px -2px rgba(0, 0, 0, 0.2),0px 7px 10px 1px rgba(0, 0, 0, 0.14),0px 2px 16px 1px rgba(0, 0, 0, 0.12)", + "0px 5px 5px -3px rgba(0, 0, 0, 0.2),0px 8px 10px 1px rgba(0, 0, 0, 0.14),0px 3px 14px 2px rgba(0, 0, 0, 0.12)", + "0px 5px 6px -3px rgba(0, 0, 0, 0.2),0px 9px 12px 1px rgba(0, 0, 0, 0.14),0px 3px 16px 2px rgba(0, 0, 0, 0.12)", + "0px 6px 6px -3px rgba(0, 0, 0, 0.2),0px 10px 14px 1px rgba(0, 0, 0, 0.14),0px 4px 18px 3px rgba(0, 0, 0, 0.12)", + "0px 6px 7px -4px rgba(0, 0, 0, 0.2),0px 11px 15px 1px rgba(0, 0, 0, 0.14),0px 4px 20px 3px rgba(0, 0, 0, 0.12)", + "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 12px 17px 2px rgba(0, 0, 0, 0.14),0px 5px 22px 4px rgba(0, 0, 0, 0.12)", + "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 13px 19px 2px rgba(0, 0, 0, 0.14),0px 5px 24px 4px rgba(0, 0, 0, 0.12)", + "0px 7px 9px -4px rgba(0, 0, 0, 0.2),0px 14px 21px 2px rgba(0, 0, 0, 0.14),0px 5px 26px 4px rgba(0, 0, 0, 0.12)", + "0px 8px 9px -5px rgba(0, 0, 0, 0.2),0px 15px 22px 2px rgba(0, 0, 0, 0.14),0px 6px 28px 5px rgba(0, 0, 0, 0.12)", + "0px 8px 10px -5px rgba(0, 0, 0, 0.2),0px 16px 24px 2px rgba(0, 0, 0, 0.14),0px 6px 30px 5px rgba(0, 0, 0, 0.12)", + "0px 8px 11px -5px rgba(0, 0, 0, 0.2),0px 17px 26px 2px rgba(0, 0, 0, 0.14),0px 6px 32px 5px rgba(0, 0, 0, 0.12)", + "0px 9px 11px -5px rgba(0, 0, 0, 0.2),0px 18px 28px 2px rgba(0, 0, 0, 0.14),0px 7px 34px 6px rgba(0, 0, 0, 0.12)", + "0px 9px 12px -6px rgba(0, 0, 0, 0.2),0px 19px 29px 2px rgba(0, 0, 0, 0.14),0px 7px 36px 6px rgba(0, 0, 0, 0.12)", + "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 20px 31px 3px rgba(0, 0, 0, 0.14),0px 8px 38px 7px rgba(0, 0, 0, 0.12)", + "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 21px 33px 3px rgba(0, 0, 0, 0.14),0px 8px 40px 7px rgba(0, 0, 0, 0.12)", + "0px 10px 14px -6px rgba(0, 0, 0, 0.2),0px 22px 35px 3px rgba(0, 0, 0, 0.14),0px 8px 42px 7px rgba(0, 0, 0, 0.12)", + "0px 11px 14px -7px rgba(0, 0, 0, 0.2),0px 23px 36px 3px rgba(0, 0, 0, 0.14),0px 9px 44px 8px rgba(0, 0, 0, 0.12)", + "0px 11px 15px -7px rgba(0, 0, 0, 0.2),0px 24px 38px 3px rgba(0, 0, 0, 0.14),0px 9px 46px 8px rgba(0, 0, 0, 0.12)", + ], + "shape": Object { + "borderRadius": 4, + }, + "spacing": Object { + "unit": 8, + }, + "transitions": Object { + "create": [Function], + "duration": Object { + "complex": 375, + "enteringScreen": 225, + "leavingScreen": 195, + "short": 250, + "shorter": 200, + "shortest": 150, + "standard": 300, + }, + "easing": Object { + "easeIn": "cubic-bezier(0.4, 0, 1, 1)", + "easeInOut": "cubic-bezier(0.4, 0, 0.2, 1)", + "easeOut": "cubic-bezier(0.0, 0, 0.2, 1)", + "sharp": "cubic-bezier(0.4, 0, 0.6, 1)", + }, + "getAutoHeightDuration": [Function], + }, + "typography": Object { + "body1": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 400, + "lineHeight": "1.46429em", + }, + "body2": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 500, + "lineHeight": "1.71429em", + }, + "button": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 500, + "textTransform": "uppercase", + }, + "caption": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.75rem", + "fontWeight": 400, + "lineHeight": "1.375em", + }, + "display1": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "2.125rem", + "fontWeight": 400, + "lineHeight": "1.20588em", + }, + "display2": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "2.8125rem", + "fontWeight": 400, + "lineHeight": "1.13333em", + "marginLeft": "-.02em", + }, + "display3": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "3.5rem", + "fontWeight": 400, + "letterSpacing": "-.02em", + "lineHeight": "1.30357em", + "marginLeft": "-.02em", + }, + "display4": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "7rem", + "fontWeight": 300, + "letterSpacing": "-.04em", + "lineHeight": "1.14286em", + "marginLeft": "-.04em", + }, + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": 14, + "fontWeightLight": 300, + "fontWeightMedium": 500, + "fontWeightRegular": 400, + "headline": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1.5rem", + "fontWeight": 400, + "lineHeight": "1.35417em", + }, + "pxToRem": [Function], + "round": [Function], + "subheading": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1rem", + "fontWeight": 400, + "lineHeight": "1.5em", + }, + "title": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1.3125rem", + "fontWeight": 500, + "lineHeight": "1.16667em", + }, + }, + "zIndex": Object { + "appBar": 1100, + "drawer": 1200, + "mobileStepper": 1000, + "modal": 1300, + "snackbar": 1400, + "tooltip": 1500, + }, + } + } + transition={true} + /> + + + +
+
+ + + + + + + + + Pipeline + + + + + + + + + + + + + + + + + Pipeline + + + } + className="MuiTooltip-popper-36" + id={null} + open={false} + placement="bottom" + transition={true} + > + + Pipeline + + + } + className="MuiTooltip-popper-36" + disablePortal={false} + id={null} + open={false} + placement="bottom" + theme={ + Object { + "breakpoints": Object { + "between": [Function], + "down": [Function], + "keys": Array [ + "xs", + "sm", + "md", + "lg", + "xl", + ], + "only": [Function], + "up": [Function], + "values": Object { + "lg": 1280, + "md": 960, + "sm": 600, + "xl": 1920, + "xs": 0, + }, + "width": [Function], + }, + "direction": "ltr", + "mixins": Object { + "gutters": [Function], + "toolbar": Object { + "@media (min-width:0px) and (orientation: landscape)": Object { + "minHeight": 48, + }, + "@media (min-width:600px)": Object { + "minHeight": 64, + }, + "minHeight": 56, + }, + }, + "overrides": Object {}, + "palette": Object { + "action": Object { + "active": "rgba(0, 0, 0, 0.54)", + "disabled": "rgba(0, 0, 0, 0.26)", + "disabledBackground": "rgba(0, 0, 0, 0.12)", + "hover": "rgba(0, 0, 0, 0.08)", + "hoverOpacity": 0.08, + "selected": "rgba(0, 0, 0, 0.14)", + }, + "augmentColor": [Function], + "background": Object { + "default": "#fafafa", + "paper": "#fff", + }, + "common": Object { + "black": "#000", + "white": "#fff", + }, + "contrastThreshold": 3, + "divider": "rgba(0, 0, 0, 0.12)", + "error": Object { + "contrastText": "#fff", + "dark": "#d32f2f", + "light": "#e57373", + "main": "#f44336", + }, + "getContrastText": [Function], + "grey": Object { + "100": "#f5f5f5", + "200": "#eeeeee", + "300": "#e0e0e0", + "400": "#bdbdbd", + "50": "#fafafa", + "500": "#9e9e9e", + "600": "#757575", + "700": "#616161", + "800": "#424242", + "900": "#212121", + "A100": "#d5d5d5", + "A200": "#aaaaaa", + "A400": "#303030", + "A700": "#616161", + }, + "primary": Object { + "contrastText": "#fff", + "dark": "#303f9f", + "light": "#7986cb", + "main": "#3f51b5", + }, + "secondary": Object { + "contrastText": "#fff", + "dark": "#c51162", + "light": "#ff4081", + "main": "#f50057", + }, + "text": Object { + "disabled": "rgba(0, 0, 0, 0.38)", + "hint": "rgba(0, 0, 0, 0.38)", + "primary": "rgba(0, 0, 0, 0.87)", + "secondary": "rgba(0, 0, 0, 0.54)", + }, + "tonalOffset": 0.2, + "type": "light", + }, + "props": Object {}, + "shadows": Array [ + "none", + "0px 1px 3px 0px rgba(0, 0, 0, 0.2),0px 1px 1px 0px rgba(0, 0, 0, 0.14),0px 2px 1px -1px rgba(0, 0, 0, 0.12)", + "0px 1px 5px 0px rgba(0, 0, 0, 0.2),0px 2px 2px 0px rgba(0, 0, 0, 0.14),0px 3px 1px -2px rgba(0, 0, 0, 0.12)", + "0px 1px 8px 0px rgba(0, 0, 0, 0.2),0px 3px 4px 0px rgba(0, 0, 0, 0.14),0px 3px 3px -2px rgba(0, 0, 0, 0.12)", + "0px 2px 4px -1px rgba(0, 0, 0, 0.2),0px 4px 5px 0px rgba(0, 0, 0, 0.14),0px 1px 10px 0px rgba(0, 0, 0, 0.12)", + "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 5px 8px 0px rgba(0, 0, 0, 0.14),0px 1px 14px 0px rgba(0, 0, 0, 0.12)", + "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 6px 10px 0px rgba(0, 0, 0, 0.14),0px 1px 18px 0px rgba(0, 0, 0, 0.12)", + "0px 4px 5px -2px rgba(0, 0, 0, 0.2),0px 7px 10px 1px rgba(0, 0, 0, 0.14),0px 2px 16px 1px rgba(0, 0, 0, 0.12)", + "0px 5px 5px -3px rgba(0, 0, 0, 0.2),0px 8px 10px 1px rgba(0, 0, 0, 0.14),0px 3px 14px 2px rgba(0, 0, 0, 0.12)", + "0px 5px 6px -3px rgba(0, 0, 0, 0.2),0px 9px 12px 1px rgba(0, 0, 0, 0.14),0px 3px 16px 2px rgba(0, 0, 0, 0.12)", + "0px 6px 6px -3px rgba(0, 0, 0, 0.2),0px 10px 14px 1px rgba(0, 0, 0, 0.14),0px 4px 18px 3px rgba(0, 0, 0, 0.12)", + "0px 6px 7px -4px rgba(0, 0, 0, 0.2),0px 11px 15px 1px rgba(0, 0, 0, 0.14),0px 4px 20px 3px rgba(0, 0, 0, 0.12)", + "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 12px 17px 2px rgba(0, 0, 0, 0.14),0px 5px 22px 4px rgba(0, 0, 0, 0.12)", + "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 13px 19px 2px rgba(0, 0, 0, 0.14),0px 5px 24px 4px rgba(0, 0, 0, 0.12)", + "0px 7px 9px -4px rgba(0, 0, 0, 0.2),0px 14px 21px 2px rgba(0, 0, 0, 0.14),0px 5px 26px 4px rgba(0, 0, 0, 0.12)", + "0px 8px 9px -5px rgba(0, 0, 0, 0.2),0px 15px 22px 2px rgba(0, 0, 0, 0.14),0px 6px 28px 5px rgba(0, 0, 0, 0.12)", + "0px 8px 10px -5px rgba(0, 0, 0, 0.2),0px 16px 24px 2px rgba(0, 0, 0, 0.14),0px 6px 30px 5px rgba(0, 0, 0, 0.12)", + "0px 8px 11px -5px rgba(0, 0, 0, 0.2),0px 17px 26px 2px rgba(0, 0, 0, 0.14),0px 6px 32px 5px rgba(0, 0, 0, 0.12)", + "0px 9px 11px -5px rgba(0, 0, 0, 0.2),0px 18px 28px 2px rgba(0, 0, 0, 0.14),0px 7px 34px 6px rgba(0, 0, 0, 0.12)", + "0px 9px 12px -6px rgba(0, 0, 0, 0.2),0px 19px 29px 2px rgba(0, 0, 0, 0.14),0px 7px 36px 6px rgba(0, 0, 0, 0.12)", + "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 20px 31px 3px rgba(0, 0, 0, 0.14),0px 8px 38px 7px rgba(0, 0, 0, 0.12)", + "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 21px 33px 3px rgba(0, 0, 0, 0.14),0px 8px 40px 7px rgba(0, 0, 0, 0.12)", + "0px 10px 14px -6px rgba(0, 0, 0, 0.2),0px 22px 35px 3px rgba(0, 0, 0, 0.14),0px 8px 42px 7px rgba(0, 0, 0, 0.12)", + "0px 11px 14px -7px rgba(0, 0, 0, 0.2),0px 23px 36px 3px rgba(0, 0, 0, 0.14),0px 9px 44px 8px rgba(0, 0, 0, 0.12)", + "0px 11px 15px -7px rgba(0, 0, 0, 0.2),0px 24px 38px 3px rgba(0, 0, 0, 0.14),0px 9px 46px 8px rgba(0, 0, 0, 0.12)", + ], + "shape": Object { + "borderRadius": 4, + }, + "spacing": Object { + "unit": 8, + }, + "transitions": Object { + "create": [Function], + "duration": Object { + "complex": 375, + "enteringScreen": 225, + "leavingScreen": 195, + "short": 250, + "shorter": 200, + "shortest": 150, + "standard": 300, + }, + "easing": Object { + "easeIn": "cubic-bezier(0.4, 0, 1, 1)", + "easeInOut": "cubic-bezier(0.4, 0, 0.2, 1)", + "easeOut": "cubic-bezier(0.0, 0, 0.2, 1)", + "sharp": "cubic-bezier(0.4, 0, 0.6, 1)", + }, + "getAutoHeightDuration": [Function], + }, + "typography": Object { + "body1": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 400, + "lineHeight": "1.46429em", + }, + "body2": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 500, + "lineHeight": "1.71429em", + }, + "button": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 500, + "textTransform": "uppercase", + }, + "caption": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.75rem", + "fontWeight": 400, + "lineHeight": "1.375em", + }, + "display1": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "2.125rem", + "fontWeight": 400, + "lineHeight": "1.20588em", + }, + "display2": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "2.8125rem", + "fontWeight": 400, + "lineHeight": "1.13333em", + "marginLeft": "-.02em", + }, + "display3": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "3.5rem", + "fontWeight": 400, + "letterSpacing": "-.02em", + "lineHeight": "1.30357em", + "marginLeft": "-.02em", + }, + "display4": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "7rem", + "fontWeight": 300, + "letterSpacing": "-.04em", + "lineHeight": "1.14286em", + "marginLeft": "-.04em", + }, + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": 14, + "fontWeightLight": 300, + "fontWeightMedium": 500, + "fontWeightRegular": 400, + "headline": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1.5rem", + "fontWeight": 400, + "lineHeight": "1.35417em", + }, + "pxToRem": [Function], + "round": [Function], + "subheading": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1rem", + "fontWeight": 400, + "lineHeight": "1.5em", + }, + "title": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1.3125rem", + "fontWeight": 500, + "lineHeight": "1.16667em", + }, + }, + "zIndex": Object { + "appBar": 1100, + "drawer": 1200, + "mobileStepper": 1000, + "modal": 1300, + "snackbar": 1400, + "tooltip": 1500, + }, + } + } + transition={true} + /> + + + +
+
+ + + + + + + + + Start time + + + + + + + + + + + + + + + + + Start time + + + } + className="MuiTooltip-popper-36" + id={null} + open={false} + placement="bottom" + transition={true} + > + + Start time + + + } + className="MuiTooltip-popper-36" + disablePortal={false} + id={null} + open={false} + placement="bottom" + theme={ + Object { + "breakpoints": Object { + "between": [Function], + "down": [Function], + "keys": Array [ + "xs", + "sm", + "md", + "lg", + "xl", + ], + "only": [Function], + "up": [Function], + "values": Object { + "lg": 1280, + "md": 960, + "sm": 600, + "xl": 1920, + "xs": 0, + }, + "width": [Function], + }, + "direction": "ltr", + "mixins": Object { + "gutters": [Function], + "toolbar": Object { + "@media (min-width:0px) and (orientation: landscape)": Object { + "minHeight": 48, + }, + "@media (min-width:600px)": Object { + "minHeight": 64, + }, + "minHeight": 56, + }, + }, + "overrides": Object {}, + "palette": Object { + "action": Object { + "active": "rgba(0, 0, 0, 0.54)", + "disabled": "rgba(0, 0, 0, 0.26)", + "disabledBackground": "rgba(0, 0, 0, 0.12)", + "hover": "rgba(0, 0, 0, 0.08)", + "hoverOpacity": 0.08, + "selected": "rgba(0, 0, 0, 0.14)", + }, + "augmentColor": [Function], + "background": Object { + "default": "#fafafa", + "paper": "#fff", + }, + "common": Object { + "black": "#000", + "white": "#fff", + }, + "contrastThreshold": 3, + "divider": "rgba(0, 0, 0, 0.12)", + "error": Object { + "contrastText": "#fff", + "dark": "#d32f2f", + "light": "#e57373", + "main": "#f44336", + }, + "getContrastText": [Function], + "grey": Object { + "100": "#f5f5f5", + "200": "#eeeeee", + "300": "#e0e0e0", + "400": "#bdbdbd", + "50": "#fafafa", + "500": "#9e9e9e", + "600": "#757575", + "700": "#616161", + "800": "#424242", + "900": "#212121", + "A100": "#d5d5d5", + "A200": "#aaaaaa", + "A400": "#303030", + "A700": "#616161", + }, + "primary": Object { + "contrastText": "#fff", + "dark": "#303f9f", + "light": "#7986cb", + "main": "#3f51b5", + }, + "secondary": Object { + "contrastText": "#fff", + "dark": "#c51162", + "light": "#ff4081", + "main": "#f50057", + }, + "text": Object { + "disabled": "rgba(0, 0, 0, 0.38)", + "hint": "rgba(0, 0, 0, 0.38)", + "primary": "rgba(0, 0, 0, 0.87)", + "secondary": "rgba(0, 0, 0, 0.54)", + }, + "tonalOffset": 0.2, + "type": "light", + }, + "props": Object {}, + "shadows": Array [ + "none", + "0px 1px 3px 0px rgba(0, 0, 0, 0.2),0px 1px 1px 0px rgba(0, 0, 0, 0.14),0px 2px 1px -1px rgba(0, 0, 0, 0.12)", + "0px 1px 5px 0px rgba(0, 0, 0, 0.2),0px 2px 2px 0px rgba(0, 0, 0, 0.14),0px 3px 1px -2px rgba(0, 0, 0, 0.12)", + "0px 1px 8px 0px rgba(0, 0, 0, 0.2),0px 3px 4px 0px rgba(0, 0, 0, 0.14),0px 3px 3px -2px rgba(0, 0, 0, 0.12)", + "0px 2px 4px -1px rgba(0, 0, 0, 0.2),0px 4px 5px 0px rgba(0, 0, 0, 0.14),0px 1px 10px 0px rgba(0, 0, 0, 0.12)", + "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 5px 8px 0px rgba(0, 0, 0, 0.14),0px 1px 14px 0px rgba(0, 0, 0, 0.12)", + "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 6px 10px 0px rgba(0, 0, 0, 0.14),0px 1px 18px 0px rgba(0, 0, 0, 0.12)", + "0px 4px 5px -2px rgba(0, 0, 0, 0.2),0px 7px 10px 1px rgba(0, 0, 0, 0.14),0px 2px 16px 1px rgba(0, 0, 0, 0.12)", + "0px 5px 5px -3px rgba(0, 0, 0, 0.2),0px 8px 10px 1px rgba(0, 0, 0, 0.14),0px 3px 14px 2px rgba(0, 0, 0, 0.12)", + "0px 5px 6px -3px rgba(0, 0, 0, 0.2),0px 9px 12px 1px rgba(0, 0, 0, 0.14),0px 3px 16px 2px rgba(0, 0, 0, 0.12)", + "0px 6px 6px -3px rgba(0, 0, 0, 0.2),0px 10px 14px 1px rgba(0, 0, 0, 0.14),0px 4px 18px 3px rgba(0, 0, 0, 0.12)", + "0px 6px 7px -4px rgba(0, 0, 0, 0.2),0px 11px 15px 1px rgba(0, 0, 0, 0.14),0px 4px 20px 3px rgba(0, 0, 0, 0.12)", + "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 12px 17px 2px rgba(0, 0, 0, 0.14),0px 5px 22px 4px rgba(0, 0, 0, 0.12)", + "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 13px 19px 2px rgba(0, 0, 0, 0.14),0px 5px 24px 4px rgba(0, 0, 0, 0.12)", + "0px 7px 9px -4px rgba(0, 0, 0, 0.2),0px 14px 21px 2px rgba(0, 0, 0, 0.14),0px 5px 26px 4px rgba(0, 0, 0, 0.12)", + "0px 8px 9px -5px rgba(0, 0, 0, 0.2),0px 15px 22px 2px rgba(0, 0, 0, 0.14),0px 6px 28px 5px rgba(0, 0, 0, 0.12)", + "0px 8px 10px -5px rgba(0, 0, 0, 0.2),0px 16px 24px 2px rgba(0, 0, 0, 0.14),0px 6px 30px 5px rgba(0, 0, 0, 0.12)", + "0px 8px 11px -5px rgba(0, 0, 0, 0.2),0px 17px 26px 2px rgba(0, 0, 0, 0.14),0px 6px 32px 5px rgba(0, 0, 0, 0.12)", + "0px 9px 11px -5px rgba(0, 0, 0, 0.2),0px 18px 28px 2px rgba(0, 0, 0, 0.14),0px 7px 34px 6px rgba(0, 0, 0, 0.12)", + "0px 9px 12px -6px rgba(0, 0, 0, 0.2),0px 19px 29px 2px rgba(0, 0, 0, 0.14),0px 7px 36px 6px rgba(0, 0, 0, 0.12)", + "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 20px 31px 3px rgba(0, 0, 0, 0.14),0px 8px 38px 7px rgba(0, 0, 0, 0.12)", + "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 21px 33px 3px rgba(0, 0, 0, 0.14),0px 8px 40px 7px rgba(0, 0, 0, 0.12)", + "0px 10px 14px -6px rgba(0, 0, 0, 0.2),0px 22px 35px 3px rgba(0, 0, 0, 0.14),0px 8px 42px 7px rgba(0, 0, 0, 0.12)", + "0px 11px 14px -7px rgba(0, 0, 0, 0.2),0px 23px 36px 3px rgba(0, 0, 0, 0.14),0px 9px 44px 8px rgba(0, 0, 0, 0.12)", + "0px 11px 15px -7px rgba(0, 0, 0, 0.2),0px 24px 38px 3px rgba(0, 0, 0, 0.14),0px 9px 46px 8px rgba(0, 0, 0, 0.12)", + ], + "shape": Object { + "borderRadius": 4, + }, + "spacing": Object { + "unit": 8, + }, + "transitions": Object { + "create": [Function], + "duration": Object { + "complex": 375, + "enteringScreen": 225, + "leavingScreen": 195, + "short": 250, + "shorter": 200, + "shortest": 150, + "standard": 300, + }, + "easing": Object { + "easeIn": "cubic-bezier(0.4, 0, 1, 1)", + "easeInOut": "cubic-bezier(0.4, 0, 0.2, 1)", + "easeOut": "cubic-bezier(0.0, 0, 0.2, 1)", + "sharp": "cubic-bezier(0.4, 0, 0.6, 1)", + }, + "getAutoHeightDuration": [Function], + }, + "typography": Object { + "body1": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 400, + "lineHeight": "1.46429em", + }, + "body2": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 500, + "lineHeight": "1.71429em", + }, + "button": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 500, + "textTransform": "uppercase", + }, + "caption": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.75rem", + "fontWeight": 400, + "lineHeight": "1.375em", + }, + "display1": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "2.125rem", + "fontWeight": 400, + "lineHeight": "1.20588em", + }, + "display2": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "2.8125rem", + "fontWeight": 400, + "lineHeight": "1.13333em", + "marginLeft": "-.02em", + }, + "display3": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "3.5rem", + "fontWeight": 400, + "letterSpacing": "-.02em", + "lineHeight": "1.30357em", + "marginLeft": "-.02em", + }, + "display4": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "7rem", + "fontWeight": 300, + "letterSpacing": "-.04em", + "lineHeight": "1.14286em", + "marginLeft": "-.04em", + }, + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": 14, + "fontWeightLight": 300, + "fontWeightMedium": 500, + "fontWeightRegular": 400, + "headline": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1.5rem", + "fontWeight": 400, + "lineHeight": "1.35417em", + }, + "pxToRem": [Function], + "round": [Function], + "subheading": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1rem", + "fontWeight": 400, + "lineHeight": "1.5em", + }, + "title": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1.3125rem", + "fontWeight": 500, + "lineHeight": "1.16667em", + }, + }, + "zIndex": Object { + "appBar": 1100, + "drawer": 1200, + "mobileStepper": 1000, + "modal": 1300, + "snackbar": 1400, + "tooltip": 1500, + }, + } + } + transition={true} + /> + + + +
+
+
+
+ No runs found. +
+
+
+ + Rows per page: + + + + +
+ + } + value={10} + > + + 10 + , + + 20 + , + + 50 + , + + 100 + , + ], + "classes": Object { + "disabled": "MuiSelect-disabled-57", + "filled": "MuiSelect-filled-54", + "icon": "MuiSelect-icon-58", + "outlined": "MuiSelect-outlined-55", + "root": "MuiSelect-root-52", + "select": "MuiSelect-select-53", + "selectMenu": "MuiSelect-selectMenu-56", + }, + "displayEmpty": false, + "multiple": false, + "onClose": undefined, + "onOpen": undefined, + "open": undefined, + "renderValue": undefined, + "type": undefined, + "variant": "standard", + } + } + onChange={[Function]} + value={10} + > + + 10 + , + + 20 + , + + 50 + , + + 100 + , + ], + "classes": Object { + "disabled": "MuiSelect-disabled-57", + "filled": "MuiSelect-filled-54", + "icon": "MuiSelect-icon-58", + "outlined": "MuiSelect-outlined-55", + "root": "MuiSelect-root-52", + "select": "MuiSelect-select-53", + "selectMenu": "MuiSelect-selectMenu-56", + }, + "displayEmpty": false, + "multiple": false, + "onClose": undefined, + "onOpen": undefined, + "open": undefined, + "renderValue": undefined, + "type": undefined, + "variant": "standard", + } + } + multiline={false} + onChange={[Function]} + type="text" + value={10} + > + + 10 + , + + 20 + , + + 50 + , + + 100 + , + ], + "classes": Object { + "disabled": "MuiSelect-disabled-57", + "filled": "MuiSelect-filled-54", + "icon": "MuiSelect-icon-58", + "outlined": "MuiSelect-outlined-55", + "root": "MuiSelect-root-52", + "select": "MuiSelect-select-53", + "selectMenu": "MuiSelect-selectMenu-56", + }, + "displayEmpty": false, + "multiple": false, + "onClose": undefined, + "onOpen": undefined, + "open": undefined, + "renderValue": undefined, + "type": undefined, + "variant": "standard", + } + } + multiline={false} + onChange={[Function]} + type="text" + value={10} + > +
+ +
+
+ 10 +
+ + + + + + + + + + + + 10 +
+ } + id="menu-" + onClose={[Function]} + open={false} + > + + 10 +
+ } + classes={ + Object { + "paper": "MuiMenu-paper-89", + } + } + disableAutoFocusItem={false} + id="menu-" + onClose={[Function]} + open={false} + theme={ + Object { + "breakpoints": Object { + "between": [Function], + "down": [Function], + "keys": Array [ + "xs", + "sm", + "md", + "lg", + "xl", + ], + "only": [Function], + "up": [Function], + "values": Object { + "lg": 1280, + "md": 960, + "sm": 600, + "xl": 1920, + "xs": 0, + }, + "width": [Function], + }, + "direction": "ltr", + "mixins": Object { + "gutters": [Function], + "toolbar": Object { + "@media (min-width:0px) and (orientation: landscape)": Object { + "minHeight": 48, + }, + "@media (min-width:600px)": Object { + "minHeight": 64, + }, + "minHeight": 56, + }, + }, + "overrides": Object {}, + "palette": Object { + "action": Object { + "active": "rgba(0, 0, 0, 0.54)", + "disabled": "rgba(0, 0, 0, 0.26)", + "disabledBackground": "rgba(0, 0, 0, 0.12)", + "hover": "rgba(0, 0, 0, 0.08)", + "hoverOpacity": 0.08, + "selected": "rgba(0, 0, 0, 0.14)", + }, + "augmentColor": [Function], + "background": Object { + "default": "#fafafa", + "paper": "#fff", + }, + "common": Object { + "black": "#000", + "white": "#fff", + }, + "contrastThreshold": 3, + "divider": "rgba(0, 0, 0, 0.12)", + "error": Object { + "contrastText": "#fff", + "dark": "#d32f2f", + "light": "#e57373", + "main": "#f44336", + }, + "getContrastText": [Function], + "grey": Object { + "100": "#f5f5f5", + "200": "#eeeeee", + "300": "#e0e0e0", + "400": "#bdbdbd", + "50": "#fafafa", + "500": "#9e9e9e", + "600": "#757575", + "700": "#616161", + "800": "#424242", + "900": "#212121", + "A100": "#d5d5d5", + "A200": "#aaaaaa", + "A400": "#303030", + "A700": "#616161", + }, + "primary": Object { + "contrastText": "#fff", + "dark": "#303f9f", + "light": "#7986cb", + "main": "#3f51b5", + }, + "secondary": Object { + "contrastText": "#fff", + "dark": "#c51162", + "light": "#ff4081", + "main": "#f50057", + }, + "text": Object { + "disabled": "rgba(0, 0, 0, 0.38)", + "hint": "rgba(0, 0, 0, 0.38)", + "primary": "rgba(0, 0, 0, 0.87)", + "secondary": "rgba(0, 0, 0, 0.54)", + }, + "tonalOffset": 0.2, + "type": "light", + }, + "props": Object {}, + "shadows": Array [ + "none", + "0px 1px 3px 0px rgba(0, 0, 0, 0.2),0px 1px 1px 0px rgba(0, 0, 0, 0.14),0px 2px 1px -1px rgba(0, 0, 0, 0.12)", + "0px 1px 5px 0px rgba(0, 0, 0, 0.2),0px 2px 2px 0px rgba(0, 0, 0, 0.14),0px 3px 1px -2px rgba(0, 0, 0, 0.12)", + "0px 1px 8px 0px rgba(0, 0, 0, 0.2),0px 3px 4px 0px rgba(0, 0, 0, 0.14),0px 3px 3px -2px rgba(0, 0, 0, 0.12)", + "0px 2px 4px -1px rgba(0, 0, 0, 0.2),0px 4px 5px 0px rgba(0, 0, 0, 0.14),0px 1px 10px 0px rgba(0, 0, 0, 0.12)", + "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 5px 8px 0px rgba(0, 0, 0, 0.14),0px 1px 14px 0px rgba(0, 0, 0, 0.12)", + "0px 3px 5px -1px rgba(0, 0, 0, 0.2),0px 6px 10px 0px rgba(0, 0, 0, 0.14),0px 1px 18px 0px rgba(0, 0, 0, 0.12)", + "0px 4px 5px -2px rgba(0, 0, 0, 0.2),0px 7px 10px 1px rgba(0, 0, 0, 0.14),0px 2px 16px 1px rgba(0, 0, 0, 0.12)", + "0px 5px 5px -3px rgba(0, 0, 0, 0.2),0px 8px 10px 1px rgba(0, 0, 0, 0.14),0px 3px 14px 2px rgba(0, 0, 0, 0.12)", + "0px 5px 6px -3px rgba(0, 0, 0, 0.2),0px 9px 12px 1px rgba(0, 0, 0, 0.14),0px 3px 16px 2px rgba(0, 0, 0, 0.12)", + "0px 6px 6px -3px rgba(0, 0, 0, 0.2),0px 10px 14px 1px rgba(0, 0, 0, 0.14),0px 4px 18px 3px rgba(0, 0, 0, 0.12)", + "0px 6px 7px -4px rgba(0, 0, 0, 0.2),0px 11px 15px 1px rgba(0, 0, 0, 0.14),0px 4px 20px 3px rgba(0, 0, 0, 0.12)", + "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 12px 17px 2px rgba(0, 0, 0, 0.14),0px 5px 22px 4px rgba(0, 0, 0, 0.12)", + "0px 7px 8px -4px rgba(0, 0, 0, 0.2),0px 13px 19px 2px rgba(0, 0, 0, 0.14),0px 5px 24px 4px rgba(0, 0, 0, 0.12)", + "0px 7px 9px -4px rgba(0, 0, 0, 0.2),0px 14px 21px 2px rgba(0, 0, 0, 0.14),0px 5px 26px 4px rgba(0, 0, 0, 0.12)", + "0px 8px 9px -5px rgba(0, 0, 0, 0.2),0px 15px 22px 2px rgba(0, 0, 0, 0.14),0px 6px 28px 5px rgba(0, 0, 0, 0.12)", + "0px 8px 10px -5px rgba(0, 0, 0, 0.2),0px 16px 24px 2px rgba(0, 0, 0, 0.14),0px 6px 30px 5px rgba(0, 0, 0, 0.12)", + "0px 8px 11px -5px rgba(0, 0, 0, 0.2),0px 17px 26px 2px rgba(0, 0, 0, 0.14),0px 6px 32px 5px rgba(0, 0, 0, 0.12)", + "0px 9px 11px -5px rgba(0, 0, 0, 0.2),0px 18px 28px 2px rgba(0, 0, 0, 0.14),0px 7px 34px 6px rgba(0, 0, 0, 0.12)", + "0px 9px 12px -6px rgba(0, 0, 0, 0.2),0px 19px 29px 2px rgba(0, 0, 0, 0.14),0px 7px 36px 6px rgba(0, 0, 0, 0.12)", + "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 20px 31px 3px rgba(0, 0, 0, 0.14),0px 8px 38px 7px rgba(0, 0, 0, 0.12)", + "0px 10px 13px -6px rgba(0, 0, 0, 0.2),0px 21px 33px 3px rgba(0, 0, 0, 0.14),0px 8px 40px 7px rgba(0, 0, 0, 0.12)", + "0px 10px 14px -6px rgba(0, 0, 0, 0.2),0px 22px 35px 3px rgba(0, 0, 0, 0.14),0px 8px 42px 7px rgba(0, 0, 0, 0.12)", + "0px 11px 14px -7px rgba(0, 0, 0, 0.2),0px 23px 36px 3px rgba(0, 0, 0, 0.14),0px 9px 44px 8px rgba(0, 0, 0, 0.12)", + "0px 11px 15px -7px rgba(0, 0, 0, 0.2),0px 24px 38px 3px rgba(0, 0, 0, 0.14),0px 9px 46px 8px rgba(0, 0, 0, 0.12)", + ], + "shape": Object { + "borderRadius": 4, + }, + "spacing": Object { + "unit": 8, + }, + "transitions": Object { + "create": [Function], + "duration": Object { + "complex": 375, + "enteringScreen": 225, + "leavingScreen": 195, + "short": 250, + "shorter": 200, + "shortest": 150, + "standard": 300, + }, + "easing": Object { + "easeIn": "cubic-bezier(0.4, 0, 1, 1)", + "easeInOut": "cubic-bezier(0.4, 0, 0.2, 1)", + "easeOut": "cubic-bezier(0.0, 0, 0.2, 1)", + "sharp": "cubic-bezier(0.4, 0, 0.6, 1)", + }, + "getAutoHeightDuration": [Function], + }, + "typography": Object { + "body1": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 400, + "lineHeight": "1.46429em", + }, + "body2": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 500, + "lineHeight": "1.71429em", + }, + "button": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.875rem", + "fontWeight": 500, + "textTransform": "uppercase", + }, + "caption": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "0.75rem", + "fontWeight": 400, + "lineHeight": "1.375em", + }, + "display1": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "2.125rem", + "fontWeight": 400, + "lineHeight": "1.20588em", + }, + "display2": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "2.8125rem", + "fontWeight": 400, + "lineHeight": "1.13333em", + "marginLeft": "-.02em", + }, + "display3": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "3.5rem", + "fontWeight": 400, + "letterSpacing": "-.02em", + "lineHeight": "1.30357em", + "marginLeft": "-.02em", + }, + "display4": Object { + "color": "rgba(0, 0, 0, 0.54)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "7rem", + "fontWeight": 300, + "letterSpacing": "-.04em", + "lineHeight": "1.14286em", + "marginLeft": "-.04em", + }, + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": 14, + "fontWeightLight": 300, + "fontWeightMedium": 500, + "fontWeightRegular": 400, + "headline": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1.5rem", + "fontWeight": 400, + "lineHeight": "1.35417em", + }, + "pxToRem": [Function], + "round": [Function], + "subheading": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1rem", + "fontWeight": 400, + "lineHeight": "1.5em", + }, + "title": Object { + "color": "rgba(0, 0, 0, 0.87)", + "fontFamily": "\\"Roboto\\", \\"Helvetica\\", \\"Arial\\", sans-serif", + "fontSize": "1.3125rem", + "fontWeight": 500, + "lineHeight": "1.16667em", + }, + }, + "zIndex": Object { + "appBar": 1100, + "drawer": 1200, + "mobileStepper": 1000, + "modal": 1300, + "snackbar": 1400, + "tooltip": 1500, + }, + } + } + transitionDuration="auto" + > + + 10 +
+ } + anchorOrigin={ + Object { + "horizontal": "left", + "vertical": "top", + } + } + getContentAnchorEl={[Function]} + id="menu-" + onClose={[Function]} + onEnter={[Function]} + open={false} + transformOrigin={ + Object { + "horizontal": "left", + "vertical": "top", + } + } + transitionDuration="auto" + > + + 10 +
+ } + anchorOrigin={ + Object { + "horizontal": "left", + "vertical": "top", + } + } + anchorReference="anchorEl" + classes={ + Object { + "paper": "MuiPopover-paper-90", + } + } + elevation={8} + getContentAnchorEl={[Function]} + id="menu-" + marginThreshold={16} + onClose={[Function]} + onEnter={[Function]} + open={false} + transformOrigin={ + Object { + "horizontal": "left", + "vertical": "top", + } + } + transitionDuration="auto" + > + } + id="menu-" + onClose={[Function]} + open={false} + > + } + disableAutoFocus={false} + disableBackdropClick={false} + disableEnforceFocus={false} + disableEscapeKeyDown={false} + disablePortal={false} + disableRestoreFocus={false} + hideBackdrop={false} + id="menu-" + keepMounted={false} + manager={ + ModalManager { + "containers": Array [], + "data": Array [], + "handleContainerOverflow": true, + "hideSiblingNodes": true, + "modals": Array [], + } + } + onClose={[Function]} + open={false} + /> + + + + + +
+ +
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +`; + +exports[`RunList renders a empty metric container when a metric has value of zero 1`] = `
`; + +exports[`RunList renders an empty metric when there is no data 1`] = `
`; + +exports[`RunList renders an empty metric when there is no data 2`] = `
`; + +exports[`RunList renders an empty metric when there is no data 3`] = `
`; + +exports[`RunList renders experiment name as link to its details page 1`] = ` + + + test experiment + + +`; + +exports[`RunList renders metric buffer 1`] = ` +
+`; + +exports[`RunList renders no experiment name 1`] = ` +
+ - +
+`; + +exports[`RunList renders no pipeline name 1`] = ` +
+ - +
+`; + +exports[`RunList renders percentage metric 1`] = ` +
+
+ 30.000% +
+
+`; + +exports[`RunList renders pipeline name as link to its details page 1`] = ` + + + test pipeline + + +`; + +exports[`RunList renders raw metric 1`] = ` +
+
+ 55.000 +
+
+`; + +exports[`RunList renders raw metric that is greater than its max value 1`] = ` +
+ 105.000 +
+`; + +exports[`RunList renders raw metric that is less than its min value 1`] = ` +
+ 5.000 +
+`; + +exports[`RunList renders raw metric with zero max/min values 1`] = ` +
+ 15.000 +
+`; + +exports[`RunList renders run name as link to its details page 1`] = ` + + + test run + + +`; + +exports[`RunList renders status as icon 1`] = ` + + + + + +`; + exports[`RunList renders the empty experience 1`] = `
`; +exports[`RunList shows experiment name 1`] = ` +
+ +
+`; + +exports[`RunList shows pipeline name 1`] = ` +
+ +
+`; + exports[`RunList shows run time for each run 1`] = `