Commit bb8f2445 authored by Martin Wortschack's avatar Martin Wortschack

Merge branch 'similarity-project-search-on-analytics-pages' into 'master'

Similarity search in projects dropdown

See merge request gitlab-org/gitlab!37700
parents 34151a30 4b353e8d
...@@ -5,7 +5,7 @@ import { featureAccessLevel } from '~/pages/projects/shared/permissions/constant ...@@ -5,7 +5,7 @@ import { featureAccessLevel } from '~/pages/projects/shared/permissions/constant
import { PROJECTS_PER_PAGE, STAGE_ACTIONS } from '../constants'; import { PROJECTS_PER_PAGE, STAGE_ACTIONS } from '../constants';
import GroupsDropdownFilter from '../../shared/components/groups_dropdown_filter.vue'; import GroupsDropdownFilter from '../../shared/components/groups_dropdown_filter.vue';
import ProjectsDropdownFilter from '../../shared/components/projects_dropdown_filter.vue'; import ProjectsDropdownFilter from '../../shared/components/projects_dropdown_filter.vue';
import { LAST_ACTIVITY_AT, DATE_RANGE_LIMIT } from '../../shared/constants'; import { SIMILARITY_ORDER, LAST_ACTIVITY_AT, 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';
...@@ -143,6 +143,16 @@ export default { ...@@ -143,6 +143,16 @@ export default {
hasProject() { hasProject() {
return this.selectedProjectIds.length > 0; return this.selectedProjectIds.length > 0;
}, },
projectsQueryParams() {
return {
per_page: PROJECTS_PER_PAGE,
with_shared: false,
order_by: this.featureFlags.hasAnalyticsSimilaritySearch
? SIMILARITY_ORDER
: LAST_ACTIVITY_AT,
include_subgroups: true,
};
},
}, },
methods: { methods: {
...@@ -203,12 +213,6 @@ export default { ...@@ -203,12 +213,6 @@ export default {
groupsQueryParams: { groupsQueryParams: {
min_access_level: featureAccessLevel.EVERYONE, min_access_level: featureAccessLevel.EVERYONE,
}, },
projectsQueryParams: {
per_page: PROJECTS_PER_PAGE,
with_shared: false,
order_by: LAST_ACTIVITY_AT,
include_subgroups: true,
},
maxDateRange: DATE_RANGE_LIMIT, maxDateRange: DATE_RANGE_LIMIT,
STAGE_ACTIONS, STAGE_ACTIONS,
}; };
...@@ -252,7 +256,7 @@ export default { ...@@ -252,7 +256,7 @@ export default {
:key="selectedGroup.id" :key="selectedGroup.id"
class="js-projects-dropdown-filter project-select" class="js-projects-dropdown-filter project-select"
:group-id="selectedGroup.id" :group-id="selectedGroup.id"
:query-params="$options.projectsQueryParams" :query-params="projectsQueryParams"
:multi-select="$options.multiProjectSelect" :multi-select="$options.multiProjectSelect"
:default-projects="selectedProjects" :default-projects="selectedProjects"
@selected="onProjectsSelect" @selected="onProjectsSelect"
......
...@@ -18,6 +18,7 @@ export default () => { ...@@ -18,6 +18,7 @@ export default () => {
valueStreamAnalyticsPathNavigation: hasPathNavigation = false, valueStreamAnalyticsPathNavigation: hasPathNavigation = false,
valueStreamAnalyticsFilterBar: hasFilterBar = false, valueStreamAnalyticsFilterBar: hasFilterBar = false,
valueStreamAnalyticsCreateMultipleValueStreams: hasCreateMultipleValueStreams = false, valueStreamAnalyticsCreateMultipleValueStreams: hasCreateMultipleValueStreams = false,
analyticsSimilaritySearch: hasAnalyticsSimilaritySearch = false,
} = gon?.features; } = gon?.features;
store.dispatch('initializeCycleAnalytics', { store.dispatch('initializeCycleAnalytics', {
...@@ -28,6 +29,7 @@ export default () => { ...@@ -28,6 +29,7 @@ export default () => {
hasPathNavigation, hasPathNavigation,
hasFilterBar, hasFilterBar,
hasCreateMultipleValueStreams, hasCreateMultipleValueStreams,
hasAnalyticsSimilaritySearch,
}, },
}); });
......
<script> <script>
import { mapState, mapActions } from 'vuex'; import { mapState, mapActions } from 'vuex';
import GroupsDropdownFilter from '../../shared/components/groups_dropdown_filter.vue'; import GroupsDropdownFilter from '../../shared/components/groups_dropdown_filter.vue';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import ProjectsDropdownFilter from '../../shared/components/projects_dropdown_filter.vue'; import ProjectsDropdownFilter from '../../shared/components/projects_dropdown_filter.vue';
import { accessLevelReporter, projectsPerPage } from '../constants'; import { accessLevelReporter, projectsPerPage } from '../constants';
import { LAST_ACTIVITY_AT } from '../../shared/constants'; import { SIMILARITY_ORDER, LAST_ACTIVITY_AT } from '../../shared/constants';
export default { export default {
components: { components: {
GroupsDropdownFilter, GroupsDropdownFilter,
ProjectsDropdownFilter, ProjectsDropdownFilter,
}, },
mixins: [glFeatureFlagsMixin()],
props: { props: {
group: { group: {
type: Object, type: Object,
...@@ -40,6 +42,14 @@ export default { ...@@ -40,6 +42,14 @@ export default {
projects() { projects() {
return this.project && Object.keys(this.project).length ? [this.project] : null; return this.project && Object.keys(this.project).length ? [this.project] : null;
}, },
projectsQueryParams() {
return {
per_page: projectsPerPage,
with_shared: false, // exclude forks
order_by: this.glFeatures.analyticsSimilaritySearch ? SIMILARITY_ORDER : LAST_ACTIVITY_AT,
include_subgroups: true,
};
},
}, },
methods: { methods: {
...mapActions('filters', ['setGroupNamespace', 'setProjectPath']), ...mapActions('filters', ['setGroupNamespace', 'setProjectPath']),
...@@ -69,12 +79,6 @@ export default { ...@@ -69,12 +79,6 @@ export default {
groupsQueryParams: { groupsQueryParams: {
min_access_level: accessLevelReporter, min_access_level: accessLevelReporter,
}, },
projectsQueryParams: {
per_page: projectsPerPage,
with_shared: false, // exclude forks
order_by: LAST_ACTIVITY_AT,
include_subgroups: true,
},
}; };
</script> </script>
...@@ -92,7 +96,7 @@ export default { ...@@ -92,7 +96,7 @@ export default {
:key="groupId" :key="groupId"
class="project-select" class="project-select"
:default-projects="projects" :default-projects="projects"
:query-params="$options.projectsQueryParams" :query-params="projectsQueryParams"
:group-id="groupId" :group-id="groupId"
@selected="onProjectsSelected" @selected="onProjectsSelected"
/> />
......
...@@ -16,6 +16,8 @@ export const scatterChartLineProps = { ...@@ -16,6 +16,8 @@ export const scatterChartLineProps = {
export const LAST_ACTIVITY_AT = 'last_activity_at'; 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;
......
...@@ -17,6 +17,7 @@ class Analytics::CycleAnalyticsController < Analytics::ApplicationController ...@@ -17,6 +17,7 @@ class Analytics::CycleAnalyticsController < Analytics::ApplicationController
push_frontend_feature_flag(:value_stream_analytics_path_navigation, @group) push_frontend_feature_flag(:value_stream_analytics_path_navigation, @group)
push_frontend_feature_flag(:value_stream_analytics_filter_bar, @group) push_frontend_feature_flag(:value_stream_analytics_filter_bar, @group)
push_frontend_feature_flag(:value_stream_analytics_create_multiple_value_streams, @group) push_frontend_feature_flag(:value_stream_analytics_create_multiple_value_streams, @group)
push_frontend_feature_flag(:analytics_similarity_search, @group)
end end
private private
......
...@@ -19,6 +19,7 @@ module Analytics ...@@ -19,6 +19,7 @@ module Analytics
before_action -> { before_action -> {
push_frontend_feature_flag(:productivity_analytics_scatterplot_enabled, default_enabled: true) push_frontend_feature_flag(:productivity_analytics_scatterplot_enabled, default_enabled: true)
push_frontend_feature_flag(:analytics_similarity_search, @group)
} }
before_action :validate_params, only: :show, if: -> { request.format.json? } before_action :validate_params, only: :show, if: -> { request.format.json? }
......
...@@ -19,6 +19,7 @@ class Groups::Analytics::ProductivityAnalyticsController < Groups::Analytics::Ap ...@@ -19,6 +19,7 @@ class Groups::Analytics::ProductivityAnalyticsController < Groups::Analytics::Ap
} }
before_action -> { before_action -> {
push_frontend_feature_flag(:productivity_analytics_scatterplot_enabled, default_enabled: true) push_frontend_feature_flag(:productivity_analytics_scatterplot_enabled, default_enabled: true)
push_frontend_feature_flag(:analytics_similarity_search, @group)
} }
before_action :validate_params, only: :show, if: -> { request.format.json? } before_action :validate_params, only: :show, if: -> { request.format.json? }
......
...@@ -21,7 +21,8 @@ RSpec.describe 'Group value stream analytics' do ...@@ -21,7 +21,8 @@ RSpec.describe 'Group value stream analytics' do
cycleAnalyticsScatterplotEnabled: true, cycleAnalyticsScatterplotEnabled: true,
cycleAnalyticsScatterplotMedianEnabled: true, cycleAnalyticsScatterplotMedianEnabled: true,
valueStreamAnalyticsPathNavigation: true, valueStreamAnalyticsPathNavigation: true,
valueStreamAnalyticsFilterBar: true valueStreamAnalyticsFilterBar: true,
analyticsSimilaritySearch: true
) )
end end
......
...@@ -304,13 +304,32 @@ describe('Cycle Analytics component', () => { ...@@ -304,13 +304,32 @@ describe('Cycle Analytics component', () => {
expect(wrapper.find(ProjectsDropdownFilter).props()).toEqual( expect(wrapper.find(ProjectsDropdownFilter).props()).toEqual(
expect.objectContaining({ expect.objectContaining({
queryParams: wrapper.vm.$options.projectsQueryParams, queryParams: wrapper.vm.projectsQueryParams,
groupId: mockData.group.id, groupId: mockData.group.id,
multiSelect: wrapper.vm.$options.multiProjectSelect, multiSelect: wrapper.vm.$options.multiProjectSelect,
}), }),
); );
}); });
describe('when analyticsSimilaritySearch feature flag is on', () => {
beforeEach(() => {
wrapper = 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);
}); });
......
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