Commit f8292c71 authored by Mike Greiling's avatar Mike Greiling

Merge branch '38260-add-type-by-tasks-chart-feature-flag' into 'master'

Add tasks by type feature flag

See merge request gitlab-org/gitlab!21294
parents 9e7db9b1 0ebfc34c
...@@ -105,6 +105,7 @@ export default { ...@@ -105,6 +105,7 @@ export default {
this.initDateRange(); this.initDateRange();
this.setFeatureFlags({ this.setFeatureFlags({
hasDurationChart: this.glFeatures.cycleAnalyticsScatterplotEnabled, hasDurationChart: this.glFeatures.cycleAnalyticsScatterplotEnabled,
hasTasksByTypeChart: this.glFeatures.tasksByTypeChart,
}); });
}, },
methods: { methods: {
......
...@@ -56,10 +56,14 @@ export const fetchStageData = ({ state, dispatch, getters }, slug) => { ...@@ -56,10 +56,14 @@ export const fetchStageData = ({ state, dispatch, getters }, slug) => {
}; };
export const requestCycleAnalyticsData = ({ commit }) => commit(types.REQUEST_CYCLE_ANALYTICS_DATA); export const requestCycleAnalyticsData = ({ commit }) => commit(types.REQUEST_CYCLE_ANALYTICS_DATA);
export const receiveCycleAnalyticsDataSuccess = ({ commit, dispatch }) => { export const receiveCycleAnalyticsDataSuccess = ({ state, commit, dispatch }) => {
commit(types.RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS); commit(types.RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS);
dispatch('fetchDurationData'); const { featureFlags: { hasDurationChart = false, hasTasksByTypeChart = false } = {} } = state;
const promises = [];
if (hasDurationChart) promises.push('fetchDurationData');
if (hasTasksByTypeChart) promises.push('fetchTasksByTypeData');
return Promise.all(promises.map(func => dispatch(func)));
}; };
export const receiveCycleAnalyticsDataError = ({ commit }, { response }) => { export const receiveCycleAnalyticsDataError = ({ commit }, { response }) => {
...@@ -77,7 +81,6 @@ export const fetchCycleAnalyticsData = ({ dispatch }) => { ...@@ -77,7 +81,6 @@ export const fetchCycleAnalyticsData = ({ dispatch }) => {
.then(() => dispatch('fetchGroupLabels')) .then(() => dispatch('fetchGroupLabels'))
.then(() => dispatch('fetchGroupStagesAndEvents')) .then(() => dispatch('fetchGroupStagesAndEvents'))
.then(() => dispatch('fetchSummaryData')) .then(() => dispatch('fetchSummaryData'))
.then(() => dispatch('fetchTasksByTypeData'))
.then(() => dispatch('receiveCycleAnalyticsDataSuccess')) .then(() => dispatch('receiveCycleAnalyticsDataSuccess'))
.catch(error => dispatch('receiveCycleAnalyticsDataError', error)); .catch(error => dispatch('receiveCycleAnalyticsDataError', error));
}; };
...@@ -306,7 +309,6 @@ export const fetchDurationData = ({ state, dispatch }) => { ...@@ -306,7 +309,6 @@ export const fetchDurationData = ({ state, dispatch }) => {
dispatch('requestDurationData'); dispatch('requestDurationData');
const { const {
featureFlags: { hasDurationChart },
stages, stages,
startDate, startDate,
endDate, endDate,
...@@ -314,29 +316,26 @@ export const fetchDurationData = ({ state, dispatch }) => { ...@@ -314,29 +316,26 @@ export const fetchDurationData = ({ state, dispatch }) => {
selectedGroup: { fullPath }, selectedGroup: { fullPath },
} = state; } = state;
if (hasDurationChart) { return Promise.all(
return Promise.all( stages.map(stage => {
stages.map(stage => { const { slug } = stage;
const { slug } = stage;
return Api.cycleAnalyticsDurationChart(slug, {
return Api.cycleAnalyticsDurationChart(slug, { group_id: fullPath,
group_id: fullPath, created_after: dateFormat(startDate, dateFormats.isoDate),
created_after: dateFormat(startDate, dateFormats.isoDate), created_before: dateFormat(endDate, dateFormats.isoDate),
created_before: dateFormat(endDate, dateFormats.isoDate), project_ids: selectedProjectIds,
project_ids: selectedProjectIds, }).then(({ data }) => ({
}).then(({ data }) => ({ slug,
slug, selected: true,
selected: true, data,
data, }));
})); }),
}), )
) .then(data => {
.then(data => { dispatch('receiveDurationDataSuccess', data);
dispatch('receiveDurationDataSuccess', data); })
}) .catch(() => dispatch('receiveDurationDataError'));
.catch(() => dispatch('receiveDurationDataError'));
}
return false;
}; };
export const updateSelectedDurationChartStages = ({ state, commit }, stages) => { export const updateSelectedDurationChartStages = ({ state, commit }, stages) => {
......
...@@ -7,5 +7,6 @@ class Analytics::CycleAnalyticsController < Analytics::ApplicationController ...@@ -7,5 +7,6 @@ class Analytics::CycleAnalyticsController < Analytics::ApplicationController
before_action do before_action do
push_frontend_feature_flag(:customizable_cycle_analytics) push_frontend_feature_flag(:customizable_cycle_analytics)
push_frontend_feature_flag(:cycle_analytics_scatterplot_enabled) push_frontend_feature_flag(:cycle_analytics_scatterplot_enabled)
push_frontend_feature_flag(:tasks_by_type_chart)
end end
end end
...@@ -30,6 +30,7 @@ function createComponent({ ...@@ -30,6 +30,7 @@ function createComponent({
shallow = true, shallow = true,
withStageSelected = false, withStageSelected = false,
scatterplotEnabled = true, scatterplotEnabled = true,
tasksByTypeChartEnabled = true,
} = {}) { } = {}) {
const func = shallow ? shallowMount : mount; const func = shallow ? shallowMount : mount;
const comp = func(Component, { const comp = func(Component, {
...@@ -43,7 +44,10 @@ function createComponent({ ...@@ -43,7 +44,10 @@ function createComponent({
baseStagesEndpoint, baseStagesEndpoint,
}, },
provide: { provide: {
glFeatures: { cycleAnalyticsScatterplotEnabled: scatterplotEnabled }, glFeatures: {
cycleAnalyticsScatterplotEnabled: scatterplotEnabled,
tasksByTypeChart: tasksByTypeChartEnabled,
},
}, },
...opts, ...opts,
}); });
...@@ -351,7 +355,7 @@ describe('Cycle Analytics component', () => { ...@@ -351,7 +355,7 @@ describe('Cycle Analytics component', () => {
describe('with failed requests while loading', () => { describe('with failed requests while loading', () => {
const { full_path: groupId } = mockData.group; const { full_path: groupId } = mockData.group;
function mockRequestCycleAnalyticsData(overrides = {}, includeDutationDataRequests = true) { function mockRequestCycleAnalyticsData(overrides = {}, includeDurationDataRequests = true) {
const defaultStatus = 200; const defaultStatus = 200;
const defaultRequests = { const defaultRequests = {
fetchSummaryData: { fetchSummaryData: {
...@@ -383,17 +387,17 @@ describe('Cycle Analytics component', () => { ...@@ -383,17 +387,17 @@ describe('Cycle Analytics component', () => {
...overrides, ...overrides,
}; };
Object.values(defaultRequests).forEach(({ endpoint, status, response }) => { if (includeDurationDataRequests) {
mock.onGet(endpoint).replyOnce(status, response);
});
if (includeDutationDataRequests) {
mockData.defaultStages.forEach(stage => { mockData.defaultStages.forEach(stage => {
mock mock
.onGet(`${baseStagesEndpoint}/${stage}/duration_chart`) .onGet(`${baseStagesEndpoint}/${stage}/duration_chart`)
.replyOnce(defaultStatus, [...mockData.rawDurationData]); .replyOnce(defaultStatus, [...mockData.rawDurationData]);
}); });
} }
Object.values(defaultRequests).forEach(({ endpoint, status, response }) => {
mock.onGet(endpoint).replyOnce(status, response);
});
} }
beforeEach(() => { beforeEach(() => {
......
...@@ -46,6 +46,7 @@ describe('Cycle analytics actions', () => { ...@@ -46,6 +46,7 @@ describe('Cycle analytics actions', () => {
getters, getters,
featureFlags: { featureFlags: {
hasDurationChart: true, hasDurationChart: true,
hasTasksByTypeChart: true,
}, },
}; };
mock = new MockAdapter(axios); mock = new MockAdapter(axios);
...@@ -237,6 +238,7 @@ describe('Cycle analytics actions', () => { ...@@ -237,6 +238,7 @@ describe('Cycle analytics actions', () => {
receiveCycleAnalyticsDataSuccess: receiveCycleAnalyticsDataSuccess:
overrides.receiveCycleAnalyticsDataSuccess || jest.fn().mockResolvedValue(), overrides.receiveCycleAnalyticsDataSuccess || jest.fn().mockResolvedValue(),
fetchDurationData: overrides.fetchDurationData || jest.fn().mockResolvedValue(), fetchDurationData: overrides.fetchDurationData || jest.fn().mockResolvedValue(),
fetchTasksByTypeData: overrides.fetchTasksByTypeData || jest.fn().mockResolvedValue(),
}; };
return { return {
mocks, mocks,
...@@ -245,8 +247,8 @@ describe('Cycle analytics actions', () => { ...@@ -245,8 +247,8 @@ describe('Cycle analytics actions', () => {
.mockImplementationOnce(mocks.requestCycleAnalyticsData) .mockImplementationOnce(mocks.requestCycleAnalyticsData)
.mockImplementationOnce(mocks.fetchGroupStagesAndEvents) .mockImplementationOnce(mocks.fetchGroupStagesAndEvents)
.mockImplementationOnce(mocks.fetchSummaryData) .mockImplementationOnce(mocks.fetchSummaryData)
.mockImplementationOnce(mocks.receiveCycleAnalyticsDataSuccess) .mockImplementationOnce(mocks.fetchDurationData)
.mockImplementationOnce(mocks.fetchDurationData), .mockImplementationOnce(mocks.fetchTasksByTypeData),
}; };
} }
...@@ -270,8 +272,9 @@ describe('Cycle analytics actions', () => { ...@@ -270,8 +272,9 @@ describe('Cycle analytics actions', () => {
expect(mocks.requestCycleAnalyticsData).toHaveBeenCalled(); expect(mocks.requestCycleAnalyticsData).toHaveBeenCalled();
expect(mocks.fetchGroupStagesAndEvents).toHaveBeenCalled(); expect(mocks.fetchGroupStagesAndEvents).toHaveBeenCalled();
expect(mocks.fetchSummaryData).toHaveBeenCalled(); expect(mocks.fetchSummaryData).toHaveBeenCalled();
expect(mocks.receiveCycleAnalyticsDataSuccess).toHaveBeenCalled();
expect(mocks.fetchDurationData).toHaveBeenCalled(); expect(mocks.fetchDurationData).toHaveBeenCalled();
expect(mocks.fetchTasksByTypeData).toHaveBeenCalled();
done(); done();
}) })
.catch(done.fail); .catch(done.fail);
......
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