Modify the frontend for wildcard protected branches.

1. Allow entering any branch name for a protected branch.

    - Either pick from a list of options, or enter it manually
    - You can enter wildcards.

2. Display branches matching a protected branch.

    -  Add a `ProtectedBranches#show` page that displays the branches
       matching the given protected branch, or a message if there are no
       matches.

    - On the `index` page, display the last commit for an exact match,
      or the number of matching branches for a wildcard match.

    -  Add an `iid` column to `protected_branches` - this is what we use for
       the `show` page URL.

    -  On the off chance that this feature is unnecessary, this commit
       encapsulates it neatly, so it can be removed without affecting
       anything else.

3. Remove the "Last Commit" column from the list of protected branches.

    - There's no way to pull these for wildcard protected branches, so it's
      best left for the `show` page.

    - Rename the `@branches` instance variable to `@protected_branches`

    - Minor styling changes with the "Unprotect" button - floated right
      like the "Revoke" button for personal access tokens

4. Paginate the list of protected branches.

5. Move the instructions to the left side of the page.
This commit is contained in:
Timothy Andrew 2016-06-16 13:03:30 +05:30
parent f51af49676
commit 2a5cb7ec52
9 changed files with 108 additions and 38 deletions

View File

@ -11,6 +11,7 @@ $ ->
dataType: "json" dataType: "json"
data: data:
id: id id: id
protected_branch:
developers_can_push: checked developers_can_push: checked
success: -> success: ->

View File

@ -2,12 +2,14 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
# Authorize # Authorize
before_action :require_non_empty_project before_action :require_non_empty_project
before_action :authorize_admin_project! before_action :authorize_admin_project!
before_action :load_protected_branch, only: [:show, :update, :destroy]
layout "project_settings" layout "project_settings"
def index def index
@branches = @project.protected_branches.to_a @protected_branches = @project.protected_branches.order(:name).page(params[:page])
@protected_branch = @project.protected_branches.new @protected_branch = @project.protected_branches.new
gon.push({ open_branches: @project.open_branches.map { |br| { text: br.name, id: br.name } } })
end end
def create def create
@ -16,26 +18,24 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
@project) @project)
end end
def show
@matching_branches = @protected_branch.matching(@project.repository.branches)
end
def update def update
protected_branch = @project.protected_branches.find(params[:id]) if @protected_branch && @protected_branch.update_attributes(protected_branch_params)
if protected_branch &&
protected_branch.update_attributes(
developers_can_push: params[:developers_can_push]
)
respond_to do |format| respond_to do |format|
format.json { render json: protected_branch, status: :ok } format.json { render json: @protected_branch, status: :ok }
end end
else else
respond_to do |format| respond_to do |format|
format.json { render json: protected_branch.errors, status: :unprocessable_entity } format.json { render json: @protected_branch.errors, status: :unprocessable_entity }
end end
end end
end end
def destroy def destroy
@project.protected_branches.find(params[:id]).destroy @protected_branch.destroy
respond_to do |format| respond_to do |format|
format.html { redirect_to namespace_project_protected_branches_path } format.html { redirect_to namespace_project_protected_branches_path }
@ -45,6 +45,10 @@ class Projects::ProtectedBranchesController < Projects::ApplicationController
private private
def load_protected_branch
@protected_branch = @project.protected_branches.find(params[:id])
end
def protected_branch_params def protected_branch_params
params.require(:protected_branch).permit(:name, :developers_can_push) params.require(:protected_branch).permit(:name, :developers_can_push)
end end

View File

@ -19,6 +19,12 @@ class ProtectedBranch < ActiveRecord::Base
(protected_branches || all).select { |protected_branch| protected_branch.matches?(branch_name) } (protected_branches || all).select { |protected_branch| protected_branch.matches?(branch_name) }
end end
# Returns all branches (among the given list of branches [`Gitlab::Git::Branch`])
# that match the current protected branch.
def matching(branches)
branches.select { |branch| self.matches?(branch.name) }
end
# Checks if the protected branch matches the given branch name. # Checks if the protected branch matches the given branch name.
def matches?(branch_name) def matches?(branch_name)
return false if self.name.blank? return false if self.name.blank?
@ -26,6 +32,11 @@ class ProtectedBranch < ActiveRecord::Base
exact_match?(branch_name) || wildcard_match?(branch_name) exact_match?(branch_name) || wildcard_match?(branch_name)
end end
# Checks if this protected branch contains a wildcard
def wildcard?
self.name.include?('*')
end
protected protected
def exact_match?(branch_name) def exact_match?(branch_name)

View File

@ -1,6 +1,6 @@
%h5.prepend-top-0 %h5.prepend-top-0
Already Protected (#{@branches.size}) Already Protected (#{@protected_branches.size})
- if @branches.empty? - if @protected_branches.empty?
%p.settings-message.text-center %p.settings-message.text-center
No branches are protected, protect a branch with the form above. No branches are protected, protect a branch with the form above.
- else - else
@ -9,33 +9,18 @@
%table.table.protected-branches-list %table.table.protected-branches-list
%colgroup %colgroup
%col{ width: "30%" } %col{ width: "30%" }
%col{ width: "30%" } %col{ width: "25%" }
%col{ width: "25%" } %col{ width: "25%" }
- if can_admin_project - if can_admin_project
%col %col
%thead %thead
%tr %tr
%th Branch %th Protected Branch
%th Last commit %th Commit
%th Developers can push %th Developers Can Push
- if can_admin_project - if can_admin_project
%th %th
%tbody %tbody
- @branches.each do |branch| = render partial: @protected_branches, locals: { can_admin_project: can_admin_project }
- @url = namespace_project_protected_branch_path(@project.namespace, @project, branch)
%tr = paginate @protected_branches, theme: 'gitlab'
%td
= link_to(branch.name, namespace_project_commits_path(@project.namespace, @project, branch.name))
- if @project.root_ref?(branch.name)
%span.label.label-info.prepend-left-5 default
%td
- if commit = branch.commit
= link_to(commit.short_id, namespace_project_commit_path(@project.namespace, @project, commit.id), class: 'commit_short_id')
#{time_ago_with_tooltip(commit.committed_date)}
- else
(branch was removed from repository)
%td
= check_box_tag("developers_can_push", branch.id, branch.developers_can_push, data: { url: @url })
- if can_admin_project
%td
= link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-warning btn-sm"

View File

@ -0,0 +1,9 @@
%tr
%td
= link_to matching_branch.name, namespace_project_tree_path(@project.namespace, @project, matching_branch.name)
- if @project.root_ref?(matching_branch.name)
%span.label.label-info.prepend-left-5 default
%td
- commit = @project.commit(matching_branch.name)
= link_to(commit.short_id, namespace_project_commit_path(@project.namespace, @project, commit.id), class: 'commit_short_id')
= time_ago_with_tooltip(commit.committed_date)

View File

@ -0,0 +1,21 @@
- url = namespace_project_protected_branch_path(@project.namespace, @project, protected_branch)
%tr
%td
= protected_branch.name
- if @project.root_ref?(protected_branch.name)
%span.label.label-info.prepend-left-5 default
%td
- if protected_branch.wildcard?
- matching_branches = protected_branch.matching(repository.branches)
= link_to pluralize(matching_branches.count, "matching branch"), namespace_project_protected_branch_path(@project.namespace, @project, protected_branch)
- else
- if commit = protected_branch.commit
= link_to(commit.short_id, namespace_project_commit_path(@project.namespace, @project, commit.id), class: 'commit_short_id')
= time_ago_with_tooltip(commit.committed_date)
- else
(branch was removed from repository)
%td
= check_box_tag("developers_can_push", protected_branch.id, protected_branch.developers_can_push, data: { url: url })
- if can_admin_project
%td
= link_to 'Unprotect', [@project.namespace.becomes(Namespace), @project, protected_branch], data: { confirm: 'Branch will be writable for developers. Are you sure?' }, method: :delete, class: "btn btn-warning btn-sm pull-right"

View File

@ -21,7 +21,14 @@
.form-group .form-group
= f.label :name, "Branch", class: "label-light" = f.label :name, "Branch", class: "label-light"
= f.select(:name, @project.open_branches.map { |br| [br.name, br.name] } , {include_blank: true}, {class: "select2", data: {placeholder: "Select branch"}}) = f.text_field(:name)
%p.help-block
Wildcards such as
%code *-stable
or
%code production/*
are supported.
.form-group .form-group
= f.check_box :developers_can_push, class: "pull-left" = f.check_box :developers_can_push, class: "pull-left"
.prepend-left-20 .prepend-left-20
@ -31,3 +38,10 @@
= f.submit "Protect", class: "btn-create btn" = f.submit "Protect", class: "btn-create btn"
%hr %hr
= render "branches_list" = render "branches_list"
:javascript
$("#protected_branch_name").select2({
placeholder: "Select branch",
createSearchChoice: function(term) { return { id: term, text: term }; },
data: gon.open_branches
})

View File

@ -0,0 +1,25 @@
- page_title @protected_branch.name, "Protected Branches"
.row.prepend-top-default.append-bottom-default
.col-lg-3
%h4.prepend-top-0
= @protected_branch.name
.col-lg-9
%h5 Matching Branches
- if @matching_branches.present?
.table-responsive
%table.table.protected-branches-list
%colgroup
%col{ width: "30%" }
%col{ width: "30%" }
%thead
%tr
%th Branch
%th Last commit
%tbody
- @matching_branches.each do |matching_branch|
= render partial: "matching_branch", object: matching_branch
- else
%p.settings-message.text-center
Couldn't find any matching branches.

View File

@ -720,7 +720,7 @@ Rails.application.routes.draw do
resource :release, only: [:edit, :update] resource :release, only: [:edit, :update]
end end
resources :protected_branches, only: [:index, :create, :update, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex } resources :protected_branches, only: [:index, :show, :create, :update, :destroy], constraints: { id: Gitlab::Regex.git_reference_regex }
resources :variables, only: [:index, :show, :update, :create, :destroy] resources :variables, only: [:index, :show, :update, :create, :destroy]
resources :triggers, only: [:index, :create, :destroy] resources :triggers, only: [:index, :create, :destroy]