From 9a250ad6d85678d7f9197a55c69cb724c81008e0 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 6 Jan 2016 11:27:23 +0100 Subject: [PATCH 1/8] Filter commits by search parameter Signed-off-by: Dmitriy Zaporozhets --- app/controllers/projects/commits_controller.rb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb index 04a88990bf4..66e27524a23 100644 --- a/app/controllers/projects/commits_controller.rb +++ b/app/controllers/projects/commits_controller.rb @@ -8,10 +8,16 @@ class Projects::CommitsController < Projects::ApplicationController before_action :authorize_download_code! def show - @repo = @project.repository @limit, @offset = (params[:limit] || 40).to_i, (params[:offset] || 0).to_i + search = params[:search] + + @commits = + if search.present? + @repository.find_commits_by_message(search).compact + else + @repository.commits(@ref, @path, @limit, @offset) + end - @commits = @repo.commits(@ref, @path, @limit, @offset) @note_counts = project.notes.where(commit_id: @commits.map(&:id)). group(:commit_id).count From 5e93f912c3d77e8e22ff563d1701e89b36ddf733 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 6 Jan 2016 11:40:03 +0100 Subject: [PATCH 2/8] Add search field to commits page Signed-off-by: Dmitriy Zaporozhets --- app/assets/stylesheets/pages/commits.scss | 10 +++------- app/views/projects/commits/show.html.haml | 18 ++++++++++++------ 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/app/assets/stylesheets/pages/commits.scss b/app/assets/stylesheets/pages/commits.scss index 879bd287470..800df95cff3 100644 --- a/app/assets/stylesheets/pages/commits.scss +++ b/app/assets/stylesheets/pages/commits.scss @@ -28,10 +28,6 @@ } } -.commits-feed-holder { - float: right; -} - li.commit { list-style: none; @@ -126,14 +122,14 @@ li.commit { .divergence-graph { padding: 12px 12px 0 0; float: right; - + .graph-side { position: relative; width: 80px; height: 22px; padding: 5px 0 13px; float: left; - + .bar { position: absolute; height: 4px; @@ -149,7 +145,7 @@ li.commit { left: 0; border-radius: 0 3px 3px 0; } - + .count { padding-top: 6px; padding-bottom: 0px; diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml index 2dd99cc8215..0d652a832f5 100644 --- a/app/views/projects/commits/show.html.haml +++ b/app/views/projects/commits/show.html.haml @@ -10,15 +10,21 @@ .tree-ref-holder = render 'shared/ref_switcher', destination: 'commits' - .commits-feed-holder.hidden-xs.hidden-sm + .pull-right.hidden-xs.hidden-sm - if create_mr_button?(@repository.root_ref, @ref) - = link_to create_mr_path(@repository.root_ref, @ref), class: 'btn btn-success' do - = icon('plus') - Create Merge Request + .pull-left.prepend-left-10 + = link_to create_mr_path(@repository.root_ref, @ref), class: 'btn btn-success' do + = icon('plus') + Create Merge Request + + .pull-left.prepend-left-10 + = form_tag(namespace_project_commits_path(@project.namespace, @project, @ref), method: :get, class: 'pull-left commits-search-form') do + = search_field_tag :search, params[:search], { placeholder: 'Filter by commit message', class: 'form-control search-text-input', spellcheck: false } - if current_user && current_user.private_token - = link_to namespace_project_commits_path(@project.namespace, @project, @ref, {format: :atom, private_token: current_user.private_token}), title: "Commits Feed", class: 'prepend-left-10 btn' do - = icon("rss") + .pull-left.prepend-left-10 + = link_to namespace_project_commits_path(@project.namespace, @project, @ref, {format: :atom, private_token: current_user.private_token}), title: "Commits Feed", class: 'btn' do + = icon("rss") %ul.breadcrumb.repo-breadcrumb From d1a40e06cc34a83f196345635e5b5ed16685ab62 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 6 Jan 2016 12:58:15 +0100 Subject: [PATCH 3/8] Add ajax filtering for commits list Also handle commits list with Pager class to prevent code duplication Signed-off-by: Dmitriy Zaporozhets --- app/assets/javascripts/commits.js.coffee | 67 +++++++++-------------- app/views/projects/commits/show.html.haml | 10 ++-- 2 files changed, 31 insertions(+), 46 deletions(-) diff --git a/app/assets/javascripts/commits.js.coffee b/app/assets/javascripts/commits.js.coffee index c183e78e513..2d33e0f6ebe 100644 --- a/app/assets/javascripts/commits.js.coffee +++ b/app/assets/javascripts/commits.js.coffee @@ -1,15 +1,5 @@ class @CommitsList - @data = - ref: null - limit: 0 - offset: 0 - @disable = false - - @showProgress: -> - $('.loading').show() - - @hideProgress: -> - $('.loading').hide() + @timer = null @init: (ref, limit) -> $("body").on "click", ".day-commits-table li.commit", (event) -> @@ -18,38 +8,35 @@ class @CommitsList e.stopPropagation() return false - @data.ref = ref - @data.limit = limit - @data.offset = limit + Pager.init limit, true - this.initLoadMore() - this.showProgress() + @content = $("#commits-list") + @searchField = $("#commits-search") + @initSearch() + + @initSearch: -> + @timer = null + @searchField.keyup => + clearTimeout(@timer) + @timer = setTimeout(@filterResults, 500) + + @filterResults: => + form = $(".commits-search-form") + search = @searchField.val() + commitsUrl = form.attr("action") + '?' + form.serialize() + @setOpacitiy("0.5") - @getOld: -> - this.showProgress() $.ajax type: "GET" - url: location.href - data: @data - complete: this.hideProgress - success: (data) -> - CommitsList.append(data.count, data.html) + url: form.attr("action") + data: form.serialize() + complete: => + @setOpacitiy("1.0") + success: (data) => + @content.html(data.html) + # Change url so if user reload a page - search results are saved + history.replaceState {page: commitsUrl}, document.title, commitsUrl dataType: "json" - @append: (count, html) -> - $("#commits-list").append(html) - if count > 0 - @data.offset += count - else - @disable = true - - @initLoadMore: -> - $(document).unbind('scroll') - $(document).endlessScroll - bottomPixels: 400 - fireDelay: 1000 - fireOnce: true - ceaseFire: => - @disable - callback: => - this.getOld() + @setOpacitiy: (opacity) -> + @content.css("opacity", opacity) diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml index 0d652a832f5..5e59afcd783 100644 --- a/app/views/projects/commits/show.html.haml +++ b/app/views/projects/commits/show.html.haml @@ -19,7 +19,7 @@ .pull-left.prepend-left-10 = form_tag(namespace_project_commits_path(@project.namespace, @project, @ref), method: :get, class: 'pull-left commits-search-form') do - = search_field_tag :search, params[:search], { placeholder: 'Filter by commit message', class: 'form-control search-text-input', spellcheck: false } + = search_field_tag :search, params[:search], { placeholder: 'Filter by commit message', id: 'commits-search', class: 'form-control search-text-input', spellcheck: false } - if current_user && current_user.private_token .pull-left.prepend-left-10 @@ -31,11 +31,9 @@ = commits_breadcrumbs %div{id: dom_id(@project)} - #commits-list= render "commits", project: @project + #commits-list.content_list= render "commits", project: @project .clear = spinner -- if @commits.count == @limit - :javascript - CommitsList.init("#{@ref}", #{@limit}); - +:javascript + CommitsList.init("#{@ref}", #{@limit}); From 0456855911448bca5996428283e0c3e9b2d27c3b Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Wed, 6 Jan 2016 17:12:25 +0100 Subject: [PATCH 4/8] Add CHANGELOG item and tests Signed-off-by: Dmitriy Zaporozhets --- CHANGELOG | 1 + features/project/commits/commits.feature | 5 +++++ features/steps/project/commits/commits.rb | 9 +++++++++ 3 files changed, 15 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 94a776a35eb..879d057fff0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -23,6 +23,7 @@ v 8.4.0 (unreleased) - Validate README format before displaying - Enable Microsoft Azure OAuth2 support (Janis Meybohm) - Add file finder feature in tree view (koreamic) + - Ajax filter by message for commits page v 8.3.3 (unreleased) - Get "Merge when build succeeds" to work when commits were pushed to MR target branch while builds were running diff --git a/features/project/commits/commits.feature b/features/project/commits/commits.feature index 5bb2d0e976b..01c10721312 100644 --- a/features/project/commits/commits.feature +++ b/features/project/commits/commits.feature @@ -55,3 +55,8 @@ Feature: Project Commits Scenario: I browse a commit with an image Given I visit a commit with an image that changed Then The diff links to both the previous and current image + + @javascript + Scenario: I filter commits by message + When I search "submodules" commits + Then I should see only "submodules" commits diff --git a/features/steps/project/commits/commits.rb b/features/steps/project/commits/commits.rb index a3141fe3be1..daf6cdaaac8 100644 --- a/features/steps/project/commits/commits.rb +++ b/features/steps/project/commits/commits.rb @@ -124,4 +124,13 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps expect(page).to have_content "build: pending" expect(page).to have_content "1 build" end + + step 'I search "submodules" commits' do + fill_in 'commits-search', with: 'submodules' + end + + step 'I should see only "submodules" commits' do + expect(page).to have_content "More submodules" + expect(page).not_to have_content "Change some files" + end end From b2b4e9a7eb925bec2a09e44940cab31199f1de5c Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 7 Jan 2016 12:38:35 +0100 Subject: [PATCH 5/8] Prevent loading first 20 commits twice Signed-off-by: Dmitriy Zaporozhets --- app/assets/javascripts/commits.js.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/commits.js.coffee b/app/assets/javascripts/commits.js.coffee index 2d33e0f6ebe..bddcf83d4dd 100644 --- a/app/assets/javascripts/commits.js.coffee +++ b/app/assets/javascripts/commits.js.coffee @@ -8,7 +8,7 @@ class @CommitsList e.stopPropagation() return false - Pager.init limit, true + Pager.init limit, false @content = $("#commits-list") @searchField = $("#commits-search") @@ -24,14 +24,14 @@ class @CommitsList form = $(".commits-search-form") search = @searchField.val() commitsUrl = form.attr("action") + '?' + form.serialize() - @setOpacitiy("0.5") + @setOpacitiy(0.5) $.ajax type: "GET" url: form.attr("action") data: form.serialize() complete: => - @setOpacitiy("1.0") + @setOpacitiy(1.0) success: (data) => @content.html(data.html) # Change url so if user reload a page - search results are saved From 4443a5f3c76015f7bf083248b6910d01839cfc88 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 7 Jan 2016 13:00:47 +0100 Subject: [PATCH 6/8] Add support for ref and path to commits filtering Signed-off-by: Dmitriy Zaporozhets --- .../projects/commits_controller.rb | 2 +- app/models/repository.rb | 21 +++++++++++-------- app/views/projects/commits/show.html.haml | 2 +- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/app/controllers/projects/commits_controller.rb b/app/controllers/projects/commits_controller.rb index 66e27524a23..bf5b54c8cb7 100644 --- a/app/controllers/projects/commits_controller.rb +++ b/app/controllers/projects/commits_controller.rb @@ -13,7 +13,7 @@ class Projects::CommitsController < Projects::ApplicationController @commits = if search.present? - @repository.find_commits_by_message(search).compact + @repository.find_commits_by_message(search, @ref, @path, @limit, @offset).compact else @repository.commits(@ref, @path, @limit, @offset) end diff --git a/app/models/repository.rb b/app/models/repository.rb index 9deb08d93b8..d9ff71c01ed 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -92,9 +92,12 @@ class Repository commits end - def find_commits_by_message(query) + def find_commits_by_message(query, ref = nil, path = nil, limit = 1000, offset = 0) + ref ||= root_ref + # Limited to 1000 commits for now, could be parameterized? - args = %W(#{Gitlab.config.git.bin_path} log --pretty=%H --max-count 1000 --grep=#{query}) + args = %W(#{Gitlab.config.git.bin_path} log #{ref} --pretty=%H --skip #{offset} --max-count #{limit} --grep=#{query}) + args = args.concat(%W(-- #{path})) if path.present? git_log_results = Gitlab::Popen.popen(args, path_to_repo).first.lines.map(&:chomp) commits = git_log_results.map { |c| commit(c) } @@ -175,7 +178,7 @@ class Repository def size cache.fetch(:size) { raw_repository.size } end - + def diverging_commit_counts(branch) root_ref_hash = raw_repository.rev_parse_target(root_ref).oid cache.fetch(:"diverging_commit_counts_#{branch.name}") do @@ -183,7 +186,7 @@ class Repository # than SHA-1 hashes number_commits_behind = commits_between(branch.target, root_ref_hash).size number_commits_ahead = commits_between(root_ref_hash, branch.target).size - + { behind: number_commits_behind, ahead: number_commits_ahead } end end @@ -192,7 +195,7 @@ class Repository %i(size branch_names tag_names commit_count readme version contribution_guide changelog license) end - + def branch_cache_keys branches.map do |branch| :"diverging_commit_counts_#{branch.name}" @@ -205,7 +208,7 @@ class Repository send(key) end end - + branches.each do |branch| unless cache.exist?(:"diverging_commit_counts_#{branch.name}") send(:diverging_commit_counts, branch) @@ -227,10 +230,10 @@ class Repository cache_keys.each do |key| cache.expire(key) end - + expire_branch_cache end - + def expire_branch_cache branches.each do |branch| cache.expire(:"diverging_commit_counts_#{branch.name}") @@ -242,7 +245,7 @@ class Repository cache.expire(key) send(key) end - + branches.each do |branch| cache.expire(:"diverging_commit_counts_#{branch.name}") diverging_commit_counts(branch) diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml index 5e59afcd783..8f6625fef8a 100644 --- a/app/views/projects/commits/show.html.haml +++ b/app/views/projects/commits/show.html.haml @@ -18,7 +18,7 @@ Create Merge Request .pull-left.prepend-left-10 - = form_tag(namespace_project_commits_path(@project.namespace, @project, @ref), method: :get, class: 'pull-left commits-search-form') do + = form_tag(namespace_project_commits_path(@project.namespace, @project, @id), method: :get, class: 'pull-left commits-search-form') do = search_field_tag :search, params[:search], { placeholder: 'Filter by commit message', id: 'commits-search', class: 'form-control search-text-input', spellcheck: false } - if current_user && current_user.private_token From 44dc9aa69e19d90564fdb279f9e8d51b5caf2cae Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 7 Jan 2016 13:04:25 +0100 Subject: [PATCH 7/8] Fix typo in js method and some repeating css Signed-off-by: Dmitriy Zaporozhets --- app/assets/javascripts/commits.js.coffee | 6 +++--- app/assets/stylesheets/framework/blocks.scss | 9 +++++++++ app/views/projects/commits/show.html.haml | 8 ++++---- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/app/assets/javascripts/commits.js.coffee b/app/assets/javascripts/commits.js.coffee index bddcf83d4dd..c337038e446 100644 --- a/app/assets/javascripts/commits.js.coffee +++ b/app/assets/javascripts/commits.js.coffee @@ -24,19 +24,19 @@ class @CommitsList form = $(".commits-search-form") search = @searchField.val() commitsUrl = form.attr("action") + '?' + form.serialize() - @setOpacitiy(0.5) + @setOpacity(0.5) $.ajax type: "GET" url: form.attr("action") data: form.serialize() complete: => - @setOpacitiy(1.0) + @setOpacity(1.0) success: (data) => @content.html(data.html) # Change url so if user reload a page - search results are saved history.replaceState {page: commitsUrl}, document.title, commitsUrl dataType: "json" - @setOpacitiy: (opacity) -> + @setOpacity: (opacity) -> @content.css("opacity", opacity) diff --git a/app/assets/stylesheets/framework/blocks.scss b/app/assets/stylesheets/framework/blocks.scss index 206d39cc9b3..fa0e70847f3 100644 --- a/app/assets/stylesheets/framework/blocks.scss +++ b/app/assets/stylesheets/framework/blocks.scss @@ -72,6 +72,15 @@ > p:last-child { margin-bottom: 0; } + + .block-controls { + float: right; + + .control { + float: left; + margin-left: 10px; + } + } } .cover-block { diff --git a/app/views/projects/commits/show.html.haml b/app/views/projects/commits/show.html.haml index 8f6625fef8a..034057da42e 100644 --- a/app/views/projects/commits/show.html.haml +++ b/app/views/projects/commits/show.html.haml @@ -10,19 +10,19 @@ .tree-ref-holder = render 'shared/ref_switcher', destination: 'commits' - .pull-right.hidden-xs.hidden-sm + .block-controls.hidden-xs.hidden-sm - if create_mr_button?(@repository.root_ref, @ref) - .pull-left.prepend-left-10 + .control = link_to create_mr_path(@repository.root_ref, @ref), class: 'btn btn-success' do = icon('plus') Create Merge Request - .pull-left.prepend-left-10 + .control = form_tag(namespace_project_commits_path(@project.namespace, @project, @id), method: :get, class: 'pull-left commits-search-form') do = search_field_tag :search, params[:search], { placeholder: 'Filter by commit message', id: 'commits-search', class: 'form-control search-text-input', spellcheck: false } - if current_user && current_user.private_token - .pull-left.prepend-left-10 + .control = link_to namespace_project_commits_path(@project.namespace, @project, @ref, {format: :atom, private_token: current_user.private_token}), title: "Commits Feed", class: 'btn' do = icon("rss") From c7fc84f5162f58d1f643beaf88196a3333c75980 Mon Sep 17 00:00:00 2001 From: Dmitriy Zaporozhets Date: Thu, 7 Jan 2016 15:15:21 +0100 Subject: [PATCH 8/8] Use fadeTo instead of css Signed-off-by: Dmitriy Zaporozhets --- app/assets/javascripts/commits.js.coffee | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/app/assets/javascripts/commits.js.coffee b/app/assets/javascripts/commits.js.coffee index c337038e446..ffd3627b1b0 100644 --- a/app/assets/javascripts/commits.js.coffee +++ b/app/assets/javascripts/commits.js.coffee @@ -24,19 +24,16 @@ class @CommitsList form = $(".commits-search-form") search = @searchField.val() commitsUrl = form.attr("action") + '?' + form.serialize() - @setOpacity(0.5) + @content.fadeTo('fast', 0.5) $.ajax type: "GET" url: form.attr("action") data: form.serialize() complete: => - @setOpacity(1.0) + @content.fadeTo('fast', 1.0) success: (data) => @content.html(data.html) # Change url so if user reload a page - search results are saved history.replaceState {page: commitsUrl}, document.title, commitsUrl dataType: "json" - - @setOpacity: (opacity) -> - @content.css("opacity", opacity)