summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouwe Maan <douwe@gitlab.com>2016-07-25 12:07:29 +0000
committerDouwe Maan <douwe@gitlab.com>2016-07-25 12:07:29 +0000
commit8ce5b4f1a30c0ab904f67c544a6b7de1bb49e664 (patch)
treefc9625d19726506d7d459327ec972071e6a3175a
parent83180110348af1b244d56e9cdf5f29c5d6f84db0 (diff)
parent850813d29867aac5935e1128880784f97071a6d8 (diff)
downloadgitlab-ce-8ce5b4f1a30c0ab904f67c544a6b7de1bb49e664.tar.gz
Merge branch 'filter-branch-by-name' into 'master'
Users can filter branches by name on project branches page This MR aims to solve #18674 by adding the possibility to filter project branches by name ![Screen_Shot_2016-07-07_at_17.21.25](/uploads/b674765d2b1cb8a121c2101715a4568b/Screen_Shot_2016-07-07_at_17.21.25.png) See merge request !5144
-rw-r--r--CHANGELOG2
-rw-r--r--app/controllers/projects/branches_controller.rb3
-rw-r--r--app/finders/branches_finder.rb31
-rw-r--r--app/helpers/branches_helper.rb11
-rw-r--r--app/models/repository.rb2
-rw-r--r--app/views/projects/branches/index.html.haml20
-rw-r--r--db/schema.rb15
-rw-r--r--spec/features/projects/branches_spec.rb32
-rw-r--r--spec/features/projects/branches_spec.rb~HEAD32
-rw-r--r--spec/finders/branches_finder_spec.rb76
10 files changed, 207 insertions, 17 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 698fbf6a160..0e887ce2119 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -14,6 +14,8 @@ v 8.10.1 (unreleased)
- Ignore invalid trusted proxies in X-Forwarded-For header
- Fix bug where replies to commit notes displayed in the MR discussion tab wouldn't show up on the commit page
+v 8.10.0 (unreleased)
+ - User can now search branches by name. !5144 (tiagonbotelho)
v 8.10.0
- Fix profile activity heatmap to show correct day name (eanplatter)
- Speed up ExternalWikiHelper#get_project_wiki_path
diff --git a/app/controllers/projects/branches_controller.rb b/app/controllers/projects/branches_controller.rb
index dd9508da049..6126acccaab 100644
--- a/app/controllers/projects/branches_controller.rb
+++ b/app/controllers/projects/branches_controller.rb
@@ -6,8 +6,7 @@ class Projects::BranchesController < Projects::ApplicationController
before_action :authorize_push_code!, only: [:new, :create, :destroy]
def index
- @sort = params[:sort] || 'name'
- @branches = @repository.branches_sorted_by(@sort)
+ @branches = BranchesFinder.new(@repository, params).execute
@branches = Kaminari.paginate_array(@branches).page(params[:page])
@max_commits = @branches.reduce(0) do |memo, branch|
diff --git a/app/finders/branches_finder.rb b/app/finders/branches_finder.rb
new file mode 100644
index 00000000000..533076585c0
--- /dev/null
+++ b/app/finders/branches_finder.rb
@@ -0,0 +1,31 @@
+class BranchesFinder
+ def initialize(repository, params)
+ @repository = repository
+ @params = params
+ end
+
+ def execute
+ branches = @repository.branches_sorted_by(sort)
+ filter_by_name(branches)
+ end
+
+ private
+
+ attr_reader :repository, :params
+
+ def search
+ @params[:search].presence
+ end
+
+ def sort
+ @params[:sort].presence || 'name'
+ end
+
+ def filter_by_name(branches)
+ if search
+ branches.select { |branch| branch.name.include?(search) }
+ else
+ branches
+ end
+ end
+end
diff --git a/app/helpers/branches_helper.rb b/app/helpers/branches_helper.rb
index bfd23aa4e04..3fc85dc6b2b 100644
--- a/app/helpers/branches_helper.rb
+++ b/app/helpers/branches_helper.rb
@@ -9,6 +9,17 @@ module BranchesHelper
end
end
+ def filter_branches_path(options = {})
+ exist_opts = {
+ search: params[:search],
+ sort: params[:sort]
+ }
+
+ options = exist_opts.merge(options)
+
+ namespace_project_branches_path(@project.namespace, @project, @id, options)
+ end
+
def can_push_branch?(project, branch_name)
return false unless project.repository.branch_exists?(branch_name)
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 793b1cf4989..69d71b7f96f 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -610,6 +610,8 @@ class Repository
# Remove archives older than 2 hours
def branches_sorted_by(value)
case value
+ when 'name'
+ branches.sort_by(&:name)
when 'recently_updated'
branches.sort do |a, b|
commit(b.target).committed_date <=> commit(a.target).committed_date
diff --git a/app/views/projects/branches/index.html.haml b/app/views/projects/branches/index.html.haml
index 77b405f1f39..6f806e3ce53 100644
--- a/app/views/projects/branches/index.html.haml
+++ b/app/views/projects/branches/index.html.haml
@@ -9,26 +9,30 @@
- if can? current_user, :push_code, @project
.nav-controls
- = link_to new_namespace_project_branch_path(@project.namespace, @project), class: 'btn btn-create' do
- New branch
+ = form_tag(filter_branches_path, method: :get) do
+ = search_field_tag :search, params[:search], { placeholder: 'Filter by branch name', id: 'branch-search', class: 'form-control search-text-input input-short', spellcheck: false }
.dropdown.inline
%button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'}
%span.light
- - if @sort.present?
- = @sort.humanize
+ - if params[:sort].present?
+ = params[:sort].humanize
- else
Name
%b.caret
%ul.dropdown-menu.dropdown-menu-align-right
%li
- = link_to namespace_project_branches_path(sort: nil) do
- Name
- = link_to namespace_project_branches_path(sort: 'recently_updated') do
+ = link_to filter_branches_path(sort: nil) do
+ = sort_title_name
+ = link_to filter_branches_path(sort: 'recently_updated') do
= sort_title_recently_updated
- = link_to namespace_project_branches_path(sort: 'last_updated') do
+ = link_to filter_branches_path(sort: 'last_updated') do
= sort_title_oldest_updated
+ = link_to new_namespace_project_branch_path(@project.namespace, @project), class: 'btn btn-create' do
+ New branch
- if @branches.any?
%ul.content-list.all-branches
- @branches.each do |branch|
= render "projects/branches/branch", branch: branch
= paginate @branches, theme: 'gitlab'
+ - else
+ .nothing-here-block No branches to show
diff --git a/db/schema.rb b/db/schema.rb
index d541e1cccb7..b87f8108bb2 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -84,7 +84,7 @@ ActiveRecord::Schema.define(version: 20160721081015) do
t.string "health_check_access_token"
t.boolean "send_user_confirmation_email", default: false
t.integer "container_registry_token_expire_delay", default: 5
- t.boolean "user_default_external", default: false, null: false
+ t.boolean "user_default_external", default: false, null: false
t.text "after_sign_up_text"
t.string "repository_storage", default: "default"
t.string "enabled_git_access_protocol"
@@ -607,9 +607,9 @@ ActiveRecord::Schema.define(version: 20160721081015) do
add_index "merge_request_diffs", ["merge_request_id"], name: "index_merge_request_diffs_on_merge_request_id", unique: true, using: :btree
create_table "merge_requests", force: :cascade do |t|
- t.string "target_branch", null: false
- t.string "source_branch", null: false
- t.integer "source_project_id", null: false
+ t.string "target_branch", null: false
+ t.string "source_branch", null: false
+ t.integer "source_project_id", null: false
t.integer "author_id"
t.integer "assignee_id"
t.string "title"
@@ -618,20 +618,21 @@ ActiveRecord::Schema.define(version: 20160721081015) do
t.integer "milestone_id"
t.string "state"
t.string "merge_status"
- t.integer "target_project_id", null: false
+ t.integer "target_project_id", null: false
t.integer "iid"
t.text "description"
- t.integer "position", default: 0
+ t.integer "position", default: 0
t.datetime "locked_at"
t.integer "updated_by_id"
t.string "merge_error"
t.text "merge_params"
- t.boolean "merge_when_build_succeeds", default: false, null: false
+ t.boolean "merge_when_build_succeeds", default: false, null: false
t.integer "merge_user_id"
t.string "merge_commit_sha"
t.datetime "deleted_at"
t.string "in_progress_merge_commit_sha"
end
+
add_index "merge_requests", ["assignee_id"], name: "index_merge_requests_on_assignee_id", using: :btree
add_index "merge_requests", ["author_id"], name: "index_merge_requests_on_author_id", using: :btree
add_index "merge_requests", ["created_at", "id"], name: "index_merge_requests_on_created_at_and_id", using: :btree
diff --git a/spec/features/projects/branches_spec.rb b/spec/features/projects/branches_spec.rb
new file mode 100644
index 00000000000..79abba21854
--- /dev/null
+++ b/spec/features/projects/branches_spec.rb
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+describe 'Branches', feature: true do
+ let(:project) { create(:project) }
+ let(:repository) { project.repository }
+
+ before do
+ login_as :user
+ project.team << [@user, :developer]
+ end
+
+ describe 'Initial branches page' do
+ it 'shows all the branches' do
+ visit namespace_project_branches_path(project.namespace, project)
+
+ repository.branches { |branch| expect(page).to have_content("#{branch.name}") }
+ expect(page).to have_content("Protected branches can be managed in project settings")
+ end
+ end
+
+ describe 'Find branches' do
+ it 'shows filtered branches', js: true do
+ visit namespace_project_branches_path(project.namespace, project, project.id)
+
+ fill_in 'branch-search', with: 'fix'
+ find('#branch-search').native.send_keys(:enter)
+
+ expect(page).to have_content('fix')
+ expect(find('.all-branches')).to have_selector('li', count: 1)
+ end
+ end
+end
diff --git a/spec/features/projects/branches_spec.rb~HEAD b/spec/features/projects/branches_spec.rb~HEAD
new file mode 100644
index 00000000000..79abba21854
--- /dev/null
+++ b/spec/features/projects/branches_spec.rb~HEAD
@@ -0,0 +1,32 @@
+require 'spec_helper'
+
+describe 'Branches', feature: true do
+ let(:project) { create(:project) }
+ let(:repository) { project.repository }
+
+ before do
+ login_as :user
+ project.team << [@user, :developer]
+ end
+
+ describe 'Initial branches page' do
+ it 'shows all the branches' do
+ visit namespace_project_branches_path(project.namespace, project)
+
+ repository.branches { |branch| expect(page).to have_content("#{branch.name}") }
+ expect(page).to have_content("Protected branches can be managed in project settings")
+ end
+ end
+
+ describe 'Find branches' do
+ it 'shows filtered branches', js: true do
+ visit namespace_project_branches_path(project.namespace, project, project.id)
+
+ fill_in 'branch-search', with: 'fix'
+ find('#branch-search').native.send_keys(:enter)
+
+ expect(page).to have_content('fix')
+ expect(find('.all-branches')).to have_selector('li', count: 1)
+ end
+ end
+end
diff --git a/spec/finders/branches_finder_spec.rb b/spec/finders/branches_finder_spec.rb
new file mode 100644
index 00000000000..9c9763d746b
--- /dev/null
+++ b/spec/finders/branches_finder_spec.rb
@@ -0,0 +1,76 @@
+require 'spec_helper'
+
+describe BranchesFinder do
+ let(:user) { create(:user) }
+ let(:project) { create(:project) }
+ let(:repository) { project.repository }
+
+ describe '#execute' do
+ context 'sort only' do
+ it 'sorts by name' do
+ branches_finder = described_class.new(repository, {})
+
+ result = branches_finder.execute
+
+ expect(result.first.name).to eq("'test'")
+ end
+
+ it 'sorts by recently_updated' do
+ branches_finder = described_class.new(repository, { sort: 'recently_updated' })
+
+ result = branches_finder.execute
+
+ expect(result.first.name).to eq('expand-collapse-lines')
+ end
+
+ it 'sorts by last_updated' do
+ branches_finder = described_class.new(repository, { sort: 'last_updated' })
+
+ result = branches_finder.execute
+
+ expect(result.first.name).to eq('feature')
+ end
+ end
+
+ context 'filter only' do
+ it 'filters branches by name' do
+ branches_finder = described_class.new(repository, { search: 'fix' })
+
+ result = branches_finder.execute
+
+ expect(result.first.name).to eq('fix')
+ expect(result.count).to eq(1)
+ end
+
+ it 'does not find any branch with that name' do
+ branches_finder = described_class.new(repository, { search: 'random' })
+
+ result = branches_finder.execute
+
+ expect(result.count).to eq(0)
+ end
+ end
+
+ context 'filter and sort' do
+ it 'filters branches by name and sorts by recently_updated' do
+ params = { sort: 'recently_updated', search: 'feature' }
+ branches_finder = described_class.new(repository, params)
+
+ result = branches_finder.execute
+
+ expect(result.first.name).to eq('feature_conflict')
+ expect(result.count).to eq(2)
+ end
+
+ it 'filters branches by name and sorts by last_updated' do
+ params = { sort: 'last_updated', search: 'feature' }
+ branches_finder = described_class.new(repository, params)
+
+ result = branches_finder.execute
+
+ expect(result.first.name).to eq('feature')
+ expect(result.count).to eq(2)
+ end
+ end
+ end
+end