Commit 2662b4b0 authored by Phil Hughes's avatar Phil Hughes

Move behind a feature flag

Added a feature flag so that if the async side stops working we can
easily revert back to original behaviour
parent d7525c0e
<script>
import { GlSkeletonLoader } from '@gitlab/ui';
export default {
components: {
GlSkeletonLoader,
},
};
</script>
<template>
<div class="prepend-top-default">
<div class="mr-widget-heading p-3">
<gl-skeleton-loader :width="577" :height="12">
<rect width="86" height="12" rx="2" />
<rect x="96" width="300" height="12" rx="2" />
</gl-skeleton-loader>
</div>
<div class="mr-widget-heading mr-widget-workflow p-3">
<gl-skeleton-loader :width="577" :height="72">
<rect width="120" height="12" rx="2" />
<rect y="20" width="300" height="12" rx="2" />
<rect y="40" width="60" height="12" rx="2" />
<rect y="40" x="68" width="100" height="12" rx="2" />
<rect y="60" width="40" height="12" rx="2" />
</gl-skeleton-loader>
</div>
</div>
</template>
...@@ -7,6 +7,7 @@ import MRWidgetStore from 'ee_else_ce/vue_merge_request_widget/stores/mr_widget_ ...@@ -7,6 +7,7 @@ import MRWidgetStore from 'ee_else_ce/vue_merge_request_widget/stores/mr_widget_
import MRWidgetService from 'ee_else_ce/vue_merge_request_widget/services/mr_widget_service'; import MRWidgetService from 'ee_else_ce/vue_merge_request_widget/services/mr_widget_service';
import stateMaps from 'ee_else_ce/vue_merge_request_widget/stores/state_maps'; import stateMaps from 'ee_else_ce/vue_merge_request_widget/stores/state_maps';
import createFlash from '../flash'; import createFlash from '../flash';
import Loading from './components/loading.vue';
import WidgetHeader from './components/mr_widget_header.vue'; import WidgetHeader from './components/mr_widget_header.vue';
import WidgetMergeHelp from './components/mr_widget_merge_help.vue'; import WidgetMergeHelp from './components/mr_widget_merge_help.vue';
import MrWidgetPipelineContainer from './components/mr_widget_pipeline_container.vue'; import MrWidgetPipelineContainer from './components/mr_widget_pipeline_container.vue';
...@@ -44,6 +45,7 @@ export default { ...@@ -44,6 +45,7 @@ export default {
// eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings // eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings
name: 'MRWidget', name: 'MRWidget',
components: { components: {
Loading,
'mr-widget-header': WidgetHeader, 'mr-widget-header': WidgetHeader,
'mr-widget-merge-help': WidgetMergeHelp, 'mr-widget-merge-help': WidgetMergeHelp,
MrWidgetPipelineContainer, MrWidgetPipelineContainer,
...@@ -80,7 +82,7 @@ export default { ...@@ -80,7 +82,7 @@ export default {
}, },
}, },
data() { data() {
const store = this.mrData ? new MRWidgetStore(this.mrData) : null; const store = this.mrData && new MRWidgetStore(this.mrData);
return { return {
mr: store, mr: store,
...@@ -134,7 +136,32 @@ export default { ...@@ -134,7 +136,32 @@ export default {
}, },
}, },
mounted() { mounted() {
return MRWidgetService.fetchInitialData().then(({ data }) => { if (gon && gon.features && gon.features.asyncMrWidget) {
MRWidgetService.fetchInitialData()
.then(({ data }) => this.initWidget(data))
.catch(() =>
createFlash(__('Unable to load the merge request widget. Try reloading the page.')),
);
} else {
this.initWidget();
}
},
beforeDestroy() {
eventHub.$off('mr.discussion.updated', this.checkStatus);
if (this.pollingInterval) {
this.pollingInterval.destroy();
}
if (this.deploymentsInterval) {
this.deploymentsInterval.destroy();
}
if (this.postMergeDeploymentsInterval) {
this.postMergeDeploymentsInterval.destroy();
}
},
methods: {
initWidget(data = {}) {
if (this.mr) { if (this.mr) {
this.mr.setData({ ...window.gl.mrWidgetData, ...data }); this.mr.setData({ ...window.gl.mrWidgetData, ...data });
} else { } else {
...@@ -159,23 +186,7 @@ export default { ...@@ -159,23 +186,7 @@ export default {
this.initPolling(); this.initPolling();
this.bindEventHubListeners(); this.bindEventHubListeners();
eventHub.$on('mr.discussion.updated', this.checkStatus); eventHub.$on('mr.discussion.updated', this.checkStatus);
}); },
},
beforeDestroy() {
eventHub.$off('mr.discussion.updated', this.checkStatus);
if (this.pollingInterval) {
this.pollingInterval.destroy();
}
if (this.deploymentsInterval) {
this.deploymentsInterval.destroy();
}
if (this.postMergeDeploymentsInterval) {
this.postMergeDeploymentsInterval.destroy();
}
},
methods: {
getServiceEndpoints(store) { getServiceEndpoints(store) {
return { return {
mergePath: store.mergePath, mergePath: store.mergePath,
...@@ -397,4 +408,5 @@ export default { ...@@ -397,4 +408,5 @@ export default {
:is-post-merge="true" :is-post-merge="true"
/> />
</div> </div>
<loading v-else />
</template> </template>
...@@ -51,6 +51,10 @@ ...@@ -51,6 +51,10 @@
position: relative; position: relative;
border: 1px solid $border-color; border: 1px solid $border-color;
border-radius: $border-radius-default; border-radius: $border-radius-default;
.gl-skeleton-loader {
display: block;
}
} }
.mr-widget-extension { .mr-widget-extension {
......
...@@ -25,6 +25,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo ...@@ -25,6 +25,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action do before_action do
push_frontend_feature_flag(:vue_issuable_sidebar, @project.group) push_frontend_feature_flag(:vue_issuable_sidebar, @project.group)
push_frontend_feature_flag(:release_search_filter, @project, default_enabled: true) push_frontend_feature_flag(:release_search_filter, @project, default_enabled: true)
push_frontend_feature_flag(:async_mr_widget, @project)
end end
around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions] around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions]
......
...@@ -68,7 +68,11 @@ class MergeRequestWidgetEntity < Grape::Entity ...@@ -68,7 +68,11 @@ class MergeRequestWidgetEntity < Grape::Entity
end end
def as_json(options = {}) def as_json(options = {})
return super(options) if Feature.enabled?(:async_mr_widget)
super(options) super(options)
.merge(MergeRequestPollCachedWidgetEntity.new(object, **@options.opts_hash).as_json(options))
.merge(MergeRequestPollWidgetEntity.new(object, **@options.opts_hash).as_json(options))
end end
private private
......
---
title: Fetches initial merge request widget data async
merge_request: 20719
author:
type: changed
...@@ -369,4 +369,5 @@ export default { ...@@ -369,4 +369,5 @@ export default {
:is-post-merge="true" :is-post-merge="true"
/> />
</div> </div>
<loading v-else />
</template> </template>
...@@ -44,6 +44,8 @@ describe('ee merge request widget options', () => { ...@@ -44,6 +44,8 @@ describe('ee merge request widget options', () => {
beforeEach(() => { beforeEach(() => {
delete mrWidgetOptions.extends.el; // Prevent component mounting delete mrWidgetOptions.extends.el; // Prevent component mounting
gon.features = { asyncMrWidget: true };
Component = Vue.extend(mrWidgetOptions); Component = Vue.extend(mrWidgetOptions);
mock = new MockAdapter(axios); mock = new MockAdapter(axios);
...@@ -54,6 +56,7 @@ describe('ee merge request widget options', () => { ...@@ -54,6 +56,7 @@ describe('ee merge request widget options', () => {
afterEach(() => { afterEach(() => {
vm.$destroy(); vm.$destroy();
mock.restore(); mock.restore();
gon.features = {};
}); });
describe('security widget', () => { describe('security widget', () => {
......
...@@ -18694,6 +18694,9 @@ msgstr "" ...@@ -18694,6 +18694,9 @@ msgstr ""
msgid "Unable to load the diff. %{button_try_again}" msgid "Unable to load the diff. %{button_try_again}"
msgstr "" msgstr ""
msgid "Unable to load the merge request widget. Try reloading the page."
msgstr ""
msgid "Unable to resolve" msgid "Unable to resolve"
msgstr "" msgstr ""
......
...@@ -28,6 +28,7 @@ describe('mrWidgetOptions', () => { ...@@ -28,6 +28,7 @@ describe('mrWidgetOptions', () => {
delete mrWidgetOptions.el; delete mrWidgetOptions.el;
gl.mrWidgetData = { ...mockData }; gl.mrWidgetData = { ...mockData };
gon.features = { asyncMrWidget: true };
mock = new MockAdapter(axios); mock = new MockAdapter(axios);
mock.onGet(mockData.merge_request_widget_path).reply(() => [200, { ...mockData }]); mock.onGet(mockData.merge_request_widget_path).reply(() => [200, { ...mockData }]);
...@@ -43,6 +44,7 @@ describe('mrWidgetOptions', () => { ...@@ -43,6 +44,7 @@ describe('mrWidgetOptions', () => {
vm.$destroy(); vm.$destroy();
mock.restore(); mock.restore();
gl.mrWidgetData = {}; gl.mrWidgetData = {};
gon.features = {};
}); });
describe('data', () => { describe('data', () => {
......
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