Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-11-06 09:08:51 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-11-06 09:08:51 +0300
commiteefbee4451565989727256d36176dc2950e3a0b7 (patch)
tree29d630cac89ec88ab5c2a22f9b2ca40b4e0fd613 /app/assets/javascripts/search
parent74d35955aa0e12ff6ed99b39adb38e0f13fb96aa (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/search')
-rw-r--r--app/assets/javascripts/search/index.js8
-rw-r--r--app/assets/javascripts/search/sidebar/components/confidentiality_filter.vue25
-rw-r--r--app/assets/javascripts/search/sidebar/components/radio_filter.vue68
-rw-r--r--app/assets/javascripts/search/sidebar/components/status_filter.vue25
-rw-r--r--app/assets/javascripts/search/sidebar/constants/confidential_filter_data.js36
-rw-r--r--app/assets/javascripts/search/sidebar/constants/state_filter_data.js42
-rw-r--r--app/assets/javascripts/search/sidebar/index.js34
-rw-r--r--app/assets/javascripts/search/store/actions.js4
-rw-r--r--app/assets/javascripts/search/store/mutation_types.js2
-rw-r--r--app/assets/javascripts/search/store/mutations.js3
10 files changed, 246 insertions, 1 deletions
diff --git a/app/assets/javascripts/search/index.js b/app/assets/javascripts/search/index.js
index 7d175bace4f..275d6351adc 100644
--- a/app/assets/javascripts/search/index.js
+++ b/app/assets/javascripts/search/index.js
@@ -1,11 +1,17 @@
import { queryToObject } from '~/lib/utils/url_utility';
import createStore from './store';
import initDropdownFilters from './dropdown_filter';
+import { initSidebar } from './sidebar';
import initGroupFilter from './group_filter';
export default () => {
const store = createStore({ query: queryToObject(window.location.search) });
- initDropdownFilters(store);
+ if (gon.features.searchFacets) {
+ initSidebar(store);
+ } else {
+ initDropdownFilters(store);
+ }
+
initGroupFilter(store);
};
diff --git a/app/assets/javascripts/search/sidebar/components/confidentiality_filter.vue b/app/assets/javascripts/search/sidebar/components/confidentiality_filter.vue
new file mode 100644
index 00000000000..f8938e799aa
--- /dev/null
+++ b/app/assets/javascripts/search/sidebar/components/confidentiality_filter.vue
@@ -0,0 +1,25 @@
+<script>
+import { mapState } from 'vuex';
+import { confidentialFilterData } from '../constants/confidential_filter_data';
+import RadioFilter from './radio_filter.vue';
+
+export default {
+ name: 'ConfidentialityFilter',
+ components: {
+ RadioFilter,
+ },
+ computed: {
+ ...mapState(['query']),
+ showDropdown() {
+ return Object.values(confidentialFilterData.scopes).includes(this.query.scope);
+ },
+ },
+ confidentialFilterData,
+};
+</script>
+
+<template>
+ <div v-if="showDropdown">
+ <radio-filter :filter-data="$options.confidentialFilterData" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/search/sidebar/components/radio_filter.vue b/app/assets/javascripts/search/sidebar/components/radio_filter.vue
new file mode 100644
index 00000000000..b27c4e26fb5
--- /dev/null
+++ b/app/assets/javascripts/search/sidebar/components/radio_filter.vue
@@ -0,0 +1,68 @@
+<script>
+import { mapState, mapActions } from 'vuex';
+import { GlFormRadioGroup, GlFormRadio } from '@gitlab/ui';
+import { sprintf, s__ } from '~/locale';
+
+export default {
+ name: 'RadioFilter',
+ components: {
+ GlFormRadioGroup,
+ GlFormRadio,
+ },
+ props: {
+ filterData: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ ...mapState(['query']),
+ ANY() {
+ return this.filterData.filters.ANY;
+ },
+ scope() {
+ return this.query.scope;
+ },
+ initialFilter() {
+ return this.query[this.filterData.filterParam];
+ },
+ filter() {
+ return this.initialFilter || this.ANY.value;
+ },
+ filtersArray() {
+ return this.filterData.filterByScope[this.scope];
+ },
+ selectedFilter: {
+ get() {
+ if (this.filtersArray.some(({ value }) => value === this.filter)) {
+ return this.filter;
+ }
+
+ return this.ANY.value;
+ },
+ set(value) {
+ this.setQuery({ key: this.filterData.filterParam, value });
+ },
+ },
+ },
+ methods: {
+ ...mapActions(['setQuery']),
+ radioLabel(filter) {
+ return filter.value === this.ANY.value
+ ? sprintf(s__('Any %{header}'), { header: this.filterData.header.toLowerCase() })
+ : filter.label;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <h5 class="gl-mt-0">{{ filterData.header }}</h5>
+ <gl-form-radio-group v-model="selectedFilter">
+ <gl-form-radio v-for="f in filtersArray" :key="f.value" :value="f.value">
+ {{ radioLabel(f) }}
+ </gl-form-radio>
+ </gl-form-radio-group>
+ </div>
+</template>
diff --git a/app/assets/javascripts/search/sidebar/components/status_filter.vue b/app/assets/javascripts/search/sidebar/components/status_filter.vue
new file mode 100644
index 00000000000..876123ccc52
--- /dev/null
+++ b/app/assets/javascripts/search/sidebar/components/status_filter.vue
@@ -0,0 +1,25 @@
+<script>
+import { mapState } from 'vuex';
+import { stateFilterData } from '../constants/state_filter_data';
+import RadioFilter from './radio_filter.vue';
+
+export default {
+ name: 'StatusFilter',
+ components: {
+ RadioFilter,
+ },
+ computed: {
+ ...mapState(['query']),
+ showDropdown() {
+ return Object.values(stateFilterData.scopes).includes(this.query.scope);
+ },
+ },
+ stateFilterData,
+};
+</script>
+
+<template>
+ <div v-if="showDropdown">
+ <radio-filter :filter-data="$options.stateFilterData" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/search/sidebar/constants/confidential_filter_data.js b/app/assets/javascripts/search/sidebar/constants/confidential_filter_data.js
new file mode 100644
index 00000000000..ecb63ed9eea
--- /dev/null
+++ b/app/assets/javascripts/search/sidebar/constants/confidential_filter_data.js
@@ -0,0 +1,36 @@
+import { __ } from '~/locale';
+
+const header = __('Confidentiality');
+
+const filters = {
+ ANY: {
+ label: __('Any'),
+ value: null,
+ },
+ CONFIDENTIAL: {
+ label: __('Confidential'),
+ value: 'yes',
+ },
+ NOT_CONFIDENTIAL: {
+ label: __('Not confidential'),
+ value: 'no',
+ },
+};
+
+const scopes = {
+ ISSUES: 'issues',
+};
+
+const filterByScope = {
+ [scopes.ISSUES]: [filters.ANY, filters.CONFIDENTIAL, filters.NOT_CONFIDENTIAL],
+};
+
+const filterParam = 'confidential';
+
+export const confidentialFilterData = {
+ header,
+ filters,
+ scopes,
+ filterByScope,
+ filterParam,
+};
diff --git a/app/assets/javascripts/search/sidebar/constants/state_filter_data.js b/app/assets/javascripts/search/sidebar/constants/state_filter_data.js
new file mode 100644
index 00000000000..7c9a029ffe4
--- /dev/null
+++ b/app/assets/javascripts/search/sidebar/constants/state_filter_data.js
@@ -0,0 +1,42 @@
+import { __ } from '~/locale';
+
+const header = __('Status');
+
+const filters = {
+ ANY: {
+ label: __('Any'),
+ value: 'all',
+ },
+ OPEN: {
+ label: __('Open'),
+ value: 'opened',
+ },
+ CLOSED: {
+ label: __('Closed'),
+ value: 'closed',
+ },
+ MERGED: {
+ label: __('Merged'),
+ value: 'merged',
+ },
+};
+
+const scopes = {
+ ISSUES: 'issues',
+ MERGE_REQUESTS: 'merge_requests',
+};
+
+const filterByScope = {
+ [scopes.ISSUES]: [filters.ANY, filters.OPEN, filters.CLOSED],
+ [scopes.MERGE_REQUESTS]: [filters.ANY, filters.OPEN, filters.MERGED, filters.CLOSED],
+};
+
+const filterParam = 'state';
+
+export const stateFilterData = {
+ header,
+ filters,
+ scopes,
+ filterByScope,
+ filterParam,
+};
diff --git a/app/assets/javascripts/search/sidebar/index.js b/app/assets/javascripts/search/sidebar/index.js
new file mode 100644
index 00000000000..b19016edf3d
--- /dev/null
+++ b/app/assets/javascripts/search/sidebar/index.js
@@ -0,0 +1,34 @@
+import Vue from 'vue';
+import Translate from '~/vue_shared/translate';
+import StatusFilter from './components/status_filter.vue';
+import ConfidentialityFilter from './components/confidentiality_filter.vue';
+
+Vue.use(Translate);
+
+const mountRadioFilters = (store, { id, component }) => {
+ const el = document.getElementById(id);
+
+ if (!el) return false;
+
+ return new Vue({
+ el,
+ store,
+ render(createElement) {
+ return createElement(component);
+ },
+ });
+};
+
+const radioFilters = [
+ {
+ id: 'js-search-filter-by-state',
+ component: StatusFilter,
+ },
+ {
+ id: 'js-search-filter-by-confidential',
+ component: ConfidentialityFilter,
+ },
+];
+
+export const initSidebar = store =>
+ [...radioFilters].map(filter => mountRadioFilters(store, filter));
diff --git a/app/assets/javascripts/search/store/actions.js b/app/assets/javascripts/search/store/actions.js
index 4bc8b2a9a5d..722ed2eec26 100644
--- a/app/assets/javascripts/search/store/actions.js
+++ b/app/assets/javascripts/search/store/actions.js
@@ -14,3 +14,7 @@ export const fetchGroups = ({ commit }, search) => {
commit(types.RECEIVE_GROUPS_ERROR);
});
};
+
+export const setQuery = ({ commit }, { key, value }) => {
+ commit(types.SET_QUERY, { key, value });
+};
diff --git a/app/assets/javascripts/search/store/mutation_types.js b/app/assets/javascripts/search/store/mutation_types.js
index 8469f3517c0..2482621d4d7 100644
--- a/app/assets/javascripts/search/store/mutation_types.js
+++ b/app/assets/javascripts/search/store/mutation_types.js
@@ -1,3 +1,5 @@
export const REQUEST_GROUPS = 'REQUEST_GROUPS';
export const RECEIVE_GROUPS_SUCCESS = 'RECEIVE_GROUPS_SUCCESS';
export const RECEIVE_GROUPS_ERROR = 'RECEIVE_GROUPS_ERROR';
+
+export const SET_QUERY = 'SET_QUERY';
diff --git a/app/assets/javascripts/search/store/mutations.js b/app/assets/javascripts/search/store/mutations.js
index 34fe14716f9..e57850b870e 100644
--- a/app/assets/javascripts/search/store/mutations.js
+++ b/app/assets/javascripts/search/store/mutations.js
@@ -12,4 +12,7 @@ export default {
state.fetchingGroups = false;
state.groups = [];
},
+ [types.SET_QUERY](state, { key, value }) {
+ state.query[key] = value;
+ },
};