Commit 062ef121 authored by Filipa Lacerda's avatar Filipa Lacerda Committed by Kamil Trzciński

Removes get requests for upstream/downstream

Recursively updates isExpanded property for
all triggered and triggered by pipelines
parent 0286eafe
...@@ -2,7 +2,7 @@ import Vue from 'vue'; ...@@ -2,7 +2,7 @@ import Vue from 'vue';
import Flash from '~/flash'; import Flash from '~/flash';
import Translate from '~/vue_shared/translate'; import Translate from '~/vue_shared/translate';
import { __ } from '~/locale'; import { __ } from '~/locale';
import PipelinesMediator from 'ee/pipelines/pipeline_details_mediator'; import PipelinesMediator from './pipeline_details_mediator';
import pipelineGraph from 'ee/pipelines/components/graph/graph_component.vue'; import pipelineGraph from 'ee/pipelines/components/graph/graph_component.vue';
import pipelineHeader from './components/header_component.vue'; import pipelineHeader from './components/header_component.vue';
import eventHub from './event_hub'; import eventHub from './event_hub';
...@@ -53,10 +53,10 @@ export default () => { ...@@ -53,10 +53,10 @@ export default () => {
on: { on: {
refreshPipelineGraph: this.requestRefreshPipelineGraph, refreshPipelineGraph: this.requestRefreshPipelineGraph,
// EE-only start // EE-only start
refreshTriggeredPipelineGraph: this.mediator.refreshTriggeredByPipelineGraph, // refreshTriggeredPipelineGraph: this.mediator.refreshTriggeredByPipelineGraph,
refreshTriggeredByPipelineGraph: this.mediator.refreshTriggeredByPipelineGraph, // refreshTriggeredByPipelineGraph: this.mediator.refreshTriggeredByPipelineGraph,
onClickTriggeredBy: pipeline => this.clickTriggeredBy(pipeline), onClickTriggeredBy: pipeline => this.clickTriggeredByPipeline(pipeline),
onClickTriggered: pipeline => this.clickTriggered(pipeline), onClickTriggered: pipeline => this.clickTriggeredPipeline(pipeline),
// EE-only end // EE-only end
}, },
}); });
......
...@@ -2,8 +2,8 @@ import Visibility from 'visibilityjs'; ...@@ -2,8 +2,8 @@ import Visibility from 'visibilityjs';
import Flash from '../flash'; import Flash from '../flash';
import Poll from '../lib/utils/poll'; import Poll from '../lib/utils/poll';
import { __ } from '../locale'; import { __ } from '../locale';
import PipelineService from '~/pipelines/services/pipeline_service';
import PipelineStore from 'ee/pipelines/stores/pipeline_store'; // eslint-disable-line import/order import PipelineStore from 'ee/pipelines/stores/pipeline_store'; // eslint-disable-line import/order
import PipelineService from 'ee/pipelines/services/pipeline_service'; // eslint-disable-line import/order
export default class pipelinesMediator { export default class pipelinesMediator {
constructor(options = {}) { constructor(options = {}) {
......
...@@ -6,6 +6,7 @@ import EEGraphMixin from 'ee/pipelines/mixins/graph_component_mixin'; ...@@ -6,6 +6,7 @@ import EEGraphMixin from 'ee/pipelines/mixins/graph_component_mixin';
import StageColumnComponent from '~/pipelines/components/graph/stage_column_component.vue'; import StageColumnComponent from '~/pipelines/components/graph/stage_column_component.vue';
export default { export default {
name: 'PipelineGraph',
components: { components: {
LinkedPipelinesColumn, LinkedPipelinesColumn,
StageColumnComponent, StageColumnComponent,
...@@ -62,21 +63,6 @@ export default { ...@@ -62,21 +63,6 @@ export default {
<div class="pipeline-visualization pipeline-graph pipeline-tab-content"> <div class="pipeline-visualization pipeline-graph pipeline-tab-content">
<div class="text-center"><gl-loading-icon v-if="isLoading" :size="3" /></div> <div class="text-center"><gl-loading-icon v-if="isLoading" :size="3" /></div>
<ul v-if="shouldRenderTriggeredByPipeline" class="d-inline-block upstream-pipeline align-top">
<stage-column-component
v-for="(stage, indexUpstream) in triggeredByGraph"
:key="stage.name"
:class="{
'has-only-one-job': hasOnlyOneJob(stage),
}"
:title="capitalizeStageName(stage.name)"
:groups="stage.groups"
:stage-connector-class="stageConnectorClass(indexUpstream, stage)"
:is-first-column="isFirstColumn(indexUpstream)"
@refreshPipelineGraph="refreshTriggeredByPipelineGraph"
/>
</ul>
<linked-pipelines-column <linked-pipelines-column
v-if="hasTriggeredBy" v-if="hasTriggeredBy"
:linked-pipelines="triggeredByPipelines" :linked-pipelines="triggeredByPipelines"
...@@ -116,25 +102,6 @@ export default { ...@@ -116,25 +102,6 @@ export default {
graph-position="right" graph-position="right"
@linkedPipelineClick="handleClickedDownstream" @linkedPipelineClick="handleClickedDownstream"
/> />
<ul
v-if="shouldRenderTriggeredPipeline"
class="d-inline-block downstream-pipeline position-relative align-top"
:style="{ 'margin-top': marginTop }"
>
<stage-column-component
v-for="(stage, indexDownstream) in triggeredGraph"
:key="stage.name"
:class="{
'has-only-one-job': hasOnlyOneJob(stage),
}"
:title="capitalizeStageName(stage.name)"
:groups="stage.groups"
:stage-connector-class="stageConnectorClass(indexDownstream, stage)"
:is-first-column="isFirstColumn(indexDownstream)"
@refreshPipelineGraph="refreshTriggeredPipelineGraph"
/>
</ul>
</div> </div>
</div> </div>
</template> </template>
...@@ -12,30 +12,23 @@ export default { ...@@ -12,30 +12,23 @@ export default {
GlButton, GlButton,
}, },
props: { props: {
pipelineId: { pipeline: {
type: Number,
required: true,
},
pipelineStatus: {
type: Object, type: Object,
required: true, required: true,
}, },
projectName: {
type: String,
required: true,
},
isLoading: {
type: Boolean,
required: false,
default: false,
},
}, },
computed: { computed: {
tooltipText() { tooltipText() {
return `${this.projectName} - ${this.pipelineStatus.label}`; return `${this.projectName} - ${this.pipelineStatus.label}`;
}, },
buttonId() { buttonId() {
return `js-linked-pipeline-${this.pipelineId}`; return `js-linked-pipeline-${this.pipeline.id}`;
},
pipelineStatus() {
return this.pipeline.details.status;
},
projectName() {
return this.pipeline.project.name;
}, },
}, },
methods: { methods: {
...@@ -57,10 +50,10 @@ export default { ...@@ -57,10 +50,10 @@ export default {
class="js-linked-pipeline-content linked-pipeline-content" class="js-linked-pipeline-content linked-pipeline-content"
@click="onClickLinkedPipeline" @click="onClickLinkedPipeline"
> >
<gl-loading-icon v-if="isLoading" class="js-linked-pipeline-loading d-inline" /> <gl-loading-icon v-if="pipeline.isLoading" class="js-linked-pipeline-loading d-inline" />
<ci-status v-else :status="pipelineStatus" class="js-linked-pipeline-status" /> <ci-status v-else :status="pipelineStatus" class="js-linked-pipeline-status" />
<span class="str-truncated align-bottom"> {{ projectName }} &#8226; #{{ pipelineId }} </span> <span class="str-truncated align-bottom"> {{ projectName }} &#8226; #{{ pipeline.id }} </span>
</gl-button> </gl-button>
</li> </li>
</template> </template>
export default { export default {
triggeredPipelines: 'triggeredPipelines', triggeredPipelines: 'triggeredPipelines',
triggeredByPipelines: 'triggeredByPipelines', triggeredByPipelines: 'triggeredByPipelines',
triggeredBy: 'triggeredBy', triggeredBy: 'triggered_by',
triggered: 'triggered', triggered: 'triggered',
}; };
import _ from 'underscore';
export default { export default {
props: {
triggered: {
type: Object,
required: false,
default: () => ({}),
},
triggeredBy: {
type: Object,
required: false,
default: () => ({}),
},
triggeredByPipelines: {
type: Array,
required: false,
default: () => [],
},
triggeredPipelines: {
type: Array,
required: false,
default: () => [],
},
},
data() { data() {
return { return {
triggeredTopIndex: 1, triggeredTopIndex: 1,
}; };
}, },
computed: { computed: {
triggeredGraph() { hasTriggeredBy() {
return this.triggered && this.triggered.details && this.triggered.details.stages; return this.pipeline.triggered_by && this.pipeline.triggered_by != null;
}, },
triggeredByGraph() { triggeredByPipelines() {
return this.triggeredBy && this.triggeredBy.details && this.triggeredBy.details.stages; return this.pipeline.triggered_by;
}, },
hasTriggered() { hasTriggered() {
return this.triggeredPipelines.length > 0; return this.pipeline.triggered && this.pipeline.triggered.length > 0;
},
hasTriggeredBy() {
return this.triggeredByPipelines.length > 0;
},
shouldRenderTriggeredPipeline() {
return !this.isLoading && !_.isEmpty(this.triggered);
}, },
shouldRenderTriggeredByPipeline() { triggeredPipelines() {
return !this.isLoading && !_.isEmpty(this.triggeredBy); return this.pipeline.triggered;
}, },
/** /**
* Calculates the margin top of the clicked downstream pipeline by * Calculates the margin top of the clicked downstream pipeline by
...@@ -56,6 +26,7 @@ export default { ...@@ -56,6 +26,7 @@ export default {
}, },
}, },
methods: { methods: {
// TODO FILIPA: REMOVE THIS
refreshTriggeredPipelineGraph() { refreshTriggeredPipelineGraph() {
this.$emit('refreshTriggeredPipelineGraph'); this.$emit('refreshTriggeredPipelineGraph');
}, },
......
import pipelinesKeys from 'ee/pipelines/constants'; import keys from '../constants';
export default { export default {
methods: { methods: {
...@@ -13,30 +13,19 @@ export default { ...@@ -13,30 +13,19 @@ export default {
* @param {String} resetStoreKey Store key for the visible pipeline that will need to be reset * @param {String} resetStoreKey Store key for the visible pipeline that will need to be reset
* @param {Object} pipeline The clicked pipeline * @param {Object} pipeline The clicked pipeline
*/ */
clickPipeline(method, storeKey, resetStoreKey, pipeline, pollKey) { clickPipeline(pipeline, method) {
debugger;
if (!pipeline.isExpanded) { if (!pipeline.isExpanded) {
this.mediator[method](pipeline); this.mediator.store[method](pipeline);
} else { } else {
this.mediator.resetPipeline(storeKey, pipeline, resetStoreKey, pollKey); this.mediator.store.closePipeline(pipeline);
} }
}, },
clickTriggered(triggered) { clickTriggeredByPipeline(pipeline) {
this.clickPipeline( this.clickPipeline(pipeline, 'openTriggeredByPipeline');
'fetchTriggeredPipeline',
pipelinesKeys.triggeredPipelines,
pipelinesKeys.triggered,
triggered,
'pollTriggered',
);
}, },
clickTriggeredBy(triggeredBy) { clickTriggeredPipeline(pipeline) {
this.clickPipeline( this.clickPipeline(pipeline, 'openTriggeredPipeline');
'fetchTriggeredByPipeline',
pipelinesKeys.triggeredByPipelines,
pipelinesKeys.triggeredBy,
triggeredBy,
'pollTriggeredBy',
);
}, },
}, },
}; };
This diff is collapsed.
import CePipelineMediator from '~/pipelines/pipeline_details_mediator';
import createFlash from '~/flash';
import Poll from '~/lib/utils/poll';
import { __ } from '~/locale';
import PipelineService from 'ee/pipelines/services/pipeline_service';
/**
* Extends CE mediator with the logic to handle the upstream/downstream pipelines
*/
export default class EePipelineMediator extends CePipelineMediator {
/**
* Requests the clicked downstream pipeline pipeline
*
* @param {Object} pipeline
*/
fetchTriggeredPipeline(pipeline) {
if (this.pollTriggered) {
this.pollTriggered.stop();
this.pollTriggered = null;
}
this.store.requestTriggeredPipeline(pipeline);
this.pollTriggered = new Poll({
resource: PipelineService,
method: 'getUpstreamDownstream',
data: pipeline.path,
successCallback: ({ data }) => this.store.receiveTriggeredPipelineSuccess(pipeline, data),
errorCallback: () => {
this.store.receiveTriggeredPipelineError(pipeline);
createFlash(
__('An error occured while fetching this downstream pipeline. Please try again'),
);
},
});
this.pollTriggered.makeRequest();
}
refreshTriggeredPipelineGraph() {
this.pollTriggered.stop();
this.pollTriggered.restart();
}
/**
* Requests the clicked upstream pipeline pipeline
* @param {*} pipeline
*/
fetchTriggeredByPipeline(pipeline) {
if (this.pollTriggeredBy) {
this.pollTriggeredBy.stop();
this.pollTriggeredBy = null;
}
this.store.requestTriggeredByPipeline(pipeline);
this.pollTriggeredBy = new Poll({
resource: PipelineService,
method: 'getUpstreamDownstream',
data: pipeline.path,
successCallback: ({ data }) => this.store.receiveTriggeredByPipelineSuccess(pipeline, data),
errorCallback: () => {
this.store.receiveTriggeredByPipelineError(pipeline);
createFlash(__('An error occured while fetching this upstream pipeline. Please try again'));
},
});
this.pollTriggeredBy.makeRequest();
}
refreshTriggeredByPipelineGraph() {
this.pollTriggeredBy.stop();
this.pollTriggeredBy.restart();
}
resetPipeline(storeKey, pipeline, resetStoreKey, pollKey) {
this[pollKey].stop();
this.store.closePipeline(storeKey, pipeline, resetStoreKey);
}
}
import axios from '~/lib/utils/axios_utils';
import CePipelineService from '~/pipelines/services/pipeline_service';
export default class PipelineStore extends CePipelineService {
static getUpstreamDownstream(endpoint) {
return axios.get(`${endpoint}.json`);
}
}
...@@ -150,89 +150,4 @@ describe('EE Pipeline store', () => { ...@@ -150,89 +150,4 @@ describe('EE Pipeline store', () => {
}); });
}); });
}); });
describe('utils', () => {
describe('parsePipeline', () => {
let parsed;
beforeAll(() => {
parsed = PipelineStore.parsePipeline(pipeline);
});
it('adds isLoading key set to false', () => {
expect(parsed.isLoading).toEqual(false);
});
it('adds isExpanded key set to false', () => {
expect(parsed.isExpanded).toEqual(false);
});
});
describe('getPipelineIndex', () => {
beforeAll(() => {
store.storePipeline(pipelineWithBoth);
});
it('returns the pipeline index for the provided pipeline and storeKey', () => {
store.getPipelineIndex('triggeredPipelines', store.triggeredPipelines[1]).toEqual(1);
});
});
describe('updateStoreOnRequest', () => {
beforeAll(() => {
store.storePipeline(pipelineWithBoth);
});
it('sets clicked pipeline isLoading to true', () => {
store.updateStoreOnRequest('triggeredPipelines', store.triggeredPipelines[1]);
expect(store.triggeredPipelines[1].isLoading).isLoading(true);
});
it('sets clicked pipeline isExpanded to true', () => {
store.updateStoreOnRequest('triggeredPipelines', store.triggeredPipelines[1]);
expect(store.triggeredPipelines[1].isExpanded).isLoading(true);
});
});
describe('updatePipeline', () => {
beforeAll(() => {
store.storePipeline(pipelineWithBoth);
store.updatePipeline(
'triggeredPipelines',
store.triggeredPipelines[1],
{ isLoading: true },
'triggered',
store.triggeredPipelines[1],
);
});
it('updates the given pipeline in the correct array', () => {
expect(store.triggeredPipelines[1].isLoading).toEqual(true);
expect(store.triggered).toEqual(store.triggeredPipelines[1]);
});
it('updates the visible pipeline to the given value', () => {});
});
describe('closePipeline', () => {
beforeAll(() => {
store.storePipeline(pipelineWithBoth);
});
it('closes the given pipeline', () => {
const clickedPipeline = store.triggeredPipelines[1];
// open it first
clickedPipeline.isExpanded = true;
store.triggered = clickedPipeline;
store.closePipeline('triggeredPipelines', clickedPipeline, 'triggered');
expect(store.triggeredPipelines[1].isExpanded).toEqual(true);
expect(store.triggered).toEqual({});
});
});
});
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment