diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-05-13 21:10:32 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-05-13 21:10:32 +0300 |
commit | 561d1f41b5803b90ef4baf0d129e28dde3fc2f25 (patch) | |
tree | eca91620c72ace1e30e339c931f65b3de78a34ba /app/assets/javascripts | |
parent | e958867b2e341329243be8db0c262233ae1238c0 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts')
23 files changed, 229 insertions, 109 deletions
diff --git a/app/assets/javascripts/batch_comments/components/preview_dropdown.vue b/app/assets/javascripts/batch_comments/components/preview_dropdown.vue index 625cd9858fb..91b3b6a685c 100644 --- a/app/assets/javascripts/batch_comments/components/preview_dropdown.vue +++ b/app/assets/javascripts/batch_comments/components/preview_dropdown.vue @@ -35,7 +35,7 @@ export default { <gl-dropdown :header-text="n__('%d pending comment', '%d pending comments', draftsCount)" dropup - toggle-class="qa-review-preview-toggle" + data-qa-selector="review_preview_dropdown" > <template #button-content> {{ __('Pending comments') }} diff --git a/app/assets/javascripts/diffs/components/commit_item.vue b/app/assets/javascripts/diffs/components/commit_item.vue index 63239728390..820c64a9502 100644 --- a/app/assets/javascripts/diffs/components/commit_item.vue +++ b/app/assets/javascripts/diffs/components/commit_item.vue @@ -138,7 +138,7 @@ export default { /> </div> <div class="commit-detail flex-list"> - <div class="commit-content qa-commit-content"> + <div class="commit-content" data-qa-selector="commit_content"> <a :href="commit.commit_url" class="commit-row-message item-title" diff --git a/app/assets/javascripts/diffs/components/diff_row.vue b/app/assets/javascripts/diffs/components/diff_row.vue index c5770a35b42..d4a1a9e0e46 100644 --- a/app/assets/javascripts/diffs/components/diff_row.vue +++ b/app/assets/javascripts/diffs/components/diff_row.vue @@ -206,6 +206,7 @@ export default { :class="classNameMapCellLeft" data-testid="left-line-number" class="diff-td diff-line-num" + data-qa-selector="new_diff_line_link" > <template v-if="!isLeftConflictMarker"> <span @@ -220,7 +221,7 @@ export default { tabindex="0" :draggable="!line.left.commentsDisabled && glFeatures.dragCommentSelection" type="button" - class="add-diff-note unified-diff-components-diff-note-button note-button js-add-diff-note-button qa-diff-comment" + class="add-diff-note unified-diff-components-diff-note-button note-button js-add-diff-note-button" data-qa-selector="diff_comment_button" :class="{ 'gl-cursor-grab': dragging }" :disabled="line.left.commentsDisabled" @@ -327,7 +328,7 @@ export default { tabindex="0" :draggable="!line.right.commentsDisabled && glFeatures.dragCommentSelection" type="button" - class="add-diff-note unified-diff-components-diff-note-button note-button js-add-diff-note-button qa-diff-comment" + class="add-diff-note unified-diff-components-diff-note-button note-button js-add-diff-note-button" :class="{ 'gl-cursor-grab': dragging }" :disabled="line.right.commentsDisabled" :aria-disabled="line.right.commentsDisabled" diff --git a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue index 25403b1547e..f903fef72b7 100644 --- a/app/assets/javascripts/diffs/components/inline_diff_table_row.vue +++ b/app/assets/javascripts/diffs/components/inline_diff_table_row.vue @@ -177,7 +177,6 @@ export default { <a v-if="line.new_line" ref="lineNumberRefNew" - data-qa-selector="new_diff_line_link" :data-linenumber="line.new_line" :href="line.lineHref" @click="setHighlightedRow(line.lineCode)" diff --git a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue index 96946d0fd88..2d33926c8aa 100644 --- a/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue +++ b/app/assets/javascripts/diffs/components/parallel_diff_table_row.vue @@ -193,7 +193,7 @@ export default { v-show="shouldShowCommentButtonLeft" ref="addDiffNoteButtonLeft" type="button" - class="add-diff-note note-button js-add-diff-note-button qa-diff-comment" + class="add-diff-note note-button js-add-diff-note-button" :disabled="line.left.commentsDisabled" :aria-label="addCommentTooltipLeft" @click="handleCommentButton(line.left)" @@ -251,7 +251,7 @@ export default { v-show="shouldShowCommentButtonRight" ref="addDiffNoteButtonRight" type="button" - class="add-diff-note note-button js-add-diff-note-button qa-diff-comment" + class="add-diff-note note-button js-add-diff-note-button" :disabled="line.right.commentsDisabled" :aria-label="addCommentTooltipRight" @click="handleCommentButton(line.right)" diff --git a/app/assets/javascripts/issues_list/components/issues_list_app.vue b/app/assets/javascripts/issues_list/components/issues_list_app.vue index 176b342d8e7..6059beee078 100644 --- a/app/assets/javascripts/issues_list/components/issues_list_app.vue +++ b/app/assets/javascripts/issues_list/components/issues_list_app.vue @@ -38,8 +38,19 @@ import { } from '~/issues_list/utils'; import axios from '~/lib/utils/axios_utils'; import { convertObjectPropsToCamelCase, getParameterByName } from '~/lib/utils/common_utils'; -import { __ } from '~/locale'; -import { DEFAULT_NONE_ANY } from '~/vue_shared/components/filtered_search_bar/constants'; +import { + DEFAULT_NONE_ANY, + OPERATOR_IS_ONLY, + TOKEN_TITLE_ASSIGNEE, + TOKEN_TITLE_AUTHOR, + TOKEN_TITLE_CONFIDENTIAL, + TOKEN_TITLE_EPIC, + TOKEN_TITLE_ITERATION, + TOKEN_TITLE_LABEL, + TOKEN_TITLE_MILESTONE, + TOKEN_TITLE_MY_REACTION, + TOKEN_TITLE_WEIGHT, +} from '~/vue_shared/components/filtered_search_bar/constants'; import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue'; import EmojiToken from '~/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue'; import EpicToken from '~/vue_shared/components/filtered_search_bar/tokens/epic_token.vue'; @@ -178,7 +189,7 @@ export default { const tokens = [ { type: 'author_username', - title: __('Author'), + title: TOKEN_TITLE_AUTHOR, icon: 'pencil', token: AuthorToken, dataType: 'user', @@ -188,7 +199,7 @@ export default { }, { type: 'assignee_username', - title: __('Assignee'), + title: TOKEN_TITLE_ASSIGNEE, icon: 'user', token: AuthorToken, dataType: 'user', @@ -198,7 +209,7 @@ export default { }, { type: 'milestone', - title: __('Milestone'), + title: TOKEN_TITLE_MILESTONE, icon: 'clock', token: MilestoneToken, unique: true, @@ -207,7 +218,7 @@ export default { }, { type: 'labels', - title: __('Label'), + title: TOKEN_TITLE_LABEL, icon: 'labels', token: LabelToken, defaultLabels: [], @@ -215,23 +226,23 @@ export default { }, { type: 'my_reaction_emoji', - title: __('My-Reaction'), + title: TOKEN_TITLE_MY_REACTION, icon: 'thumb-up', token: EmojiToken, unique: true, - operators: [{ value: '=', description: __('is') }], + operators: OPERATOR_IS_ONLY, fetchEmojis: this.fetchEmojis, }, { type: 'confidential', - title: __('Confidential'), + title: TOKEN_TITLE_CONFIDENTIAL, icon: 'eye-slash', token: GlFilteredSearchToken, unique: true, - operators: [{ value: '=', description: __('is') }], + operators: OPERATOR_IS_ONLY, options: [ - { icon: 'eye-slash', value: 'yes', title: __('Yes') }, - { icon: 'eye', value: 'no', title: __('No') }, + { icon: 'eye-slash', value: 'yes', title: this.$options.i18n.confidentialYes }, + { icon: 'eye', value: 'no', title: this.$options.i18n.confidentialNo }, ], }, ]; @@ -239,7 +250,7 @@ export default { if (this.projectIterationsPath) { tokens.push({ type: 'iteration', - title: __('Iteration'), + title: TOKEN_TITLE_ITERATION, icon: 'iteration', token: IterationToken, unique: true, @@ -250,7 +261,7 @@ export default { if (this.groupEpicsPath) { tokens.push({ type: 'epic_id', - title: __('Epic'), + title: TOKEN_TITLE_EPIC, icon: 'epic', token: EpicToken, unique: true, @@ -261,7 +272,7 @@ export default { if (this.hasIssueWeightsFeature) { tokens.push({ type: 'weight', - title: __('Weight'), + title: TOKEN_TITLE_WEIGHT, icon: 'weight', token: WeightToken, unique: true, @@ -371,7 +382,7 @@ export default { this.exportCsvPathWithQuery = this.getExportCsvPathWithQuery(); }) .catch(() => { - createFlash({ message: __('An error occurred while loading issues') }); + createFlash({ message: this.$options.i18n.errorFetchingIssues }); }) .finally(() => { this.isLoading = false; @@ -382,10 +393,10 @@ export default { }, getStatus(issue) { if (issue.closedAt && issue.movedToId) { - return __('CLOSED (MOVED)'); + return this.$options.i18n.closedMoved; } if (issue.closedAt) { - return __('CLOSED'); + return this.$options.i18n.closed; } return undefined; }, @@ -474,7 +485,7 @@ export default { <issuable-list :namespace="projectPath" recent-searches-storage-key="issues" - :search-input-placeholder="__('Search or filter results…')" + :search-input-placeholder="$options.i18n.searchPlaceholder" :search-tokens="searchTokens" :initial-filter-value="filterTokens" :sort-options="sortOptions" @@ -525,7 +536,7 @@ export default { :disabled="isBulkEditButtonDisabled" @click="handleBulkUpdateClick" > - {{ __('Edit issues') }} + {{ $options.i18n.editIssues }} </gl-button> <gl-button v-if="showNewIssueLink" :href="newIssuePath" variant="confirm"> {{ $options.i18n.newIssueLabel }} @@ -545,7 +556,7 @@ export default { v-if="issuable.mergeRequestsCount" v-gl-tooltip class="gl-display-none gl-sm-display-block" - :title="__('Related merge requests')" + :title="$options.i18n.relatedMergeRequests" data-testid="issuable-mr" > <gl-icon name="merge-request" /> @@ -555,7 +566,7 @@ export default { v-if="issuable.upvotes" v-gl-tooltip class="gl-display-none gl-sm-display-block" - :title="__('Upvotes')" + :title="$options.i18n.upvotes" data-testid="issuable-upvotes" > <gl-icon name="thumb-up" /> @@ -565,7 +576,7 @@ export default { v-if="issuable.downvotes" v-gl-tooltip class="gl-display-none gl-sm-display-block" - :title="__('Downvotes')" + :title="$options.i18n.downvotes" data-testid="issuable-downvotes" > <gl-icon name="thumb-down" /> diff --git a/app/assets/javascripts/issues_list/constants.js b/app/assets/javascripts/issues_list/constants.js index cb5da81ea5a..5f0bbd2145d 100644 --- a/app/assets/javascripts/issues_list/constants.js +++ b/app/assets/javascripts/issues_list/constants.js @@ -3,6 +3,8 @@ import { FILTER_ANY, FILTER_CURRENT, FILTER_NONE, + OPERATOR_IS, + OPERATOR_IS_NOT, } from '~/vue_shared/components/filtered_search_bar/constants'; // Maps sort order as it appears in the URL query to API `order_by` and `sort` params. @@ -60,6 +62,13 @@ export const availableSortOptionsJira = [ export const i18n = { calendarLabel: __('Subscribe to calendar'), + closed: __('CLOSED'), + closedMoved: __('CLOSED (MOVED)'), + confidentialNo: __('No'), + confidentialYes: __('Yes'), + downvotes: __('Downvotes'), + editIssues: __('Edit issues'), + errorFetchingIssues: __('An error occurred while loading issues'), jiraIntegrationMessage: s__( 'JiraService|%{jiraDocsLinkStart}Enable the Jira integration%{jiraDocsLinkEnd} to view your Jira issues in GitLab.', ), @@ -82,8 +91,11 @@ export const i18n = { noIssuesSignedOutTitle: __('There are no issues to show'), noSearchResultsDescription: __('To widen your search, change or remove filters above'), noSearchResultsTitle: __('Sorry, your filter produced no results'), + relatedMergeRequests: __('Related merge requests'), reorderError: __('An error occurred while reordering issues.'), rssLabel: __('Subscribe to RSS feed'), + searchPlaceholder: __('Search or filter results…'), + upvotes: __('Upvotes'), }; export const JIRA_IMPORT_SUCCESS_ALERT_HIDE_MAP_KEY = 'jira-import-success-alert-hide-map'; @@ -246,10 +258,6 @@ export const urlSortParams = { export const MAX_LIST_SIZE = 10; -export const FILTERED_SEARCH_TERM = 'filtered-search-term'; -export const OPERATOR_IS = '='; -export const OPERATOR_IS_NOT = '!='; - export const NORMAL_FILTER = 'normalFilter'; export const SPECIAL_FILTER = 'specialFilter'; export const SPECIAL_FILTER_VALUES = [FILTER_NONE, FILTER_ANY, FILTER_CURRENT]; diff --git a/app/assets/javascripts/issues_list/utils.js b/app/assets/javascripts/issues_list/utils.js index d212226e139..b6551eb4ac8 100644 --- a/app/assets/javascripts/issues_list/utils.js +++ b/app/assets/javascripts/issues_list/utils.js @@ -4,7 +4,6 @@ import { CREATED_DESC, DUE_DATE_ASC, DUE_DATE_DESC, - FILTERED_SEARCH_TERM, filters, LABEL_PRIORITY_DESC, MILESTONE_DUE_ASC, @@ -23,6 +22,7 @@ import { WEIGHT_DESC, } from '~/issues_list/constants'; import { __ } from '~/locale'; +import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_bar/constants'; export const getSortKey = (sort) => Object.keys(urlSortParams).find((key) => urlSortParams[key].sort === sort); diff --git a/app/assets/javascripts/logs/components/log_advanced_filters.vue b/app/assets/javascripts/logs/components/log_advanced_filters.vue index 9159ca5b9dc..c6d7c9ad1dc 100644 --- a/app/assets/javascripts/logs/components/log_advanced_filters.vue +++ b/app/assets/javascripts/logs/components/log_advanced_filters.vue @@ -1,8 +1,9 @@ <script> import { GlFilteredSearch } from '@gitlab/ui'; import { mapActions, mapState } from 'vuex'; -import { __, s__ } from '~/locale'; +import { s__ } from '~/locale'; import DateTimePicker from '~/vue_shared/components/date_time_picker/date_time_picker.vue'; +import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants'; import { timeRanges } from '~/vue_shared/constants'; import { TOKEN_TYPE_POD_NAME } from '../constants'; import TokenWithLoadingState from './tokens/token_with_loading_state.vue'; @@ -54,7 +55,7 @@ export default { type: TOKEN_TYPE_POD_NAME, title: s__('Environments|Pod name'), token: TokenWithLoadingState, - operators: [{ value: '=', description: __('is'), default: 'true' }], + operators: OPERATOR_IS_ONLY, unique: true, options: this.podOptions, loading: this.logs.isLoading, diff --git a/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue b/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue index b92d9211f91..cc0533391df 100644 --- a/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue +++ b/app/assets/javascripts/members/components/filter_sort/members_filtered_search_bar.vue @@ -5,6 +5,7 @@ import { getParameterByName, urlParamsToObject } from '~/lib/utils/common_utils' import { setUrlParams } from '~/lib/utils/url_utility'; import { s__ } from '~/locale'; import { SEARCH_TOKEN_TYPE, SORT_PARAM } from '~/members/constants'; +import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants'; import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue'; export default { @@ -17,7 +18,7 @@ export default { title: s__('Members|2FA'), token: GlFilteredSearchToken, unique: true, - operators: [{ value: '=', description: 'is' }], + operators: OPERATOR_IS_ONLY, options: [ { value: 'enabled', title: s__('Members|Enabled') }, { value: 'disabled', title: s__('Members|Disabled') }, @@ -30,7 +31,7 @@ export default { title: s__('Members|Membership'), token: GlFilteredSearchToken, unique: true, - operators: [{ value: '=', description: 'is' }], + operators: OPERATOR_IS_ONLY, options: [ { value: 'exclude', title: s__('Members|Direct') }, { value: 'only', title: s__('Members|Inherited') }, diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue index 5b40f4f86f5..4ce81219f11 100644 --- a/app/assets/javascripts/notes/components/note_form.vue +++ b/app/assets/javascripts/notes/components/note_form.vue @@ -367,21 +367,11 @@ export default { <p v-if="showResolveDiscussionToggle"> <label> <template v-if="discussionResolved"> - <input - v-model="isUnresolving" - type="checkbox" - class="js-unresolve-checkbox" - data-qa-selector="unresolve_review_discussion_checkbox" - /> + <input v-model="isUnresolving" type="checkbox" class="js-unresolve-checkbox" /> {{ __('Unresolve thread') }} </template> <template v-else> - <input - v-model="isResolving" - type="checkbox" - class="js-resolve-checkbox" - data-qa-selector="resolve_review_discussion_checkbox" - /> + <input v-model="isResolving" type="checkbox" class="js-resolve-checkbox" /> {{ __('Resolve thread') }} </template> </label> diff --git a/app/assets/javascripts/packages/list/components/package_search.vue b/app/assets/javascripts/packages/list/components/package_search.vue index 2e183b1b978..869a2c2f641 100644 --- a/app/assets/javascripts/packages/list/components/package_search.vue +++ b/app/assets/javascripts/packages/list/components/package_search.vue @@ -1,6 +1,7 @@ <script> import { mapState, mapActions } from 'vuex'; -import { __, s__ } from '~/locale'; +import { s__ } from '~/locale'; +import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants'; import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue'; import UrlSync from '~/vue_shared/components/url_sync.vue'; import { sortableFields } from '../utils'; @@ -14,7 +15,7 @@ export default { title: s__('PackageRegistry|Type'), unique: true, token: PackageTypeToken, - operators: [{ value: '=', description: __('is'), default: 'true' }], + operators: OPERATOR_IS_ONLY, }, ], components: { RegistrySearch, UrlSync }, 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 af5f77e2d64..1acf3a03e73 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 @@ -1,34 +1,77 @@ <script> -import { GlDropdown, GlDropdownItem, GlDropdownSectionHeader, GlIcon } from '@gitlab/ui'; +import { + GlDropdown, + GlDropdownItem, + GlDropdownSectionHeader, + GlInfiniteScroll, + GlLoadingIcon, + GlSearchBoxByType, +} from '@gitlab/ui'; import { historyPushState } from '~/lib/utils/common_utils'; import { setUrlParams } from '~/lib/utils/url_utility'; import { s__ } from '~/locale'; -import { DEFAULT_FAILURE } from '~/pipeline_editor/constants'; +import { + BRANCH_PAGINATION_LIMIT, + 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'; export default { i18n: { + dropdownHeader: s__('Switch Branch'), title: s__('Branches'), fetchError: s__('Unable to fetch branch list for this project.'), }, + inputDebounce: BRANCH_SEARCH_DEBOUNCE, components: { GlDropdown, GlDropdownItem, GlDropdownSectionHeader, - GlIcon, + GlInfiniteScroll, + GlLoadingIcon, + GlSearchBoxByType, + }, + inject: ['projectFullPath', 'totalBranches'], + props: { + paginationLimit: { + type: Number, + required: false, + default: BRANCH_PAGINATION_LIMIT, + }, + }, + data() { + return { + branches: [], + page: { + limit: this.paginationLimit, + offset: 0, + searchTerm: '', + }, + }; }, - inject: ['projectFullPath'], apollo: { - branches: { + availableBranches: { query: getAvailableBranches, variables() { return { + limit: this.page.limit, + offset: this.page.offset, projectFullPath: this.projectFullPath, + searchPattern: this.searchPattern, }; }, update(data) { - return data.project?.repository?.branches || []; + 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); + } }, error() { this.$emit('showError', { @@ -42,11 +85,37 @@ export default { }, }, computed: { - hasBranchList() { - return this.branches?.length > 0; + isBranchesLoading() { + return this.$apollo.queries.availableBranches.loading; + }, + showBranchSwitcher() { + return this.branches.length > 0 || this.page.searchTerm.length > 0; + }, + searchPattern() { + if (this.page.searchTerm === '') { + return '*'; + } + + return `*${this.page.searchTerm}*`; }, }, methods: { + // if there is no searchPattern, paginate by {paginationLimit} branches + fetchNextBranches() { + if ( + this.isBranchesLoading || + this.page.searchTerm.length > 0 || + this.branches.length === this.totalBranches + ) { + return; + } + + this.page = { + ...this.page, + limit: this.paginationLimit, + offset: this.page.offset + this.paginationLimit, + }; + }, async selectBranch(newBranch) { if (newBranch === this.currentBranch) { return; @@ -62,24 +131,53 @@ export default { this.$emit('refetchContent'); }, + setSearchTerm(newSearchTerm) { + this.branches = []; + this.page = { + limit: newSearchTerm.trim() === '' ? this.paginationLimit : this.totalBranches, + offset: 0, + searchTerm: newSearchTerm.trim(), + }; + }, }, }; </script> <template> - <gl-dropdown v-if="hasBranchList" class="gl-ml-2" :text="currentBranch" icon="branch"> + <gl-dropdown + v-if="showBranchSwitcher" + class="gl-ml-2" + :header-text="$options.i18n.dropdownHeader" + :text="currentBranch" + icon="branch" + > + <gl-search-box-by-type :debounce="$options.inputDebounce" @input="setSearchTerm" /> <gl-dropdown-section-header> - {{ this.$options.i18n.title }} + {{ $options.i18n.title }} </gl-dropdown-section-header> - <gl-dropdown-item - v-for="branch in branches" - :key="branch.name" - :is-checked="currentBranch === branch.name" - :is-check-item="true" - @click="selectBranch(branch.name)" + + <gl-infinite-scroll + :fetched-items="branches.length" + :total-items="totalBranches" + :max-list-height="250" + @bottomReached="fetchNextBranches" > - <gl-icon name="check" class="gl-visibility-hidden" /> - {{ branch.name }} - </gl-dropdown-item> + <template #items> + <gl-dropdown-item + v-for="branch in branches" + :key="branch" + :is-checked="currentBranch === branch" + :is-check-item="true" + @click="selectBranch(branch)" + > + {{ branch }} + </gl-dropdown-item> + </template> + <template #default> + <gl-dropdown-item v-if="isBranchesLoading" key="loading"> + <gl-loading-icon size="md" /> + </gl-dropdown-item> + </template> + </gl-infinite-scroll> </gl-dropdown> </template> diff --git a/app/assets/javascripts/pipeline_editor/constants.js b/app/assets/javascripts/pipeline_editor/constants.js index dba815368eb..f0a24e0c061 100644 --- a/app/assets/javascripts/pipeline_editor/constants.js +++ b/app/assets/javascripts/pipeline_editor/constants.js @@ -28,3 +28,6 @@ export const COMMIT_ACTION_CREATE = 'CREATE'; export const COMMIT_ACTION_UPDATE = 'UPDATE'; export const DRAWER_EXPANDED_KEY = 'pipeline_editor_drawer_expanded'; + +export const BRANCH_PAGINATION_LIMIT = 20; +export const BRANCH_SEARCH_DEBOUNCE = '500'; diff --git a/app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.graphql b/app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.graphql index f162bb11d47..46e9b108b41 100644 --- a/app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.graphql +++ b/app/assets/javascripts/pipeline_editor/graphql/queries/available_branches.graphql @@ -1,9 +1,12 @@ -query getAvailableBranches($projectFullPath: ID!) { - project(fullPath: $projectFullPath) @client { +query getAvailableBranches( + $limit: Int! + $offset: Int! + $projectFullPath: ID! + $searchPattern: String! +) { + project(fullPath: $projectFullPath) { repository { - branches { - name - } + branchNames(limit: $limit, offset: $offset, searchPattern: $searchPattern) } } } diff --git a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js index 1028770667a..81e75c32846 100644 --- a/app/assets/javascripts/pipeline_editor/graphql/resolvers.js +++ b/app/assets/javascripts/pipeline_editor/graphql/resolvers.js @@ -11,22 +11,6 @@ export const resolvers = { }), }; }, - /* eslint-disable @gitlab/require-i18n-strings */ - project() { - return { - __typename: 'Project', - repository: { - __typename: 'Repository', - branches: [ - { __typename: 'Branch', name: 'main' }, - { __typename: 'Branch', name: 'develop' }, - { __typename: 'Branch', name: 'production' }, - { __typename: 'Branch', name: 'test' }, - ], - }, - }; - }, - /* eslint-enable @gitlab/require-i18n-strings */ }, Mutation: { lintCI: (_, { endpoint, content, dry_run }) => { diff --git a/app/assets/javascripts/pipeline_editor/index.js b/app/assets/javascripts/pipeline_editor/index.js index 361e2b64e0b..66158bdba88 100644 --- a/app/assets/javascripts/pipeline_editor/index.js +++ b/app/assets/javascripts/pipeline_editor/index.js @@ -43,6 +43,7 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => { projectPath, projectNamespace, runnerHelpPagePath, + totalBranches, ymlHelpPagePath, } = el?.dataset; @@ -100,6 +101,7 @@ export const initPipelineEditor = (selector = '#js-pipeline-editor') => { projectPath, projectNamespace, runnerHelpPagePath, + totalBranches: parseInt(totalBranches, 10), ymlHelpPagePath, }, render(h) { diff --git a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue index 492c562ec5c..de3f783ac84 100644 --- a/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue +++ b/app/assets/javascripts/pipelines/components/pipelines_list/pipelines_filtered_search.vue @@ -1,7 +1,8 @@ <script> import { GlFilteredSearch } from '@gitlab/ui'; import { map } from 'lodash'; -import { __, s__ } from '~/locale'; +import { s__ } from '~/locale'; +import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants'; import PipelineBranchNameToken from './tokens/pipeline_branch_name_token.vue'; import PipelineStatusToken from './tokens/pipeline_status_token.vue'; import PipelineTagNameToken from './tokens/pipeline_tag_name_token.vue'; @@ -43,7 +44,7 @@ export default { title: s__('Pipeline|Trigger author'), unique: true, token: PipelineTriggerAuthorToken, - operators: [{ value: '=', description: __('is'), default: 'true' }], + operators: OPERATOR_IS_ONLY, projectId: this.projectId, }, { @@ -52,7 +53,7 @@ export default { title: s__('Pipeline|Branch name'), unique: true, token: PipelineBranchNameToken, - operators: [{ value: '=', description: __('is'), default: 'true' }], + operators: OPERATOR_IS_ONLY, projectId: this.projectId, disabled: this.selectedTypes.includes(this.$options.tagType), }, @@ -62,7 +63,7 @@ export default { title: s__('Pipeline|Tag name'), unique: true, token: PipelineTagNameToken, - operators: [{ value: '=', description: __('is'), default: 'true' }], + operators: OPERATOR_IS_ONLY, projectId: this.projectId, disabled: this.selectedTypes.includes(this.$options.branchType), }, @@ -72,7 +73,7 @@ export default { title: s__('Pipeline|Status'), unique: true, token: PipelineStatusToken, - operators: [{ value: '=', description: __('is'), default: 'true' }], + operators: OPERATOR_IS_ONLY, }, ]; }, diff --git a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue index 6d68c15cf2d..75831643f6a 100644 --- a/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue +++ b/app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_auto_merge_enabled.vue @@ -154,7 +154,7 @@ export default { <status-icon status="success" /> <div class="media-body"> <h4 class="gl-display-flex"> - <span class="gl-mr-3" data-qa-selector="merge_request_status_content"> + <span class="gl-mr-3"> <span class="js-status-text-before-author" data-testid="beforeStatusText">{{ statusTextBeforeAuthor }}</span> diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js b/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js index 519b461c015..784f7cccf15 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js @@ -1,4 +1,3 @@ -/* eslint-disable @gitlab/require-i18n-strings */ import { __ } from '~/locale'; export const DEBOUNCE_DELAY = 200; @@ -7,6 +6,12 @@ export const FILTER_NONE = 'None'; export const FILTER_ANY = 'Any'; export const FILTER_CURRENT = 'Current'; +export const OPERATOR_IS = '='; +export const OPERATOR_IS_TEXT = __('is'); +export const OPERATOR_IS_NOT = '!='; + +export const OPERATOR_IS_ONLY = [{ value: OPERATOR_IS, description: OPERATOR_IS_TEXT }]; + export const DEFAULT_LABEL_NONE = { value: FILTER_NONE, text: __(FILTER_NONE) }; export const DEFAULT_LABEL_ANY = { value: FILTER_ANY, text: __(FILTER_ANY) }; export const DEFAULT_NONE_ANY = [DEFAULT_LABEL_NONE, DEFAULT_LABEL_ANY]; @@ -15,15 +20,26 @@ export const DEFAULT_ITERATIONS = DEFAULT_NONE_ANY.concat([ { value: FILTER_CURRENT, text: __(FILTER_CURRENT) }, ]); -export const DEFAULT_LABELS = [{ value: 'No label', text: __('No label') }]; +export const DEFAULT_LABELS = [{ value: 'No label', text: __('No label') }]; // eslint-disable-line @gitlab/require-i18n-strings export const DEFAULT_MILESTONES = DEFAULT_NONE_ANY.concat([ - { value: 'Upcoming', text: __('Upcoming') }, - { value: 'Started', text: __('Started') }, + { value: 'Upcoming', text: __('Upcoming') }, // eslint-disable-line @gitlab/require-i18n-strings + { value: 'Started', text: __('Started') }, // eslint-disable-line @gitlab/require-i18n-strings ]); export const SortDirection = { descending: 'descending', ascending: 'ascending', }; -/* eslint-enable @gitlab/require-i18n-strings */ + +export const FILTERED_SEARCH_TERM = 'filtered-search-term'; + +export const TOKEN_TITLE_AUTHOR = __('Author'); +export const TOKEN_TITLE_ASSIGNEE = __('Assignee'); +export const TOKEN_TITLE_MILESTONE = __('Milestone'); +export const TOKEN_TITLE_LABEL = __('Label'); +export const TOKEN_TITLE_MY_REACTION = __('My-Reaction'); +export const TOKEN_TITLE_CONFIDENTIAL = __('Confidential'); +export const TOKEN_TITLE_ITERATION = __('Iteration'); +export const TOKEN_TITLE_EPIC = __('Epic'); +export const TOKEN_TITLE_WEIGHT = __('Weight'); diff --git a/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue b/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue index 90ac20fe748..d6a20984ad1 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/apply_suggestion.vue @@ -34,7 +34,7 @@ export default { boundary="window" right menu-class="gl-w-full!" - data-qa-selector="apply_suggestion_button" + data-qa-selector="apply_suggestion_dropdown" @shown="$refs.commitMessage.$el.focus()" > <gl-dropdown-form class="gl-px-4! gl-m-0!"> @@ -45,7 +45,7 @@ export default { v-model="message" :placeholder="defaultCommitMessage" submit-on-enter - data-qa-selector="commit_message_textbox" + data-qa-selector="commit_message_field" @submit="onApply" /> <gl-button diff --git a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue index bcd8c02e968..9c954fce322 100644 --- a/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue +++ b/app/assets/javascripts/vue_shared/components/markdown/suggestion_diff.vue @@ -70,7 +70,7 @@ export default { <template> <div class="md-suggestion"> <suggestion-diff-header - class="qa-suggestion-diff-header js-suggestion-diff-header" + class="js-suggestion-diff-header" :suggestions-count="suggestionsCount" :can-apply="suggestion.appliable && suggestion.current_user.can_apply && !disabled" :is-applied="suggestion.applied" diff --git a/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue b/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue index e2591362611..d05e45e90b3 100644 --- a/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue +++ b/app/assets/javascripts/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue @@ -4,6 +4,7 @@ import Api from '~/api'; import { updateHistory, setUrlParams } from '~/lib/utils/url_utility'; import { __ } from '~/locale'; import Tracking from '~/tracking'; +import { OPERATOR_IS_ONLY } from '~/vue_shared/components/filtered_search_bar/constants'; import FilteredSearchBar from '~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue'; import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue'; import { initialPaginationState, defaultI18n, defaultPageSize } from './constants'; @@ -105,7 +106,7 @@ export default { unique: true, symbol: '@', token: AuthorToken, - operators: [{ value: '=', description: __('is'), default: 'true' }], + operators: OPERATOR_IS_ONLY, fetchPath: this.projectPath, fetchAuthors: Api.projectUsers.bind(Api), }, @@ -116,7 +117,7 @@ export default { unique: true, symbol: '@', token: AuthorToken, - operators: [{ value: '=', description: __('is'), default: 'true' }], + operators: OPERATOR_IS_ONLY, fetchPath: this.projectPath, fetchAuthors: Api.projectUsers.bind(Api), }, |