Merge branch 'ajax-filter-commits' into 'master'
Ajax filter commits Fixes #3509 ![Screenshot_2016-01-06_13.07.53](/uploads/7400d855d8207e37e3c0ec09cb2265e9/Screenshot_2016-01-06_13.07.53.png) See merge request !2314
This commit is contained in:
commit
0d59e7b90f
|
@ -23,6 +23,7 @@ v 8.4.0 (unreleased)
|
||||||
- Validate README format before displaying
|
- Validate README format before displaying
|
||||||
- Enable Microsoft Azure OAuth2 support (Janis Meybohm)
|
- Enable Microsoft Azure OAuth2 support (Janis Meybohm)
|
||||||
- Add file finder feature in tree view (koreamic)
|
- Add file finder feature in tree view (koreamic)
|
||||||
|
- Ajax filter by message for commits page
|
||||||
|
|
||||||
v 8.3.3 (unreleased)
|
v 8.3.3 (unreleased)
|
||||||
- Get "Merge when build succeeds" to work when commits were pushed to MR target branch while builds were running
|
- Get "Merge when build succeeds" to work when commits were pushed to MR target branch while builds were running
|
||||||
|
|
|
@ -1,15 +1,5 @@
|
||||||
class @CommitsList
|
class @CommitsList
|
||||||
@data =
|
@timer = null
|
||||||
ref: null
|
|
||||||
limit: 0
|
|
||||||
offset: 0
|
|
||||||
@disable = false
|
|
||||||
|
|
||||||
@showProgress: ->
|
|
||||||
$('.loading').show()
|
|
||||||
|
|
||||||
@hideProgress: ->
|
|
||||||
$('.loading').hide()
|
|
||||||
|
|
||||||
@init: (ref, limit) ->
|
@init: (ref, limit) ->
|
||||||
$("body").on "click", ".day-commits-table li.commit", (event) ->
|
$("body").on "click", ".day-commits-table li.commit", (event) ->
|
||||||
|
@ -18,38 +8,32 @@ class @CommitsList
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
return false
|
return false
|
||||||
|
|
||||||
@data.ref = ref
|
Pager.init limit, false
|
||||||
@data.limit = limit
|
|
||||||
@data.offset = limit
|
|
||||||
|
|
||||||
this.initLoadMore()
|
@content = $("#commits-list")
|
||||||
this.showProgress()
|
@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()
|
||||||
|
@content.fadeTo('fast', 0.5)
|
||||||
|
|
||||||
@getOld: ->
|
|
||||||
this.showProgress()
|
|
||||||
$.ajax
|
$.ajax
|
||||||
type: "GET"
|
type: "GET"
|
||||||
url: location.href
|
url: form.attr("action")
|
||||||
data: @data
|
data: form.serialize()
|
||||||
complete: this.hideProgress
|
complete: =>
|
||||||
success: (data) ->
|
@content.fadeTo('fast', 1.0)
|
||||||
CommitsList.append(data.count, data.html)
|
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"
|
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()
|
|
||||||
|
|
|
@ -72,6 +72,15 @@
|
||||||
> p:last-child {
|
> p:last-child {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.block-controls {
|
||||||
|
float: right;
|
||||||
|
|
||||||
|
.control {
|
||||||
|
float: left;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.cover-block {
|
.cover-block {
|
||||||
|
|
|
@ -28,10 +28,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.commits-feed-holder {
|
|
||||||
float: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
li.commit {
|
li.commit {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
|
|
||||||
|
@ -126,14 +122,14 @@ li.commit {
|
||||||
.divergence-graph {
|
.divergence-graph {
|
||||||
padding: 12px 12px 0 0;
|
padding: 12px 12px 0 0;
|
||||||
float: right;
|
float: right;
|
||||||
|
|
||||||
.graph-side {
|
.graph-side {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 80px;
|
width: 80px;
|
||||||
height: 22px;
|
height: 22px;
|
||||||
padding: 5px 0 13px;
|
padding: 5px 0 13px;
|
||||||
float: left;
|
float: left;
|
||||||
|
|
||||||
.bar {
|
.bar {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
height: 4px;
|
height: 4px;
|
||||||
|
@ -149,7 +145,7 @@ li.commit {
|
||||||
left: 0;
|
left: 0;
|
||||||
border-radius: 0 3px 3px 0;
|
border-radius: 0 3px 3px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.count {
|
.count {
|
||||||
padding-top: 6px;
|
padding-top: 6px;
|
||||||
padding-bottom: 0px;
|
padding-bottom: 0px;
|
||||||
|
|
|
@ -8,10 +8,16 @@ class Projects::CommitsController < Projects::ApplicationController
|
||||||
before_action :authorize_download_code!
|
before_action :authorize_download_code!
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@repo = @project.repository
|
|
||||||
@limit, @offset = (params[:limit] || 40).to_i, (params[:offset] || 0).to_i
|
@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, @ref, @path, @limit, @offset).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)).
|
@note_counts = project.notes.where(commit_id: @commits.map(&:id)).
|
||||||
group(:commit_id).count
|
group(:commit_id).count
|
||||||
|
|
||||||
|
|
|
@ -92,9 +92,12 @@ class Repository
|
||||||
commits
|
commits
|
||||||
end
|
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?
|
# 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)
|
git_log_results = Gitlab::Popen.popen(args, path_to_repo).first.lines.map(&:chomp)
|
||||||
commits = git_log_results.map { |c| commit(c) }
|
commits = git_log_results.map { |c| commit(c) }
|
||||||
|
@ -175,7 +178,7 @@ class Repository
|
||||||
def size
|
def size
|
||||||
cache.fetch(:size) { raw_repository.size }
|
cache.fetch(:size) { raw_repository.size }
|
||||||
end
|
end
|
||||||
|
|
||||||
def diverging_commit_counts(branch)
|
def diverging_commit_counts(branch)
|
||||||
root_ref_hash = raw_repository.rev_parse_target(root_ref).oid
|
root_ref_hash = raw_repository.rev_parse_target(root_ref).oid
|
||||||
cache.fetch(:"diverging_commit_counts_#{branch.name}") do
|
cache.fetch(:"diverging_commit_counts_#{branch.name}") do
|
||||||
|
@ -183,7 +186,7 @@ class Repository
|
||||||
# than SHA-1 hashes
|
# than SHA-1 hashes
|
||||||
number_commits_behind = commits_between(branch.target, root_ref_hash).size
|
number_commits_behind = commits_between(branch.target, root_ref_hash).size
|
||||||
number_commits_ahead = commits_between(root_ref_hash, branch.target).size
|
number_commits_ahead = commits_between(root_ref_hash, branch.target).size
|
||||||
|
|
||||||
{ behind: number_commits_behind, ahead: number_commits_ahead }
|
{ behind: number_commits_behind, ahead: number_commits_ahead }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -192,7 +195,7 @@ class Repository
|
||||||
%i(size branch_names tag_names commit_count
|
%i(size branch_names tag_names commit_count
|
||||||
readme version contribution_guide changelog license)
|
readme version contribution_guide changelog license)
|
||||||
end
|
end
|
||||||
|
|
||||||
def branch_cache_keys
|
def branch_cache_keys
|
||||||
branches.map do |branch|
|
branches.map do |branch|
|
||||||
:"diverging_commit_counts_#{branch.name}"
|
:"diverging_commit_counts_#{branch.name}"
|
||||||
|
@ -205,7 +208,7 @@ class Repository
|
||||||
send(key)
|
send(key)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
branches.each do |branch|
|
branches.each do |branch|
|
||||||
unless cache.exist?(:"diverging_commit_counts_#{branch.name}")
|
unless cache.exist?(:"diverging_commit_counts_#{branch.name}")
|
||||||
send(:diverging_commit_counts, branch)
|
send(:diverging_commit_counts, branch)
|
||||||
|
@ -227,10 +230,10 @@ class Repository
|
||||||
cache_keys.each do |key|
|
cache_keys.each do |key|
|
||||||
cache.expire(key)
|
cache.expire(key)
|
||||||
end
|
end
|
||||||
|
|
||||||
expire_branch_cache
|
expire_branch_cache
|
||||||
end
|
end
|
||||||
|
|
||||||
def expire_branch_cache
|
def expire_branch_cache
|
||||||
branches.each do |branch|
|
branches.each do |branch|
|
||||||
cache.expire(:"diverging_commit_counts_#{branch.name}")
|
cache.expire(:"diverging_commit_counts_#{branch.name}")
|
||||||
|
@ -242,7 +245,7 @@ class Repository
|
||||||
cache.expire(key)
|
cache.expire(key)
|
||||||
send(key)
|
send(key)
|
||||||
end
|
end
|
||||||
|
|
||||||
branches.each do |branch|
|
branches.each do |branch|
|
||||||
cache.expire(:"diverging_commit_counts_#{branch.name}")
|
cache.expire(:"diverging_commit_counts_#{branch.name}")
|
||||||
diverging_commit_counts(branch)
|
diverging_commit_counts(branch)
|
||||||
|
|
|
@ -10,26 +10,30 @@
|
||||||
.tree-ref-holder
|
.tree-ref-holder
|
||||||
= render 'shared/ref_switcher', destination: 'commits'
|
= render 'shared/ref_switcher', destination: 'commits'
|
||||||
|
|
||||||
.commits-feed-holder.hidden-xs.hidden-sm
|
.block-controls.hidden-xs.hidden-sm
|
||||||
- if create_mr_button?(@repository.root_ref, @ref)
|
- if create_mr_button?(@repository.root_ref, @ref)
|
||||||
= link_to create_mr_path(@repository.root_ref, @ref), class: 'btn btn-success' do
|
.control
|
||||||
= icon('plus')
|
= link_to create_mr_path(@repository.root_ref, @ref), class: 'btn btn-success' do
|
||||||
Create Merge Request
|
= icon('plus')
|
||||||
|
Create Merge Request
|
||||||
|
|
||||||
|
.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
|
- 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
|
.control
|
||||||
= icon("rss")
|
= 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
|
%ul.breadcrumb.repo-breadcrumb
|
||||||
= commits_breadcrumbs
|
= commits_breadcrumbs
|
||||||
|
|
||||||
%div{id: dom_id(@project)}
|
%div{id: dom_id(@project)}
|
||||||
#commits-list= render "commits", project: @project
|
#commits-list.content_list= render "commits", project: @project
|
||||||
.clear
|
.clear
|
||||||
= spinner
|
= spinner
|
||||||
|
|
||||||
- if @commits.count == @limit
|
:javascript
|
||||||
:javascript
|
CommitsList.init("#{@ref}", #{@limit});
|
||||||
CommitsList.init("#{@ref}", #{@limit});
|
|
||||||
|
|
||||||
|
|
|
@ -55,3 +55,8 @@ Feature: Project Commits
|
||||||
Scenario: I browse a commit with an image
|
Scenario: I browse a commit with an image
|
||||||
Given I visit a commit with an image that changed
|
Given I visit a commit with an image that changed
|
||||||
Then The diff links to both the previous and current image
|
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
|
||||||
|
|
|
@ -124,4 +124,13 @@ class Spinach::Features::ProjectCommits < Spinach::FeatureSteps
|
||||||
expect(page).to have_content "build: pending"
|
expect(page).to have_content "build: pending"
|
||||||
expect(page).to have_content "1 build"
|
expect(page).to have_content "1 build"
|
||||||
end
|
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
|
end
|
||||||
|
|
Loading…
Reference in New Issue