diff options
Diffstat (limited to 'app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue')
-rw-r--r-- | app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue | 162 |
1 files changed, 108 insertions, 54 deletions
diff --git a/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue b/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue index 1acf3a03e73..05b87abecd5 100644 --- a/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue +++ b/app/assets/javascripts/pipeline_editor/components/file_nav/branch_switcher.vue @@ -6,7 +6,10 @@ import { GlInfiniteScroll, GlLoadingIcon, GlSearchBoxByType, + GlTooltipDirective, } from '@gitlab/ui'; +import { produce } from 'immer'; +import { fetchPolicies } from '~/lib/graphql'; import { historyPushState } from '~/lib/utils/common_utils'; import { setUrlParams } from '~/lib/utils/url_utility'; import { s__ } from '~/locale'; @@ -15,12 +18,14 @@ import { BRANCH_SEARCH_DEBOUNCE, DEFAULT_FAILURE, } from '~/pipeline_editor/constants'; -import getAvailableBranches from '~/pipeline_editor/graphql/queries/available_branches.graphql'; -import getCurrentBranch from '~/pipeline_editor/graphql/queries/client/current_branch.graphql'; +import updateCurrentBranchMutation from '~/pipeline_editor/graphql/mutations/update_current_branch.mutation.graphql'; +import getAvailableBranchesQuery from '~/pipeline_editor/graphql/queries/available_branches.graphql'; +import getCurrentBranchQuery from '~/pipeline_editor/graphql/queries/client/current_branch.graphql'; +import getLastCommitBranchQuery from '~/pipeline_editor/graphql/queries/client/last_commit_branch.query.graphql'; export default { i18n: { - dropdownHeader: s__('Switch Branch'), + dropdownHeader: s__('Switch branch'), title: s__('Branches'), fetchError: s__('Unable to fetch branch list for this project.'), }, @@ -33,6 +38,9 @@ export default { GlLoadingIcon, GlSearchBoxByType, }, + directives: { + GlTooltip: GlTooltipDirective, + }, inject: ['projectFullPath', 'totalBranches'], props: { paginationLimit: { @@ -43,101 +51,147 @@ export default { }, data() { return { - branches: [], - page: { - limit: this.paginationLimit, - offset: 0, - searchTerm: '', - }, + availableBranches: [], + filteredBranches: [], + isSearchingBranches: false, + pageLimit: this.paginationLimit, + pageCounter: 0, + searchTerm: '', + lastCommitBranch: '', }; }, apollo: { availableBranches: { - query: getAvailableBranches, + query: getAvailableBranchesQuery, variables() { return { - limit: this.page.limit, - offset: this.page.offset, + limit: this.paginationLimit, + offset: 0, projectFullPath: this.projectFullPath, - searchPattern: this.searchPattern, + searchPattern: '*', }; }, update(data) { return data.project?.repository?.branchNames || []; }, - result({ data }) { - const newBranches = data.project?.repository?.branchNames || []; - - // check that we're not re-concatenating existing fetch results - if (!this.branches.includes(newBranches[0])) { - this.branches = this.branches.concat(newBranches); - } + result() { + this.pageCounter += 1; }, error() { - this.$emit('showError', { - type: DEFAULT_FAILURE, - reasons: [this.$options.i18n.fetchError], - }); + this.showFetchError(); }, }, currentBranch: { - query: getCurrentBranch, + query: getCurrentBranchQuery, + }, + lastCommitBranch: { + query: getLastCommitBranchQuery, + result({ data: { lastCommitBranch } }) { + if (lastCommitBranch === '' || this.availableBranches.includes(lastCommitBranch)) { + return; + } + this.availableBranches.unshift(lastCommitBranch); + }, }, }, computed: { + branches() { + return this.searchTerm.length > 0 ? this.filteredBranches : this.availableBranches; + }, isBranchesLoading() { - return this.$apollo.queries.availableBranches.loading; + return this.$apollo.queries.availableBranches.loading || this.isSearchingBranches; }, showBranchSwitcher() { - return this.branches.length > 0 || this.page.searchTerm.length > 0; + return this.branches.length > 0 || this.searchTerm.length > 0; }, - searchPattern() { - if (this.page.searchTerm === '') { - return '*'; + }, + methods: { + availableBranchesQueryVars(varsOverride = {}) { + if (this.searchTerm.length > 0) { + return { + limit: this.totalBranches, + offset: 0, + projectFullPath: this.projectFullPath, + searchPattern: `*${this.searchTerm}*`, + ...varsOverride, + }; } - return `*${this.page.searchTerm}*`; + return { + limit: this.paginationLimit, + offset: this.pageCounter * this.paginationLimit, + projectFullPath: this.projectFullPath, + searchPattern: '*', + ...varsOverride, + }; }, - }, - methods: { // if there is no searchPattern, paginate by {paginationLimit} branches fetchNextBranches() { if ( this.isBranchesLoading || - this.page.searchTerm.length > 0 || - this.branches.length === this.totalBranches + this.searchTerm.length > 0 || + this.branches.length >= this.totalBranches ) { return; } - this.page = { - ...this.page, - limit: this.paginationLimit, - offset: this.page.offset + this.paginationLimit, - }; + this.$apollo.queries.availableBranches + .fetchMore({ + variables: this.availableBranchesQueryVars(), + updateQuery(previousResult, { fetchMoreResult }) { + const previousBranches = previousResult.project.repository.branchNames; + const newBranches = fetchMoreResult.project.repository.branchNames; + + return produce(fetchMoreResult, (draftData) => { + draftData.project.repository.branchNames = previousBranches.concat(newBranches); + }); + }, + }) + .catch(this.showFetchError); }, async selectBranch(newBranch) { if (newBranch === this.currentBranch) { return; } - await this.$apollo.getClient().writeQuery({ - query: getCurrentBranch, - data: { currentBranch: newBranch }, - }); - + this.updateCurrentBranch(newBranch); const updatedPath = setUrlParams({ branch_name: newBranch }); historyPushState(updatedPath); this.$emit('refetchContent'); }, - setSearchTerm(newSearchTerm) { - this.branches = []; - this.page = { - limit: newSearchTerm.trim() === '' ? this.paginationLimit : this.totalBranches, - offset: 0, - searchTerm: newSearchTerm.trim(), - }; + async setSearchTerm(newSearchTerm) { + this.pageCounter = 0; + this.searchTerm = newSearchTerm.trim(); + + if (this.searchTerm === '') { + this.pageLimit = this.paginationLimit; + return; + } + + this.isSearchingBranches = true; + const fetchResults = await this.$apollo + .query({ + query: getAvailableBranchesQuery, + fetchPolicy: fetchPolicies.NETWORK_ONLY, + variables: this.availableBranchesQueryVars(), + }) + .catch(this.showFetchError); + + this.isSearchingBranches = false; + this.filteredBranches = fetchResults?.data?.project?.repository?.branchNames || []; + }, + showFetchError() { + this.$emit('showError', { + type: DEFAULT_FAILURE, + reasons: [this.$options.i18n.fetchError], + }); + }, + updateCurrentBranch(currentBranch) { + this.$apollo.mutate({ + mutation: updateCurrentBranchMutation, + variables: { currentBranch }, + }); }, }, }; @@ -146,7 +200,8 @@ export default { <template> <gl-dropdown v-if="showBranchSwitcher" - class="gl-ml-2" + v-gl-tooltip.hover + :title="$options.i18n.dropdownHeader" :header-text="$options.i18n.dropdownHeader" :text="currentBranch" icon="branch" @@ -158,7 +213,6 @@ export default { <gl-infinite-scroll :fetched-items="branches.length" - :total-items="totalBranches" :max-list-height="250" @bottomReached="fetchNextBranches" > |