Commit 8d3dc79d authored by Miguel Rincon's avatar Miguel Rincon

Merge branch '321079-fe-vsa-add-url-sort-params' into 'master'

[FE] VSA - Add URL sort params

See merge request gitlab-org/gitlab!62439
parents cb9cf4ab ba9face4
......@@ -94,6 +94,17 @@ export default {
},
query() {
const selectedProjectIds = this.selectedProjectIds?.length ? this.selectedProjectIds : null;
const paginationUrlParams = !this.isOverviewStageSelected
? {
sort: this.pagination?.sort || null,
direction: this.pagination?.direction || null,
page: this.pagination?.page || null,
}
: {
sort: null,
direction: null,
page: null,
};
return {
value_stream_id: this.selectedValueStream?.id || null,
......@@ -101,8 +112,7 @@ export default {
created_after: toYmd(this.startDate),
created_before: toYmd(this.endDate),
stage_id: (!this.isOverviewStageSelected && this.selectedStage?.id) || null, // the `overview` stage is always the default, so dont persist the id if its selected
sort: (!this.isOverviewStageSelected && this.pagination?.sort) || null,
direction: (!this.isOverviewStageSelected && this.pagination?.direction) || null,
...paginationUrlParams,
};
},
stageCount() {
......@@ -134,7 +144,7 @@ export default {
this.setDefaultSelectedStage();
} else {
this.setSelectedStage(stage);
this.fetchStageData(stage.slug);
this.updateStageTablePagination({ ...this.pagination, page: 1 });
}
},
onHandleUpdatePagination(data) {
......
......@@ -28,6 +28,7 @@ export default () => {
label_name = [],
sort,
direction,
page,
} = urlQueryToFilter(window.location.search);
store.dispatch('initializeCycleAnalytics', {
......@@ -37,7 +38,11 @@ export default () => {
selectedAssigneeList: assignee_username,
selectedLabelList: label_name,
featureFlags: { hasDurationChart },
pagination: { sort: sort?.value || null, direction: direction?.value || null },
pagination: {
sort: sort?.value || null,
direction: direction?.value || null,
page: page?.value || null,
},
});
return new Vue({
......
......@@ -30,10 +30,7 @@ export const setFeatureFlags = ({ commit }, featureFlags) =>
export const setSelectedProjects = ({ commit }, projects) =>
commit(types.SET_SELECTED_PROJECTS, projects);
export const setSelectedStage = ({ commit, getters: { paginationParams } }, stage) => {
commit(types.SET_SELECTED_STAGE, stage);
commit(types.SET_PAGINATION, { ...paginationParams, page: 1, hasNextPage: null });
};
export const setSelectedStage = ({ commit }, stage) => commit(types.SET_SELECTED_STAGE, stage);
export const setDateRange = (
{ commit, dispatch, getters: { isOverviewStageSelected }, state: { selectedStage } },
......
......@@ -11,10 +11,7 @@ import PathNavigation from 'ee/analytics/cycle_analytics/components/path_navigat
import StageTableNew from 'ee/analytics/cycle_analytics/components/stage_table_new.vue';
import TypeOfWorkCharts from 'ee/analytics/cycle_analytics/components/type_of_work_charts.vue';
import ValueStreamSelect from 'ee/analytics/cycle_analytics/components/value_stream_select.vue';
import {
PAGINATION_SORT_FIELD_END_EVENT,
PAGINATION_SORT_DIRECTION_DESC,
} from 'ee/analytics/cycle_analytics/constants';
import { OVERVIEW_STAGE_ID } from 'ee/analytics/cycle_analytics/constants';
import createStore from 'ee/analytics/cycle_analytics/store';
import Daterange from 'ee/analytics/shared/components/daterange.vue';
import ProjectsDropdownFilter from 'ee/analytics/shared/components/projects_dropdown_filter.vue';
......@@ -142,7 +139,7 @@ describe('Value Stream Analytics component', () => {
...opts,
});
if (withStageSelected) {
if (withStageSelected || selectedStage) {
await store.dispatch(
'receiveGroupStagesSuccess',
mockData.customizableStagesAndEvents.stages,
......@@ -181,8 +178,10 @@ describe('Value Stream Analytics component', () => {
expect(wrapper.findComponent(TypeOfWorkCharts).exists()).toBe(flag);
};
const findPathNavigation = () => wrapper.findComponent(PathNavigation);
const displaysPathNavigation = (flag) => {
expect(wrapper.findComponent(PathNavigation).exists()).toBe(flag);
expect(findPathNavigation().exists()).toBe(flag);
};
const displaysFilterBar = (flag) => {
......@@ -350,10 +349,7 @@ describe('Value Stream Analytics component', () => {
beforeEach(async () => {
mock = new MockAdapter(axios);
mockRequiredRoutes(mock);
wrapper = await createComponent({
withStageSelected: true,
selectedStage: mockData.issueStage,
});
wrapper = await createComponent({ selectedStage: mockData.issueStage });
});
it('displays the stage table', () => {
......@@ -405,7 +401,7 @@ describe('Value Stream Analytics component', () => {
.onGet(mockData.endpoints.stageData)
.reply(httpStatusCodes.NOT_FOUND, { response: { status: httpStatusCodes.NOT_FOUND } });
await createComponent({ withStageSelected: true, selectedStage: mockData.issueStage });
await createComponent({ selectedStage: mockData.issueStage });
await findError('There was an error fetching data for the selected stage');
});
......@@ -447,6 +443,48 @@ describe('Value Stream Analytics component', () => {
});
});
describe('Path navigation', () => {
const selectedStage = { title: 'Plan', slug: 2 };
const overviewStage = { title: 'Overview', slug: OVERVIEW_STAGE_ID };
let actionSpies = {};
beforeEach(async () => {
mock = new MockAdapter(axios);
mockRequiredRoutes(mock);
wrapper = await createComponent();
actionSpies = {
setDefaultSelectedStage: jest.spyOn(wrapper.vm, 'setDefaultSelectedStage'),
setSelectedStage: jest.spyOn(wrapper.vm, 'setSelectedStage'),
updateStageTablePagination: jest.spyOn(wrapper.vm, 'updateStageTablePagination'),
};
});
afterEach(() => {
wrapper.destroy();
mock.restore();
wrapper = null;
});
it('when a stage is selected', () => {
findPathNavigation().vm.$emit('selected', selectedStage);
expect(actionSpies.setDefaultSelectedStage).not.toHaveBeenCalled();
expect(actionSpies.setSelectedStage).toHaveBeenCalledWith(selectedStage);
expect(actionSpies.updateStageTablePagination).toHaveBeenCalledWith({
...mockData.initialPaginationQuery,
page: 1,
});
});
it('when the overview is selected', () => {
findPathNavigation().vm.$emit('selected', overviewStage);
expect(actionSpies.setSelectedStage).not.toHaveBeenCalled();
expect(actionSpies.updateStageTablePagination).not.toHaveBeenCalled();
expect(actionSpies.setDefaultSelectedStage).toHaveBeenCalled();
});
});
describe('Url parameters', () => {
const defaultParams = {
value_stream_id: selectedValueStream.id,
......@@ -456,6 +494,7 @@ describe('Value Stream Analytics component', () => {
project_ids: null,
sort: null,
direction: null,
page: null,
};
const selectedProjectIds = mockData.selectedProjects.map(({ id }) => getIdFromGraphQLId(id));
......@@ -527,17 +566,20 @@ describe('Value Stream Analytics component', () => {
describe('with selectedStage set', () => {
beforeEach(async () => {
wrapper = await createComponent();
store.dispatch('setSelectedStage', selectedStage);
await wrapper.vm.$nextTick();
wrapper = await createComponent({
initialState: {
...initialCycleAnalyticsState,
pagination: mockData.initialPaginationQuery,
},
selectedStage,
});
});
it('sets the stage, sort and direction parameters', async () => {
it('sets the stage, sort, direction and page parameters', async () => {
await shouldMergeUrlParams(wrapper, {
...defaultParams,
...mockData.initialPaginationQuery,
stage_id: selectedStage.id,
direction: PAGINATION_SORT_DIRECTION_DESC,
sort: PAGINATION_SORT_FIELD_END_EVENT,
});
});
});
......
......@@ -325,11 +325,16 @@ export const selectedProjects = [
export const pathNavIssueMetric = 172800;
export const initialPaginationQuery = {
page: 15,
sort: PAGINATION_SORT_FIELD_END_EVENT,
direction: PAGINATION_SORT_DIRECTION_DESC,
};
export const initialPaginationState = {
...initialPaginationQuery,
page: null,
hasNextPage: false,
sort: PAGINATION_SORT_FIELD_END_EVENT,
direction: PAGINATION_SORT_DIRECTION_DESC,
};
export const basePaginationResult = {
......
......@@ -92,12 +92,10 @@ describe('Value Stream Analytics actions', () => {
describe('setSelectedStage', () => {
const data = { id: 'someStageId' };
const payload = { hasNextPage: null, page: 1 };
it(`dispatches the ${types.SET_SELECTED_STAGE} and ${types.SET_PAGINATION} actions`, () => {
return testAction(actions.setSelectedStage, data, { ...state, selectedValueStream: {} }, [
{ type: types.SET_SELECTED_STAGE, payload: data },
{ type: types.SET_PAGINATION, payload },
]);
});
});
......@@ -625,6 +623,16 @@ describe('Value Stream Analytics actions', () => {
});
});
describe('with pagination parameters', () => {
it('dispatches "setSelectedStage" and "fetchStageData"', async () => {
const stage = { id: 2, title: 'plan' };
const pagination = { sort: 'end_event', direction: 'desc', page: 1337 };
const payload = { ...initialData, stage, pagination };
await actions.initializeCycleAnalytics(store, payload);
expect(mockCommit).toHaveBeenCalledWith('INITIALIZE_VSA', payload);
});
});
describe('without a selected stage', () => {
it('dispatches "setDefaultSelectedStage"', async () => {
await actions.initializeCycleAnalytics(store, {
......
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