diff --git a/app/components/pipeline/jobs/table/component.js b/app/components/pipeline/jobs/table/component.js index a05a25886..15ae757b9 100644 --- a/app/components/pipeline/jobs/table/component.js +++ b/app/components/pipeline/jobs/table/component.js @@ -1,6 +1,7 @@ import Component from '@glimmer/component'; import { service } from '@ember/service'; import { action } from '@ember/object'; +import { tracked } from '@glimmer/tracking'; import { dom } from '@fortawesome/fontawesome-svg-core'; import DataReloader from './dataReloader'; import getDisplayName from './util'; @@ -10,11 +11,23 @@ const INITIAL_PAGE_SIZE = 10; export default class PipelineJobsTableComponent extends Component { @service shuttle; + @service workflowDataReload; + @service('emt-themes/ember-bootstrap-v5') emberModelTableBootstrapTheme; + pipeline; + + userSettings; + + event; + + jobs; + dataReloader; - data = []; + numBuilds; + + @tracked data; columns = [ { @@ -66,24 +79,53 @@ export default class PipelineJobsTableComponent extends Component { constructor() { super(...arguments); - const jobIds = this.args.jobs.map(job => job.id); + this.pipeline = this.args.pipeline; + this.event = this.args.event; + this.jobs = this.args.jobs; + this.userSettings = this.args.userSettings; + this.numBuilds = this.args.numBuilds; + this.data = null; + } + + willDestroy() { + super.willDestroy(); + + this.dataReloader.stop(this.event?.id); + } + + @action + initialize(element) { + dom.i2svg({ node: element }); + this.initializeDataLoader().then(() => {}); + } + + @action + async initializeDataLoader() { + const prNum = this.event?.prNum; + + if (prNum) { + this.jobs = this.workflowDataReload.getJobsForPr(prNum); + } + + const jobIds = this.jobs.map(job => job.id); this.dataReloader = new DataReloader( - this.shuttle, + { shuttle: this.shuttle, workflowDataReload: this.workflowDataReload }, jobIds, INITIAL_PAGE_SIZE, - this.args.numBuilds + this.numBuilds ); - const initialJobIds = this.dataReloader.newJobIds(); - this.args.jobs.forEach(job => { + this.data = []; + + this.jobs.forEach(job => { this.data.push({ job, - jobName: getDisplayName(job), + jobName: getDisplayName(job, prNum), stageName: job?.permutations?.[0]?.stage?.name || 'N/A', - pipeline: this.args.pipeline, - jobs: this.args.jobs, - timestampFormat: this.args.userSettings.timestampFormat, + pipeline: this.pipeline, + jobs: this.jobs, + timestampFormat: this.userSettings.timestampFormat, onCreate: (jobToMonitor, buildsCallback) => { this.dataReloader.addCallbackForJobId( jobToMonitor.id, @@ -96,15 +138,27 @@ export default class PipelineJobsTableComponent extends Component { }); }); - this.dataReloader.fetchBuildsForJobs(initialJobIds).then(() => { - this.dataReloader.start(); - }); + const eventId = this.event?.id; + + if (!eventId) { + const initialJobIds = this.dataReloader.newJobIds(); + + await this.dataReloader.fetchBuildsForJobs(initialJobIds); + } + + this.dataReloader.start(eventId); } - willDestroy() { - super.willDestroy(); + @action + update(element, [event]) { + this.data = []; + + if (event) { + this.dataReloader.stop(this.event?.id); + this.event = event; + } - this.dataReloader.destroy(); + this.initializeDataLoader().then(() => {}); } get theme() { @@ -129,9 +183,4 @@ export default class PipelineJobsTableComponent extends Component { .fetchBuildsForJobs(this.dataReloader.newJobIds()) .then(() => {}); } - - @action - handleDidInsert(element) { - dom.i2svg({ node: element }); - } } diff --git a/app/components/pipeline/jobs/table/template.hbs b/app/components/pipeline/jobs/table/template.hbs index 86598ae56..d19bc311a 100644 --- a/app/components/pipeline/jobs/table/template.hbs +++ b/app/components/pipeline/jobs/table/template.hbs @@ -1,9 +1,13 @@ - - +
-
+ - +
+ diff --git a/app/components/pipeline/workflow/component.js b/app/components/pipeline/workflow/component.js index d48f19849..7cf96c9c6 100644 --- a/app/components/pipeline/workflow/component.js +++ b/app/components/pipeline/workflow/component.js @@ -45,6 +45,8 @@ export default class PipelineWorkflowComponent extends Component { @tracked workflowGraphToDisplay; + @tracked showGraph; + workflowGraph; workflowGraphWithDownstreamTriggers; @@ -107,6 +109,8 @@ export default class PipelineWorkflowComponent extends Component { this.setWorkflowGraphFromEvent(); } } + + this.showGraph = true; } willDestroy() { @@ -180,9 +184,9 @@ export default class PipelineWorkflowComponent extends Component { return getDisplayJobNameLength(this.userSettings); } - get disableDownstreamTriggers() { + get hasDownstreamTriggers() { return ( - this.workflowGraph.nodes.length === + this.workflowGraph.nodes.length !== this.workflowGraphWithDownstreamTriggers.nodes.length ); } @@ -217,4 +221,9 @@ export default class PipelineWorkflowComponent extends Component { this.d3Data = null; } } + + @action + setShowGraph(showGraph) { + this.showGraph = showGraph; + } } diff --git a/app/components/pipeline/workflow/event-rail/styles.scss b/app/components/pipeline/workflow/event-rail/styles.scss index 0b320fca7..6a7867b83 100644 --- a/app/components/pipeline/workflow/event-rail/styles.scss +++ b/app/components/pipeline/workflow/event-rail/styles.scss @@ -1,10 +1,7 @@ @use 'screwdriver-colors' as colors; -@use 'screwdriver-button' as button; @mixin styles { #event-rail { - @include button.styles; - height: 100%; border-top: 1px solid rgba(colors.$sd-text-med, 0.5); border-right: 1px solid rgba(colors.$sd-text-med, 0.5); diff --git a/app/components/pipeline/workflow/styles.scss b/app/components/pipeline/workflow/styles.scss index 6292c962b..08d14e026 100644 --- a/app/components/pipeline/workflow/styles.scss +++ b/app/components/pipeline/workflow/styles.scss @@ -1,4 +1,6 @@ @use 'variables'; +@use 'screwdriver-colors' as colors; +@use 'screwdriver-button' as button; @use 'event-rail/styles' as event-rail; @use 'graph/styles' as graph; @@ -6,6 +8,8 @@ @mixin styles { #pipeline-workflow-container { + @include button.styles; + display: grid; $events-rail-width: 26rem; @@ -19,37 +23,74 @@ grid-area: events; } - #workflow-graph-container { + #workflow-display-container { grid-area: workflow; overflow: auto; $graph-controls-height: 2.5rem; - #workflow-graph-controls { + #workflow-display-controls { display: flex; align-content: center; padding-left: 1rem; height: $graph-controls-height; - .button-container { + #show-workflow-graph-button, + #show-workflow-table-button { + display: flex; + + svg { + margin: auto; + } + + &:disabled { + background: colors.$sd-pale-purple; + } + } + + #show-workflow-graph-button { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + + #show-workflow-table-button { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + translate: -1px; + } + + .downstream-triggers-container { + margin-left: 1rem; + display: flex; + .x-toggle-component { + &.x-toggle-focused .x-toggle-btn:not(.x-toggle-disabled)::after, + &.x-toggle-focused .x-toggle-btn:not(.x-toggle-disabled)::before { + box-shadow: 0 0 2px 3px colors.$sd-running; + } + + .x-toggle-light.x-toggle-btn { + background: colors.$sd-text-light; + } + + .x-toggle:checked + label > .x-toggle-light.x-toggle-btn { + background: colors.$sd-pale-purple; + } + label { margin-bottom: 0; &.off-label { padding-right: 0; } - - &.on-label { - padding-left: 0.85rem; - } } } } } - #graph-container { + #display-container { position: relative; height: calc(100% - $graph-controls-height); + padding-top: 1rem; overflow: auto; #workflow-graph { diff --git a/app/components/pipeline/workflow/template.hbs b/app/components/pipeline/workflow/template.hbs index 4f1b225f9..9e5d010b6 100644 --- a/app/components/pipeline/workflow/template.hbs +++ b/app/components/pipeline/workflow/template.hbs @@ -12,57 +12,98 @@ /> {{#if this.event}} -
-
-
+
+ - -
-
+ + + + -
- + {{#if (and this.showGraph this.hasDownstreamTriggers)}} +
+ +
+ {{/if}} +
- {{#if this.showTooltip}} - + {{#if this.showGraph}} + - {{/if}} - {{#if this.showStageTooltip}} - + {{/if}} + {{#if this.showStageTooltip}} + + {{/if}} + {{else}} + {{/if}}
diff --git a/tests/integration/components/pipeline/workflow/component-test.js b/tests/integration/components/pipeline/workflow/component-test.js index a4334c940..06b8e7e99 100644 --- a/tests/integration/components/pipeline/workflow/component-test.js +++ b/tests/integration/components/pipeline/workflow/component-test.js @@ -30,7 +30,7 @@ module('Integration | Component | pipeline/workflow', function (hooks) { ); assert.dom('#event-rail').exists({ count: 1 }); - assert.dom('#workflow-graph-container').doesNotExist(); + assert.dom('#workflow-display-container').doesNotExist(); assert.dom('#no-events').exists({ count: 1 }); assert.dom('#no-events').hasText('This pipeline has no events yet'); assert.dom('#invalid-event').doesNotExist(); @@ -59,7 +59,7 @@ module('Integration | Component | pipeline/workflow', function (hooks) { ); assert.dom('#event-rail').exists({ count: 1 }); - assert.dom('#workflow-graph-container').doesNotExist(); + assert.dom('#workflow-display-container').doesNotExist(); assert.dom('#no-events').exists({ count: 1 }); assert .dom('#no-events') @@ -107,7 +107,7 @@ module('Integration | Component | pipeline/workflow', function (hooks) { ); assert.dom('#event-rail').exists({ count: 1 }); - assert.dom('#workflow-graph-container').doesNotExist(); + assert.dom('#workflow-display-container').doesNotExist(); assert.dom('#no-events').doesNotExist(); assert.dom('#invalid-event').exists({ count: 1 }); assert @@ -148,7 +148,7 @@ module('Integration | Component | pipeline/workflow', function (hooks) { ); assert.dom('#event-rail').exists({ count: 1 }); - assert.dom('#workflow-graph-container').doesNotExist(); + assert.dom('#workflow-display-container').doesNotExist(); assert.dom('#no-events').doesNotExist(); assert.dom('#invalid-event').exists({ count: 1 }); assert @@ -204,7 +204,7 @@ module('Integration | Component | pipeline/workflow', function (hooks) { ); assert.dom('#event-rail').exists({ count: 1 }); - assert.dom('#workflow-graph-container').exists({ count: 1 }); + assert.dom('#workflow-display-container').exists({ count: 1 }); assert.dom('#no-events').doesNotExist(); assert.dom('#invalid-event').doesNotExist(); }); @@ -262,7 +262,7 @@ module('Integration | Component | pipeline/workflow', function (hooks) { ); assert.dom('#event-rail').exists({ count: 1 }); - assert.dom('#workflow-graph-container').exists({ count: 1 }); + assert.dom('#workflow-display-container').exists({ count: 1 }); assert.dom('#no-events').doesNotExist(); assert.dom('#invalid-event').doesNotExist(); });