Commit 45dcd491 authored by Ezekiel Kigbo's avatar Ezekiel Kigbo

Merge branch '246544-vsa-use-similarity-search-option-for-graphql-projects-queries' into 'master'

VSA: Use similarity search option for GraphQL projects queries

See merge request gitlab-org/gitlab!43974
parents c70d2901 a65be6a1
...@@ -3,7 +3,7 @@ import { GlEmptyState } from '@gitlab/ui'; ...@@ -3,7 +3,7 @@ import { GlEmptyState } from '@gitlab/ui';
import { mapActions, mapState, mapGetters } from 'vuex'; import { mapActions, mapState, mapGetters } from 'vuex';
import { PROJECTS_PER_PAGE } from '../constants'; import { PROJECTS_PER_PAGE } from '../constants';
import ProjectsDropdownFilter from '../../shared/components/projects_dropdown_filter.vue'; import ProjectsDropdownFilter from '../../shared/components/projects_dropdown_filter.vue';
import { SIMILARITY_ORDER, LAST_ACTIVITY_AT, DATE_RANGE_LIMIT } from '../../shared/constants'; import { DATE_RANGE_LIMIT } from '../../shared/constants';
import DateRange from '../../shared/components/daterange.vue'; import DateRange from '../../shared/components/daterange.vue';
import StageTable from './stage_table.vue'; import StageTable from './stage_table.vue';
import DurationChart from './duration_chart.vue'; import DurationChart from './duration_chart.vue';
...@@ -118,12 +118,8 @@ export default { ...@@ -118,12 +118,8 @@ export default {
}, },
projectsQueryParams() { projectsQueryParams() {
return { return {
per_page: PROJECTS_PER_PAGE, first: PROJECTS_PER_PAGE,
with_shared: false, includeSubgroups: true,
order_by: this.featureFlags.hasAnalyticsSimilaritySearch
? SIMILARITY_ORDER
: LAST_ACTIVITY_AT,
include_subgroups: true,
}; };
}, },
}, },
......
import Vue from 'vue'; import Vue from 'vue';
import VueApollo from 'vue-apollo';
import { GlToast } from '@gitlab/ui'; import { GlToast } from '@gitlab/ui';
import CycleAnalytics from './components/base.vue'; import CycleAnalytics from './components/base.vue';
import createStore from './store'; import createStore from './store';
import { buildCycleAnalyticsInitialData } from '../shared/utils'; import { buildCycleAnalyticsInitialData } from '../shared/utils';
import createDefaultClient from '~/lib/graphql';
import { urlQueryToFilter } from '~/vue_shared/components/filtered_search_bar/filtered_search_utils'; import { urlQueryToFilter } from '~/vue_shared/components/filtered_search_bar/filtered_search_utils';
Vue.use(GlToast); Vue.use(GlToast);
Vue.use(VueApollo);
const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(),
});
export default () => { export default () => {
const el = document.querySelector('#js-cycle-analytics-app'); const el = document.querySelector('#js-cycle-analytics-app');
...@@ -43,6 +50,7 @@ export default () => { ...@@ -43,6 +50,7 @@ export default () => {
return new Vue({ return new Vue({
el, el,
name: 'CycleAnalyticsApp', name: 'CycleAnalyticsApp',
apolloProvider,
store, store,
render: createElement => render: createElement =>
createElement(CycleAnalytics, { createElement(CycleAnalytics, {
......
import dateFormat from 'dateformat'; import dateFormat from 'dateformat';
import { isNumber } from 'lodash'; import { isNumber } from 'lodash';
import httpStatus from '~/lib/utils/http_status'; import httpStatus from '~/lib/utils/http_status';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { filterToQueryObject } from '~/vue_shared/components/filtered_search_bar/filtered_search_utils'; import { filterToQueryObject } from '~/vue_shared/components/filtered_search_bar/filtered_search_utils';
import { dateFormats } from '../../shared/constants'; import { dateFormats } from '../../shared/constants';
import { transformStagesForPathNavigation } from '../utils'; import { transformStagesForPathNavigation } from '../utils';
...@@ -14,7 +15,7 @@ export const currentValueStreamId = ({ selectedValueStream }) => ...@@ -14,7 +15,7 @@ export const currentValueStreamId = ({ selectedValueStream }) =>
export const currentGroupPath = ({ currentGroup }) => currentGroup?.fullPath || null; export const currentGroupPath = ({ currentGroup }) => currentGroup?.fullPath || null;
export const selectedProjectIds = ({ selectedProjects }) => export const selectedProjectIds = ({ selectedProjects }) =>
selectedProjects?.map(({ id }) => id) || []; selectedProjects?.map(({ id }) => getIdFromGraphQLId(id)) || [];
export const cycleAnalyticsRequestParams = (state, getters) => { export const cycleAnalyticsRequestParams = (state, getters) => {
const { const {
......
...@@ -10,7 +10,6 @@ import { ...@@ -10,7 +10,6 @@ import {
GlSearchBoxByType, GlSearchBoxByType,
} from '@gitlab/ui'; } from '@gitlab/ui';
import { n__, s__, __ } from '~/locale'; import { n__, s__, __ } from '~/locale';
import Api from '~/api';
import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { DATA_REFETCH_DELAY } from '../constants'; import { DATA_REFETCH_DELAY } from '../constants';
import { filterBySearchTerm } from '../utils'; import { filterBySearchTerm } from '../utils';
...@@ -56,11 +55,6 @@ export default { ...@@ -56,11 +55,6 @@ export default {
required: false, required: false,
default: () => [], default: () => [],
}, },
useGraphql: {
type: Boolean,
required: false,
default: false,
},
}, },
data() { data() {
return { return {
...@@ -133,7 +127,6 @@ export default { ...@@ -133,7 +127,6 @@ export default {
fetchData() { fetchData() {
this.loading = true; this.loading = true;
if (this.useGraphql) {
return this.$apollo return this.$apollo
.query({ .query({
query: getProjects, query: getProjects,
...@@ -155,20 +148,12 @@ export default { ...@@ -155,20 +148,12 @@ export default {
this.loading = false; this.loading = false;
this.projects = nodes; this.projects = nodes;
}); });
}
return Api.groupProjects(this.groupId, this.searchTerm, this.queryParams, projects => {
this.projects = projects;
this.loading = false;
});
}, },
isProjectSelected(id) { isProjectSelected(id) {
return this.selectedProjects ? this.selectedProjectIds.includes(id) : false; return this.selectedProjects ? this.selectedProjectIds.includes(id) : false;
}, },
getEntityId(project) { getEntityId(project) {
if (this.useGraphql) return getIdFromGraphQLId(project.id); return getIdFromGraphQLId(project.id);
return project?.id || null;
}, },
}, },
}; };
...@@ -184,7 +169,7 @@ export default { ...@@ -184,7 +169,7 @@ export default {
<div class="gl-display-flex gl-flex-fill-1"> <div class="gl-display-flex gl-flex-fill-1">
<gl-avatar <gl-avatar
v-if="isOnlyOneProjectSelected" v-if="isOnlyOneProjectSelected"
:src="useGraphql ? selectedProjects[0].avatarUrl : selectedProjects[0].avatar_url" :src="selectedProjects[0].avatarUrl"
:entity-id="getEntityId(selectedProjects[0])" :entity-id="getEntityId(selectedProjects[0])"
:entity-name="selectedProjects[0].name" :entity-name="selectedProjects[0].name"
:size="16" :size="16"
...@@ -213,7 +198,7 @@ export default { ...@@ -213,7 +198,7 @@ export default {
:size="16" :size="16"
:entity-id="getEntityId(project)" :entity-id="getEntityId(project)"
:entity-name="project.name" :entity-name="project.name"
:src="useGraphql ? project.avatarUrl : project.avatar_url" :src="project.avatarUrl"
shape="rect" shape="rect"
/> />
{{ project.name }} {{ project.name }}
......
...@@ -14,10 +14,6 @@ export const scatterChartLineProps = { ...@@ -14,10 +14,6 @@ export const scatterChartLineProps = {
}, },
}; };
export const LAST_ACTIVITY_AT = 'last_activity_at';
export const SIMILARITY_ORDER = 'similarity';
export const DATE_RANGE_LIMIT = 180; export const DATE_RANGE_LIMIT = 180;
export const OFFSET_DATE_BY_ONE = 1; export const OFFSET_DATE_BY_ONE = 1;
......
...@@ -115,7 +115,7 @@ module Gitlab ...@@ -115,7 +115,7 @@ module Gitlab
def project_data_attributes(project) def project_data_attributes(project)
{ {
id: project.id, id: project.to_gid.to_s,
name: project.name, name: project.name,
path_with_namespace: project.path_with_namespace, path_with_namespace: project.path_with_namespace,
avatar_url: project.avatar_url avatar_url: project.avatar_url
......
...@@ -24,6 +24,7 @@ import httpStatusCodes from '~/lib/utils/http_status'; ...@@ -24,6 +24,7 @@ import httpStatusCodes from '~/lib/utils/http_status';
import UrlSync from '~/vue_shared/components/url_sync.vue'; import UrlSync from '~/vue_shared/components/url_sync.vue';
import * as commonUtils from '~/lib/utils/common_utils'; import * as commonUtils from '~/lib/utils/common_utils';
import * as urlUtils from '~/lib/utils/url_utility'; import * as urlUtils from '~/lib/utils/url_utility';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import * as mockData from '../mock_data'; import * as mockData from '../mock_data';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
...@@ -65,6 +66,11 @@ const mocks = { ...@@ -65,6 +66,11 @@ const mocks = {
$toast: { $toast: {
show: jest.fn(), show: jest.fn(),
}, },
$apollo: {
query: jest.fn().mockResolvedValue({
data: { group: { projects: { nodes: [] } } },
}),
},
}; };
function mockRequiredRoutes(mockAdapter) { function mockRequiredRoutes(mockAdapter) {
...@@ -390,25 +396,6 @@ describe('Cycle Analytics component', () => { ...@@ -390,25 +396,6 @@ describe('Cycle Analytics component', () => {
}); });
}); });
describe('when analyticsSimilaritySearch feature flag is on', () => {
beforeEach(async () => {
wrapper = await createComponent({
withStageSelected: true,
featureFlags: {
hasAnalyticsSimilaritySearch: true,
},
});
});
it('uses similarity as the order param', () => {
displaysProjectsDropdownFilter(true);
expect(wrapper.find(ProjectsDropdownFilter).props().queryParams.order_by).toEqual(
'similarity',
);
});
});
it('displays the date range picker', () => { it('displays the date range picker', () => {
displaysDateRangePicker(true); displaysDateRangePicker(true);
}); });
...@@ -636,7 +623,7 @@ describe('Cycle Analytics component', () => { ...@@ -636,7 +623,7 @@ describe('Cycle Analytics component', () => {
project_ids: null, project_ids: null,
}; };
const selectedProjectIds = mockData.selectedProjects.map(({ id }) => id); const selectedProjectIds = mockData.selectedProjects.map(({ id }) => getIdFromGraphQLId(id));
beforeEach(async () => { beforeEach(async () => {
commonUtils.historyPushState = jest.fn(); commonUtils.historyPushState = jest.fn();
......
...@@ -251,13 +251,13 @@ export const rawDurationMedianData = [ ...@@ -251,13 +251,13 @@ export const rawDurationMedianData = [
export const selectedProjects = [ export const selectedProjects = [
{ {
id: 1, id: 'gid://gitlab/Project/1',
name: 'cool project', name: 'cool project',
pathWithNamespace: 'group/cool-project', pathWithNamespace: 'group/cool-project',
avatarUrl: null, avatarUrl: null,
}, },
{ {
id: 2, id: 'gid://gitlab/Project/2',
name: 'another cool project', name: 'another cool project',
pathWithNamespace: 'group/another-cool-project', pathWithNamespace: 'group/another-cool-project',
avatarUrl: null, avatarUrl: null,
......
...@@ -82,7 +82,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::RequestParams do ...@@ -82,7 +82,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::RequestParams do
describe 'optional `project_ids`' do describe 'optional `project_ids`' do
context 'when `project_ids` is not empty' do context 'when `project_ids` is not empty' do
def json_project(project) def json_project(project)
{ id: project.id, { id: project.to_gid.to_s,
name: project.name, name: project.name,
path_with_namespace: project.path_with_namespace, path_with_namespace: project.path_with_namespace,
avatar_url: project.avatar_url }.to_json avatar_url: project.avatar_url }.to_json
......
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