diff options
Diffstat (limited to 'app/assets/javascripts/projects/settings/branch_rules')
4 files changed, 182 insertions, 0 deletions
diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/branch_dropdown.vue b/app/assets/javascripts/projects/settings/branch_rules/components/branch_dropdown.vue new file mode 100644 index 00000000000..6bbe0ab7d5f --- /dev/null +++ b/app/assets/javascripts/projects/settings/branch_rules/components/branch_dropdown.vue @@ -0,0 +1,110 @@ +<script> +import { GlDropdown, GlDropdownItem, GlDropdownDivider, GlSearchBoxByType } from '@gitlab/ui'; +import { createAlert } from '~/flash'; +import { __, sprintf } from '~/locale'; +import branchesQuery from '../queries/branches.query.graphql'; + +export const i18n = { + fetchBranchesError: __('An error occurred while fetching branches.'), + noMatch: __('No matching results'), +}; + +export default { + i18n, + name: 'BranchDropdown', + components: { + GlDropdown, + GlDropdownItem, + GlDropdownDivider, + GlSearchBoxByType, + }, + apollo: { + branchNames: { + query: branchesQuery, + variables() { + return { + projectPath: this.projectPath, + searchPattern: `*${this.searchTerm}*`, + }; + }, + update({ project: { repository = {} } } = {}) { + return repository.branchNames || []; + }, + error(e) { + createAlert({ + message: this.$options.i18n.fetchBranchesError, + captureError: true, + error: e, + }); + }, + }, + }, + props: { + projectPath: { + type: String, + required: true, + }, + value: { + type: String, + required: false, + default: null, + }, + }, + data() { + return { + searchTerm: '', + branchNames: [], + }; + }, + computed: { + createButtonLabel() { + return sprintf(__('Create wildcard: %{searchTerm}'), { searchTerm: this.searchTerm }); + }, + shouldRenderCreateButton() { + return this.searchTerm && !this.branchNames.includes(this.searchTerm); + }, + isLoading() { + return this.$apollo.queries.branchNames.loading; + }, + }, + methods: { + selectBranch(selected) { + this.$emit('input', selected); + }, + createWildcard() { + this.$emit('createWildcard', this.searchTerm); + }, + isSelected(branch) { + return this.value === branch; + }, + }, +}; +</script> +<template> + <gl-dropdown :text="value || branchNames[0]"> + <gl-search-box-by-type + v-model.trim="searchTerm" + data-testid="branch-search" + debounce="250" + :is-loading="isLoading" + /> + <gl-dropdown-item + v-for="branch in branchNames" + :key="branch" + :is-checked="isSelected(branch)" + is-check-item + @click="selectBranch(branch)" + > + {{ branch }} + </gl-dropdown-item> + <gl-dropdown-item v-if="!branchNames.length && !isLoading" data-testid="no-data">{{ + $options.i18n.noMatch + }}</gl-dropdown-item> + <template v-if="shouldRenderCreateButton"> + <gl-dropdown-divider /> + <gl-dropdown-item data-testid="create-wildcard-button" @click="createWildcard"> + {{ createButtonLabel }} + </gl-dropdown-item> + </template> + </gl-dropdown> +</template> diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/rule_edit.vue b/app/assets/javascripts/projects/settings/branch_rules/components/rule_edit.vue new file mode 100644 index 00000000000..c2e7f4e9b1b --- /dev/null +++ b/app/assets/javascripts/projects/settings/branch_rules/components/rule_edit.vue @@ -0,0 +1,38 @@ +<script> +import { GlFormGroup } from '@gitlab/ui'; +import { __ } from '~/locale'; +import { getParameterByName } from '~/lib/utils/url_utility'; +import BranchDropdown from './branch_dropdown.vue'; + +export default { + name: 'RuleEdit', + i18n: { + branch: __('Branch'), + }, + components: { BranchDropdown, GlFormGroup }, + props: { + projectPath: { + type: String, + required: true, + }, + }, + data() { + return { + branch: getParameterByName('branch'), + }; + }, +}; +</script> + +<template> + <gl-form-group :label="$options.i18n.branch"> + <branch-dropdown + id="branches" + v-model="branch" + class="gl-w-half" + :project-path="projectPath" + @createWildcard="branch = $event" + /> + </gl-form-group> + <!-- TODO - Add branch protections (https://gitlab.com/gitlab-org/gitlab/-/issues/362212) --> +</template> diff --git a/app/assets/javascripts/projects/settings/branch_rules/mount_branch_rules.js b/app/assets/javascripts/projects/settings/branch_rules/mount_branch_rules.js new file mode 100644 index 00000000000..8452542540e --- /dev/null +++ b/app/assets/javascripts/projects/settings/branch_rules/mount_branch_rules.js @@ -0,0 +1,26 @@ +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createDefaultClient from '~/lib/graphql'; +import RuleEdit from './components/rule_edit.vue'; + +export default function mountBranchRules(el) { + if (!el) { + return null; + } + + Vue.use(VueApollo); + + const apolloProvider = new VueApollo({ + defaultClient: createDefaultClient(), + }); + + const { projectPath } = el.dataset; + + return new Vue({ + el, + apolloProvider, + render(h) { + return h(RuleEdit, { props: { projectPath } }); + }, + }); +} diff --git a/app/assets/javascripts/projects/settings/branch_rules/queries/branches.query.graphql b/app/assets/javascripts/projects/settings/branch_rules/queries/branches.query.graphql new file mode 100644 index 00000000000..a532b544757 --- /dev/null +++ b/app/assets/javascripts/projects/settings/branch_rules/queries/branches.query.graphql @@ -0,0 +1,8 @@ +query getBranches($projectPath: ID!, $searchPattern: String!) { + project(fullPath: $projectPath) { + id + repository { + branchNames(searchPattern: $searchPattern, limit: 100, offset: 0) + } + } +} |