diff options
Diffstat (limited to 'app/assets/javascripts/boards/components/project_select.vue')
-rw-r--r-- | app/assets/javascripts/boards/components/project_select.vue | 119 |
1 files changed, 78 insertions, 41 deletions
diff --git a/app/assets/javascripts/boards/components/project_select.vue b/app/assets/javascripts/boards/components/project_select.vue index 960c8e472b8..7bbc444701a 100644 --- a/app/assets/javascripts/boards/components/project_select.vue +++ b/app/assets/javascripts/boards/components/project_select.vue @@ -1,11 +1,8 @@ <script> import { GlCollapsibleListbox } from '@gitlab/ui'; -import { mapActions, mapGetters, mapState } from 'vuex'; -import { debounce } from 'lodash'; import { s__ } from '~/locale'; -import { featureAccessLevel } from '~/pages/projects/shared/permissions/constants'; -import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants'; -import { ListType } from '../constants'; +import groupProjectsQuery from '../graphql/group_projects.query.graphql'; +import { setError } from '../graphql/cache_updates'; export default { name: 'ProjectSelect', @@ -14,6 +11,9 @@ export default { dropdownText: s__(`BoardNewIssue|Select a project`), searchPlaceholder: s__(`BoardNewIssue|Search projects`), emptySearchResult: s__(`BoardNewIssue|No matching results`), + errorFetchingProjects: s__( + 'Boards|An error occurred while fetching group projects. Please try again.', + ), }, defaultFetchOptions: { with_issues_enabled: true, @@ -24,70 +24,107 @@ export default { components: { GlCollapsibleListbox, }, - inject: ['groupId'], + inject: ['groupId', 'fullPath'], + model: { + prop: 'selectedProject', + event: 'selectProject', + }, props: { list: { type: Object, required: true, }, + selectedProject: { + type: Object, + required: true, + }, }, data() { return { initialLoading: true, selectedProjectId: '', - selectedProject: {}, searchTerm: '', + projects: {}, + isLoadingMore: false, }; }, + apollo: { + projects: { + query: groupProjectsQuery, + variables() { + return { + fullPath: this.fullPath, + search: this.searchTerm, + }; + }, + update(data) { + return data.group.projects; + }, + error(error) { + setError({ + error, + message: this.$options.i18n.errorFetchingProjects, + }); + }, + result() { + this.initialLoading = false; + }, + }, + }, computed: { - ...mapState(['groupProjectsFlags']), - ...mapGetters(['activeGroupProjects']), - projects() { - return this.activeGroupProjects.map((project) => ({ - value: project.id, - text: project.nameWithNamespace, - })); + isLoading() { + return this.$apollo.queries.projects.loading && !this.isLoadingMore; + }, + activeGroupProjects() { + return ( + this.projects?.nodes?.map((project) => ({ + value: project.id, + text: project.nameWithNamespace, + })) || [] + ); }, selectedProjectName() { return this.selectedProject.name || this.$options.i18n.dropdownText; }, - fetchOptions() { - const additionalAttrs = {}; - if (this.list.type && this.list.type !== ListType.backlog) { - additionalAttrs.min_access_level = featureAccessLevel.EVERYONE; - } - - return { - ...this.$options.defaultFetchOptions, - ...additionalAttrs, - }; - }, isFetchResultEmpty() { return this.activeGroupProjects.length === 0; }, hasNextPage() { - return this.groupProjectsFlags.pageInfo?.hasNextPage; + return this.projects.pageInfo?.hasNextPage; }, }, watch: { - searchTerm: debounce(function debouncedSearch() { - this.fetchGroupProjects({ search: this.searchTerm }); - }, DEFAULT_DEBOUNCE_AND_THROTTLE_MS), - }, - mounted() { - this.fetchGroupProjects({}); - this.initialLoading = false; + endCursor() { + return this.projects.pageInfo?.endCursor; + }, }, methods: { - ...mapActions(['fetchGroupProjects', 'setSelectedProject']), selectProject(projectId) { this.selectedProjectId = projectId; - this.selectedProject = this.activeGroupProjects.find((project) => project.id === projectId); - this.setSelectedProject(this.selectedProject); + this.$emit( + 'selectProject', + this.projects.nodes.find((project) => project.id === projectId), + ); }, - loadMoreProjects() { + async loadMoreProjects() { if (!this.hasNextPage) return; - this.fetchGroupProjects({ search: this.searchTerm, fetchNext: true }); + this.isLoadingMore = true; + try { + await this.$apollo.queries.projects.fetchMore({ + variables: { + fullPath: this.fullPath, + search: this.searchTerm, + after: this.endCursor, + }, + }); + } catch (error) { + setError({ + error, + message: this.$options.i18n.errorFetchingProjects, + }); + } finally { + this.isLoadingMore = false; + } }, onSearch(query) { this.searchTerm = query; @@ -107,14 +144,14 @@ export default { searchable infinite-scroll data-testid="project-select-dropdown" - :items="projects" + :items="activeGroupProjects" :toggle-text="selectedProjectName" :header-text="$options.i18n.headerTitle" :loading="initialLoading" - :searching="groupProjectsFlags.isLoading" + :searching="isLoading" :search-placeholder="$options.i18n.searchPlaceholder" :no-results-text="$options.i18n.emptySearchResult" - :infinite-scroll-loading="groupProjectsFlags.isLoadingMore" + :infinite-scroll-loading="isLoadingMore" @select="selectProject" @search="onSearch" @bottom-reached="loadMoreProjects" |