From bcfe703b8af6fd74993d897efb5bf0e93ad6bed6 Mon Sep 17 00:00:00 2001 From: Alan Greene Date: Fri, 16 Aug 2019 18:51:42 +0100 Subject: [PATCH] Continue moving components to @tektoncd/dashboard-components This also involves restructuring some of the components so they no longer embed containers. In these cases, the containers are passed as props by the parent so the components remain purely presentational and are more easily reused outside the context of the dashboard application. - new presentational component for PipelineRuns list (excludes create button/dialog, etc.) - stories and tests for this too, which we didn't have before - pass the Rebuild button as a prop to RunHeader (making RunHeader a purely presentational component, also fixes a bug where we displayed the Rebuild button in some cases where we didn't have enough info to rebuild) - pass the Log container as a prop to StepDetails (making StepDetails a purely presentational component) - the rest of the components just needed a `git mv` and update the import references --- package-lock.json | 1 + packages/components/package.json | 1 + .../components/CancelButton/CancelButton.js | 0 .../components/CancelButton/CancelButton.scss | 0 .../CancelButton/CancelButton.stories.js | 0 .../CancelButton/CancelButton.test.js | 0 .../src}/components/CancelButton/index.js | 0 .../components/ErrorBoundary/ErrorBoundary.js | 3 +- .../ErrorBoundary/ErrorBoundary.test.js | 0 .../src}/components/ErrorBoundary/index.js | 0 .../components/PipelineRuns/PipelineRuns.js | 148 ++++++++++++++++++ .../components/PipelineRuns/PipelineRuns.scss | 45 ++++++ .../PipelineRuns/PipelineRuns.stories.js | 84 ++++++++++ .../PipelineRuns/PipelineRuns.test.js | 72 +++++++++ .../src/components/PipelineRuns/index.js | 14 ++ .../src}/components/Rebuild/Rebuild.js | 4 +- .../src}/components/Rebuild/Rebuild.scss | 0 .../src}/components/Rebuild/Rebuild.test.js | 19 ++- .../src}/components/Rebuild/index.js | 0 .../ResourceTable/ResourceTable.test.js | 2 +- .../src}/components/RunHeader/RunHeader.js | 20 +-- .../src}/components/RunHeader/RunHeader.scss | 0 .../components/RunHeader/RunHeader.stories.js | 0 .../components/RunHeader/RunHeader.test.js | 0 .../src}/components/RunHeader/index.js | 0 .../StepDefinition/StepDefinition.js | 2 +- .../StepDefinition/StepDefinition.scss | 0 .../StepDefinition/StepDefinition.stories.js | 1 + .../StepDefinition/StepDefinition.test.js | 0 .../src}/components/StepDefinition/index.js | 0 .../components/StepDetails/StepDetails.js | 15 +- .../components/StepDetails/StepDetails.scss | 0 .../StepDetails/StepDetails.stories.js | 39 +++++ .../StepDetails/StepDetails.test.js | 0 .../src}/components/StepDetails/index.js | 0 .../components/src}/components/Task/Task.js | 0 .../components/src}/components/Task/Task.scss | 0 .../src}/components/Task/Task.stories.js | 0 .../src}/components/Task/Task.test.js | 0 .../components/src}/components/Task/index.js | 0 .../src}/components/TaskTree/TaskTree.js | 0 .../src}/components/TaskTree/TaskTree.scss | 0 .../components/TaskTree/TaskTree.stories.js | 0 .../src}/components/TaskTree/TaskTree.test.js | 0 .../src}/components/TaskTree/index.js | 0 packages/components/src/components/index.js | 9 ++ packages/utils/package.json | 2 +- packages/utils/src/utils/index.js | 38 +++++ packages/utils/src/utils/index.test.js | 41 ++++- src/api/index.js | 2 +- src/components/SecretsTable/SecretsTable.js | 3 +- .../StepDetails/StepDetails.stories.js | 35 ----- src/constants/index.js | 2 - src/containers/ClusterTasks/ClusterTasks.js | 3 +- .../CreatePipelineRun/CreatePipelineRun.js | 2 +- .../CreatePipelineRun.test.js | 2 +- .../CustomResourceDefinition.js | 3 +- src/containers/Extension/Extension.js | 3 +- src/containers/Extensions/Extensions.js | 3 +- .../ImportResources/ImportResources.js | 3 +- .../ImportResources/ImportResources.test.js | 4 +- src/containers/Log/Log.js | 4 +- .../NamespacesDropdown/NamespacesDropdown.js | 2 +- .../PipelineResource/PipelineResource.js | 2 +- .../PipelineResources/PipelineResources.js | 8 +- .../PipelineResourcesDropdown.js | 2 +- src/containers/PipelineRun/PipelineRun.js | 37 +++-- src/containers/PipelineRuns/PipelineRuns.js | 129 ++------------- src/containers/Pipelines/Pipelines.js | 8 +- .../PipelinesDropdown/PipelinesDropdown.js | 2 +- src/containers/ResourceList/ResourceList.js | 9 +- src/containers/Secrets/Secrets.js | 3 +- .../ServiceAccountsDropdown.js | 2 +- src/containers/SideNav/SideNav.js | 3 +- src/containers/SideNav/SideNav.test.js | 3 +- src/containers/TaskRun/TaskRun.js | 20 ++- src/containers/TaskRunList/TaskRunList.js | 13 +- src/containers/TaskRuns/TaskRuns.js | 20 ++- src/containers/Tasks/Tasks.js | 8 +- src/containers/index.js | 1 + src/reducers/namespaces.js | 2 +- src/reducers/namespaces.test.js | 3 +- src/reducers/reducerCreators.test.js | 4 +- src/reducers/secrets.js | 3 +- src/reducers/selectorCreators.js | 2 +- src/reducers/selectorCreators.test.js | 3 +- src/utils/index.js | 36 ----- src/utils/index.test.js | 22 --- 88 files changed, 649 insertions(+), 327 deletions(-) rename {src => packages/components/src}/components/CancelButton/CancelButton.js (100%) rename {src => packages/components/src}/components/CancelButton/CancelButton.scss (100%) rename {src => packages/components/src}/components/CancelButton/CancelButton.stories.js (100%) rename {src => packages/components/src}/components/CancelButton/CancelButton.test.js (100%) rename {src => packages/components/src}/components/CancelButton/index.js (100%) rename {src => packages/components/src}/components/ErrorBoundary/ErrorBoundary.js (95%) rename {src => packages/components/src}/components/ErrorBoundary/ErrorBoundary.test.js (100%) rename {src => packages/components/src}/components/ErrorBoundary/index.js (100%) create mode 100644 packages/components/src/components/PipelineRuns/PipelineRuns.js create mode 100644 packages/components/src/components/PipelineRuns/PipelineRuns.scss create mode 100644 packages/components/src/components/PipelineRuns/PipelineRuns.stories.js create mode 100644 packages/components/src/components/PipelineRuns/PipelineRuns.test.js create mode 100644 packages/components/src/components/PipelineRuns/index.js rename {src => packages/components/src}/components/Rebuild/Rebuild.js (96%) rename {src => packages/components/src}/components/Rebuild/Rebuild.scss (100%) rename {src => packages/components/src}/components/Rebuild/Rebuild.test.js (84%) rename {src => packages/components/src}/components/Rebuild/index.js (100%) rename {src => packages/components/src}/components/RunHeader/RunHeader.js (80%) rename {src => packages/components/src}/components/RunHeader/RunHeader.scss (100%) rename {src => packages/components/src}/components/RunHeader/RunHeader.stories.js (100%) rename {src => packages/components/src}/components/RunHeader/RunHeader.test.js (100%) rename {src => packages/components/src}/components/RunHeader/index.js (100%) rename {src => packages/components/src}/components/StepDefinition/StepDefinition.js (98%) rename {src => packages/components/src}/components/StepDefinition/StepDefinition.scss (100%) rename {src => packages/components/src}/components/StepDefinition/StepDefinition.stories.js (99%) rename {src => packages/components/src}/components/StepDefinition/StepDefinition.test.js (100%) rename {src => packages/components/src}/components/StepDefinition/index.js (100%) rename {src => packages/components/src}/components/StepDetails/StepDetails.js (83%) rename {src => packages/components/src}/components/StepDetails/StepDetails.scss (100%) create mode 100644 packages/components/src/components/StepDetails/StepDetails.stories.js rename {src => packages/components/src}/components/StepDetails/StepDetails.test.js (100%) rename {src => packages/components/src}/components/StepDetails/index.js (100%) rename {src => packages/components/src}/components/Task/Task.js (100%) rename {src => packages/components/src}/components/Task/Task.scss (100%) rename {src => packages/components/src}/components/Task/Task.stories.js (100%) rename {src => packages/components/src}/components/Task/Task.test.js (100%) rename {src => packages/components/src}/components/Task/index.js (100%) rename {src => packages/components/src}/components/TaskTree/TaskTree.js (100%) rename {src => packages/components/src}/components/TaskTree/TaskTree.scss (100%) rename {src => packages/components/src}/components/TaskTree/TaskTree.stories.js (100%) rename {src => packages/components/src}/components/TaskTree/TaskTree.test.js (100%) rename {src => packages/components/src}/components/TaskTree/index.js (100%) delete mode 100644 src/components/StepDetails/StepDetails.stories.js diff --git a/package-lock.json b/package-lock.json index 642d9c4dd..7394f88e3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3682,6 +3682,7 @@ "@carbon/icons-react": "^10.3.0", "@tektoncd/dashboard-utils": "file:packages/utils", "ansi-to-react": "^5.0.0", + "js-yaml": "^3.13.0", "prop-types": "^15.7.2", "react-window": "^1.8.5" } diff --git a/packages/components/package.json b/packages/components/package.json index ddf9397d6..2f7d7fe1e 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -13,6 +13,7 @@ "@carbon/icons-react": "^10.3.0", "@tektoncd/dashboard-utils": "file:../utils", "ansi-to-react": "^5.0.0", + "js-yaml": "^3.13.0", "prop-types": "^15.7.2", "react-window": "^1.8.5" }, diff --git a/src/components/CancelButton/CancelButton.js b/packages/components/src/components/CancelButton/CancelButton.js similarity index 100% rename from src/components/CancelButton/CancelButton.js rename to packages/components/src/components/CancelButton/CancelButton.js diff --git a/src/components/CancelButton/CancelButton.scss b/packages/components/src/components/CancelButton/CancelButton.scss similarity index 100% rename from src/components/CancelButton/CancelButton.scss rename to packages/components/src/components/CancelButton/CancelButton.scss diff --git a/src/components/CancelButton/CancelButton.stories.js b/packages/components/src/components/CancelButton/CancelButton.stories.js similarity index 100% rename from src/components/CancelButton/CancelButton.stories.js rename to packages/components/src/components/CancelButton/CancelButton.stories.js diff --git a/src/components/CancelButton/CancelButton.test.js b/packages/components/src/components/CancelButton/CancelButton.test.js similarity index 100% rename from src/components/CancelButton/CancelButton.test.js rename to packages/components/src/components/CancelButton/CancelButton.test.js diff --git a/src/components/CancelButton/index.js b/packages/components/src/components/CancelButton/index.js similarity index 100% rename from src/components/CancelButton/index.js rename to packages/components/src/components/CancelButton/index.js diff --git a/src/components/ErrorBoundary/ErrorBoundary.js b/packages/components/src/components/ErrorBoundary/ErrorBoundary.js similarity index 95% rename from src/components/ErrorBoundary/ErrorBoundary.js rename to packages/components/src/components/ErrorBoundary/ErrorBoundary.js index aa36b5b37..9e38ec413 100644 --- a/src/components/ErrorBoundary/ErrorBoundary.js +++ b/packages/components/src/components/ErrorBoundary/ErrorBoundary.js @@ -13,8 +13,7 @@ limitations under the License. import React from 'react'; import { InlineNotification } from 'carbon-components-react'; - -import { getErrorMessage } from '../../utils'; +import { getErrorMessage } from '@tektoncd/dashboard-utils'; class ErrorBoundary extends React.Component { state = { error: null }; diff --git a/src/components/ErrorBoundary/ErrorBoundary.test.js b/packages/components/src/components/ErrorBoundary/ErrorBoundary.test.js similarity index 100% rename from src/components/ErrorBoundary/ErrorBoundary.test.js rename to packages/components/src/components/ErrorBoundary/ErrorBoundary.test.js diff --git a/src/components/ErrorBoundary/index.js b/packages/components/src/components/ErrorBoundary/index.js similarity index 100% rename from src/components/ErrorBoundary/index.js rename to packages/components/src/components/ErrorBoundary/index.js diff --git a/packages/components/src/components/PipelineRuns/PipelineRuns.js b/packages/components/src/components/PipelineRuns/PipelineRuns.js new file mode 100644 index 000000000..6e8793cfa --- /dev/null +++ b/packages/components/src/components/PipelineRuns/PipelineRuns.js @@ -0,0 +1,148 @@ +/* +Copyright 2019 The Tekton Authors +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from 'react'; +import { injectIntl } from 'react-intl'; +import { Link } from 'react-router-dom'; +import { + StructuredListBody, + StructuredListCell, + StructuredListHead, + StructuredListRow, + StructuredListWrapper +} from 'carbon-components-react'; +import { + ALL_NAMESPACES, + getStatus, + getStatusIcon, + isRunning, + urls +} from '@tektoncd/dashboard-utils'; + +import { CancelButton } from '..'; + +import './PipelineRuns.scss'; + +const PipelineRuns = ({ + cancelPipelineRun, + intl, + pipelineName, + pipelineRuns, + selectedNamespace +}) => ( + + + + PipelineRun + {!pipelineName && ( + Pipeline + )} + {selectedNamespace === ALL_NAMESPACES && ( + Namespace + )} + + {intl.formatMessage({ + id: 'dashboard.pipelineRuns.status', + defaultMessage: 'Status' + })} + + + {intl.formatMessage({ + id: 'dashboard.pipelineRuns.transitionTime', + defaultMessage: 'Last Transition Time' + })} + + + + + + {!pipelineRuns.length && ( + + + {pipelineName ? ( + No PipelineRuns for {pipelineName} + ) : ( + No PipelineRuns + )} + + + )} + {pipelineRuns.map(pipelineRun => { + const { name: pipelineRunName, namespace } = pipelineRun.metadata; + const pipelineRefName = pipelineRun.spec.pipelineRef.name; + const { lastTransitionTime, reason, status } = getStatus(pipelineRun); + + return ( + + + + {pipelineRunName} + + + {!pipelineName && ( + + + {pipelineRefName} + + + )} + {selectedNamespace === ALL_NAMESPACES && ( + {namespace} + )} + + {getStatusIcon({ reason, status })} + {pipelineRun.status.conditions + ? pipelineRun.status.conditions[0].message + : ''} + + {lastTransitionTime} + + {isRunning(reason, status) && ( + + cancelPipelineRun({ + name: pipelineRunName, + namespace + }) + } + /> + )} + + + ); + })} + + +); + +export default injectIntl(PipelineRuns); diff --git a/packages/components/src/components/PipelineRuns/PipelineRuns.scss b/packages/components/src/components/PipelineRuns/PipelineRuns.scss new file mode 100644 index 000000000..4b2ccae77 --- /dev/null +++ b/packages/components/src/components/PipelineRuns/PipelineRuns.scss @@ -0,0 +1,45 @@ +/* +Copyright 2019 The Tekton Authors +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +@import '../../scss/vars'; + +.definition .status { + .status-icon { + margin-right: 0.5em; + vertical-align: sub; + } + + &:not([data-status]) { + .status-icon { + fill: $unknown; + } + } + + &[data-status='True'] { + .status-icon { + fill: $success; + } + } + + &[data-status='False'] { + .status-icon { + fill: $failed; + } + } + + &[data-status='Unknown'][data-reason='Running'] { + .status-icon { + fill: $running; + } + } +} diff --git a/packages/components/src/components/PipelineRuns/PipelineRuns.stories.js b/packages/components/src/components/PipelineRuns/PipelineRuns.stories.js new file mode 100644 index 000000000..a3e526fac --- /dev/null +++ b/packages/components/src/components/PipelineRuns/PipelineRuns.stories.js @@ -0,0 +1,84 @@ +/* +Copyright 2019 The Tekton Authors +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from 'react'; +import { storiesOf } from '@storybook/react'; +import StoryRouter from 'storybook-react-router'; + +import PipelineRuns from '.'; + +storiesOf('PipelineRuns', module) + .addDecorator(StoryRouter()) + .add('default', () => ( + {}} + /> + )) + .add('empty', () => ( + {}} + /> + )); diff --git a/packages/components/src/components/PipelineRuns/PipelineRuns.test.js b/packages/components/src/components/PipelineRuns/PipelineRuns.test.js new file mode 100644 index 000000000..4297006c6 --- /dev/null +++ b/packages/components/src/components/PipelineRuns/PipelineRuns.test.js @@ -0,0 +1,72 @@ +/* +Copyright 2019 The Tekton Authors +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from 'react'; +import { ALL_NAMESPACES } from '@tektoncd/dashboard-utils'; + +import { renderWithIntl, renderWithRouter } from '../../utils/test'; +import PipelineRuns from './PipelineRuns'; + +it('PipelineRuns renders empty state', () => { + const { queryByText } = renderWithIntl(); + expect(queryByText(/no pipelineruns/i)).toBeTruthy(); + expect(queryByText(/namespace/i)).toBeFalsy(); +}); + +it('PipelineRuns renders optional columns', () => { + const { queryByText } = renderWithIntl( + + ); + expect(queryByText(/namespace/i)).toBeTruthy(); + expect(queryByText(/pipeline/i)).toBeTruthy(); + expect(queryByText(/no pipelineruns for some-pipeline/i)).toBeTruthy(); +}); + +it('PipelineRuns renders data', () => { + const pipelineRunName = 'pipeline-run-20190816124708'; + const { queryByText } = renderWithRouter( + + ); + expect(queryByText(pipelineRunName)).toBeTruthy(); + expect(queryByText(/all tasks have completed executing/i)).toBeTruthy(); +}); diff --git a/packages/components/src/components/PipelineRuns/index.js b/packages/components/src/components/PipelineRuns/index.js new file mode 100644 index 000000000..51aa37cf5 --- /dev/null +++ b/packages/components/src/components/PipelineRuns/index.js @@ -0,0 +1,14 @@ +/* +Copyright 2019 The Tekton Authors +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +export default from './PipelineRuns'; diff --git a/src/components/Rebuild/Rebuild.js b/packages/components/src/components/Rebuild/Rebuild.js similarity index 96% rename from src/components/Rebuild/Rebuild.js rename to packages/components/src/components/Rebuild/Rebuild.js index f9ae2a159..cdcae057d 100644 --- a/src/components/Rebuild/Rebuild.js +++ b/packages/components/src/components/Rebuild/Rebuild.js @@ -15,7 +15,6 @@ import React, { Component } from 'react'; import { Button } from 'carbon-components-react'; import { urls } from '@tektoncd/dashboard-utils'; import Restart from '@carbon/icons-react/lib/restart/32'; -import { rebuildPipelineRun } from '../../api'; import './Rebuild.scss'; export class Rebuild extends Component { @@ -30,7 +29,8 @@ export class Rebuild extends Component { pipelinerunname: this.props.runName }; - rebuildPipelineRun(namespace, payload) + this.props + .rebuildPipelineRun(namespace, payload) .then(headers => { const logsURL = headers.get('Content-Location'); const newPipelineRunName = logsURL.substring( diff --git a/src/components/Rebuild/Rebuild.scss b/packages/components/src/components/Rebuild/Rebuild.scss similarity index 100% rename from src/components/Rebuild/Rebuild.scss rename to packages/components/src/components/Rebuild/Rebuild.scss diff --git a/src/components/Rebuild/Rebuild.test.js b/packages/components/src/components/Rebuild/Rebuild.test.js similarity index 84% rename from src/components/Rebuild/Rebuild.test.js rename to packages/components/src/components/Rebuild/Rebuild.test.js index aa42fd460..efe408693 100644 --- a/src/components/Rebuild/Rebuild.test.js +++ b/packages/components/src/components/Rebuild/Rebuild.test.js @@ -2,7 +2,6 @@ import React from 'react'; import { fireEvent, waitForElement } from 'react-testing-library'; import { renderWithRouter } from '../../utils/test'; import { Rebuild } from './Rebuild'; -import * as API from '../../api'; /* Rebuild should sit on the PipelineRun page and display notifications there It would be useful to have tests at the container level too, but for now just do it at the component level */ @@ -28,10 +27,14 @@ const headers = { it('rebuild button creates API call with correct parameters', () => { const rebuildMock = jest - .spyOn(API, 'rebuildPipelineRun') + .fn() .mockImplementation(() => Promise.resolve(headers)); const { getByText } = renderWithRouter( - + ); const theButton = getByText('Rebuild'); fireEvent.click(theButton); @@ -41,11 +44,15 @@ it('rebuild button creates API call with correct parameters', () => { }); it('rebuild button is ghost styled', async () => { - jest - .spyOn(API, 'rebuildPipelineRun') + const rebuildMock = jest + .fn() .mockImplementation(() => Promise.resolve(headers)); const { getByTestId } = renderWithRouter( - + ); const rebuildButton = getByTestId('rebuild-btn'); const rebuildButtonIsGhost = rebuildButton.getElementsByClassName( diff --git a/src/components/Rebuild/index.js b/packages/components/src/components/Rebuild/index.js similarity index 100% rename from src/components/Rebuild/index.js rename to packages/components/src/components/Rebuild/index.js diff --git a/packages/components/src/components/ResourceTable/ResourceTable.test.js b/packages/components/src/components/ResourceTable/ResourceTable.test.js index e3ba2b230..1d38c99af 100644 --- a/packages/components/src/components/ResourceTable/ResourceTable.test.js +++ b/packages/components/src/components/ResourceTable/ResourceTable.test.js @@ -15,7 +15,7 @@ import React from 'react'; import { render } from 'react-testing-library'; import ResourceTable from './ResourceTable'; -it('ResourcesTable renders with one row', () => { +it('ResourceTable renders with one row', () => { const title = 'testTitle'; const id = 'id'; const headerValue = 'header'; diff --git a/src/components/RunHeader/RunHeader.js b/packages/components/src/components/RunHeader/RunHeader.js similarity index 80% rename from src/components/RunHeader/RunHeader.js rename to packages/components/src/components/RunHeader/RunHeader.js index 7481eae07..0a4e358f8 100644 --- a/src/components/RunHeader/RunHeader.js +++ b/packages/components/src/components/RunHeader/RunHeader.js @@ -13,20 +13,12 @@ limitations under the License. import React, { Component } from 'react'; import { SkeletonPlaceholder, Tab, Tabs } from 'carbon-components-react'; -import { getStatusIcon } from '../../utils'; -import Rebuild from '../Rebuild'; +import { getStatusIcon } from '@tektoncd/dashboard-utils'; import './RunHeader.scss'; class RunHeader extends Component { render() { - const { - lastTransitionTime, - loading, - pipelineRun, - runName, - reason, - status - } = this.props; + const { lastTransitionTime, loading, runName, reason, status } = this.props; return (
{reason} {lastTransitionTime} - {pipelineRun && ( - - )} + {this.props.children} ) ); diff --git a/src/components/RunHeader/RunHeader.scss b/packages/components/src/components/RunHeader/RunHeader.scss similarity index 100% rename from src/components/RunHeader/RunHeader.scss rename to packages/components/src/components/RunHeader/RunHeader.scss diff --git a/src/components/RunHeader/RunHeader.stories.js b/packages/components/src/components/RunHeader/RunHeader.stories.js similarity index 100% rename from src/components/RunHeader/RunHeader.stories.js rename to packages/components/src/components/RunHeader/RunHeader.stories.js diff --git a/src/components/RunHeader/RunHeader.test.js b/packages/components/src/components/RunHeader/RunHeader.test.js similarity index 100% rename from src/components/RunHeader/RunHeader.test.js rename to packages/components/src/components/RunHeader/RunHeader.test.js diff --git a/src/components/RunHeader/index.js b/packages/components/src/components/RunHeader/index.js similarity index 100% rename from src/components/RunHeader/index.js rename to packages/components/src/components/RunHeader/index.js diff --git a/src/components/StepDefinition/StepDefinition.js b/packages/components/src/components/StepDefinition/StepDefinition.js similarity index 98% rename from src/components/StepDefinition/StepDefinition.js rename to packages/components/src/components/StepDefinition/StepDefinition.js index 29ea171fa..c5783ab7c 100644 --- a/src/components/StepDefinition/StepDefinition.js +++ b/packages/components/src/components/StepDefinition/StepDefinition.js @@ -18,8 +18,8 @@ import { Link } from 'react-router-dom'; import jsYaml from 'js-yaml'; import { FormattedMessage, injectIntl } from 'react-intl'; import { urls } from '@tektoncd/dashboard-utils'; -import { ResourceTable } from '@tektoncd/dashboard-components'; +import { ResourceTable } from '..'; import './StepDefinition.scss'; const resourceTable = (title, namespace, resources, intl) => { diff --git a/src/components/StepDefinition/StepDefinition.scss b/packages/components/src/components/StepDefinition/StepDefinition.scss similarity index 100% rename from src/components/StepDefinition/StepDefinition.scss rename to packages/components/src/components/StepDefinition/StepDefinition.scss diff --git a/src/components/StepDefinition/StepDefinition.stories.js b/packages/components/src/components/StepDefinition/StepDefinition.stories.js similarity index 99% rename from src/components/StepDefinition/StepDefinition.stories.js rename to packages/components/src/components/StepDefinition/StepDefinition.stories.js index 23d0cba0b..55901abb5 100644 --- a/src/components/StepDefinition/StepDefinition.stories.js +++ b/packages/components/src/components/StepDefinition/StepDefinition.stories.js @@ -13,6 +13,7 @@ limitations under the License. import React from 'react'; import { storiesOf } from '@storybook/react'; + import StepDefinition from './StepDefinition'; storiesOf('StepDefinition', module) diff --git a/src/components/StepDefinition/StepDefinition.test.js b/packages/components/src/components/StepDefinition/StepDefinition.test.js similarity index 100% rename from src/components/StepDefinition/StepDefinition.test.js rename to packages/components/src/components/StepDefinition/StepDefinition.test.js diff --git a/src/components/StepDefinition/index.js b/packages/components/src/components/StepDefinition/index.js similarity index 100% rename from src/components/StepDefinition/index.js rename to packages/components/src/components/StepDefinition/index.js diff --git a/src/components/StepDetails/StepDetails.js b/packages/components/src/components/StepDetails/StepDetails.js similarity index 83% rename from src/components/StepDetails/StepDetails.js rename to packages/components/src/components/StepDetails/StepDetails.js index a1dd4212f..4e04d4ff0 100644 --- a/src/components/StepDetails/StepDetails.js +++ b/packages/components/src/components/StepDetails/StepDetails.js @@ -14,10 +14,7 @@ limitations under the License. import { injectIntl } from 'react-intl'; import React from 'react'; import { Tab, Tabs } from 'carbon-components-react'; -import { StepDetailsHeader, StepStatus } from '@tektoncd/dashboard-components'; - -import Log from '../../containers/Log'; -import StepDefinition from '../StepDefinition'; +import { StepDefinition, StepDetailsHeader, StepStatus } from '..'; import './StepDetails.scss'; @@ -25,13 +22,13 @@ const StepDetails = props => { const { definition, intl, + logContainer, reason, status, stepName, stepStatus, taskRun } = props; - const { pod } = taskRun; return (
{ defaultMessage: 'Logs' })} > - + {logContainer} ; + +storiesOf('StepDetails', module) + .addDecorator(StoryRouter()) + .add('default', () => ( +
+ +
+ )); diff --git a/src/components/StepDetails/StepDetails.test.js b/packages/components/src/components/StepDetails/StepDetails.test.js similarity index 100% rename from src/components/StepDetails/StepDetails.test.js rename to packages/components/src/components/StepDetails/StepDetails.test.js diff --git a/src/components/StepDetails/index.js b/packages/components/src/components/StepDetails/index.js similarity index 100% rename from src/components/StepDetails/index.js rename to packages/components/src/components/StepDetails/index.js diff --git a/src/components/Task/Task.js b/packages/components/src/components/Task/Task.js similarity index 100% rename from src/components/Task/Task.js rename to packages/components/src/components/Task/Task.js diff --git a/src/components/Task/Task.scss b/packages/components/src/components/Task/Task.scss similarity index 100% rename from src/components/Task/Task.scss rename to packages/components/src/components/Task/Task.scss diff --git a/src/components/Task/Task.stories.js b/packages/components/src/components/Task/Task.stories.js similarity index 100% rename from src/components/Task/Task.stories.js rename to packages/components/src/components/Task/Task.stories.js diff --git a/src/components/Task/Task.test.js b/packages/components/src/components/Task/Task.test.js similarity index 100% rename from src/components/Task/Task.test.js rename to packages/components/src/components/Task/Task.test.js diff --git a/src/components/Task/index.js b/packages/components/src/components/Task/index.js similarity index 100% rename from src/components/Task/index.js rename to packages/components/src/components/Task/index.js diff --git a/src/components/TaskTree/TaskTree.js b/packages/components/src/components/TaskTree/TaskTree.js similarity index 100% rename from src/components/TaskTree/TaskTree.js rename to packages/components/src/components/TaskTree/TaskTree.js diff --git a/src/components/TaskTree/TaskTree.scss b/packages/components/src/components/TaskTree/TaskTree.scss similarity index 100% rename from src/components/TaskTree/TaskTree.scss rename to packages/components/src/components/TaskTree/TaskTree.scss diff --git a/src/components/TaskTree/TaskTree.stories.js b/packages/components/src/components/TaskTree/TaskTree.stories.js similarity index 100% rename from src/components/TaskTree/TaskTree.stories.js rename to packages/components/src/components/TaskTree/TaskTree.stories.js diff --git a/src/components/TaskTree/TaskTree.test.js b/packages/components/src/components/TaskTree/TaskTree.test.js similarity index 100% rename from src/components/TaskTree/TaskTree.test.js rename to packages/components/src/components/TaskTree/TaskTree.test.js diff --git a/src/components/TaskTree/index.js b/packages/components/src/components/TaskTree/index.js similarity index 100% rename from src/components/TaskTree/index.js rename to packages/components/src/components/TaskTree/index.js diff --git a/packages/components/src/components/index.js b/packages/components/src/components/index.js index f021cfac7..9c978388c 100644 --- a/packages/components/src/components/index.js +++ b/packages/components/src/components/index.js @@ -12,11 +12,20 @@ limitations under the License. */ export { default as Breadcrumbs } from './Breadcrumbs'; +export { default as CancelButton } from './CancelButton'; +export { default as ErrorBoundary } from './ErrorBoundary'; export { default as Header } from './Header'; export { default as Log } from './Log'; +export { default as PipelineRuns } from './PipelineRuns'; +export { default as Rebuild } from './Rebuild'; export { default as ResourceTable } from './ResourceTable'; +export { default as RunHeader } from './RunHeader'; export { default as Spinner } from './Spinner'; export { default as Step } from './Step'; +export { default as StepDefinition } from './StepDefinition'; +export { default as StepDetails } from './StepDetails'; export { default as StepDetailsHeader } from './StepDetailsHeader'; export { default as StepStatus } from './StepStatus'; +export { default as Task } from './Task'; export { default as TaskSkeleton } from './TaskSkeleton'; +export { default as TaskTree } from './TaskTree'; diff --git a/packages/utils/package.json b/packages/utils/package.json index c988a7b58..f5c4eec25 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,7 +1,7 @@ { "name": "@tektoncd/dashboard-utils", "version": "0.1.0", - "private": true, + "private": false, "main": "./dist/utils/index.js", "scripts": { "build": "rimraf dist && NODE_ENV=production babel src --out-dir dist --root-mode upward --ignore \"src/**/*.test.js,src/**/*.stories.js\"", diff --git a/packages/utils/src/utils/index.js b/packages/utils/src/utils/index.js index 1b8c4ebc1..975319ea4 100644 --- a/packages/utils/src/utils/index.js +++ b/packages/utils/src/utils/index.js @@ -11,9 +11,47 @@ See the License for the specific language governing permissions and limitations under the License. */ +import React from 'react'; +import CheckmarkFilled from '@carbon/icons-react/lib/checkmark--filled/16'; +import CloseFilled from '@carbon/icons-react/lib/close--filled/16'; +import { Spinner } from '@tektoncd/dashboard-components'; + export { paths, urls } from './router'; +export const ALL_NAMESPACES = '*'; + +export function getErrorMessage(error) { + if (!error || typeof error === 'string') { + return error; + } + + return ( + error.message || JSON.stringify(error, Object.getOwnPropertyNames(error)) + ); +} + export function getStatus(resource) { const { conditions = [] } = resource.status || {}; return conditions.find(condition => condition.type === 'Succeeded') || {}; } + +export function isRunning(reason, status) { + return ( + status === 'Unknown' && (reason === 'Running' || reason === 'Building') + ); +} + +export function getStatusIcon({ reason, status }) { + if (isRunning(reason, status)) { + return ; + } + + let Icon; + if (status === 'True') { + Icon = CheckmarkFilled; + } else if (status === 'False') { + Icon = CloseFilled; + } + + return Icon ? : null; +} diff --git a/packages/utils/src/utils/index.test.js b/packages/utils/src/utils/index.test.js index 5cd400390..8eff9b88d 100644 --- a/packages/utils/src/utils/index.test.js +++ b/packages/utils/src/utils/index.test.js @@ -11,7 +11,28 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { getStatus } from '.'; +import { getErrorMessage, getStatus, getStatusIcon, isRunning } from '.'; + +it('getErrorMessage falsy', () => { + expect(getErrorMessage()).toBeUndefined(); +}); + +it('getErrorMessage string', () => { + const error = 'this is an error message'; + expect(getErrorMessage(error)).toEqual(error); +}); + +it('getErrorMessage error object', () => { + const message = 'this is an error message'; + const error = new Error(message); + expect(getErrorMessage(error)).toEqual(message); +}); + +it('getErrorMessage custom object', () => { + const message = 'this is an error message'; + const error = { custom: message }; + expect(getErrorMessage(error)).toContain(`"custom":"${message}"`); +}); it('getStatus', () => { const taskRun = { @@ -42,3 +63,21 @@ it('getStatus with no status', () => { const status = getStatus(taskRun); expect(status).toEqual({}); }); + +it('isRunning', () => { + expect(isRunning('Running', 'Unknown')).toBe(true); + expect(isRunning('Building', 'Unknown')).toBe(true); + expect(isRunning('?', 'Unknown')).toBe(false); + expect(isRunning('Running', '?')).toBe(false); +}); + +it('getStatusIcon', () => { + let icon = getStatusIcon({ reason: 'Running', status: 'Unknown' }); + expect(icon).not.toBeNull(); + icon = getStatusIcon({ status: 'True' }); + expect(icon).not.toBeNull(); + icon = getStatusIcon({ status: 'False' }); + expect(icon).not.toBeNull(); + icon = getStatusIcon({}); + expect(icon).toBeNull(); +}); diff --git a/src/api/index.js b/src/api/index.js index 0c014790d..5f252ed26 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -11,8 +11,8 @@ See the License for the specific language governing permissions and limitations under the License. */ +import { ALL_NAMESPACES } from '@tektoncd/dashboard-utils'; import { deleteRequest, get, post, put } from './comms'; -import { ALL_NAMESPACES } from '../constants'; export function getAPIRoot() { const { href, hash } = window.location; diff --git a/src/components/SecretsTable/SecretsTable.js b/src/components/SecretsTable/SecretsTable.js index 0668022d3..311b72314 100644 --- a/src/components/SecretsTable/SecretsTable.js +++ b/src/components/SecretsTable/SecretsTable.js @@ -25,8 +25,9 @@ import { } from 'carbon-components-react'; import Add from '@carbon/icons-react/lib/add/16'; import Delete from '@carbon/icons-react/lib/delete/16'; +import { ALL_NAMESPACES } from '@tektoncd/dashboard-utils'; + import './Secrets.scss'; -import { ALL_NAMESPACES } from '../../constants'; const { TableContainer, diff --git a/src/components/StepDetails/StepDetails.stories.js b/src/components/StepDetails/StepDetails.stories.js deleted file mode 100644 index 6fa527669..000000000 --- a/src/components/StepDetails/StepDetails.stories.js +++ /dev/null @@ -1,35 +0,0 @@ -/* -Copyright 2019 The Tekton Authors -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import React from 'react'; -import { Provider } from 'react-redux'; -import { storiesOf } from '@storybook/react'; -import StoryRouter from 'storybook-react-router'; - -import { configureStore } from '../../store'; -import StepDetails from './StepDetails'; - -storiesOf('StepDetails', module) - .addDecorator(StoryRouter()) - .add('default', () => ( - -
- -
-
- )); diff --git a/src/constants/index.js b/src/constants/index.js index dfd9878cf..c37201f64 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -1,5 +1,3 @@ -export const ALL_NAMESPACES = '*'; - export const messages = { en: { 'dashboard.pipelineRuns.transitionTime': 'Last Transition Time', diff --git a/src/containers/ClusterTasks/ClusterTasks.js b/src/containers/ClusterTasks/ClusterTasks.js index 3efb649f8..4537e5db0 100644 --- a/src/containers/ClusterTasks/ClusterTasks.js +++ b/src/containers/ClusterTasks/ClusterTasks.js @@ -23,7 +23,7 @@ import { StructuredListSkeleton, StructuredListWrapper } from 'carbon-components-react'; -import { urls } from '@tektoncd/dashboard-utils'; +import { getErrorMessage, urls } from '@tektoncd/dashboard-utils'; import Information16 from '@carbon/icons-react/lib/information/16'; import { fetchClusterTasks } from '../../actions/tasks'; @@ -32,7 +32,6 @@ import { getClusterTasksErrorMessage, isFetchingClusterTasks } from '../../reducers'; -import { getErrorMessage } from '../../utils'; import '../../components/Definitions/Definitions.scss'; diff --git a/src/containers/CreatePipelineRun/CreatePipelineRun.js b/src/containers/CreatePipelineRun/CreatePipelineRun.js index bee8e3e01..fc59d608f 100644 --- a/src/containers/CreatePipelineRun/CreatePipelineRun.js +++ b/src/containers/CreatePipelineRun/CreatePipelineRun.js @@ -20,6 +20,7 @@ import { Modal, TextInput } from 'carbon-components-react'; +import { ALL_NAMESPACES } from '@tektoncd/dashboard-utils'; import { NamespacesDropdown, PipelineResourcesDropdown, @@ -31,7 +32,6 @@ import { createPipelineRunAtProxy } from '../../api'; import { getStore } from '../../store/index'; import './CreatePipelineRun.scss'; -import { ALL_NAMESPACES } from '../../constants'; const NAMESPACE = 'namespace'; const PIPELINE_REF = 'pipelineRef'; diff --git a/src/containers/CreatePipelineRun/CreatePipelineRun.test.js b/src/containers/CreatePipelineRun/CreatePipelineRun.test.js index 4719b83d5..d9b1c5754 100644 --- a/src/containers/CreatePipelineRun/CreatePipelineRun.test.js +++ b/src/containers/CreatePipelineRun/CreatePipelineRun.test.js @@ -23,11 +23,11 @@ import { import { Provider } from 'react-redux'; import thunk from 'redux-thunk'; import configureStore from 'redux-mock-store'; +import { ALL_NAMESPACES } from '@tektoncd/dashboard-utils'; import CreatePipelineRun from './CreatePipelineRun'; import * as API from '../../api'; import * as store from '../../store'; import * as reducers from '../../reducers'; -import { ALL_NAMESPACES } from '../../constants'; const namespacesTestStore = { namespaces: { diff --git a/src/containers/CustomResourceDefinition/CustomResourceDefinition.js b/src/containers/CustomResourceDefinition/CustomResourceDefinition.js index 5b7bc2d1f..e54d33227 100644 --- a/src/containers/CustomResourceDefinition/CustomResourceDefinition.js +++ b/src/containers/CustomResourceDefinition/CustomResourceDefinition.js @@ -17,12 +17,11 @@ import { CodeSnippetSkeleton, InlineNotification } from 'carbon-components-react'; - import jsYaml from 'js-yaml'; +import { getErrorMessage } from '@tektoncd/dashboard-utils'; import { fetchClusterTask, fetchTask } from '../../actions/tasks'; import { fetchPipeline } from '../../actions/pipelines'; -import { getErrorMessage } from '../../utils'; import { getClusterTask, diff --git a/src/containers/Extension/Extension.js b/src/containers/Extension/Extension.js index d46f03c9f..e6b26f5dc 100644 --- a/src/containers/Extension/Extension.js +++ b/src/containers/Extension/Extension.js @@ -12,10 +12,9 @@ limitations under the License. */ import React, { Component, Suspense } from 'react'; +import { ErrorBoundary } from '@tektoncd/dashboard-components'; import { paths, urls } from '@tektoncd/dashboard-utils'; -import ErrorBoundary from '../../components/ErrorBoundary'; - import * as actions from './actions'; import * as selectors from '../../reducers'; import './globals'; diff --git a/src/containers/Extensions/Extensions.js b/src/containers/Extensions/Extensions.js index 076a09c28..d46c361c7 100644 --- a/src/containers/Extensions/Extensions.js +++ b/src/containers/Extensions/Extensions.js @@ -23,14 +23,13 @@ import { StructuredListSkeleton, StructuredListWrapper } from 'carbon-components-react'; -import { urls } from '@tektoncd/dashboard-utils'; +import { getErrorMessage, urls } from '@tektoncd/dashboard-utils'; import { getExtensions, getExtensionsErrorMessage, isFetchingExtensions } from '../../reducers'; -import { getErrorMessage } from '../../utils'; import '../../components/Definitions/Definitions.scss'; diff --git a/src/containers/ImportResources/ImportResources.js b/src/containers/ImportResources/ImportResources.js index 60e0405f0..1c19b15e3 100644 --- a/src/containers/ImportResources/ImportResources.js +++ b/src/containers/ImportResources/ImportResources.js @@ -21,9 +21,8 @@ import { } from 'carbon-components-react'; import { connect } from 'react-redux'; import { Link } from 'react-router-dom'; -import { urls } from '@tektoncd/dashboard-utils'; +import { ALL_NAMESPACES, urls } from '@tektoncd/dashboard-utils'; -import { ALL_NAMESPACES } from '../../constants'; import { createPipelineRun, getInstallProperties } from '../../api'; import { getSelectedNamespace } from '../../reducers'; import { NamespacesDropdown, ServiceAccountsDropdown } from '..'; diff --git a/src/containers/ImportResources/ImportResources.test.js b/src/containers/ImportResources/ImportResources.test.js index 78d3ed2a0..c240f2eb6 100644 --- a/src/containers/ImportResources/ImportResources.test.js +++ b/src/containers/ImportResources/ImportResources.test.js @@ -16,14 +16,12 @@ import { fireEvent, render, waitForElement } from 'react-testing-library'; import { Provider } from 'react-redux'; import thunk from 'redux-thunk'; import configureStore from 'redux-mock-store'; -import { urls } from '@tektoncd/dashboard-utils'; +import { ALL_NAMESPACES, urls } from '@tektoncd/dashboard-utils'; import { renderWithRouter } from '../../utils/test'; import ImportResourcesContainer from './ImportResources'; import * as API from '../../api'; -import { ALL_NAMESPACES } from '../../constants'; - beforeEach(jest.resetAllMocks); describe('ImportResources component', () => { diff --git a/src/containers/Log/Log.js b/src/containers/Log/Log.js index f8ec7c9ee..e5ba7aca0 100644 --- a/src/containers/Log/Log.js +++ b/src/containers/Log/Log.js @@ -92,10 +92,10 @@ export class LoggingContainer extends Component { } render() { - const { stepName, stepStatus } = this.props; + const { stepStatus } = this.props; const { reason } = (stepStatus && stepStatus.terminated) || {}; const { logs } = this.state; - return ; + return ; } } diff --git a/src/containers/NamespacesDropdown/NamespacesDropdown.js b/src/containers/NamespacesDropdown/NamespacesDropdown.js index a680a5b9e..66772fdaf 100644 --- a/src/containers/NamespacesDropdown/NamespacesDropdown.js +++ b/src/containers/NamespacesDropdown/NamespacesDropdown.js @@ -13,10 +13,10 @@ limitations under the License. import React from 'react'; import { connect } from 'react-redux'; +import { ALL_NAMESPACES } from '@tektoncd/dashboard-utils'; import TooltipDropdown from '../../components/TooltipDropdown'; import { getNamespaces, isFetchingNamespaces } from '../../reducers'; -import { ALL_NAMESPACES } from '../../constants'; const NamespacesDropdown = props => { return ; diff --git a/src/containers/PipelineResource/PipelineResource.js b/src/containers/PipelineResource/PipelineResource.js index e389aed1c..2556593a0 100644 --- a/src/containers/PipelineResource/PipelineResource.js +++ b/src/containers/PipelineResource/PipelineResource.js @@ -19,13 +19,13 @@ import { DataTableSkeleton, InlineNotification } from 'carbon-components-react'; +import { getErrorMessage } from '@tektoncd/dashboard-utils'; import { getPipelineResource, getPipelineResourcesErrorMessage, isFetchingPipelineResources } from '../../reducers'; -import { getErrorMessage } from '../../utils'; import { fetchPipelineResource } from '../../actions/pipelineResources'; diff --git a/src/containers/PipelineResources/PipelineResources.js b/src/containers/PipelineResources/PipelineResources.js index c853ef35c..fb9c323d7 100644 --- a/src/containers/PipelineResources/PipelineResources.js +++ b/src/containers/PipelineResources/PipelineResources.js @@ -23,10 +23,12 @@ import { StructuredListSkeleton, StructuredListWrapper } from 'carbon-components-react'; -import { urls } from '@tektoncd/dashboard-utils'; +import { + ALL_NAMESPACES, + getErrorMessage, + urls +} from '@tektoncd/dashboard-utils'; -import { ALL_NAMESPACES } from '../../constants'; -import { getErrorMessage } from '../../utils'; import { fetchPipelineResources } from '../../actions/pipelineResources'; import { diff --git a/src/containers/PipelineResourcesDropdown/PipelineResourcesDropdown.js b/src/containers/PipelineResourcesDropdown/PipelineResourcesDropdown.js index 9c8e7d830..127a8b277 100644 --- a/src/containers/PipelineResourcesDropdown/PipelineResourcesDropdown.js +++ b/src/containers/PipelineResourcesDropdown/PipelineResourcesDropdown.js @@ -13,6 +13,7 @@ limitations under the License. import React from 'react'; import { connect } from 'react-redux'; +import { ALL_NAMESPACES } from '@tektoncd/dashboard-utils'; import { getPipelineResources, @@ -21,7 +22,6 @@ import { } from '../../reducers'; import { fetchPipelineResources } from '../../actions/pipelineResources'; import TooltipDropdown from '../../components/TooltipDropdown'; -import { ALL_NAMESPACES } from '../../constants'; class PipelineResourcesDropdown extends React.Component { componentDidMount() { diff --git a/src/containers/PipelineRun/PipelineRun.js b/src/containers/PipelineRun/PipelineRun.js index 67dd2de37..7dc3cdf1f 100644 --- a/src/containers/PipelineRun/PipelineRun.js +++ b/src/containers/PipelineRun/PipelineRun.js @@ -20,9 +20,14 @@ import { StructuredListSkeleton, ToastNotification } from 'carbon-components-react'; - import { injectIntl } from 'react-intl'; -import { getStatus } from '@tektoncd/dashboard-utils'; +import { + Rebuild, + RunHeader, + StepDetails, + TaskTree +} from '@tektoncd/dashboard-components'; +import { getErrorMessage, getStatus } from '@tektoncd/dashboard-utils'; import { getClusterTasks, @@ -37,11 +42,9 @@ import { import { fetchPipelineRun } from '../../actions/pipelineRuns'; import { fetchClusterTasks, fetchTasks } from '../../actions/tasks'; import { fetchTaskRuns } from '../../actions/taskRuns'; -import RunHeader from '../../components/RunHeader'; -import StepDetails from '../../components/StepDetails'; -import TaskTree from '../../components/TaskTree'; +import { Log } from '..'; +import { rebuildPipelineRun } from '../../api'; import { - getErrorMessage, selectedTask, selectedTaskRun, stepsStatus, @@ -254,6 +257,16 @@ export /* istanbul ignore next */ class PipelineRunContainer extends Component { taskRun ); + const logContainer = ( + + ); + return ( <> {showRebuildNotification && !showRebuildNotification.logsURL && ( @@ -290,12 +303,17 @@ export /* istanbul ignore next */ class PipelineRunContainer extends Component { + > + +
- - - - PipelineRun - {!pipelineName && ( - Pipeline - )} - {selectedNamespace === ALL_NAMESPACES && ( - Namespace - )} - - {intl.formatMessage({ - id: 'dashboard.pipelineRuns.status' - })} - - - {intl.formatMessage({ - id: 'dashboard.pipelineRuns.transitionTime' - })} - - - - - - {!pipelineRuns.length && ( - - - {pipelineName ? ( - No PipelineRuns for {pipelineName} - ) : ( - No PipelineRuns - )} - - - )} - {pipelineRuns.map(pipelineRun => { - const { name: pipelineRunName, namespace } = pipelineRun.metadata; - const pipelineRefName = pipelineRun.spec.pipelineRef.name; - const { lastTransitionTime, reason, status } = getStatus( - pipelineRun - ); - - return ( - - - - {pipelineRunName} - - - {!pipelineName && ( - - - {pipelineRefName} - - - )} - {selectedNamespace === ALL_NAMESPACES && ( - {namespace} - )} - - {getStatusIcon({ reason, status })} - {pipelineRun.status.conditions - ? pipelineRun.status.conditions[0].message - : ''} - - {lastTransitionTime} - - {isRunning(reason, status) && ( - - cancelPipelineRun({ - name: pipelineRunName, - namespace - }) - } - /> - )} - - - ); - })} - - + ); } diff --git a/src/containers/Pipelines/Pipelines.js b/src/containers/Pipelines/Pipelines.js index ac5bac2f4..9dc1a9720 100644 --- a/src/containers/Pipelines/Pipelines.js +++ b/src/containers/Pipelines/Pipelines.js @@ -25,9 +25,12 @@ import { StructuredListSkeleton, StructuredListWrapper } from 'carbon-components-react'; -import { urls } from '@tektoncd/dashboard-utils'; +import { + ALL_NAMESPACES, + getErrorMessage, + urls +} from '@tektoncd/dashboard-utils'; -import { ALL_NAMESPACES } from '../../constants'; import { fetchPipelines } from '../../actions/pipelines'; import { getPipelines, @@ -35,7 +38,6 @@ import { getSelectedNamespace, isFetchingPipelines } from '../../reducers'; -import { getErrorMessage } from '../../utils'; import '../../components/Definitions/Definitions.scss'; diff --git a/src/containers/PipelinesDropdown/PipelinesDropdown.js b/src/containers/PipelinesDropdown/PipelinesDropdown.js index 5ac817be5..0ec82f745 100644 --- a/src/containers/PipelinesDropdown/PipelinesDropdown.js +++ b/src/containers/PipelinesDropdown/PipelinesDropdown.js @@ -13,6 +13,7 @@ limitations under the License. import React from 'react'; import { connect } from 'react-redux'; +import { ALL_NAMESPACES } from '@tektoncd/dashboard-utils'; import { getPipelines, @@ -21,7 +22,6 @@ import { } from '../../reducers'; import { fetchPipelines } from '../../actions/pipelines'; import TooltipDropdown from '../../components/TooltipDropdown'; -import { ALL_NAMESPACES } from '../../constants'; class PipelinesDropdown extends React.Component { componentDidMount() { diff --git a/src/containers/ResourceList/ResourceList.js b/src/containers/ResourceList/ResourceList.js index 4247ea467..119434c95 100644 --- a/src/containers/ResourceList/ResourceList.js +++ b/src/containers/ResourceList/ResourceList.js @@ -24,9 +24,12 @@ import { } from 'carbon-components-react'; import { Link } from 'react-router-dom'; import { connect } from 'react-redux'; -import { urls } from '@tektoncd/dashboard-utils'; -import { getErrorMessage } from '../../utils'; -import { ALL_NAMESPACES } from '../../constants'; +import { + ALL_NAMESPACES, + getErrorMessage, + urls +} from '@tektoncd/dashboard-utils'; + import { getCustomResources } from '../../api'; import { getSelectedNamespace } from '../../reducers'; diff --git a/src/containers/Secrets/Secrets.js b/src/containers/Secrets/Secrets.js index 3e09ff5fc..cbb48214c 100644 --- a/src/containers/Secrets/Secrets.js +++ b/src/containers/Secrets/Secrets.js @@ -14,6 +14,8 @@ limitations under the License. import React, { Component } from 'react'; import { connect } from 'react-redux'; import { InlineNotification } from 'carbon-components-react'; +import { getErrorMessage } from '@tektoncd/dashboard-utils'; + import Modal from '../SecretsModal'; import DeleteModal from '../../components/SecretsDeleteModal'; import Table from '../../components/SecretsTable'; @@ -28,7 +30,6 @@ import { getSelectedNamespace, isFetchingSecrets } from '../../reducers'; -import { getErrorMessage } from '../../utils'; export /* istanbul ignore next */ class Secrets extends Component { constructor(props) { diff --git a/src/containers/ServiceAccountsDropdown/ServiceAccountsDropdown.js b/src/containers/ServiceAccountsDropdown/ServiceAccountsDropdown.js index 13907676f..b39767ea4 100644 --- a/src/containers/ServiceAccountsDropdown/ServiceAccountsDropdown.js +++ b/src/containers/ServiceAccountsDropdown/ServiceAccountsDropdown.js @@ -13,6 +13,7 @@ limitations under the License. import React from 'react'; import { connect } from 'react-redux'; +import { ALL_NAMESPACES } from '@tektoncd/dashboard-utils'; import { getSelectedNamespace, @@ -21,7 +22,6 @@ import { } from '../../reducers'; import { fetchServiceAccounts } from '../../actions/serviceAccounts'; import TooltipDropdown from '../../components/TooltipDropdown'; -import { ALL_NAMESPACES } from '../../constants'; class ServiceAccountsDropdown extends React.Component { componentDidMount() { diff --git a/src/containers/SideNav/SideNav.js b/src/containers/SideNav/SideNav.js index 53e6d9218..42f984a90 100644 --- a/src/containers/SideNav/SideNav.js +++ b/src/containers/SideNav/SideNav.js @@ -20,13 +20,12 @@ import { SideNavMenu, SideNavMenuItem } from 'carbon-components-react'; -import { urls } from '@tektoncd/dashboard-utils'; +import { ALL_NAMESPACES, urls } from '@tektoncd/dashboard-utils'; import { NamespacesDropdown } from '..'; import { selectNamespace } from '../../actions/namespaces'; import { getExtensions, getSelectedNamespace } from '../../reducers'; -import { ALL_NAMESPACES } from '../../constants'; import './SideNav.scss'; diff --git a/src/containers/SideNav/SideNav.test.js b/src/containers/SideNav/SideNav.test.js index 9ae813f0b..4c19fcbac 100644 --- a/src/containers/SideNav/SideNav.test.js +++ b/src/containers/SideNav/SideNav.test.js @@ -16,10 +16,9 @@ import { Provider } from 'react-redux'; import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import { fireEvent } from 'react-testing-library'; -import { paths } from '@tektoncd/dashboard-utils'; +import { ALL_NAMESPACES, paths } from '@tektoncd/dashboard-utils'; import { renderWithRouter } from '../../utils/test'; -import { ALL_NAMESPACES } from '../../constants'; import SideNavContainer, { SideNav } from './SideNav'; it('SideNav renders with extensions', () => { diff --git a/src/containers/TaskRun/TaskRun.js b/src/containers/TaskRun/TaskRun.js index 7757989d2..446567eab 100644 --- a/src/containers/TaskRun/TaskRun.js +++ b/src/containers/TaskRun/TaskRun.js @@ -18,6 +18,11 @@ import { InlineNotification, StructuredListSkeleton } from 'carbon-components-react'; +import { + RunHeader, + StepDetails, + TaskTree +} from '@tektoncd/dashboard-components'; import { getStatus } from '@tektoncd/dashboard-utils'; import { @@ -27,9 +32,7 @@ import { getTaskRunsErrorMessage } from '../../reducers'; -import RunHeader from '../../components/RunHeader'; -import StepDetails from '../../components/StepDetails'; -import TaskTree from '../../components/TaskTree'; +import { Log } from '..'; import { stepsStatus, taskRunStep } from '../../utils'; import '../../components/Run/Run.scss'; @@ -158,6 +161,16 @@ export /* istanbul ignore next */ class TaskRunContainer extends Component { taskRun ); + const logContainer = ( + + ); + return ( <> + ); + return ( <> { return { metadata: { diff --git a/src/reducers/secrets.js b/src/reducers/secrets.js index d58e42a77..fa4999cd2 100644 --- a/src/reducers/secrets.js +++ b/src/reducers/secrets.js @@ -13,8 +13,7 @@ limitations under the License. import { combineReducers } from 'redux'; import merge from 'lodash.merge'; - -import { ALL_NAMESPACES } from '../constants'; +import { ALL_NAMESPACES } from '@tektoncd/dashboard-utils'; function byNamespace(state = {}, action) { switch (action.type) { diff --git a/src/reducers/selectorCreators.js b/src/reducers/selectorCreators.js index e2654de95..225cdb370 100644 --- a/src/reducers/selectorCreators.js +++ b/src/reducers/selectorCreators.js @@ -11,7 +11,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { ALL_NAMESPACES } from '../constants'; +import { ALL_NAMESPACES } from '@tektoncd/dashboard-utils'; export function getCollection(state, namespace) { if (namespace === ALL_NAMESPACES) { diff --git a/src/reducers/selectorCreators.test.js b/src/reducers/selectorCreators.test.js index edc52dc40..30a117f49 100644 --- a/src/reducers/selectorCreators.test.js +++ b/src/reducers/selectorCreators.test.js @@ -11,8 +11,9 @@ See the License for the specific language governing permissions and limitations under the License. */ +import { ALL_NAMESPACES } from '@tektoncd/dashboard-utils'; + import { getCollection, getResource } from './selectorCreators'; -import { ALL_NAMESPACES } from '../constants'; it('getCollection', () => { const id = 'id'; diff --git a/src/utils/index.js b/src/utils/index.js index 940c09146..d893b42a6 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -11,43 +11,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React from 'react'; import snakeCase from 'lodash.snakecase'; -import CheckmarkFilled from '@carbon/icons-react/lib/checkmark--filled/16'; -import CloseFilled from '@carbon/icons-react/lib/close--filled/16'; - -import { Spinner } from '@tektoncd/dashboard-components'; - -export function getErrorMessage(error) { - if (!error || typeof error === 'string') { - return error; - } - - return ( - error.message || JSON.stringify(error, Object.getOwnPropertyNames(error)) - ); -} - -export function isRunning(reason, status) { - return ( - status === 'Unknown' && (reason === 'Running' || reason === 'Building') - ); -} - -export function getStatusIcon({ reason, status }) { - if (isRunning(reason, status)) { - return ; - } - - let Icon; - if (status === 'True') { - Icon = CheckmarkFilled; - } else if (status === 'False') { - Icon = CloseFilled; - } - - return Icon ? : null; -} export function taskRunStep(selectedStepId, taskRun) { if (!taskRun || !taskRun.steps) { diff --git a/src/utils/index.test.js b/src/utils/index.test.js index 1e13c0204..0b265640b 100644 --- a/src/utils/index.test.js +++ b/src/utils/index.test.js @@ -12,7 +12,6 @@ limitations under the License. */ import { - getErrorMessage, selectedTask, sortRunsByStartTime, stepsStatus, @@ -20,27 +19,6 @@ import { typeToPlural } from '.'; -it('getErrorMessage falsy', () => { - expect(getErrorMessage()).toBeUndefined(); -}); - -it('getErrorMessage string', () => { - const error = 'this is an error message'; - expect(getErrorMessage(error)).toEqual(error); -}); - -it('getErrorMessage error object', () => { - const message = 'this is an error message'; - const error = new Error(message); - expect(getErrorMessage(error)).toEqual(message); -}); - -it('getErrorMessage custom object', () => { - const message = 'this is an error message'; - const error = { custom: message }; - expect(getErrorMessage(error)).toContain(`"custom":"${message}"`); -}); - it('taskRunSteps with no taskRun', () => { const taskRun = null; const step = taskRunStep('selected run', taskRun);