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>2023-01-20 00:07:28 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-01-20 00:07:28 +0300
commit9bc3ee9ad4c857570b7a029345cc6fff3ed46b5f (patch)
tree4de11c170947a73056c72b47f1036c048e7c082e /app/assets/javascripts/vue_shared
parentdc539af30068062bd6fc2f9c6b478d4a1feb8c23 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/vue_shared')
-rw-r--r--app/assets/javascripts/vue_shared/components/entity_select/constants.js (renamed from app/assets/javascripts/vue_shared/components/group_select/constants.js)1
-rw-r--r--app/assets/javascripts/vue_shared/components/entity_select/entity_select.vue (renamed from app/assets/javascripts/vue_shared/components/group_select/group_select.vue)137
-rw-r--r--app/assets/javascripts/vue_shared/components/entity_select/group_select.vue132
-rw-r--r--app/assets/javascripts/vue_shared/components/entity_select/init_group_selects.js (renamed from app/assets/javascripts/vue_shared/components/group_select/init_group_selects.js)0
-rw-r--r--app/assets/javascripts/vue_shared/components/entity_select/utils.js (renamed from app/assets/javascripts/vue_shared/components/group_select/utils.js)0
5 files changed, 183 insertions, 87 deletions
diff --git a/app/assets/javascripts/vue_shared/components/group_select/constants.js b/app/assets/javascripts/vue_shared/components/entity_select/constants.js
index 06537d682fe..a48bba3be8c 100644
--- a/app/assets/javascripts/vue_shared/components/group_select/constants.js
+++ b/app/assets/javascripts/vue_shared/components/entity_select/constants.js
@@ -1,6 +1,7 @@
import { __ } from '~/locale';
export const TOGGLE_TEXT = __('Search for a group');
+export const HEADER_TEXT = __('Select a group');
export const RESET_LABEL = __('Reset');
export const FETCH_GROUPS_ERROR = __('Unable to fetch groups. Reload the page to try again.');
export const FETCH_GROUP_ERROR = __('Unable to fetch group. Reload the page to try again.');
diff --git a/app/assets/javascripts/vue_shared/components/group_select/group_select.vue b/app/assets/javascripts/vue_shared/components/entity_select/entity_select.vue
index d295052e2ce..42a37eef1eb 100644
--- a/app/assets/javascripts/vue_shared/components/group_select/group_select.vue
+++ b/app/assets/javascripts/vue_shared/components/entity_select/entity_select.vue
@@ -1,28 +1,15 @@
<script>
import { debounce } from 'lodash';
-import { GlFormGroup, GlAlert, GlCollapsibleListbox } from '@gitlab/ui';
-import * as Sentry from '@sentry/browser';
-import axios from '~/lib/utils/axios_utils';
-import { normalizeHeaders, parseIntPagination } from '~/lib/utils/common_utils';
-import Api from '~/api';
+import { GlFormGroup, GlCollapsibleListbox } from '@gitlab/ui';
import { __ } from '~/locale';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
-import { groupsPath } from './utils';
-import {
- TOGGLE_TEXT,
- RESET_LABEL,
- FETCH_GROUPS_ERROR,
- FETCH_GROUP_ERROR,
- QUERY_TOO_SHORT_MESSAGE,
-} from './constants';
+import { RESET_LABEL, QUERY_TOO_SHORT_MESSAGE } from './constants';
const MINIMUM_QUERY_LENGTH = 3;
-const GROUPS_PER_PAGE = 20;
export default {
components: {
GlFormGroup,
- GlAlert,
GlCollapsibleListbox,
},
props: {
@@ -48,13 +35,20 @@ export default {
required: false,
default: false,
},
- parentGroupID: {
+ headerText: {
type: String,
- required: false,
- default: null,
+ required: true,
},
- groupsFilter: {
+ defaultToggleText: {
type: String,
+ required: true,
+ },
+ fetchItems: {
+ type: Function,
+ required: true,
+ },
+ fetchInitialSelectionText: {
+ type: Function,
required: false,
default: null,
},
@@ -63,10 +57,10 @@ export default {
return {
pristine: true,
searching: false,
- hasMoreGroups: true,
+ hasMoreItems: true,
infiniteScrollLoading: false,
searchString: '',
- groups: [],
+ items: [],
page: 1,
selectedValue: null,
selectedText: null,
@@ -78,14 +72,14 @@ export default {
set(value) {
this.selectedValue = value;
this.selectedText =
- value === null ? null : this.groups.find((group) => group.value === value).full_name;
+ value === null ? null : this.items.find((item) => item.value === value).text;
},
get() {
return this.selectedValue;
},
},
toggleText() {
- return this.selectedText ?? this.$options.i18n.toggleText;
+ return this.selectedText ?? this.defaultToggleText;
},
resetButtonLabel() {
return this.clearable ? RESET_LABEL : '';
@@ -109,90 +103,64 @@ export default {
search: debounce(function debouncedSearch(searchString) {
this.searchString = searchString;
if (this.isSearchQueryTooShort) {
- this.groups = [];
+ this.items = [];
} else {
- this.fetchGroups();
+ this.fetchEntities();
}
}, DEFAULT_DEBOUNCE_AND_THROTTLE_MS),
- async fetchGroups(page = 1) {
+ async fetchEntities(page = 1) {
if (page === 1) {
this.searching = true;
- this.groups = [];
- this.hasMoreGroups = true;
+ this.items = [];
+ this.hasMoreItems = true;
} else {
this.infiniteScrollLoading = true;
}
- try {
- const { data, headers } = await axios.get(
- Api.buildUrl(groupsPath(this.groupsFilter, this.parentGroupID)),
- {
- params: {
- search: this.searchString,
- per_page: GROUPS_PER_PAGE,
- page,
- },
- },
- );
- const groups = data.length ? data : data.results || [];
-
- this.groups.push(
- ...groups.map((group) => ({
- ...group,
- value: String(group.id),
- })),
- );
+ const { items, totalPages } = await this.fetchItems(this.searchString, page);
- const { totalPages } = parseIntPagination(normalizeHeaders(headers));
- if (page === totalPages) {
- this.hasMoreGroups = false;
- }
+ this.items.push(...items);
- this.page = page;
- this.searching = false;
- this.infiniteScrollLoading = false;
- } catch (error) {
- this.handleError({ message: FETCH_GROUPS_ERROR, error });
+ if (page === totalPages) {
+ this.hasMoreItems = false;
}
+
+ this.page = page;
+ this.searching = false;
+ this.infiniteScrollLoading = false;
},
async fetchInitialSelection() {
if (!this.initialSelection) {
this.pristine = false;
return;
}
- this.searching = true;
- try {
- const group = await Api.group(this.initialSelection);
- this.selectedValue = this.initialSelection;
- this.selectedText = group.full_name;
- this.pristine = false;
- this.searching = false;
- } catch (error) {
- this.handleError({ message: FETCH_GROUP_ERROR, error });
+
+ if (!this.fetchInitialSelectionText) {
+ throw new Error(
+ '`initialSelection` is provided but lacks `fetchInitialSelectionText` to retrieve the corresponding text',
+ );
}
+
+ this.searching = true;
+ const name = await this.fetchInitialSelectionText(this.initialSelection);
+ this.selectedValue = this.initialSelection;
+ this.selectedText = name;
+ this.pristine = false;
+ this.searching = false;
},
onShown() {
- if (!this.searchString && !this.groups.length) {
- this.fetchGroups();
+ if (!this.searchString && !this.items.length) {
+ this.fetchEntities();
}
},
onReset() {
this.selected = null;
},
onBottomReached() {
- this.fetchGroups(this.page + 1);
- },
- handleError({ message, error }) {
- Sentry.captureException(error);
- this.errorMessage = message;
- },
- dismissError() {
- this.errorMessage = '';
+ this.fetchEntities(this.page + 1);
},
},
i18n: {
- toggleText: TOGGLE_TEXT,
- selectGroup: __('Select a group'),
noResultsText: __('No results found.'),
searchQueryTooShort: QUERY_TOO_SHORT_MESSAGE,
},
@@ -201,20 +169,18 @@ export default {
<template>
<gl-form-group :label="label">
- <gl-alert v-if="errorMessage" class="gl-mb-3" variant="danger" @dismiss="dismissError">{{
- errorMessage
- }}</gl-alert>
+ <slot name="error"></slot>
<gl-collapsible-listbox
ref="listbox"
v-model="selected"
- :header-text="$options.i18n.selectGroup"
+ :header-text="headerText"
:reset-button-label="resetButtonLabel"
:toggle-text="toggleText"
:loading="searching && pristine"
:searching="searching"
- :items="groups"
+ :items="items"
:no-results-text="noResultsText"
- :infinite-scroll="hasMoreGroups"
+ :infinite-scroll="hasMoreItems"
:infinite-scroll-loading="infiniteScrollLoading"
searchable
@shown="onShown"
@@ -223,10 +189,7 @@ export default {
@bottom-reached="onBottomReached"
>
<template #list-item="{ item }">
- <div class="gl-font-weight-bold">
- {{ item.full_name }}
- </div>
- <div class="gl-text-gray-300">{{ item.full_path }}</div>
+ <slot name="list-item" :item="item"></slot>
</template>
</gl-collapsible-listbox>
<input :id="inputId" data-testid="input" type="hidden" :name="inputName" :value="inputValue" />
diff --git a/app/assets/javascripts/vue_shared/components/entity_select/group_select.vue b/app/assets/javascripts/vue_shared/components/entity_select/group_select.vue
new file mode 100644
index 00000000000..a5fc438e932
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/entity_select/group_select.vue
@@ -0,0 +1,132 @@
+<script>
+import { GlAlert } from '@gitlab/ui';
+import * as Sentry from '@sentry/browser';
+import axios from '~/lib/utils/axios_utils';
+import { normalizeHeaders, parseIntPagination } from '~/lib/utils/common_utils';
+import Api, { DEFAULT_PER_PAGE } from '~/api';
+import { groupsPath } from './utils';
+import { TOGGLE_TEXT, HEADER_TEXT, FETCH_GROUPS_ERROR, FETCH_GROUP_ERROR } from './constants';
+import EntitySelect from './entity_select.vue';
+
+export default {
+ components: {
+ GlAlert,
+ EntitySelect,
+ },
+ props: {
+ label: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ inputName: {
+ type: String,
+ required: true,
+ },
+ inputId: {
+ type: String,
+ required: true,
+ },
+ initialSelection: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ clearable: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ parentGroupID: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ groupsFilter: {
+ type: String,
+ required: false,
+ default: null,
+ },
+ },
+ data() {
+ return {
+ errorMessage: '',
+ };
+ },
+ methods: {
+ async fetchGroups(searchString = '', page = 1) {
+ let groups = [];
+ let totalPages = 0;
+ try {
+ const { data, headers } = await axios.get(
+ Api.buildUrl(groupsPath(this.groupsFilter, this.parentGroupID)),
+ {
+ params: {
+ search: searchString,
+ per_page: DEFAULT_PER_PAGE,
+ page,
+ },
+ },
+ );
+ groups = (data.length ? data : data.results || []).map((group) => ({
+ ...group,
+ text: group.full_name,
+ value: String(group.id),
+ }));
+
+ totalPages = parseIntPagination(normalizeHeaders(headers)).totalPages;
+ } catch (error) {
+ this.handleError({ message: FETCH_GROUPS_ERROR, error });
+ }
+ return { items: groups, totalPages };
+ },
+ async fetchGroupName(groupId) {
+ let groupName = '';
+ try {
+ const group = await Api.group(groupId);
+ groupName = group.full_name;
+ } catch (error) {
+ this.handleError({ message: FETCH_GROUP_ERROR, error });
+ }
+ return groupName;
+ },
+ handleError({ message, error }) {
+ Sentry.captureException(error);
+ this.errorMessage = message;
+ },
+ dismissError() {
+ this.errorMessage = '';
+ },
+ },
+ i18n: {
+ toggleText: TOGGLE_TEXT,
+ selectGroup: HEADER_TEXT,
+ },
+};
+</script>
+
+<template>
+ <entity-select
+ :label="label"
+ :input-name="inputName"
+ :input-id="inputId"
+ :initial-selection="initialSelection"
+ :clearable="clearable"
+ :header-text="$options.i18n.selectGroup"
+ :default-toggle-text="$options.i18n.toggleText"
+ :fetch-items="fetchGroups"
+ :fetch-initial-selection-text="fetchGroupName"
+ >
+ <template #error>
+ <gl-alert v-if="errorMessage" class="gl-mb-3" variant="danger" @dismiss="dismissError">{{
+ errorMessage
+ }}</gl-alert>
+ </template>
+ <template #list-item="{ item }">
+ <div class="gl-font-weight-bold">
+ {{ item.full_name }}
+ </div>
+ <div class="gl-text-gray-300">{{ item.full_path }}</div>
+ </template>
+ </entity-select>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/group_select/init_group_selects.js b/app/assets/javascripts/vue_shared/components/entity_select/init_group_selects.js
index dbfac8a0339..dbfac8a0339 100644
--- a/app/assets/javascripts/vue_shared/components/group_select/init_group_selects.js
+++ b/app/assets/javascripts/vue_shared/components/entity_select/init_group_selects.js
diff --git a/app/assets/javascripts/vue_shared/components/group_select/utils.js b/app/assets/javascripts/vue_shared/components/entity_select/utils.js
index 0a4622269f4..0a4622269f4 100644
--- a/app/assets/javascripts/vue_shared/components/group_select/utils.js
+++ b/app/assets/javascripts/vue_shared/components/entity_select/utils.js