Skip to content
Snippets Groups Projects
Commit 67948368 authored by Alfredo Sumaran's avatar Alfredo Sumaran
Browse files

Merge branch 'master' into sidebar-sizing-higher-viewport

parents 60801262 7c809985
No related branches found
No related tags found
No related merge requests found
Showing
with 346 additions and 34 deletions
Loading
Loading
@@ -9,6 +9,7 @@ module MergeRequests
event_service.close_mr(merge_request, current_user)
create_note(merge_request)
notification_service.close_mr(merge_request, current_user)
todo_service.close_merge_request(merge_request, current_user)
execute_hooks(merge_request, 'close')
end
 
Loading
Loading
Loading
Loading
@@ -2,7 +2,7 @@ module MergeRequests
class CreateService < MergeRequests::BaseService
def execute
# @project is used to determine whether the user can set the merge request's
# assignee, milestone and labels. Whether they can depends on their
# assignee, milestone and labels. Whether they can depends on their
# permissions on the target project.
source_project = @project
@project = Project.find(params[:target_project_id]) if params[:target_project_id]
Loading
Loading
@@ -18,6 +18,7 @@ module MergeRequests
merge_request.update_attributes(label_ids: label_params)
event_service.open_mr(merge_request, current_user)
notification_service.new_merge_request(merge_request, current_user)
todo_service.new_merge_request(merge_request, current_user)
merge_request.create_cross_references!(current_user)
execute_hooks(merge_request)
end
Loading
Loading
Loading
Loading
@@ -34,7 +34,8 @@ module MergeRequests
committer: committer
}
 
repository.merge(current_user, merge_request.source_sha, merge_request.target_branch, options)
commit_id = repository.merge(current_user, merge_request.source_sha, merge_request.target_branch, options)
merge_request.update(merge_commit_sha: commit_id)
rescue StandardError => e
merge_request.update(merge_error: "Something went wrong during merge")
Rails.logger.error(e.message)
Loading
Loading
Loading
Loading
@@ -19,15 +19,19 @@ module MergeRequests
end
 
# Triggers the automatic merge of merge_request once the build succeeds
def trigger(build)
merge_requests = merge_request_from(build)
def trigger(commit_status)
merge_requests = merge_request_from(commit_status)
 
merge_requests.each do |merge_request|
next unless merge_request.merge_when_build_succeeds?
next unless merge_request.mergeable?
 
if merge_request.ci_commit && merge_request.ci_commit.success? && merge_request.mergeable?
MergeWorker.perform_async(merge_request.id, merge_request.merge_user_id, merge_request.merge_params)
end
ci_commit = merge_request.ci_commit
next unless ci_commit
next unless ci_commit.sha == commit_status.sha
next unless ci_commit.success?
MergeWorker.perform_async(merge_request.id, merge_request.merge_user_id, merge_request.merge_params)
end
end
 
Loading
Loading
@@ -45,9 +49,16 @@ module MergeRequests
 
private
 
def merge_request_from(build)
merge_requests = @project.origin_merge_requests.opened.where(source_branch: build.ref).to_a
merge_requests += @project.fork_merge_requests.opened.where(source_branch: build.ref).to_a
def merge_request_from(commit_status)
branches = commit_status.ref
# This is for ref-less builds
branches ||= @project.repository.branch_names_contains(commit_status.sha)
return [] if branches.blank?
merge_requests = @project.origin_merge_requests.opened.where(source_branch: branches).to_a
merge_requests += @project.fork_merge_requests.opened.where(source_branch: branches).to_a
 
merge_requests.uniq.select(&:source_project)
end
Loading
Loading
Loading
Loading
@@ -14,7 +14,16 @@ module MergeRequests
update(merge_request)
end
 
def handle_changes(merge_request)
def handle_changes(merge_request, options = {})
if has_changes?(merge_request, options)
todo_service.mark_pending_todos_as_done(merge_request, current_user)
end
if merge_request.previous_changes.include?('title') ||
merge_request.previous_changes.include?('description')
todo_service.update_merge_request(merge_request, current_user)
end
if merge_request.previous_changes.include?('target_branch')
create_branch_change_note(merge_request, 'target',
merge_request.previous_changes['target_branch'].first,
Loading
Loading
@@ -28,6 +37,7 @@ module MergeRequests
if merge_request.previous_changes.include?('assignee_id')
create_assignee_note(merge_request)
notification_service.reassigned_merge_request(merge_request, current_user)
todo_service.reassigned_merge_request(merge_request, current_user)
end
 
if merge_request.previous_changes.include?('target_branch') ||
Loading
Loading
Loading
Loading
@@ -8,6 +8,7 @@ module Notes
if note.save
# Finish the harder work in the background
NewNoteWorker.perform_in(2.seconds, note.id, params)
TodoService.new.new_note(note, current_user)
end
 
note
Loading
Loading
module Notes
class PostProcessService
attr_accessor :note
 
def initialize(note)
Loading
Loading
@@ -25,6 +24,5 @@ module Notes
@note.project.execute_hooks(note_data, :note_hooks)
@note.project.execute_services(note_data, :note_hooks)
end
end
end
Loading
Loading
@@ -7,6 +7,10 @@ module Notes
note.create_new_cross_references!(current_user)
note.reset_events_cache
 
if note.previous_changes.include?('note')
TodoService.new.update_note(note, current_user)
end
note
end
end
Loading
Loading
Loading
Loading
@@ -16,11 +16,15 @@ module Projects
return false unless can?(current_user, :remove_project, project)
 
project.team.truncate
project.repository.expire_cache unless project.empty_repo?
 
repo_path = project.path_with_namespace
wiki_path = repo_path + '.wiki'
 
# Flush the cache for both repositories. This has to be done _before_
# removing the physical repositories as some expiration code depends on
# Git data (e.g. a list of branch names).
flush_caches(project, wiki_path)
Project.transaction do
project.destroy!
 
Loading
Loading
@@ -70,5 +74,13 @@ module Projects
def removal_path(path)
"#{path}+#{project.id}#{DELETED_FLAG}"
end
def flush_caches(project, wiki_path)
project.repository.expire_all_caches! if project.repository.exists?
wiki_repo = Repository.new(wiki_path, project)
wiki_repo.expire_all_caches! if wiki_repo.exists?
end
end
end
# TodoService class
#
# Used for creating todos after certain user actions
#
# Ex.
# TodoService.new.new_issue(issue, current_user)
#
class TodoService
# When create an issue we should:
#
# * create a todo for assignee if issue is assigned
# * create a todo for each mentioned user on issue
#
def new_issue(issue, current_user)
new_issuable(issue, current_user)
end
# When update an issue we should:
#
# * mark all pending todos related to the issue for the current user as done
#
def update_issue(issue, current_user)
create_mention_todos(issue.project, issue, current_user)
end
# When close an issue we should:
#
# * mark all pending todos related to the target for the current user as done
#
def close_issue(issue, current_user)
mark_pending_todos_as_done(issue, current_user)
end
# When we reassign an issue we should:
#
# * create a pending todo for new assignee if issue is assigned
#
def reassigned_issue(issue, current_user)
create_assignment_todo(issue, current_user)
end
# When create a merge request we should:
#
# * creates a pending todo for assignee if merge request is assigned
# * create a todo for each mentioned user on merge request
#
def new_merge_request(merge_request, current_user)
new_issuable(merge_request, current_user)
end
# When update a merge request we should:
#
# * create a todo for each mentioned user on merge request
#
def update_merge_request(merge_request, current_user)
create_mention_todos(merge_request.project, merge_request, current_user)
end
# When close a merge request we should:
#
# * mark all pending todos related to the target for the current user as done
#
def close_merge_request(merge_request, current_user)
mark_pending_todos_as_done(merge_request, current_user)
end
# When we reassign a merge request we should:
#
# * creates a pending todo for new assignee if merge request is assigned
#
def reassigned_merge_request(merge_request, current_user)
create_assignment_todo(merge_request, current_user)
end
# When merge a merge request we should:
#
# * mark all pending todos related to the target for the current user as done
#
def merge_merge_request(merge_request, current_user)
mark_pending_todos_as_done(merge_request, current_user)
end
# When create a note we should:
#
# * mark all pending todos related to the noteable for the note author as done
# * create a todo for each mentioned user on note
#
def new_note(note, current_user)
handle_note(note, current_user)
end
# When update a note we should:
#
# * mark all pending todos related to the noteable for the current user as done
# * create a todo for each new user mentioned on note
#
def update_note(note, current_user)
handle_note(note, current_user)
end
# When marking pending todos as done we should:
#
# * mark all pending todos related to the target for the current user as done
#
def mark_pending_todos_as_done(target, user)
pending_todos(user, target.project, target).update_all(state: :done)
end
private
def create_todos(project, target, author, users, action, note = nil)
Array(users).each do |user|
next if pending_todos(user, project, target).exists?
Todo.create(
project: project,
user_id: user.id,
author_id: author.id,
target_id: target.id,
target_type: target.class.name,
action: action,
note: note
)
end
end
def new_issuable(issuable, author)
create_assignment_todo(issuable, author)
create_mention_todos(issuable.project, issuable, author)
end
def handle_note(note, author)
# Skip system notes, like status changes and cross-references
return if note.system
project = note.project
target = note.noteable
mark_pending_todos_as_done(target, author)
create_mention_todos(project, target, author, note)
end
def create_assignment_todo(issuable, author)
if issuable.assignee && issuable.assignee != author
create_todos(issuable.project, issuable, author, issuable.assignee, Todo::ASSIGNED)
end
end
def create_mention_todos(project, issuable, author, note = nil)
mentioned_users = filter_mentioned_users(project, note || issuable, author)
create_todos(project, issuable, author, mentioned_users, Todo::MENTIONED, note)
end
def filter_mentioned_users(project, target, author)
mentioned_users = target.mentioned_users.select do |user|
user.can?(:read_project, project)
end
mentioned_users.delete(author)
mentioned_users.uniq
end
def pending_todos(user, project, target)
user.todos.pending.where(
project_id: project.id,
target_id: target.id,
target_type: target.class.name
)
end
end
Loading
Loading
@@ -11,6 +11,10 @@
= f.label :title, class: 'control-label'
.col-sm-10
= f.text_field :title, class: "form-control", required: true
.form-group
= f.label :description, class: 'control-label'
.col-sm-10
= f.text_field :description, class: "form-control js-quick-submit"
.form-group
= f.label :color, "Background color", class: 'control-label'
.col-sm-10
Loading
Loading
%li{id: dom_id(label)}
= render_colored_label(label)
.pull-right
= link_to 'Edit', edit_admin_label_path(label), class: 'btn btn-sm'
= link_to 'Delete', admin_label_path(label), class: 'btn btn-sm btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Delete this label? Are you sure?"}
.label-row
= render_colored_label(label)
= markdown(label.description, pipeline: :single_line)
.pull-right
= link_to 'Edit', edit_admin_label_path(label), class: 'btn btn-sm'
= link_to 'Delete', admin_label_path(label), class: 'btn btn-sm btn-remove remove-row', method: :delete, remote: true, data: {confirm: "Delete this label? Are you sure?"}
Loading
Loading
@@ -11,7 +11,7 @@
%br
- if current_user.can_create_project?
You can create up to
%strong= pluralize(current_user.projects_limit, "project") + "."
%strong= pluralize(number_with_delimiter(current_user.projects_limit), "project") + "."
- else
If you are added to a project, it will be displayed here.
 
Loading
Loading
@@ -44,7 +44,7 @@
.dashboard-intro-text
%p.slead
There are
%strong= publicish_project_count
%strong= number_with_delimiter(publicish_project_count)
public projects on this server.
%br
Public projects are an easy way to allow everyone to have read-only access.
Loading
Loading
%li{class: "todo todo-#{todo.done? ? 'done' : 'pending'}", id: dom_id(todo) }
.todo-item{class: 'todo-block'}
= image_tag avatar_icon(todo.author_email, 40), class: 'avatar s40', alt:''
.todo-title
%span.author_name
= link_to_author todo
%span.todo_label
= todo_action_name(todo)
= todo_target_link(todo)
&middot; #{time_ago_with_tooltip(todo.created_at)}
- if todo.pending?
.todo-actions.pull-right
= link_to 'Done', [:dashboard, todo], method: :delete, class: 'btn'
.todo-body
.todo-note
.md
= event_note(todo.body, project: todo.project)
- page_title "Todos"
- header_title "Todos", dashboard_todos_path
.top-area
%ul.nav-links
%li{class: ('active' if params[:state].blank? || params[:state] == 'pending')}
= link_to todos_filter_path(state: 'pending') do
%span
To do
%span{class: 'badge'}
= todos_pending_count
%li{class: ('active' if params[:state] == 'done')}
= link_to todos_filter_path(state: 'done') do
%span
Done
%span{class: 'badge'}
= todos_done_count
.nav-controls
- if @todos.any?(&:pending?)
= link_to 'Mark all as done', destroy_all_dashboard_todos_path(todos_filter_params), class: 'btn', method: :delete
.todos-filters
.gray-content-block.second-block
= form_tag todos_filter_path(without: [:project_id, :author_id, :type, :action_id]), method: :get, class: 'filter-form' do
.filter-item.inline
= select_tag('project_id', todo_projects_options,
class: 'select2 trigger-submit', include_blank: true,
data: {placeholder: 'Project'})
.filter-item.inline
= users_select_tag(:author_id, selected: params[:author_id],
placeholder: 'Author', class: 'trigger-submit', any_user: "Any Author", first_user: true, current_user: true)
.filter-item.inline
= select_tag('type', todo_types_options,
class: 'select2 trigger-submit', include_blank: true,
data: {placeholder: 'Type'})
.filter-item.inline.actions-filter
= select_tag('action_id', todo_actions_options,
class: 'select2 trigger-submit', include_blank: true,
data: {placeholder: 'Action'})
.prepend-top-default
- if @todos.any?
- @todos.group_by(&:project).each do |group|
.panel.panel-default.panel-small
- project = group[0]
.panel-heading
= link_to project.name_with_namespace, namespace_project_path(project.namespace, project)
%ul.well-list.todos-list
= render group[1]
= paginate @todos, theme: "gitlab"
- else
.nothing-here-block You're all done!
:javascript
new UsersSelect();
$('form.filter-form').on('submit', function (event) {
event.preventDefault();
Turbolinks.visit(this.action + '&' + $(this).serialize());
});
Loading
Loading
@@ -44,6 +44,7 @@
= favicon_link_tag 'touch-icon-ipad.png', rel: 'apple-touch-icon', sizes: '76x76'
= favicon_link_tag 'touch-icon-iphone-retina.png', rel: 'apple-touch-icon', sizes: '120x120'
= favicon_link_tag 'touch-icon-ipad-retina.png', rel: 'apple-touch-icon', sizes: '152x152'
%link{rel: 'mask-icon', href: image_path('logo.svg'), color: 'rgb(226, 67, 41)'}
 
-# Windows 8 pinned site tile
%meta{name: 'msapplication-TileImage', content: image_path('msapplication-tile.png')}
Loading
Loading
Loading
Loading
@@ -21,6 +21,10 @@
%li
= link_to admin_root_path, title: 'Admin Area', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
= icon('wrench fw')
%li
= link_to dashboard_todos_path, title: 'Todos', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
%span.badge.todos-pending-count
= todos_pending_count
- if current_user.can_create_project?
%li
= link_to new_project_path, title: 'New project', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
Loading
Loading
@@ -39,4 +43,4 @@
= render 'shared/outdated_browser'
- if @project && !@project.empty_repo?
:javascript
var findFileURL = "#{namespace_project_find_file_path(@project.namespace, @project, @ref || @project.repository.root_ref)}";
\ No newline at end of file
var findFileURL = "#{namespace_project_find_file_path(@project.namespace, @project, @ref || @project.repository.root_ref)}";
Loading
Loading
@@ -4,6 +4,12 @@
= icon('home fw')
%span
Projects
= nav_link(controller: :todos) do
= link_to dashboard_todos_path, title: 'Todos' do
= icon('bell fw')
%span
Todos
%span.count= number_with_delimiter(todos_pending_count)
= nav_link(path: 'dashboard#activity') do
= link_to activity_dashboard_path, class: 'shortcuts-activity', title: 'Activity' do
= icon('dashboard fw')
Loading
Loading
@@ -25,12 +31,12 @@
%span
Issues
%span.count= number_with_delimiter(current_user.assigned_issues.opened.count)
= nav_link(path: 'dashboard#merge_requests') do
= link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'shortcuts-merge_requests' do
= icon('tasks fw')
%span
Merge Requests
%span.count= number_with_delimiter(current_user.assigned_merge_requests.opened.count)
= nav_link(path: 'dashboard#merge_requests') do
= link_to assigned_mrs_dashboard_path, title: 'Merge Requests', class: 'shortcuts-merge_requests' do
= icon('tasks fw')
%span
Merge Requests
%span.count= number_with_delimiter(current_user.assigned_merge_requests.opened.count)
= nav_link(controller: :snippets) do
= link_to dashboard_snippets_path, title: 'Snippets' do
= icon('clipboard fw')
Loading
Loading
Loading
Loading
@@ -3,7 +3,12 @@
.project-identicon-holder
= project_icon(@project, alt: '', class: 'project-avatar avatar s90')
.project-home-desc
%h1= @project.name
%h1
= @project.name
%span.visibility-icon.has_tooltip{data: { container: 'body' },
title: "#{visibility_level_label(@project.visibility_level)} - #{project_visibility_level_description(@project.visibility_level)}"}
= visibility_level_icon(@project.visibility_level, fw: false)
- if @project.description.present?
= markdown(@project.description, pipeline: :description)
 
Loading
Loading
@@ -12,10 +17,6 @@
Forked from
= link_to project_path(forked_from_project) do
= forked_from_project.namespace.try(:name)
.cover-controls.left
.visibility-level-label.has_tooltip{title: project_visibility_level_description(@project.visibility_level), data: { container: 'body' } }
= visibility_level_icon(@project.visibility_level, fw: false)
= visibility_level_label(@project.visibility_level)
 
.cover-controls
- if current_user
Loading
Loading
Loading
Loading
@@ -3,7 +3,7 @@
 
%h3.page-title Blame view
 
#tree-holder.tree-holder
#blob-content-holder.tree-holder
.file-holder
.file-title
= blob_icon @blob.mode, @blob.name
Loading
Loading
@@ -33,7 +33,9 @@
%td.line-numbers
- line_count = blame_group[:lines].count
- (current_line...(current_line + line_count)).each do |i|
%a.diff-line-num= i
%a.diff-line-num{href: "#L#{i}", id: "L#{i}", 'data-line-number' => i}
= icon("link")
= i
\
- current_line += line_count
%td.lines
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment