@@ -70,6 +75,7 @@
:key="stage.name"
:stage-connector-class="stageConnectorClass(index, stage)"
:is-first-column="isFirstColumn(index)"
+ :action-disabled="actionDisabled"
/>
diff --git a/app/assets/javascripts/pipelines/components/graph/job_component.vue b/app/assets/javascripts/pipelines/components/graph/job_component.vue
index d501c465a96..c6e5ae6df41 100644
--- a/app/assets/javascripts/pipelines/components/graph/job_component.vue
+++ b/app/assets/javascripts/pipelines/components/graph/job_component.vue
@@ -1,96 +1,102 @@
@@ -132,7 +138,7 @@
:tooltip-text="status.action.title"
:link="status.action.path"
:action-icon="status.action.icon"
- :action-method="status.action.method"
+ :button-disabled="actionDisabled"
/>
- import jobComponent from './job_component.vue';
- import dropdownJobComponent from './dropdown_job_component.vue';
+import JobComponent from './job_component.vue';
+import DropdownJobComponent from './dropdown_job_component.vue';
- export default {
- components: {
- jobComponent,
- dropdownJobComponent,
- },
- props: {
- title: {
- type: String,
- required: true,
- },
-
- jobs: {
- type: Array,
- required: true,
- },
-
- isFirstColumn: {
- type: Boolean,
- required: false,
- default: false,
- },
-
- stageConnectorClass: {
- type: String,
- required: false,
- default: '',
- },
+export default {
+ components: {
+ JobComponent,
+ DropdownJobComponent,
+ },
+ props: {
+ title: {
+ type: String,
+ required: true,
},
- methods: {
- firstJob(list) {
- return list[0];
- },
-
- jobId(job) {
- return `ci-badge-${job.name}`;
- },
-
- buildConnnectorClass(index) {
- return index === 0 && !this.isFirstColumn ? 'left-connector' : '';
- },
+ jobs: {
+ type: Array,
+ required: true,
},
- };
+
+ isFirstColumn: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+
+ stageConnectorClass: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ actionDisabled: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
+
+ methods: {
+ firstJob(list) {
+ return list[0];
+ },
+
+ jobId(job) {
+ return `ci-badge-${job.name}`;
+ },
+
+ buildConnnectorClass(index) {
+ return index === 0 && !this.isFirstColumn ? 'left-connector' : '';
+ },
+ },
+};
{
data() {
return {
mediator,
+ actionDisabled: null,
};
},
+ created() {
+ eventHub.$on('graphAction', this.postAction);
+ },
+ beforeDestroy() {
+ eventHub.$off('graphAction', this.postAction);
+ },
+ methods: {
+ postAction(action) {
+ this.actionDisabled = action;
+
+ this.mediator.service.postAction(action)
+ .then(() => {
+ this.mediator.refreshPipeline();
+ this.actionDisabled = null;
+ })
+ .catch(() => {
+ this.actionDisabled = null;
+ Flash(__('An error occurred while making the request.'));
+ });
+ },
+ },
render(createElement) {
return createElement('pipeline-graph', {
props: {
isLoading: this.mediator.state.isLoading,
pipeline: this.mediator.store.state.pipeline,
+ actionDisabled: this.actionDisabled,
},
});
},
diff --git a/app/assets/javascripts/pipelines/pipeline_details_mediator.js b/app/assets/javascripts/pipelines/pipeline_details_mediator.js
index 10f238fe73b..621969cd622 100644
--- a/app/assets/javascripts/pipelines/pipeline_details_mediator.js
+++ b/app/assets/javascripts/pipelines/pipeline_details_mediator.js
@@ -52,8 +52,11 @@ export default class pipelinesMediator {
}
refreshPipeline() {
- this.service.getPipeline()
+ this.poll.stop();
+
+ return this.service.getPipeline()
.then(response => this.successCallback(response))
- .catch(() => this.errorCallback());
+ .catch(() => this.errorCallback())
+ .finally(() => this.poll.restart());
}
}
diff --git a/app/assets/stylesheets/pages/pipelines.scss b/app/assets/stylesheets/pages/pipelines.scss
index ce2f1482456..8d5eb2e8c5a 100644
--- a/app/assets/stylesheets/pages/pipelines.scss
+++ b/app/assets/stylesheets/pages/pipelines.scss
@@ -495,17 +495,17 @@
svg {
fill: $gl-text-color-secondary;
position: relative;
- left: 5px;
- top: 2px;
- width: 18px;
- height: 18px;
+ left: 1px;
+ top: -1px;
+ width: 16px;
+ height: 16px;
}
&.play {
svg {
- width: #{$ci-action-icon-size - 8};
- height: #{$ci-action-icon-size - 8};
- left: 8px;
+ width: 16px;
+ height: 16px;
+ left: 3px;
}
}
}
diff --git a/changelogs/unreleased/fl-fix-annoying-actions.yml b/changelogs/unreleased/fl-fix-annoying-actions.yml
new file mode 100644
index 00000000000..fe17f9a8978
--- /dev/null
+++ b/changelogs/unreleased/fl-fix-annoying-actions.yml
@@ -0,0 +1,5 @@
+---
+title: Stop redirecting the page in pipeline main actions
+merge_request:
+author:
+type: fixed
diff --git a/spec/javascripts/pipelines/graph/action_component_spec.js b/spec/javascripts/pipelines/graph/action_component_spec.js
index e8fcd4b1a36..581209f215d 100644
--- a/spec/javascripts/pipelines/graph/action_component_spec.js
+++ b/spec/javascripts/pipelines/graph/action_component_spec.js
@@ -1,25 +1,30 @@
import Vue from 'vue';
import actionComponent from '~/pipelines/components/graph/action_component.vue';
+import eventHub from '~/pipelines/event_hub';
+import mountComponent from '../../helpers/vue_mount_component_helper';
describe('pipeline graph action component', () => {
let component;
beforeEach((done) => {
const ActionComponent = Vue.extend(actionComponent);
- component = new ActionComponent({
- propsData: {
- tooltipText: 'bar',
- link: 'foo',
- actionMethod: 'post',
- actionIcon: 'cancel',
- },
- }).$mount();
+ component = mountComponent(ActionComponent, {
+ tooltipText: 'bar',
+ link: 'foo',
+ actionIcon: 'cancel',
+ });
Vue.nextTick(done);
});
- it('should render a link', () => {
- expect(component.$el.getAttribute('href')).toEqual('foo');
+ afterEach(() => {
+ component.$destroy();
+ });
+
+ it('should emit an event with the provided link', () => {
+ eventHub.$on('graphAction', (link) => {
+ expect(link).toEqual('foo');
+ });
});
it('should render the provided title as a bootstrap tooltip', () => {