Commit 747dbd8b authored by Ezekiel Kigbo's avatar Ezekiel Kigbo

Fetch chart data when the date range changes

Ensure that the chart data gets refreshed when a
the date range specified gets updated. Also adds
additional specs to ensure the correct error messages
are displayed if any of the requests fail after we
select a group'
parent 8776744c
<script>
import { GlEmptyState, GlDaterangePicker, GlLoadingIcon } from '@gitlab/ui';
import { mapActions, mapState, mapGetters } from 'vuex';
import { __ } from '~/locale';
import createFlash from '~/flash';
import { getDateInPast } from '~/lib/utils/datetime_utility';
import { featureAccessLevel } from '~/pages/projects/shared/permissions/constants';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
......@@ -46,6 +48,7 @@ export default {
...mapState([
'isLoading',
'isLoadingStage',
'isLoadingChartData',
'isEmptyStage',
'isAddingCustomStage',
'isSavingCustomStage',
......@@ -60,6 +63,7 @@ export default {
'errorCode',
'startDate',
'endDate',
'tasksByType',
]),
...mapGetters(['currentStage', 'defaultStage', 'hasNoAccessError', 'currentGroupPath']),
shouldRenderEmptyState() {
......@@ -106,12 +110,20 @@ export default {
this.setCycleAnalyticsDataEndpoint(group.full_path);
this.setSelectedGroup(group);
this.fetchCycleAnalyticsData();
this.fetchTasksByTypeData(group.path);
this.fetchGroupLabels(this.currentGroupPath)
.then(() => {
// TODO: Move this request into the `fetchCycleAnalyticsData` request, because we
// need to send the group labels, this request should fire after fetchGroupLablels is completed
// https://gitlab.com/gitlab-org/gitlab/merge_requests/18514
this.fetchTasksByTypeData();
})
.catch(() => createFlash(__('There was an error fetching data for the chart')));
},
onProjectsSelect(projects) {
const projectIds = projects.map(value => value.id);
this.setSelectedProjects(projectIds);
this.fetchCycleAnalyticsData();
this.fetchTasksByTypeData();
},
onStageSelect(stage) {
this.hideCustomStageForm();
......
......@@ -30,5 +30,5 @@ export const EMPTY_STAGE_TEXT = {
),
};
export const TASKS_BY_TYPE_SUBJECT_ISSUE = 'issues';
export const TASKS_BY_TYPE_SUBJECT_MERGE_REQUEST = 'merge_requests';
export const TASKS_BY_TYPE_SUBJECT_ISSUE = 'Issue';
export const TASKS_BY_TYPE_SUBJECT_MERGE_REQUEST = 'MergeRequest';
......@@ -32,7 +32,10 @@ export const setDateRange = (
if (skipFetch) return false;
return dispatch('fetchCycleAnalyticsData', { state, dispatch });
return Promise.all([
dispatch('fetchCycleAnalyticsData', { state, dispatch }),
dispatch('fetchTasksByTypeData'),
]);
};
export const requestStageData = ({ commit }) => commit(types.REQUEST_STAGE_DATA);
......@@ -208,23 +211,24 @@ export const receiveTasksByTypeDataError = ({ commit }, error) => {
};
export const requestTasksByTypeData = ({ commit }) => commit(types.REQUEST_TASKS_BY_TYPE_DATA);
export const fetchTasksByTypeData = ({ dispatch, state }, groupPath) => {
export const fetchTasksByTypeData = ({ dispatch, state, getters }) => {
const endpoint = '/-/analytics/type_of_work/tasks_by_type';
const { currentGroupPath } = getters;
const {
tasksByType: { labelIds, subject },
selectedProjectIds,
timeFrameCreatedBefore,
timeFrameCreatedAfter,
startDate,
endDate,
} = state;
// dont request if we have no labels selected...for now
if (!labelIds.length) {
if (labelIds.length) {
const params = {
group_id: groupPath,
label_ids: labelIds,
project_ids: selectedProjectIds,
created_before: timeFrameCreatedBefore,
created_after: timeFrameCreatedAfter,
group_id: currentGroupPath,
label_ids: `[${labelIds}]`,
project_ids: selectedProjectIds || [],
created_after: dateFormat(startDate, dateFormats.isoDate),
created_before: dateFormat(endDate, dateFormats.isoDate),
subject,
};
......@@ -236,4 +240,5 @@ export const fetchTasksByTypeData = ({ dispatch, state }, groupPath) => {
.then(data => dispatch('receiveTasksByTypeDataSuccess', data))
.catch(error => dispatch('receiveTasksByTypeDataError', error));
}
return Promise.resolve();
};
......@@ -60,12 +60,26 @@ export default {
},
[types.REQUEST_GROUP_LABELS](state) {
state.labels = [];
state.tasksByType = {
...state.tasksByType,
labelIds: [],
};
},
[types.RECEIVE_GROUP_LABELS_SUCCESS](state, data = []) {
const { tasksByType } = state;
state.labels = data.map(convertObjectPropsToCamelCase);
state.tasksByType = {
...tasksByType,
labelIds: data.map(({ id }) => id),
};
},
[types.RECEIVE_GROUP_LABELS_ERROR](state) {
const { tasksByType } = state;
state.labels = [];
state.tasksByType = {
...tasksByType,
labelIds: [],
};
},
[types.HIDE_CUSTOM_STAGE_FORM](state) {
state.isAddingCustomStage = false;
......
......@@ -13,6 +13,7 @@ export default () => ({
isLoading: false,
isLoadingStage: false,
isLoadingChartData: false,
isEmptyStage: false,
errorCode: null,
......@@ -35,6 +36,6 @@ export default () => ({
subject: TASKS_BY_TYPE_SUBJECT_ISSUE, // issues | merge_requests, defaults to issues
// list of selected labels for the tasks by type chart
labelIds: [],
data: []
data: [],
},
});
......@@ -429,9 +429,16 @@ describe('Cycle Analytics component', () => {
mock
.onGet('/groups/foo/-/labels')
.replyOnce(httpStatusCodes.OK, { response: { ...mockData.groupLabels } })
.replyOnce(httpStatusCodes.OK, [...mockData.groupLabels])
.onGet('/groups/foo/-/cycle_analytics')
.replyOnce(httpStatusCodes.OK, { response: { status: httpStatusCodes.OK } })
.replyOnce(httpStatusCodes.OK, {
...mockData.cycleAnalyticsData,
response: { status: httpStatusCodes.OK },
})
.onGet('/groups/foo/-/cycle_analytics/events/issue.json')
.replyOnce(httpStatusCodes.OK, {
response: { events: mockData.issueEvents },
})
.onGet('/-/analytics/type_of_work/tasks_by_type')
.replyOnce(httpStatusCodes.BAD_REQUEST, {
response: { status: httpStatusCodes.BAD_REQUEST },
......
......@@ -79,7 +79,10 @@ describe('Cycle analytics actions', () => {
{ startDate, endDate },
state,
[{ type: types.SET_DATE_RANGE, payload: { startDate, endDate } }],
[{ type: 'fetchCycleAnalyticsData', payload: { dispatch, state } }],
[
{ type: 'fetchCycleAnalyticsData', payload: { dispatch, state } },
{ type: 'fetchTasksByTypeData' },
],
done,
);
});
......
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