diff --git a/.prettierrc.yaml b/.prettierrc.yaml index 5b0cda474c..8301dee3be 100644 --- a/.prettierrc.yaml +++ b/.prettierrc.yaml @@ -6,7 +6,7 @@ # There is extra configuration in those files specific to the Blue Ocean build process and mix of source languages. printWidth: 160 -parser: babylon +parser: babel tabWidth: 4 trailingComma: es5 singleQuote: true diff --git a/blueocean-core-js/src/js/index.ts b/blueocean-core-js/src/js/index.ts index 76369daf5a..f849f4fd0a 100644 --- a/blueocean-core-js/src/js/index.ts +++ b/blueocean-core-js/src/js/index.ts @@ -71,7 +71,7 @@ window.JenkinsBlueOceanCoreJSSSEConnected = false; // Create and export the SSE connection that will be shared by other // Blue Ocean components via this package. -export const sseConnection = sse.connect('jenkins-blueocean-core-js', function() { +export const sseConnection = sse.connect('jenkins-blueocean-core-js', function () { // Declare SSE is fully loaded and ready for events. // Mostly used by our ATH to prevent actions from happening // too quickly @@ -119,7 +119,6 @@ export const DEBUG = { disableMocksForI18n, }; -export { ComponentLink } from './utils/ComponentLink'; export { TimeManager } from './utils/TimeManager'; export { TimeHarmonizer, TimeHarmonizerUtil } from './components/TimeHarmonizer'; diff --git a/blueocean-core-js/src/js/utils/ComponentLink.js b/blueocean-core-js/src/js/utils/ComponentLink.js deleted file mode 100644 index 33a6547205..0000000000 --- a/blueocean-core-js/src/js/utils/ComponentLink.js +++ /dev/null @@ -1,27 +0,0 @@ -import { PropTypes, Component } from 'react'; -import { SandboxedComponent } from '@jenkins-cd/js-extensions'; - -export class ComponentLink { - constructor(props) { - if (props) { - for (const key of Object.keys(props)) { - this[key] = props[key]; - } - } - } - get view() { - const children = this.component; - return class ViewRenderer extends SandboxedComponent { - constructor(props) { - super(); - this.children = children; - } - }; - } - static propTypes = { - name: PropTypes.string.isRequired, - title: PropTypes.string.isRequired, - notification: PropTypes.string, - component: PropTypes.element.isRequired, - }; -} diff --git a/blueocean-dashboard/src/main/js/PipelineRoutes.jsx b/blueocean-dashboard/src/main/js/PipelineRoutes.jsx index 1d3c9106e0..9f75b4888b 100644 --- a/blueocean-dashboard/src/main/js/PipelineRoutes.jsx +++ b/blueocean-dashboard/src/main/js/PipelineRoutes.jsx @@ -1,7 +1,6 @@ import { Route, Redirect, IndexRedirect } from 'react-router'; import React from 'react'; -import { AppConfig, NotFound } from '@jenkins-cd/blueocean-core-js'; -import Extensions from '@jenkins-cd/js-extensions'; +import { AppConfig } from '@jenkins-cd/blueocean-core-js'; import { analytics } from './analytics'; import Dashboard from './Dashboard'; @@ -14,6 +13,9 @@ import { PipelineTrends, RunDetails, RunDetailsPipeline, + RunDetailsChanges, + RunDetailsArtifacts, + RunDetailsTests, } from './components'; import { CreatePipeline } from './creation'; @@ -125,27 +127,6 @@ function onLeaveCheckBackground() { const trends = AppConfig.isFeatureEnabled('trends'); -function getActions(extensionPoint, params, callback) { - Extensions.store.getExtensions([ extensionPoint ], Extensions.Utils.sortByOrdinal, (actions = []) => { - const action = actions.map(a => new a()).find(action => action.name === params.action); - if (action) { - callback(null, action.component); - } else { - callback(null, NotFound); - } - }); -} - -function getRunDetailsAction({ params }, callback) { - // TODO generify this - switch (params.action) { - case 'changes': analytics.trackPipelineRunChangesVisited(); break; - case 'tests': analytics.trackPipelineRunTestsVisited(); break; - case 'artifacts': analytics.trackPipelineRunArtifactsVisited(); break; - } - getActions('jenkins.run.actions', params, callback); -} - export default ( @@ -162,7 +143,9 @@ export default ( - + + + diff --git a/blueocean-dashboard/src/main/js/components/RunDetails.jsx b/blueocean-dashboard/src/main/js/components/RunDetails.jsx index 8c41a6bdb5..29a90c6677 100644 --- a/blueocean-dashboard/src/main/js/components/RunDetails.jsx +++ b/blueocean-dashboard/src/main/js/components/RunDetails.jsx @@ -19,7 +19,7 @@ const logger = logging.logger('io.jenkins.blueocean.dashboard.RunDetails'); const translate = i18nTranslator('blueocean-dashboard'); const webTranslate = i18nTranslator('blueocean-web'); -const classicConfigLink = pipeline => { +const classicConfigLink = (pipeline) => { let link = null; if (Security.permit(pipeline).configure()) { let url = UrlBuilder.buildClassicConfigUrl(pipeline); @@ -57,14 +57,11 @@ function getTestSummaryUrl(runDetails) { class RunDetails extends Component { constructor(props) { super(props); - this.state = { isVisible: true, actions: [] }; + this.state = { isVisible: true }; } componentWillMount() { this._fetchRun(this.props); - Extensions.store.getExtensions(['jenkins.run.actions'], Extensions.Utils.sortByOrdinal, (actions = []) => { - this.setState({ actions }); - }); } componentWillReceiveProps(nextProps) { @@ -91,7 +88,7 @@ class RunDetails extends Component { runId: props.params.runId, }); - this.context.activityService.fetchActivity(this.href, { useCache: true }).then(run => { + this.context.activityService.fetchActivity(this.href, { useCache: true }).then((run) => { const testSummaryUrl = getTestSummaryUrl(run); return testSummaryUrl && this.context.activityService.fetchTestSummary(testSummaryUrl); }); @@ -147,7 +144,7 @@ class RunDetails extends Component { const { router, location, params } = this.context; const { pipeline, setTitle, t, locale } = this.props; - const { isVisible, actions } = this.state; + const { isVisible } = this.state; if (!run || !pipeline) { this.props.setTitle(translate('common.pager.loading', { defaultValue: 'Loading...' })); @@ -162,29 +159,38 @@ class RunDetails extends Component { }`; setTitle(computedTitle); - const switchRunDetails = newUrl => { + const switchRunDetails = (newUrl) => { location.pathname = newUrl; router.push(location); }; const base = { base: baseUrl }; + const failureCount = Math.min(99, (testSummary && parseInt(testSummary.failed)) || 0); + const testsBadge = failureCount > 0 &&
{failureCount}
; + const tabs = [ {t('rundetail.header.tab.pipeline', { defaultValue: 'Pipeline', })} , + + {t('rundetail.header.tab.changes', { + defaultValue: 'Changes', + })} + , + + {t('rundetail.header.tab.tests', { defaultValue: 'Tests' })} + {testsBadge} + , + + {t('rundetail.header.tab.artifacts', { + defaultValue: 'Artifacts', + })} + , ]; - actions.map(descriptor => { - const action = new descriptor({pipeline, run: currentRun}); - const badge = action.notification &&
{ action.notification }
; - tabs.push( - {action.title}{badge} - ); - }); - const iconButtons = [ , , diff --git a/blueocean-dashboard/src/main/js/components/RunDetailsArtifacts.jsx b/blueocean-dashboard/src/main/js/components/RunDetailsArtifacts.jsx index 18e5e19053..7d7ee6aa48 100644 --- a/blueocean-dashboard/src/main/js/components/RunDetailsArtifacts.jsx +++ b/blueocean-dashboard/src/main/js/components/RunDetailsArtifacts.jsx @@ -2,13 +2,12 @@ import React, { Component, PropTypes } from 'react'; import { FileSize, JTable, TableRow, TableCell, TableHeaderRow } from '@jenkins-cd/design-language'; import { Icon } from '@jenkins-cd/design-language'; import { observer } from 'mobx-react'; -import { logging, UrlConfig, ShowMoreButton, i18nTranslator, ComponentLink } from '@jenkins-cd/blueocean-core-js'; +import { logging, UrlConfig, ShowMoreButton } from '@jenkins-cd/blueocean-core-js'; const logger = logging.logger('io.jenkins.blueocean.dashboard.artifacts'); -const t = i18nTranslator('blueocean-dashboard'); -const ZipFileDownload = props => { - const { zipFile } = props; +const ZipFileDownload = (props) => { + const { zipFile, t } = props; if (!zipFile) { return null; } @@ -27,13 +26,14 @@ const ZipFileDownload = props => { ZipFileDownload.propTypes = { zipFile: PropTypes.string, + t: PropTypes.func, }; /** * Displays a list of artifacts from the supplied build run property. */ @observer -export class RunDetailsArtifacts extends Component { +export default class RunDetailsArtifacts extends Component { componentWillMount() { this._fetchArtifacts(this.props); } @@ -55,7 +55,7 @@ export class RunDetailsArtifacts extends Component { } render() { - const { result } = this.props; + const { result, t } = this.props; if (!result || !this.pager || this.pager.pendingD) { return null; @@ -66,7 +66,7 @@ export class RunDetailsArtifacts extends Component { const nameLabel = t('rundetail.artifacts.header.name', { defaultValue: 'Name' }); const sizeLabel = t('rundetail.artifacts.header.size', { defaultValue: 'Size' }); - const displayLabel = t('rundetail.artifacts.button.display', { defaultValue: 'Display the artifact in new window' }); + const displayLabel = t('rundetail.artifacts.button.display', { defaultValue: 'Display the artifact in new window' }); const downloadLabel = t('rundetail.artifacts.button.download', { defaultValue: 'Download the artifact' }); const openLabel = t('rundetail.artifacts.button.open', { defaultValue: 'Open the artifact' }); @@ -74,7 +74,7 @@ export class RunDetailsArtifacts extends Component { const rootURL = UrlConfig.getJenkinsRootURL(); - const artifactsRendered = artifacts.map(artifact => { + const artifactsRendered = artifacts.map((artifact) => { const urlArray = artifact.url.split('/'); const fileName = urlArray[urlArray.length - 1]; logger.debug('artifact - url:', artifact.url, 'artifact - fileName:', fileName); @@ -104,7 +104,10 @@ export class RunDetailsArtifacts extends Component { {artifactSize} - {displayLink}{downloadLink} + + {displayLink} + {downloadLink} + ); }); @@ -147,10 +150,5 @@ RunDetailsArtifacts.contextTypes = { RunDetailsArtifacts.propTypes = { result: PropTypes.object, + t: PropTypes.func, }; - -export default class RunDetailsArtifactsLink extends ComponentLink { - name = "artifacts"; - title = t('rundetail.header.tab.artifacts'); - component = RunDetailsArtifacts; -} diff --git a/blueocean-dashboard/src/main/js/components/RunDetailsChanges.jsx b/blueocean-dashboard/src/main/js/components/RunDetailsChanges.jsx index 708bc2ed46..eaca12c6bf 100644 --- a/blueocean-dashboard/src/main/js/components/RunDetailsChanges.jsx +++ b/blueocean-dashboard/src/main/js/components/RunDetailsChanges.jsx @@ -4,11 +4,10 @@ import { CommitId, PlaceholderTable, ReadableDate, JTable, TableHeaderRow, Table import Icon from './placeholder/Icon'; import { PlaceholderDialog } from './placeholder/PlaceholderDialog'; import LinkifiedText from './LinkifiedText'; -import { ShowMoreButton, i18nTranslator, ComponentLink } from '@jenkins-cd/blueocean-core-js'; - -const t = i18nTranslator('blueocean-dashboard'); +import { ShowMoreButton } from '@jenkins-cd/blueocean-core-js'; function NoChangesPlaceholder(props) { + const { t } = props; const columns = [ { width: 750, isFlexible: true, head: { text: 40 }, cell: { text: 150 } }, @@ -29,8 +28,12 @@ function NoChangesPlaceholder(props) { ); } +NoChangesPlaceholder.propTypes = { + t: PropTypes.func, +}; + @observer -export class RunDetailsChanges extends Component { +export default class RunDetailsChanges extends Component { componentWillMount() { this._fetchChangeSet(this.props); } @@ -46,7 +49,7 @@ export class RunDetailsChanges extends Component { } render() { - const { locale } = this.props; + const { t, locale } = this.props; if (!this.pager) { return null; @@ -75,7 +78,7 @@ export class RunDetailsChanges extends Component { ]; const changeSetSplitBySource = []; - changeSet.map(commit => { + changeSet.map((commit) => { if (changeSetSplitBySource[commit.checkoutCount] === undefined) { changeSetSplitBySource[commit.checkoutCount] = []; } @@ -87,7 +90,7 @@ export class RunDetailsChanges extends Component { {changeSetSplitBySource.map((changeSet, changeSetIdx) => ( - {changeSet.map(commit => ( + {changeSet.map((commit) => ( @@ -118,6 +121,7 @@ export class RunDetailsChanges extends Component { RunDetailsChanges.propTypes = { result: PropTypes.object, locale: PropTypes.string, + t: PropTypes.func, params: PropTypes.any, pipeline: PropTypes.object, results: PropTypes.object, @@ -127,9 +131,3 @@ RunDetailsChanges.contextTypes = { params: PropTypes.object.isRequired, activityService: PropTypes.object.isRequired, }; - -export default class RunDetailsChangesLink extends ComponentLink { - name = 'changes'; - title = t('rundetail.header.tab.changes'); - component = RunDetailsChanges; -} \ No newline at end of file diff --git a/blueocean-dashboard/src/main/js/components/RunDetailsTests.jsx b/blueocean-dashboard/src/main/js/components/RunDetailsTests.jsx index 6ac84b9b38..e169f70e3b 100644 --- a/blueocean-dashboard/src/main/js/components/RunDetailsTests.jsx +++ b/blueocean-dashboard/src/main/js/components/RunDetailsTests.jsx @@ -1,22 +1,21 @@ import React, { Component, PropTypes } from 'react'; -import { pagerService, i18nTranslator, ComponentLink } from '@jenkins-cd/blueocean-core-js'; +import { pagerService } from '@jenkins-cd/blueocean-core-js'; import TestResults from './testing/TestResults'; import TestService from './testing/TestService'; import NoTestsPlaceholder from './testing/NoTestsPlaceholder'; -const t = i18nTranslator('blueocean-dashboard'); - /** * Displays a list of tests from the supplied build run property. */ -export class RunDetailsTests extends Component { +export default class RunDetailsTests extends Component { propTypes = { params: PropTypes.object, pipeline: PropTypes.object, isMultiBranch: PropTypes.bool, result: PropTypes.object, fetchTypeInfo: PropTypes.func, + t: PropTypes.func, locale: PropTypes.string, testSummary: PropTypes.object, }; @@ -30,7 +29,7 @@ export class RunDetailsTests extends Component { } render() { - const { locale, testSummary } = this.props; + const { t, locale, testSummary } = this.props; let result; if (testSummary && (testSummary.total || testSummary.total > 0)) { @@ -47,15 +46,8 @@ export class RunDetailsTests extends Component { ); } else { - result = ; + result = ; } return result; } } - -export default class RunDetailsTestsLink extends ComponentLink { - name = 'tests'; - title = t('rundetail.header.tab.tests'); - component = RunDetailsTests; - get notification() { return Math.min(99, (this.run.testSummary && parseInt(this.run.testSummary.failed)) || 0) || null; } -} diff --git a/blueocean-dashboard/src/main/js/components/index.jsx b/blueocean-dashboard/src/main/js/components/index.jsx index 87111eed11..a3472e11aa 100644 --- a/blueocean-dashboard/src/main/js/components/index.jsx +++ b/blueocean-dashboard/src/main/js/components/index.jsx @@ -6,6 +6,9 @@ import PipelineTrends from './PipelineTrends'; import PipelinePage from './PipelinePage'; import RunDetails from './RunDetails'; import RunDetailsPipeline from './RunDetailsPipeline'; +import RunDetailsChanges from './RunDetailsChanges'; +import RunDetailsArtifacts from './RunDetailsArtifacts'; +import RunDetailsTests from './RunDetailsTests'; export { Pipelines, @@ -16,4 +19,7 @@ export { PipelinePage, RunDetails, RunDetailsPipeline, + RunDetailsChanges, + RunDetailsTests, + RunDetailsArtifacts, }; diff --git a/blueocean-dashboard/src/main/js/jenkins-js-extension.yaml b/blueocean-dashboard/src/main/js/jenkins-js-extension.yaml index 5edf3e8dfa..e0799766a0 100644 --- a/blueocean-dashboard/src/main/js/jenkins-js-extension.yaml +++ b/blueocean-dashboard/src/main/js/jenkins-js-extension.yaml @@ -41,13 +41,3 @@ extensions: # Trends - component: components/trends/StageDurationChart extensionPoint: jenkins.pipeline.trends -# Actions - - component: components/RunDetailsChanges - extensionPoint: jenkins.run.actions - ordinal: 100 - - component: components/RunDetailsTests - extensionPoint: jenkins.run.actions - ordinal: 200 - - component: components/RunDetailsArtifacts - extensionPoint: jenkins.run.actions - ordinal: 300 diff --git a/blueocean-dashboard/src/test/js/run-details-changes-spec.js b/blueocean-dashboard/src/test/js/run-details-changes-spec.js index 61eccddbb6..ce219ebfb3 100644 --- a/blueocean-dashboard/src/test/js/run-details-changes-spec.js +++ b/blueocean-dashboard/src/test/js/run-details-changes-spec.js @@ -4,7 +4,7 @@ import { mount } from 'enzyme'; import { i18nTranslator } from '@jenkins-cd/blueocean-core-js'; import { latestRuns } from './data/runs/latestRuns'; -import { RunDetailsChanges } from '../../main/js/components/RunDetailsChanges'; +import RunDetailsChanges from '../../main/js/components/RunDetailsChanges'; const t = i18nTranslator('blueocean-dashboard');