Commit f1702175 authored by David O'Regan's avatar David O'Regan

Merge branch '326701-move-ee-vsa-filter-components-to-ce' into 'master'

Moves the VSA filter EE to CE[RUN-AS-IF-FOSS]

See merge request gitlab-org/gitlab!65433
parents 99f5cbd3 50db70aa
......@@ -9,11 +9,11 @@ import {
GlSearchBoxByType,
} from '@gitlab/ui';
import { debounce } from 'lodash';
import { filterBySearchTerm } from '~/analytics/shared/utils';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import { n__, s__, __ } from '~/locale';
import { DATA_REFETCH_DELAY } from '../constants';
import getProjects from '../graphql/projects.query.graphql';
import { filterBySearchTerm } from '../utils';
export default {
name: 'ProjectsDropdownFilter',
......@@ -106,7 +106,7 @@ export default {
methods: {
search: debounce(function debouncedSearch() {
this.fetchData();
}, DATA_REFETCH_DELAY),
}, DEFAULT_DEBOUNCE_AND_THROTTLE_MS),
getSelectedProjects(selectedProject, isMarking) {
return isMarking
? this.selectedProjects.concat([selectedProject])
......
export const DATE_RANGE_LIMIT = 180;
export const OFFSET_DATE_BY_ONE = 1;
export const PROJECTS_PER_PAGE = 50;
export const filterBySearchTerm = (data = [], searchTerm = '', filterByKey = 'name') => {
if (!searchTerm?.length) return data;
return data.filter((item) => item[filterByKey].toLowerCase().includes(searchTerm.toLowerCase()));
};
<script>
import DateRange from '../../shared/components/daterange.vue';
import ProjectsDropdownFilter from '../../shared/components/projects_dropdown_filter.vue';
import { DATE_RANGE_LIMIT } from '../../shared/constants';
import { PROJECTS_PER_PAGE } from '../constants';
import DateRange from '~/analytics/shared/components/daterange.vue';
import ProjectsDropdownFilter from '~/analytics/shared/components/projects_dropdown_filter.vue';
import { DATE_RANGE_LIMIT, PROJECTS_PER_PAGE } from '~/analytics/shared/constants';
import FilterBar from './filter_bar.vue';
export default {
......
export const DEFAULT_DAYS_IN_PAST = 30;
export const DEFAULT_DAYS_TO_DISPLAY = 30;
export const OVERVIEW_STAGE_ID = 'overview';
......
......@@ -92,6 +92,8 @@ const refetchData = (dispatch, commit) => {
.finally(() => commit(types.SET_LOADING, false));
};
export const setFilters = ({ dispatch, commit }) => refetchData(dispatch, commit);
export const setDateRange = ({ dispatch, commit }, { startDate = DEFAULT_DAYS_TO_DISPLAY }) => {
commit(types.SET_DATE_RANGE, { startDate });
return refetchData(dispatch, commit);
......
......@@ -7,6 +7,7 @@
import Vue from 'vue';
import Vuex from 'vuex';
import filters from '~/vue_shared/components/filtered_search_bar/store/modules/filters';
import * as actions from './actions';
import * as getters from './getters';
import mutations from './mutations';
......@@ -20,4 +21,5 @@ export default () =>
getters,
mutations,
state,
modules: { filters },
});
......@@ -2,6 +2,7 @@
import { GlEmptyState } from '@gitlab/ui';
import { mapActions, mapState, mapGetters } from 'vuex';
import PathNavigation from '~/cycle_analytics/components/path_navigation.vue';
import ValueStreamFilters from '~/cycle_analytics/components/value_stream_filters.vue';
import { OVERVIEW_STAGE_ID } from '~/cycle_analytics/constants';
import UrlSync from '~/vue_shared/components/url_sync.vue';
import { toYmd } from '../../shared/utils';
......@@ -9,7 +10,6 @@ import DurationChart from './duration_chart.vue';
import Metrics from './metrics.vue';
import StageTable from './stage_table.vue';
import TypeOfWorkCharts from './type_of_work_charts.vue';
import ValueStreamFilters from './value_stream_filters.vue';
import ValueStreamSelect from './value_stream_select.vue';
export default {
......
import { OVERVIEW_STAGE_ID } from '~/cycle_analytics/constants';
import { __, s__ } from '~/locale';
export const PROJECTS_PER_PAGE = 50;
export const DEFAULT_DAYS_IN_PAST = 30;
export const EVENTS_LIST_ITEM_LIMIT = 50;
export const TASKS_BY_TYPE_SUBJECT_ISSUE = 'Issue';
......
<script>
import dateFormat from 'dateformat';
import DateRange from '~/analytics/shared/components/daterange.vue';
import UrlSync from '~/vue_shared/components/url_sync.vue';
import DateRange from '../../shared/components/daterange.vue';
import { dateFormats } from '../../shared/constants';
import { DEFAULT_NUMBER_OF_DAYS } from '../constants';
import FilterBar from './filter_bar.vue';
......
<script>
import { mapState, mapActions } from 'vuex';
import ProjectsDropdownFilter from '~/analytics/shared/components/projects_dropdown_filter.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import GroupsDropdownFilter from '../../shared/components/groups_dropdown_filter.vue';
import ProjectsDropdownFilter from '../../shared/components/projects_dropdown_filter.vue';
import { accessLevelReporter, projectsPerPage } from '../constants';
export default {
......
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { mapState, mapActions } from 'vuex';
import DateRange from '~/analytics/shared/components/daterange.vue';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import createDefaultClient from '~/lib/graphql';
import { parseBoolean } from '~/lib/utils/common_utils';
import DateRange from '../shared/components/daterange.vue';
import { buildGroupFromDataset, buildProjectFromDataset } from '../shared/utils';
import ProductivityAnalyticsApp from './components/app.vue';
import FilterDropdowns from './components/filter_dropdowns.vue';
......
......@@ -10,10 +10,10 @@ import {
GlSafeHtmlDirective as SafeHtml,
} from '@gitlab/ui';
import { debounce } from 'lodash';
import { filterBySearchTerm } from '~/analytics/shared/utils';
import Api from '~/api';
import { s__, __ } from '~/locale';
import { DATA_REFETCH_DELAY } from '../constants';
import { filterBySearchTerm } from '../utils';
export default {
name: 'GroupsDropdownFilter',
......
......@@ -19,10 +19,6 @@ export const scatterChartLineProps = {
},
};
export const DATE_RANGE_LIMIT = 180;
export const OFFSET_DATE_BY_ONE = 1;
export const NO_DRAG_CLASS = 'no-drag';
export const DATA_REFETCH_DELAY = DEFAULT_DEBOUNCE_AND_THROTTLE_MS;
......@@ -135,8 +135,3 @@ export const buildCycleAnalyticsInitialData = ({
: [],
stage: JSON.parse(stage),
});
export const filterBySearchTerm = (data = [], searchTerm = '', filterByKey = 'name') => {
if (!searchTerm?.length) return data;
return data.filter((item) => item[filterByKey].toLowerCase().includes(searchTerm.toLowerCase()));
};
......@@ -3,8 +3,9 @@ import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import Metrics from 'ee/analytics/cycle_analytics/components/metrics.vue';
import Api from 'ee/api';
import { group } from 'jest/cycle_analytics/mock_data';
import createFlash from '~/flash';
import { group, timeMetricsData, recentActivityData } from '../mock_data';
import { timeMetricsData, recentActivityData } from '../mock_data';
jest.mock('~/flash');
......
import { uniq } from 'lodash';
import {
DEFAULT_DAYS_IN_PAST,
TASKS_BY_TYPE_SUBJECT_ISSUE,
OVERVIEW_STAGE_CONFIG,
PAGINATION_TYPE,
......@@ -15,11 +14,16 @@ import {
} from 'ee/analytics/cycle_analytics/utils';
import { toYmd } from 'ee/analytics/shared/utils';
import { getJSONFixture } from 'helpers/fixtures';
import { TEST_HOST } from 'helpers/test_constants';
import { getStageByTitle, defaultStages, rawStageMedians } from 'jest/cycle_analytics/mock_data';
import {
getStageByTitle,
defaultStages,
rawStageMedians,
createdBefore,
createdAfter,
} from 'jest/cycle_analytics/mock_data';
import { transformStagesForPathNavigation } from '~/cycle_analytics/utils';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { getDateInPast, getDatesInRange } from '~/lib/utils/datetime_utility';
import { getDatesInRange } from '~/lib/utils/datetime_utility';
const fixtureEndpoints = {
customizableCycleAnalyticsStagesAndEvents: 'analytics/value_stream_analytics/stages.json', // customizable stages and events endpoint
......@@ -54,16 +58,6 @@ export const groupLabels = getJSONFixture(fixtureEndpoints.groupLabels).map(
convertObjectPropsToCamelCase,
);
export const group = {
id: 1,
name: 'foo',
path: 'foo',
full_path: 'foo',
avatar_url: `${TEST_HOST}/images/home/nasa.svg`,
};
export const currentGroup = convertObjectPropsToCamelCase(group, { deep: true });
export const recentActivityData = getJSONFixture(fixtureEndpoints.recentActivityData);
export const timeMetricsData = getJSONFixture(fixtureEndpoints.timeMetricsData);
......@@ -158,9 +152,6 @@ export const stageCounts = rawStageMedians.reduce((acc, { id, value }) => {
return { ...acc, [stageId]: value };
}, {});
export const createdBefore = new Date(2019, 0, 14);
export const createdAfter = getDateInPast(createdBefore, DEFAULT_DAYS_IN_PAST);
export const issueEvents = deepCamelCase(stageFixtures.issue);
export const planEvents = deepCamelCase(stageFixtures.plan);
export const reviewEvents = deepCamelCase(stageFixtures.review);
......@@ -299,21 +290,6 @@ export const rawDurationMedianData = [
},
];
export const selectedProjects = [
{
id: 'gid://gitlab/Project/1',
name: 'cool project',
pathWithNamespace: 'group/cool-project',
avatarUrl: null,
},
{
id: 'gid://gitlab/Project/2',
name: 'another cool project',
pathWithNamespace: 'group/another-cool-project',
avatarUrl: null,
},
];
export const pathNavIssueMetric = 172800;
export const initialPaginationQuery = {
......
......@@ -5,13 +5,11 @@ import * as actions from 'ee/analytics/cycle_analytics/store/actions';
import * as getters from 'ee/analytics/cycle_analytics/store/getters';
import * as types from 'ee/analytics/cycle_analytics/store/mutation_types';
import testAction from 'helpers/vuex_action_helper';
import { createdAfter, createdBefore, currentGroup } from 'jest/cycle_analytics/mock_data';
import createFlash from '~/flash';
import httpStatusCodes from '~/lib/utils/http_status';
import {
currentGroup,
allowedStages as stages,
createdAfter,
createdBefore,
customizableStagesAndEvents,
endpoints,
valueStreams,
......
import * as getters from 'ee/analytics/cycle_analytics/store/getters';
import { createdAfter, createdBefore, selectedProjects } from 'jest/cycle_analytics/mock_data';
import {
filterMilestones,
filterUsers,
......@@ -9,10 +10,7 @@ import {
getFilterValues,
} from 'jest/vue_shared/components/filtered_search_bar/store/modules/filters/test_helper';
import {
createdAfter,
createdBefore,
allowedStages,
selectedProjects,
issueStage,
stageMedians,
stageCounts,
......
......@@ -5,13 +5,11 @@ import * as actions from 'ee/analytics/cycle_analytics/store/modules/duration_ch
import * as getters from 'ee/analytics/cycle_analytics/store/modules/duration_chart/getters';
import * as types from 'ee/analytics/cycle_analytics/store/modules/duration_chart/mutation_types';
import testAction from 'helpers/vuex_action_helper';
import { createdAfter, createdBefore, group } from 'jest/cycle_analytics/mock_data';
import createFlash from '~/flash';
import httpStatusCodes from '~/lib/utils/http_status';
import {
group,
allowedStages as stages,
createdAfter,
createdBefore,
rawDurationData,
transformedDurationData,
endpoints,
......
import * as getters from 'ee/analytics/cycle_analytics/store/modules/duration_chart/getters';
import {
createdAfter,
createdBefore,
transformedDurationData,
durationChartPlottableData,
} from '../../../mock_data';
import { createdAfter, createdBefore } from 'jest/cycle_analytics/mock_data';
import { transformedDurationData, durationChartPlottableData } from '../../../mock_data';
const rootState = {
createdAfter,
......
......@@ -9,15 +9,10 @@ import * as actions from 'ee/analytics/cycle_analytics/store/modules/type_of_wor
import * as getters from 'ee/analytics/cycle_analytics/store/modules/type_of_work/getters';
import * as types from 'ee/analytics/cycle_analytics/store/modules/type_of_work/mutation_types';
import testAction from 'helpers/vuex_action_helper';
import { createdAfter, createdBefore } from 'jest/cycle_analytics/mock_data';
import createFlash from '~/flash';
import httpStatusCodes from '~/lib/utils/http_status';
import {
groupLabels,
endpoints,
createdAfter,
createdBefore,
rawTasksByTypeData,
} from '../../../mock_data';
import { groupLabels, endpoints, rawTasksByTypeData } from '../../../mock_data';
jest.mock('~/flash');
......
import { tasksByTypeChartData } from 'ee/analytics/cycle_analytics/store/modules/type_of_work/getters';
import {
rawTasksByTypeData,
transformedTasksByTypeData,
createdAfter,
createdBefore,
} from '../../../mock_data';
import { createdAfter, createdBefore } from 'jest/cycle_analytics/mock_data';
import { rawTasksByTypeData, transformedTasksByTypeData } from '../../../mock_data';
describe('Type of work getters', () => {
describe('tasksByTypeChartData', () => {
......
......@@ -4,16 +4,13 @@ import {
} from 'ee/analytics/cycle_analytics/constants';
import * as types from 'ee/analytics/cycle_analytics/store/mutation_types';
import mutations from 'ee/analytics/cycle_analytics/store/mutations';
import { createdAfter, createdBefore, selectedProjects } from 'jest/cycle_analytics/mock_data';
import {
issueStage,
planStage,
codeStage,
stagingStage,
reviewStage,
createdAfter,
createdBefore,
selectedProjects,
customizableStagesAndEvents,
valueStreams,
rawCustomStageEvents,
......
......@@ -19,7 +19,7 @@ import {
formatMedianValuesWithOverview,
} from 'ee/analytics/cycle_analytics/utils';
import { toYmd } from 'ee/analytics/shared/utils';
import { rawStageMedians } from 'jest/cycle_analytics/mock_data';
import { createdAfter, createdBefore, rawStageMedians } from 'jest/cycle_analytics/mock_data';
import { OVERVIEW_STAGE_ID } from '~/cycle_analytics/constants';
import { medianTimeToParsedSeconds } from '~/cycle_analytics/utils';
import { getDatesInRange } from '~/lib/utils/datetime_utility';
......@@ -32,8 +32,6 @@ import {
transformedDurationData,
flattenedDurationData,
durationChartPlottableData,
createdAfter,
createdBefore,
issueStage,
rawCustomStage,
rawTasksByTypeData,
......
......@@ -3,7 +3,7 @@ import MergeRequestAnalyticsApp from 'ee/analytics/merge_request_analytics/compo
import FilterBar from 'ee/analytics/merge_request_analytics/components/filter_bar.vue';
import ThroughputChart from 'ee/analytics/merge_request_analytics/components/throughput_chart.vue';
import ThroughputTable from 'ee/analytics/merge_request_analytics/components/throughput_table.vue';
import DateRange from 'ee/analytics/shared/components/daterange.vue';
import DateRange from '~/analytics/shared/components/daterange.vue';
import UrlSync from '~/vue_shared/components/url_sync.vue';
describe('MergeRequestAnalyticsApp', () => {
......
......@@ -3,7 +3,7 @@ import Vuex from 'vuex';
import FilterDropdowns from 'ee/analytics/productivity_analytics/components/filter_dropdowns.vue';
import { getStoreConfig } from 'ee/analytics/productivity_analytics/store';
import GroupsDropdownFilter from 'ee/analytics/shared/components/groups_dropdown_filter.vue';
import ProjectsDropdownFilter from 'ee/analytics/shared/components/projects_dropdown_filter.vue';
import ProjectsDropdownFilter from '~/analytics/shared/components/projects_dropdown_filter.vue';
import resetStore from '../helpers';
const localVue = createLocalVue();
......
......@@ -2,7 +2,6 @@ import {
buildGroupFromDataset,
buildProjectFromDataset,
buildCycleAnalyticsInitialData,
filterBySearchTerm,
} from 'ee/analytics/shared/utils';
const rawValueStream = `{
......@@ -179,27 +178,4 @@ describe('buildCycleAnalyticsInitialData', () => {
expect(buildCycleAnalyticsInitialData()).toMatchObject({ [field]: null });
});
});
describe('filterBySearchTerm', () => {
const data = [
{ name: 'eins', title: 'one' },
{ name: 'zwei', title: 'two' },
{ name: 'drei', title: 'three' },
];
const searchTerm = 'rei';
it('filters data by `name` for the provided search term', () => {
expect(filterBySearchTerm(data, searchTerm)).toEqual([data[2]]);
});
it('with no search term returns the data', () => {
['', null].forEach((search) => {
expect(filterBySearchTerm(data, search)).toEqual(data);
});
});
it('with a key, filters by the provided key', () => {
expect(filterBySearchTerm(data, 'ne', 'title')).toEqual([data[0]]);
});
});
});
import { GlDaterangePicker } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import Daterange from 'ee/analytics/shared/components/daterange.vue';
import { useFakeDate } from 'helpers/fake_date';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import Daterange from '~/analytics/shared/components/daterange.vue';
const defaultProps = {
startDate: new Date(2019, 8, 1),
......
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
import ProjectsDropdownFilter from 'ee/analytics/shared/components/projects_dropdown_filter.vue';
import getProjects from 'ee/analytics/shared/graphql/projects.query.graphql';
import { TEST_HOST } from 'helpers/test_constants';
import ProjectsDropdownFilter from '~/analytics/shared/components/projects_dropdown_filter.vue';
import getProjects from '~/analytics/shared/graphql/projects.query.graphql';
const projects = [
{
......
import { filterBySearchTerm } from '~/analytics/shared/utils';
describe('filterBySearchTerm', () => {
const data = [
{ name: 'eins', title: 'one' },
{ name: 'zwei', title: 'two' },
{ name: 'drei', title: 'three' },
];
const searchTerm = 'rei';
it('filters data by `name` for the provided search term', () => {
expect(filterBySearchTerm(data, searchTerm)).toEqual([data[2]]);
});
it('with no search term returns the data', () => {
['', null].forEach((search) => {
expect(filterBySearchTerm(data, search)).toEqual(data);
});
});
it('with a key, filters by the provided key', () => {
expect(filterBySearchTerm(data, 'ne', 'title')).toEqual([data[0]]);
});
});
......@@ -2,12 +2,12 @@ import { createLocalVue, shallowMount } from '@vue/test-utils';
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import Vuex from 'vuex';
import FilterBar from 'ee/analytics/cycle_analytics/components/filter_bar.vue';
import storeConfig from 'ee/analytics/cycle_analytics/store';
import {
filterMilestones,
filterLabels,
} from 'jest/vue_shared/components/filtered_search_bar/store/modules/filters/mock_data';
import FilterBar from '~/cycle_analytics/components/filter_bar.vue';
import storeConfig from '~/cycle_analytics/store';
import * as commonUtils from '~/lib/utils/common_utils';
import * as urlUtils from '~/lib/utils/url_utility';
import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue';
......
import { DEFAULT_VALUE_STREAM } from '~/cycle_analytics/constants';
import { TEST_HOST } from 'helpers/test_constants';
import { DEFAULT_VALUE_STREAM, DEFAULT_DAYS_IN_PAST } from '~/cycle_analytics/constants';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { getDateInPast } from '~/lib/utils/datetime_utility';
export const createdBefore = new Date(2019, 0, 14);
export const createdAfter = getDateInPast(createdBefore, DEFAULT_DAYS_IN_PAST);
export const getStageByTitle = (stages, title) =>
stages.find((stage) => stage.title && stage.title.toLowerCase().trim() === title) || {};
......@@ -212,6 +217,31 @@ export const transformedProjectStagePathData = [
export const selectedValueStream = DEFAULT_VALUE_STREAM;
export const group = {
id: 1,
name: 'foo',
path: 'foo',
full_path: 'foo',
avatar_url: `${TEST_HOST}/images/home/nasa.svg`,
};
export const currentGroup = convertObjectPropsToCamelCase(group, { deep: true });
export const selectedProjects = [
{
id: 'gid://gitlab/Project/1',
name: 'cool project',
pathWithNamespace: 'group/cool-project',
avatarUrl: null,
},
{
id: 'gid://gitlab/Project/2',
name: 'another cool project',
pathWithNamespace: 'group/another-cool-project',
avatarUrl: null,
},
];
export const rawValueStreamStages = [
{
title: 'Issue',
......
import { shallowMount } from '@vue/test-utils';
import FilterBar from 'ee/analytics/cycle_analytics/components/filter_bar.vue';
import ValueStreamFilters from 'ee/analytics/cycle_analytics/components/value_stream_filters.vue';
import Daterange from 'ee/analytics/shared/components/daterange.vue';
import ProjectsDropdownFilter from 'ee/analytics/shared/components/projects_dropdown_filter.vue';
import Daterange from '~/analytics/shared/components/daterange.vue';
import ProjectsDropdownFilter from '~/analytics/shared/components/projects_dropdown_filter.vue';
import FilterBar from '~/cycle_analytics/components/filter_bar.vue';
import ValueStreamFilters from '~/cycle_analytics/components/value_stream_filters.vue';
import {
createdAfter as startDate,
createdBefore as endDate,
currentGroup,
selectedProjects,
} from '../mock_data';
} from './mock_data';
function createComponent(props = {}) {
return shallowMount(ValueStreamFilters, {
......
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