Rename Tasks to Todos
This commit is contained in:
		
							parent
							
								
									408e010d65
								
							
						
					
					
						commit
						3d52e139b1
					
				|  | @ -75,7 +75,7 @@ v 8.5.0 (unreleased) | |||
|   - Emoji comment on diffs are not award emoji | ||||
|   - Add label description (Nuttanart Pornprasitsakul) | ||||
|   - Show label row when filtering issues or merge requests by label (Nuttanart Pornprasitsakul) | ||||
|   - Add Task Queue | ||||
|   - Add Todos | ||||
| 
 | ||||
| v 8.4.4 | ||||
|   - Update omniauth-saml gem to 1.4.2 | ||||
|  |  | |||
|  | @ -1,37 +1,37 @@ | |||
| /** | ||||
|  * Dashboard tasks queue | ||||
|  * Dashboard Todos | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| .navbar-nav { | ||||
|   li { | ||||
|     .badge.tasks-pending-count { | ||||
|     .badge.todos-pending-count { | ||||
|       background-color: #7f8fa4; | ||||
|       margin-top: -5px; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| .tasks { | ||||
| .todos { | ||||
|   .panel { | ||||
|     border-top: none; | ||||
|     margin-bottom: 0; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| .task-item { | ||||
| .todo-item { | ||||
|   font-size: $gl-font-size; | ||||
|   padding: $gl-padding-top 0 $gl-padding-top ($gl-avatar-size + $gl-padding-top); | ||||
|   border-bottom: 1px solid $table-border-color; | ||||
|   color: #7f8fa4; | ||||
| 
 | ||||
|   &.task-inline { | ||||
|   &.todo-inline { | ||||
|     .avatar { | ||||
|       position: relative; | ||||
|       top: -2px; | ||||
|     } | ||||
| 
 | ||||
|     .task-title { | ||||
|     .todo-title { | ||||
|       line-height: 40px; | ||||
|     } | ||||
|   } | ||||
|  | @ -44,7 +44,7 @@ | |||
|     margin-left: -($gl-avatar-size + $gl-padding-top); | ||||
|   } | ||||
| 
 | ||||
|   .task-title { | ||||
|   .todo-title { | ||||
|     @include str-truncated(calc(100% - 174px)); | ||||
|     font-weight: 600; | ||||
| 
 | ||||
|  | @ -53,10 +53,10 @@ | |||
|     } | ||||
|   } | ||||
| 
 | ||||
|   .task-body { | ||||
|   .todo-body { | ||||
|     margin-right: 174px; | ||||
| 
 | ||||
|     .task-note { | ||||
|     .todo-note { | ||||
|       word-wrap: break-word; | ||||
| 
 | ||||
|       .md { | ||||
|  | @ -89,7 +89,7 @@ | |||
|       } | ||||
|     } | ||||
| 
 | ||||
|     .task-note-icon { | ||||
|     .todo-note-icon { | ||||
|       color: #777; | ||||
|       float: left; | ||||
|       font-size: $gl-font-size; | ||||
|  | @ -102,10 +102,10 @@ | |||
| } | ||||
| 
 | ||||
| @media (max-width: $screen-xs-max) { | ||||
|   .task-item { | ||||
|   .todo-item { | ||||
|     padding-left: $gl-padding; | ||||
| 
 | ||||
|     .task-title { | ||||
|     .todo-title { | ||||
|       white-space: normal; | ||||
|       overflow: visible; | ||||
|       max-width: 100%; | ||||
|  | @ -115,7 +115,7 @@ | |||
|       display: none; | ||||
|     } | ||||
| 
 | ||||
|     .task-body { | ||||
|     .todo-body { | ||||
|       margin: 0; | ||||
|       border-left: 2px solid #DDD; | ||||
|       padding-left: 10px; | ||||
|  | @ -1,21 +0,0 @@ | |||
| class Dashboard::TasksController < Dashboard::ApplicationController | ||||
|   def index | ||||
|     @tasks = TasksFinder.new(current_user, params).execute | ||||
|     @tasks = @tasks.page(params[:page]).per(PER_PAGE) | ||||
|   end | ||||
| 
 | ||||
|   def destroy | ||||
|     task.done! | ||||
| 
 | ||||
|     respond_to do |format| | ||||
|       format.html { redirect_to dashboard_tasks_path, notice: 'Task was successfully marked as done.' } | ||||
|       format.js { render nothing: true } | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def task | ||||
|     @task ||= current_user.tasks.find(params[:id]) | ||||
|   end | ||||
| end | ||||
|  | @ -0,0 +1,23 @@ | |||
| class Dashboard::TodosController < Dashboard::ApplicationController | ||||
|   def index | ||||
|     @todos = TodosFinder.new(current_user, params).execute | ||||
|     @todos = @todos.page(params[:page]).per(PER_PAGE) | ||||
|   end | ||||
| 
 | ||||
|   def destroy | ||||
|     todo.done! | ||||
| 
 | ||||
|     respond_to do |format| | ||||
|       format.html { redirect_to dashboard_todos_path, notice: 'Todo was successfully marked as done.' } | ||||
|       format.js { render nothing: true } | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def todo | ||||
|     @todo ||= current_user.todos.find(params[:id]) | ||||
|   end | ||||
| end | ||||
| 
 | ||||
| 
 | ||||
|  | @ -181,7 +181,7 @@ class Projects::MergeRequestsController < Projects::ApplicationController | |||
|       return | ||||
|     end | ||||
| 
 | ||||
|     TaskService.new.merge_merge_request(merge_request, current_user) | ||||
|     TodoService.new.merge_merge_request(merge_request, current_user) | ||||
| 
 | ||||
|     @merge_request.update(merge_error: nil) | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| # TasksFinder | ||||
| # TodosFinder | ||||
| # | ||||
| # Used to filter Tasks by set of params | ||||
| # Used to filter Todos by set of params | ||||
| # | ||||
| # Arguments: | ||||
| #   current_user - which user use | ||||
|  | @ -12,7 +12,7 @@ | |||
| #     type: 'Issue' or 'MergeRequest' | ||||
| # | ||||
| 
 | ||||
| class TasksFinder | ||||
| class TodosFinder | ||||
|   NONE = '0' | ||||
| 
 | ||||
|   attr_accessor :current_user, :params | ||||
|  | @ -23,7 +23,7 @@ class TasksFinder | |||
|   end | ||||
| 
 | ||||
|   def execute | ||||
|     items = current_user.tasks | ||||
|     items = current_user.todos | ||||
|     items = by_action_id(items) | ||||
|     items = by_author(items) | ||||
|     items = by_project(items) | ||||
|  | @ -36,7 +36,7 @@ class TasksFinder | |||
|   private | ||||
| 
 | ||||
|   def action_id? | ||||
|     action_id.present? && [Task::ASSIGNED, Task::MENTIONED].include?(action_id.to_i) | ||||
|     action_id.present? && [Todo::ASSIGNED, Todo::MENTIONED].include?(action_id.to_i) | ||||
|   end | ||||
| 
 | ||||
|   def action_id | ||||
|  | @ -1,69 +0,0 @@ | |||
| module TasksHelper | ||||
|   def link_to_author(task) | ||||
|     author = task.author | ||||
| 
 | ||||
|     if author | ||||
|       link_to author.name, user_path(author.username) | ||||
|     else | ||||
|       task.author_name | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def tasks_pending_count | ||||
|     current_user.tasks.pending.count | ||||
|   end | ||||
| 
 | ||||
|   def tasks_done_count | ||||
|     current_user.tasks.done.count | ||||
|   end | ||||
| 
 | ||||
|   def task_action_name(task) | ||||
|     target =  task.target_type.titleize.downcase | ||||
| 
 | ||||
|     [task.action_name, target].join(" ") | ||||
|   end | ||||
| 
 | ||||
|   def task_target_link_html(task) | ||||
|     link_to "##{task.target_iid}", task_target_path(task) | ||||
|   end | ||||
| 
 | ||||
|   def task_target_path(task) | ||||
|     anchor = dom_id(task.note) if task.note.present? | ||||
| 
 | ||||
|     polymorphic_path([task.project.namespace.becomes(Namespace), | ||||
|                       task.project, task.target], anchor: anchor) | ||||
|   end | ||||
| 
 | ||||
|   def task_actions_options | ||||
|     actions = [ | ||||
|       OpenStruct.new(id: '', title: 'Any Action'), | ||||
|       OpenStruct.new(id: Task::ASSIGNED, title: 'Assigned'), | ||||
|       OpenStruct.new(id: Task::MENTIONED, title: 'Mentioned') | ||||
|     ] | ||||
| 
 | ||||
|     options_from_collection_for_select(actions, 'id', 'title', params[:action_id]) | ||||
|   end | ||||
| 
 | ||||
|   def task_projects_options | ||||
|     projects = current_user.authorized_projects.sorted_by_activity.non_archived | ||||
|     projects = projects.includes(:namespace) | ||||
| 
 | ||||
|     projects = projects.map do |project| | ||||
|       OpenStruct.new(id: project.id, title: project.name_with_namespace) | ||||
|     end | ||||
| 
 | ||||
|     projects.unshift(OpenStruct.new(id: '', title: 'Any Project')) | ||||
| 
 | ||||
|     options_from_collection_for_select(projects, 'id', 'title', params[:project_id]) | ||||
|   end | ||||
| 
 | ||||
|   def task_types_options | ||||
|     types = [ | ||||
|       OpenStruct.new(title: 'Any Type', name: ''), | ||||
|       OpenStruct.new(title: 'Issue', name: 'Issue'), | ||||
|       OpenStruct.new(title: 'Merge Request', name: 'MergeRequest') | ||||
|     ] | ||||
| 
 | ||||
|     options_from_collection_for_select(types, 'name', 'title', params[:type]) | ||||
|   end | ||||
| end | ||||
|  | @ -0,0 +1,59 @@ | |||
| module TodosHelper | ||||
|   def todos_pending_count | ||||
|     current_user.todos.pending.count | ||||
|   end | ||||
| 
 | ||||
|   def todos_done_count | ||||
|     current_user.todos.done.count | ||||
|   end | ||||
| 
 | ||||
|   def todo_action_name(todo) | ||||
|     target =  todo.target_type.titleize.downcase | ||||
| 
 | ||||
|     [todo.action_name, target].join(" ") | ||||
|   end | ||||
| 
 | ||||
|   def todo_target_link_html(todo) | ||||
|     link_to "##{todo.target_iid}", todo_target_path(todo) | ||||
|   end | ||||
| 
 | ||||
|   def todo_target_path(todo) | ||||
|     anchor = dom_id(todo.note) if todo.note.present? | ||||
| 
 | ||||
|     polymorphic_path([todo.project.namespace.becomes(Namespace), | ||||
|                       todo.project, todo.target], anchor: anchor) | ||||
|   end | ||||
| 
 | ||||
|   def todo_actions_options | ||||
|     actions = [ | ||||
|       OpenStruct.new(id: '', title: 'Any Action'), | ||||
|       OpenStruct.new(id: Todo::ASSIGNED, title: 'Assigned'), | ||||
|       OpenStruct.new(id: Todo::MENTIONED, title: 'Mentioned') | ||||
|     ] | ||||
| 
 | ||||
|     options_from_collection_for_select(actions, 'id', 'title', params[:action_id]) | ||||
|   end | ||||
| 
 | ||||
|   def todo_projects_options | ||||
|     projects = current_user.authorized_projects.sorted_by_activity.non_archived | ||||
|     projects = projects.includes(:namespace) | ||||
| 
 | ||||
|     projects = projects.map do |project| | ||||
|       OpenStruct.new(id: project.id, title: project.name_with_namespace) | ||||
|     end | ||||
| 
 | ||||
|     projects.unshift(OpenStruct.new(id: '', title: 'Any Project')) | ||||
| 
 | ||||
|     options_from_collection_for_select(projects, 'id', 'title', params[:project_id]) | ||||
|   end | ||||
| 
 | ||||
|   def todo_types_options | ||||
|     types = [ | ||||
|       OpenStruct.new(title: 'Any Type', name: ''), | ||||
|       OpenStruct.new(title: 'Issue', name: 'Issue'), | ||||
|       OpenStruct.new(title: 'Merge Request', name: 'MergeRequest') | ||||
|     ] | ||||
| 
 | ||||
|     options_from_collection_for_select(types, 'name', 'title', params[:type]) | ||||
|   end | ||||
| end | ||||
|  | @ -37,7 +37,7 @@ class Note < ActiveRecord::Base | |||
|   belongs_to :author, class_name: "User" | ||||
|   belongs_to :updated_by, class_name: "User" | ||||
| 
 | ||||
|   has_many :tasks, dependent: :destroy | ||||
|   has_many :todos, dependent: :destroy | ||||
| 
 | ||||
|   delegate :name, to: :project, prefix: true | ||||
|   delegate :name, :email, to: :author, prefix: true | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| # == Schema Information | ||||
| # | ||||
| # Table name: tasks | ||||
| # Table name: todos | ||||
| # | ||||
| #  id          :integer          not null, primary key | ||||
| #  user_id     :integer          not null | ||||
|  | @ -15,7 +15,7 @@ | |||
| #  updated_at  :datetime | ||||
| # | ||||
| 
 | ||||
| class Task < ActiveRecord::Base | ||||
| class Todo < ActiveRecord::Base | ||||
|   ASSIGNED  = 1 | ||||
|   MENTIONED = 2 | ||||
| 
 | ||||
|  | @ -140,7 +140,7 @@ class User < ActiveRecord::Base | |||
|   has_one  :abuse_report,             dependent: :destroy | ||||
|   has_many :spam_logs,                dependent: :destroy | ||||
|   has_many :builds,                   dependent: :nullify, class_name: 'Ci::Build' | ||||
|   has_many :tasks,                    dependent: :destroy | ||||
|   has_many :todos,                    dependent: :destroy | ||||
| 
 | ||||
|   # | ||||
|   # Validations | ||||
|  |  | |||
|  | @ -23,8 +23,8 @@ class BaseService | |||
|     EventCreateService.new | ||||
|   end | ||||
| 
 | ||||
|   def task_service | ||||
|     TaskService.new | ||||
|   def todo_service | ||||
|     TodoService.new | ||||
|   end | ||||
| 
 | ||||
|   def log_info(message) | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ module Issues | |||
|     def execute(issue, commit = nil) | ||||
|       if project.jira_tracker? && project.jira_service.active | ||||
|         project.jira_service.execute(commit, issue) | ||||
|         task_service.close_issue(issue, current_user) | ||||
|         todo_service.close_issue(issue, current_user) | ||||
|         return issue | ||||
|       end | ||||
| 
 | ||||
|  | @ -11,7 +11,7 @@ module Issues | |||
|         event_service.close_issue(issue, current_user) | ||||
|         create_note(issue, commit) | ||||
|         notification_service.close_issue(issue, current_user) | ||||
|         task_service.close_issue(issue, current_user) | ||||
|         todo_service.close_issue(issue, current_user) | ||||
|         execute_hooks(issue, 'close') | ||||
|       end | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ module Issues | |||
|       if issue.save | ||||
|         issue.update_attributes(label_ids: label_params) | ||||
|         notification_service.new_issue(issue, current_user) | ||||
|         task_service.new_issue(issue, current_user) | ||||
|         todo_service.new_issue(issue, current_user) | ||||
|         event_service.open_issue(issue, current_user) | ||||
|         issue.create_cross_references!(current_user) | ||||
|         execute_hooks(issue, 'open') | ||||
|  |  | |||
|  | @ -6,12 +6,12 @@ module Issues | |||
| 
 | ||||
|     def handle_changes(issue, options = {}) | ||||
|       if has_changes?(issue, options) | ||||
|         task_service.mark_pending_tasks_as_done(issue, current_user) | ||||
|         todo_service.mark_pending_todos_as_done(issue, current_user) | ||||
|       end | ||||
| 
 | ||||
|       if issue.previous_changes.include?('title') || | ||||
|          issue.previous_changes.include?('description') | ||||
|         task_service.update_issue(issue, current_user) | ||||
|         todo_service.update_issue(issue, current_user) | ||||
|       end | ||||
| 
 | ||||
|       if issue.previous_changes.include?('milestone_id') | ||||
|  | @ -21,7 +21,7 @@ module Issues | |||
|       if issue.previous_changes.include?('assignee_id') | ||||
|         create_assignee_note(issue) | ||||
|         notification_service.reassigned_issue(issue, current_user) | ||||
|         task_service.reassigned_issue(issue, current_user) | ||||
|         todo_service.reassigned_issue(issue, current_user) | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ module MergeRequests | |||
|         event_service.close_mr(merge_request, current_user) | ||||
|         create_note(merge_request) | ||||
|         notification_service.close_mr(merge_request, current_user) | ||||
|         task_service.close_merge_request(merge_request, current_user) | ||||
|         todo_service.close_merge_request(merge_request, current_user) | ||||
|         execute_hooks(merge_request, 'close') | ||||
|       end | ||||
| 
 | ||||
|  |  | |||
|  | @ -18,7 +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) | ||||
|         task_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 | ||||
|  |  | |||
|  | @ -16,12 +16,12 @@ module MergeRequests | |||
| 
 | ||||
|     def handle_changes(merge_request, options = {}) | ||||
|       if has_changes?(merge_request, options) | ||||
|         task_service.mark_pending_tasks_as_done(merge_request, current_user) | ||||
|         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') | ||||
|         task_service.update_merge_request(merge_request, current_user) | ||||
|         todo_service.update_merge_request(merge_request, current_user) | ||||
|       end | ||||
| 
 | ||||
|       if merge_request.previous_changes.include?('target_branch') | ||||
|  | @ -37,7 +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) | ||||
|         task_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') || | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ module Notes | |||
|       if note.save | ||||
|         # Finish the harder work in the background | ||||
|         NewNoteWorker.perform_in(2.seconds, note.id, params) | ||||
|         TaskService.new.new_note(note, current_user) | ||||
|         TodoService.new.new_note(note, current_user) | ||||
|       end | ||||
| 
 | ||||
|       note | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ module Notes | |||
|       note.reset_events_cache | ||||
| 
 | ||||
|       if note.previous_changes.include?('note') | ||||
|         TaskService.new.update_note(note, current_user) | ||||
|         TodoService.new.update_note(note, current_user) | ||||
|       end | ||||
| 
 | ||||
|       note | ||||
|  |  | |||
|  | @ -1,15 +1,15 @@ | |||
| # TaskService class | ||||
| # TodoService class | ||||
| # | ||||
| # Used for creating tasks on task queue after certain user action | ||||
| # Used for creating todos after certain user actions | ||||
| # | ||||
| # Ex. | ||||
| #   TaskService.new.new_issue(issue, current_user) | ||||
| #   TodoService.new.new_issue(issue, current_user) | ||||
| # | ||||
| class TaskService | ||||
| class TodoService | ||||
|   # When create an issue we should: | ||||
|   # | ||||
|   #  * create a task for assignee if issue is assigned | ||||
|   #  * create a task for each mentioned user on issue | ||||
|   #  * 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) | ||||
|  | @ -17,32 +17,32 @@ class TaskService | |||
| 
 | ||||
|   # When update an issue we should: | ||||
|   # | ||||
|   #  * mark all pending tasks related to the issue for the current user as done | ||||
|   #  * mark all pending todos related to the issue for the current user as done | ||||
|   # | ||||
|   def update_issue(issue, current_user) | ||||
|     create_mention_tasks(issue.project, issue, current_user) | ||||
|     create_mention_todos(issue.project, issue, current_user) | ||||
|   end | ||||
| 
 | ||||
|   # When close an issue we should: | ||||
|   # | ||||
|   #  * mark all pending tasks related to the target for the current user as done | ||||
|   #  * mark all pending todos related to the target for the current user as done | ||||
|   # | ||||
|   def close_issue(issue, current_user) | ||||
|     mark_pending_tasks_as_done(issue, current_user) | ||||
|     mark_pending_todos_as_done(issue, current_user) | ||||
|   end | ||||
| 
 | ||||
|   # When we reassign an issue we should: | ||||
|   # | ||||
|   #  * create a pending task for new assignee if issue is assigned | ||||
|   #  * create a pending todo for new assignee if issue is assigned | ||||
|   # | ||||
|   def reassigned_issue(issue, current_user) | ||||
|     create_assignment_task(issue, current_user) | ||||
|     create_assignment_todo(issue, current_user) | ||||
|   end | ||||
| 
 | ||||
|   # When create a merge request we should: | ||||
|   # | ||||
|   #  * creates a pending task for assignee if merge request is assigned | ||||
|   #  * create a task for each mentioned user on merge request | ||||
|   #  * 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) | ||||
|  | @ -50,40 +50,40 @@ class TaskService | |||
| 
 | ||||
|   # When update a merge request we should: | ||||
|   # | ||||
|   #  * create a task for each mentioned user on merge request | ||||
|   #  * create a todo for each mentioned user on merge request | ||||
|   # | ||||
|   def update_merge_request(merge_request, current_user) | ||||
|     create_mention_tasks(merge_request.project, 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 tasks related to the target for the current user as done | ||||
|   #  * mark all pending todos related to the target for the current user as done | ||||
|   # | ||||
|   def close_merge_request(merge_request, current_user) | ||||
|     mark_pending_tasks_as_done(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 task for new assignee if merge request is assigned | ||||
|   #  * creates a pending todo for new assignee if merge request is assigned | ||||
|   # | ||||
|   def reassigned_merge_request(merge_request, current_user) | ||||
|     create_assignment_task(merge_request, current_user) | ||||
|     create_assignment_todo(merge_request, current_user) | ||||
|   end | ||||
| 
 | ||||
|   # When merge a merge request we should: | ||||
|   # | ||||
|   #  * mark all pending tasks related to the target for the current user as done | ||||
|   #  * mark all pending todos related to the target for the current user as done | ||||
|   # | ||||
|   def merge_merge_request(merge_request, current_user) | ||||
|     mark_pending_tasks_as_done(merge_request, current_user) | ||||
|     mark_pending_todos_as_done(merge_request, current_user) | ||||
|   end | ||||
| 
 | ||||
|   # When create a note we should: | ||||
|   # | ||||
|   #  * mark all pending tasks related to the noteable for the note author as done | ||||
|   #  * create a task for each mentioned user on note | ||||
|   #  * 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) | ||||
|  | @ -91,28 +91,28 @@ class TaskService | |||
| 
 | ||||
|   # When update a note we should: | ||||
|   # | ||||
|   #  * mark all pending tasks related to the noteable for the current user as done | ||||
|   #  * create a task for each new user mentioned on note | ||||
|   #  * 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 tasks as done we should: | ||||
|   # When marking pending todos as done we should: | ||||
|   # | ||||
|   #  * mark all pending tasks related to the target for the current user as done | ||||
|   #  * mark all pending todos related to the target for the current user as done | ||||
|   # | ||||
|   def mark_pending_tasks_as_done(target, user) | ||||
|     pending_tasks(user, target.project, target).update_all(state: :done) | ||||
|   def mark_pending_todos_as_done(target, user) | ||||
|     pending_todos(user, target.project, target).update_all(state: :done) | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def create_tasks(project, target, author, users, action, note = nil) | ||||
|   def create_todos(project, target, author, users, action, note = nil) | ||||
|     Array(users).each do |user| | ||||
|       next if pending_tasks(user, project, target).exists? | ||||
|       next if pending_todos(user, project, target).exists? | ||||
| 
 | ||||
|       Task.create( | ||||
|       Todo.create( | ||||
|         project: project, | ||||
|         user_id: user.id, | ||||
|         author_id: author.id, | ||||
|  | @ -125,8 +125,8 @@ class TaskService | |||
|   end | ||||
| 
 | ||||
|   def new_issuable(issuable, author) | ||||
|     create_assignment_task(issuable, author) | ||||
|     create_mention_tasks(issuable.project, issuable, author) | ||||
|     create_assignment_todo(issuable, author) | ||||
|     create_mention_todos(issuable.project, issuable, author) | ||||
|   end | ||||
| 
 | ||||
|   def handle_note(note, author) | ||||
|  | @ -136,19 +136,19 @@ class TaskService | |||
|     project = note.project | ||||
|     target  = note.noteable | ||||
| 
 | ||||
|     mark_pending_tasks_as_done(target, author) | ||||
|     create_mention_tasks(project, target, author, note) | ||||
|     mark_pending_todos_as_done(target, author) | ||||
|     create_mention_todos(project, target, author, note) | ||||
|   end | ||||
| 
 | ||||
|   def create_assignment_task(issuable, author) | ||||
|   def create_assignment_todo(issuable, author) | ||||
|     if issuable.assignee && issuable.assignee != author | ||||
|       create_tasks(issuable.project, issuable, author, issuable.assignee, Task::ASSIGNED) | ||||
|       create_todos(issuable.project, issuable, author, issuable.assignee, Todo::ASSIGNED) | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def create_mention_tasks(project, issuable, author, note = nil) | ||||
|   def create_mention_todos(project, issuable, author, note = nil) | ||||
|     mentioned_users = filter_mentioned_users(project, note || issuable, author) | ||||
|     create_tasks(project, issuable, author, mentioned_users, Task::MENTIONED, note) | ||||
|     create_todos(project, issuable, author, mentioned_users, Todo::MENTIONED, note) | ||||
|   end | ||||
| 
 | ||||
|   def filter_mentioned_users(project, target, author) | ||||
|  | @ -160,8 +160,8 @@ class TaskService | |||
|     mentioned_users.uniq | ||||
|   end | ||||
| 
 | ||||
|   def pending_tasks(user, project, target) | ||||
|     user.tasks.pending.where( | ||||
|   def pending_todos(user, project, target) | ||||
|     user.todos.pending.where( | ||||
|       project_id: project.id, | ||||
|       target_id: target.id, | ||||
|       target_type: target.class.name | ||||
|  | @ -1,21 +0,0 @@ | |||
| %li{class: "task task-#{task.done? ? 'done' : 'pending'}", id: dom_id(task) } | ||||
|   .task-item{class: 'task-block'} | ||||
|     = image_tag avatar_icon(task.author_email, 40), class: 'avatar s40', alt:'' | ||||
| 
 | ||||
|     .task-title | ||||
|       %span.author_name | ||||
|         = link_to_author task | ||||
|       %span.task_label | ||||
|         = task_action_name(task) | ||||
|         = task_target_link_html(task) | ||||
| 
 | ||||
|       · #{time_ago_with_tooltip(task.created_at)} | ||||
| 
 | ||||
|     - if task.pending? | ||||
|       .task-actions.pull-right | ||||
|         = link_to 'Done', [:dashboard, task], method: :delete, class: 'btn' | ||||
| 
 | ||||
|     .task-body | ||||
|       .task-note | ||||
|         .md | ||||
|           = event_note(task.body, project: task.project) | ||||
|  | @ -0,0 +1,21 @@ | |||
| %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_html(todo) | ||||
| 
 | ||||
|       · #{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) | ||||
|  | @ -1,53 +1,53 @@ | |||
| - page_title "Tasks" | ||||
| - header_title "Tasks", dashboard_tasks_path | ||||
| - 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 page_filter_path(state: 'pending') do | ||||
|         %span | ||||
|           Tasks | ||||
|           Todos | ||||
|         %span{class: 'badge'} | ||||
|           = tasks_pending_count | ||||
|           = todos_pending_count | ||||
|     %li{class: ('active' if params[:state] == 'done')} | ||||
|       = link_to page_filter_path(state: 'done') do | ||||
|         %span | ||||
|           Done | ||||
|         %span{class: 'badge'} | ||||
|           = tasks_done_count | ||||
|           = todos_done_count | ||||
| 
 | ||||
| .tasks-filters | ||||
| .todos-filters | ||||
|   .gray-content-block.second-block | ||||
|     = form_tag page_filter_path(without: [:assignee_id, :milestone_title, :label_name, :scope, :sort]), method: :get, class: 'filter-form' do | ||||
|       .filter-item.inline | ||||
|         = select_tag('project_id', task_projects_options, | ||||
|         = 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', task_types_options, | ||||
|         = 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', task_actions_options, | ||||
|         = select_tag('action_id', todo_actions_options, | ||||
|           class: 'select2 trigger-submit', include_blank: true, | ||||
|           data: {placeholder: 'Action'}) | ||||
| 
 | ||||
| .prepend-top-default | ||||
|   - if @tasks.any? | ||||
|     - @tasks.group_by(&:project).each do |group| | ||||
|   - 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.tasks-list | ||||
|         %ul.well-list.todos-list | ||||
|           = render group[1] | ||||
|     = paginate @tasks, theme: "gitlab" | ||||
|     = paginate @todos, theme: "gitlab" | ||||
|   - else | ||||
|     .nothing-here-block No tasks to show | ||||
|     .nothing-here-block No todos to show | ||||
| 
 | ||||
| :javascript | ||||
|   new UsersSelect(); | ||||
|  | @ -22,9 +22,9 @@ | |||
|               = link_to admin_root_path, title: 'Admin Area', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do | ||||
|                 = icon('wrench fw') | ||||
|           %li | ||||
|             = link_to dashboard_tasks_path, title: 'Tasks', data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do | ||||
|               %span.badge.tasks-pending-count | ||||
|                 = tasks_pending_count | ||||
|             = 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 | ||||
|  |  | |||
|  | @ -4,12 +4,12 @@ | |||
|       = icon('home fw') | ||||
|       %span | ||||
|         Projects | ||||
|   = nav_link(controller: :tasks) do | ||||
|     = link_to dashboard_tasks_path, title: 'Tasks' do | ||||
|   = nav_link(controller: :todos) do | ||||
|     = link_to dashboard_todos_path, title: 'Todos' do | ||||
|       = icon('bell fw') | ||||
|       %span | ||||
|         Tasks | ||||
|         %span.count= number_with_delimiter(tasks_pending_count) | ||||
|         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') | ||||
|  |  | |||
|  | @ -333,7 +333,7 @@ Rails.application.routes.draw do | |||
| 
 | ||||
|       resources :groups, only: [:index] | ||||
|       resources :snippets, only: [:index] | ||||
|       resources :tasks, only: [:index, :destroy] | ||||
|       resources :todos, only: [:index, :destroy] | ||||
| 
 | ||||
|       resources :projects, only: [:index] do | ||||
|         collection do | ||||
|  |  | |||
|  | @ -0,0 +1,5 @@ | |||
| class RenameTasksToTodos < ActiveRecord::Migration | ||||
|   def change | ||||
|     rename_table :tasks, :todos | ||||
|   end | ||||
| end | ||||
							
								
								
									
										16
									
								
								db/schema.rb
								
								
								
								
							
							
						
						
									
										16
									
								
								db/schema.rb
								
								
								
								
							|  | @ -11,7 +11,7 @@ | |||
| # | ||||
| # It's strongly recommended that you check this file into your version control system. | ||||
| 
 | ||||
| ActiveRecord::Schema.define(version: 20160217174422) do | ||||
| ActiveRecord::Schema.define(version: 20160220123949) do | ||||
| 
 | ||||
|   # These are extensions that must be enabled in order to support this database | ||||
|   enable_extension "plpgsql" | ||||
|  | @ -824,7 +824,7 @@ ActiveRecord::Schema.define(version: 20160217174422) do | |||
| 
 | ||||
|   add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree | ||||
| 
 | ||||
|   create_table "tasks", force: :cascade do |t| | ||||
|   create_table "todos", force: :cascade do |t| | ||||
|     t.integer  "user_id",     null: false | ||||
|     t.integer  "project_id",  null: false | ||||
|     t.integer  "target_id",   null: false | ||||
|  | @ -837,12 +837,12 @@ ActiveRecord::Schema.define(version: 20160217174422) do | |||
|     t.integer  "note_id" | ||||
|   end | ||||
| 
 | ||||
|   add_index "tasks", ["author_id"], name: "index_tasks_on_author_id", using: :btree | ||||
|   add_index "tasks", ["note_id"], name: "index_tasks_on_note_id", using: :btree | ||||
|   add_index "tasks", ["project_id"], name: "index_tasks_on_project_id", using: :btree | ||||
|   add_index "tasks", ["state"], name: "index_tasks_on_state", using: :btree | ||||
|   add_index "tasks", ["target_type", "target_id"], name: "index_tasks_on_target_type_and_target_id", using: :btree | ||||
|   add_index "tasks", ["user_id"], name: "index_tasks_on_user_id", using: :btree | ||||
|   add_index "todos", ["author_id"], name: "index_todos_on_author_id", using: :btree | ||||
|   add_index "todos", ["note_id"], name: "index_todos_on_note_id", using: :btree | ||||
|   add_index "todos", ["project_id"], name: "index_todos_on_project_id", using: :btree | ||||
|   add_index "todos", ["state"], name: "index_todos_on_state", using: :btree | ||||
|   add_index "todos", ["target_type", "target_id"], name: "index_todos_on_target_type_and_target_id", using: :btree | ||||
|   add_index "todos", ["user_id"], name: "index_todos_on_user_id", using: :btree | ||||
| 
 | ||||
|   create_table "users", force: :cascade do |t| | ||||
|     t.string   "email",                       default: "",    null: false | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| @dashboard | ||||
| Feature: Dashboard Tasks | ||||
| Feature: Dashboard Todos | ||||
|   Background: | ||||
|     Given I sign in as a user | ||||
|     And I own project "Shop" | ||||
|  | @ -7,32 +7,32 @@ Feature: Dashboard Tasks | |||
|     And "Mary Jane" is a developer of project "Shop" | ||||
|     And "Mary Jane" owns private project "Enterprise" | ||||
|     And I am a developer of project "Enterprise" | ||||
|     And I have pending tasks | ||||
|     And I visit dashboard task queue page | ||||
|     And I have todos | ||||
|     And I visit dashboard todos page | ||||
| 
 | ||||
|   @javascript | ||||
|   Scenario: I mark pending tasks as done | ||||
|     Then I should see pending tasks assigned to me | ||||
|     And I mark the pending task as done | ||||
|   Scenario: I mark todos as done | ||||
|     Then I should see todos assigned to me | ||||
|     And I mark the todo as done | ||||
|     And I click on the "Done" tab | ||||
|     Then I should see all tasks marked as done | ||||
|     Then I should see all todos marked as done | ||||
| 
 | ||||
|   @javascript | ||||
|     Scenario: I filter by project | ||||
|       Given I filter by "Enterprise" | ||||
|       Then I should not see tasks | ||||
|       Then I should not see todos | ||||
| 
 | ||||
|   @javascript | ||||
|     Scenario: I filter by author | ||||
|       Given I filter by "John Doe" | ||||
|       Then I should not see tasks related to "Mary Jane" in the list | ||||
|       Then I should not see todos related to "Mary Jane" in the list | ||||
| 
 | ||||
|   @javascript | ||||
|     Scenario: I filter by type | ||||
|       Given I filter by "Issue" | ||||
|       Then I should not see tasks related to "Merge Requests" in the list | ||||
|       Then I should not see todos related to "Merge Requests" in the list | ||||
| 
 | ||||
|   @javascript | ||||
|     Scenario: I filter by action | ||||
|       Given I filter by "Mentioned" | ||||
|       Then I should not see tasks related to "Assignments" in the list | ||||
|       Then I should not see todos related to "Assignments" in the list | ||||
|  | @ -1,4 +1,4 @@ | |||
| class Spinach::Features::DashboardTasks < Spinach::FeatureSteps | ||||
| class Spinach::Features::DashboardTodos < Spinach::FeatureSteps | ||||
|   include SharedAuthentication | ||||
|   include SharedPaths | ||||
|   include SharedProject | ||||
|  | @ -17,43 +17,43 @@ class Spinach::Features::DashboardTasks < Spinach::FeatureSteps | |||
|     project.team << [john_doe, :developer] | ||||
|   end | ||||
| 
 | ||||
|   step 'I have pending tasks' do | ||||
|     create(:task, user: current_user, project: project, author: mary_jane, target: issue, action: Task::MENTIONED) | ||||
|     create(:task, user: current_user, project: project, author: john_doe, target: issue, action: Task::ASSIGNED) | ||||
|   step 'I have todos' do | ||||
|     create(:todo, user: current_user, project: project, author: mary_jane, target: issue, action: Todo::MENTIONED) | ||||
|     create(:todo, user: current_user, project: project, author: john_doe, target: issue, action: Todo::ASSIGNED) | ||||
|     note = create(:note, author: john_doe, noteable: issue, note: "#{current_user.to_reference} Wdyt?") | ||||
|     create(:task, user: current_user, project: project, author: john_doe, target: issue, action: Task::MENTIONED, note: note) | ||||
|     create(:task, user: current_user, project: project, author: john_doe, target: merge_request, action: Task::ASSIGNED) | ||||
|     create(:todo, user: current_user, project: project, author: john_doe, target: issue, action: Todo::MENTIONED, note: note) | ||||
|     create(:todo, user: current_user, project: project, author: john_doe, target: merge_request, action: Todo::ASSIGNED) | ||||
|   end | ||||
| 
 | ||||
|   step 'I should see pending tasks assigned to me' do | ||||
|     expect(page).to have_content 'Tasks 4' | ||||
|   step 'I should see todos assigned to me' do | ||||
|     expect(page).to have_content 'Todos 4' | ||||
|     expect(page).to have_content 'Done 0' | ||||
| 
 | ||||
|     expect(page).to have_link project.name_with_namespace | ||||
|     should_see_task(1, "John Doe assigned merge request ##{merge_request.iid}", merge_request.title) | ||||
|     should_see_task(2, "John Doe mentioned you on issue ##{issue.iid}", "#{current_user.to_reference} Wdyt?") | ||||
|     should_see_task(3, "John Doe assigned issue ##{issue.iid}", issue.title) | ||||
|     should_see_task(4, "Mary Jane mentioned you on issue ##{issue.iid}", issue.title) | ||||
|     should_see_todo(1, "John Doe assigned merge request ##{merge_request.iid}", merge_request.title) | ||||
|     should_see_todo(2, "John Doe mentioned you on issue ##{issue.iid}", "#{current_user.to_reference} Wdyt?") | ||||
|     should_see_todo(3, "John Doe assigned issue ##{issue.iid}", issue.title) | ||||
|     should_see_todo(4, "Mary Jane mentioned you on issue ##{issue.iid}", issue.title) | ||||
|   end | ||||
| 
 | ||||
|   step 'I mark the pending task as done' do | ||||
|     page.within('.task:nth-child(1)') do | ||||
|   step 'I mark the todo as done' do | ||||
|     page.within('.todo:nth-child(1)') do | ||||
|       click_link 'Done' | ||||
|     end | ||||
| 
 | ||||
|     expect(page).to have_content 'Task was successfully marked as done.' | ||||
|     expect(page).to have_content 'Tasks 3' | ||||
|     expect(page).to have_content 'Todo was successfully marked as done.' | ||||
|     expect(page).to have_content 'Todos 3' | ||||
|     expect(page).to have_content 'Done 1' | ||||
|     should_not_see_task "John Doe assigned merge request ##{merge_request.iid}" | ||||
|     should_not_see_todo "John Doe assigned merge request ##{merge_request.iid}" | ||||
|   end | ||||
| 
 | ||||
|   step 'I click on the "Done" tab' do | ||||
|     click_link 'Done 1' | ||||
|   end | ||||
| 
 | ||||
|   step 'I should see all tasks marked as done' do | ||||
|   step 'I should see all todos marked as done' do | ||||
|     expect(page).to have_link project.name_with_namespace | ||||
|     should_see_task(1, "John Doe assigned merge request ##{merge_request.iid}", merge_request.title, false) | ||||
|     should_see_todo(1, "John Doe assigned merge request ##{merge_request.iid}", merge_request.title, false) | ||||
|   end | ||||
| 
 | ||||
|   step 'I filter by "Enterprise"' do | ||||
|  | @ -69,28 +69,28 @@ class Spinach::Features::DashboardTasks < Spinach::FeatureSteps | |||
|   end | ||||
| 
 | ||||
|   step 'I filter by "Mentioned"' do | ||||
|     select2("#{Task::MENTIONED}", from: '#action_id') | ||||
|     select2("#{Todo::MENTIONED}", from: '#action_id') | ||||
|   end | ||||
| 
 | ||||
|   step 'I should not see tasks' do | ||||
|     expect(page).to have_content 'No tasks to show' | ||||
|   step 'I should not see todos' do | ||||
|     expect(page).to have_content 'No todos to show' | ||||
|   end | ||||
| 
 | ||||
|   step 'I should not see tasks related to "Mary Jane" in the list' do | ||||
|     should_not_see_task "Mary Jane mentioned you on issue ##{issue.iid}" | ||||
|   step 'I should not see todos related to "Mary Jane" in the list' do | ||||
|     should_not_see_todo "Mary Jane mentioned you on issue ##{issue.iid}" | ||||
|   end | ||||
| 
 | ||||
|   step 'I should not see tasks related to "Merge Requests" in the list' do | ||||
|     should_not_see_task "John Doe assigned merge request ##{merge_request.iid}" | ||||
|   step 'I should not see todos related to "Merge Requests" in the list' do | ||||
|     should_not_see_todo "John Doe assigned merge request ##{merge_request.iid}" | ||||
|   end | ||||
| 
 | ||||
|   step 'I should not see tasks related to "Assignments" in the list' do | ||||
|     should_not_see_task "John Doe assigned merge request ##{merge_request.iid}" | ||||
|     should_not_see_task "John Doe assigned issue ##{issue.iid}" | ||||
|   step 'I should not see todos related to "Assignments" in the list' do | ||||
|     should_not_see_todo "John Doe assigned merge request ##{merge_request.iid}" | ||||
|     should_not_see_todo "John Doe assigned issue ##{issue.iid}" | ||||
|   end | ||||
| 
 | ||||
|   def should_see_task(position, title, body, pending = true) | ||||
|     page.within(".task:nth-child(#{position})") do | ||||
|   def should_see_todo(position, title, body, pending = true) | ||||
|     page.within(".todo:nth-child(#{position})") do | ||||
|       expect(page).to have_content title | ||||
|       expect(page).to have_content body | ||||
| 
 | ||||
|  | @ -102,7 +102,7 @@ class Spinach::Features::DashboardTasks < Spinach::FeatureSteps | |||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def should_not_see_task(title) | ||||
|   def should_not_see_todo(title) | ||||
|     expect(page).not_to have_content title | ||||
|   end | ||||
| 
 | ||||
|  | @ -103,8 +103,8 @@ module SharedPaths | |||
|     visit dashboard_groups_path | ||||
|   end | ||||
| 
 | ||||
|   step 'I visit dashboard task queue page' do | ||||
|     visit dashboard_tasks_path | ||||
|   step 'I visit dashboard todos page' do | ||||
|     visit dashboard_todos_path | ||||
|   end | ||||
| 
 | ||||
|   step 'I should be redirected to the dashboard groups page' do | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| # == Schema Information | ||||
| # | ||||
| # Table name: tasks | ||||
| # Table name: todos | ||||
| # | ||||
| #  id          :integer          not null, primary key | ||||
| #  user_id     :integer          not null | ||||
|  | @ -16,19 +16,19 @@ | |||
| # | ||||
| 
 | ||||
| FactoryGirl.define do | ||||
|   factory :task do | ||||
|   factory :todo do | ||||
|     project | ||||
|     author | ||||
|     user | ||||
|     target factory: :issue | ||||
|     action { Task::ASSIGNED } | ||||
|     action { Todo::ASSIGNED } | ||||
| 
 | ||||
|     trait :assigned do | ||||
|       action { Task::ASSIGNED } | ||||
|       action { Todo::ASSIGNED } | ||||
|     end | ||||
| 
 | ||||
|     trait :mentioned do | ||||
|       action { Task::MENTIONED } | ||||
|       action { Todo::MENTIONED } | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  | @ -27,7 +27,7 @@ describe Note, models: true do | |||
|     it { is_expected.to belong_to(:noteable) } | ||||
|     it { is_expected.to belong_to(:author).class_name('User') } | ||||
| 
 | ||||
|     it { is_expected.to have_many(:tasks).dependent(:destroy) } | ||||
|     it { is_expected.to have_many(:todos).dependent(:destroy) } | ||||
|   end | ||||
| 
 | ||||
|   describe 'validation' do | ||||
|  |  | |||
|  | @ -1,6 +1,6 @@ | |||
| # == Schema Information | ||||
| # | ||||
| # Table name: tasks | ||||
| # Table name: todos | ||||
| # | ||||
| #  id          :integer          not null, primary key | ||||
| #  user_id     :integer          not null | ||||
|  | @ -17,7 +17,7 @@ | |||
| 
 | ||||
| require 'spec_helper' | ||||
| 
 | ||||
| describe Task, models: true do | ||||
| describe Todo, models: true do | ||||
|   describe 'relationships' do | ||||
|     it { is_expected.to belong_to(:author).class_name("User") } | ||||
|     it { is_expected.to belong_to(:note) } | ||||
|  | @ -39,13 +39,13 @@ describe Task, models: true do | |||
| 
 | ||||
|   describe '#action_name' do | ||||
|     it 'returns proper message when action is an assigment' do | ||||
|       subject.action = Task::ASSIGNED | ||||
|       subject.action = Todo::ASSIGNED | ||||
| 
 | ||||
|       expect(subject.action_name).to eq 'assigned' | ||||
|     end | ||||
| 
 | ||||
|     it 'returns proper message when action is a mention' do | ||||
|       subject.action = Task::MENTIONED | ||||
|       subject.action = Todo::MENTIONED | ||||
| 
 | ||||
|       expect(subject.action_name).to eq 'mentioned you on' | ||||
|     end | ||||
|  | @ -92,7 +92,7 @@ describe User, models: true do | |||
|     it { is_expected.to have_many(:identities).dependent(:destroy) } | ||||
|     it { is_expected.to have_one(:abuse_report) } | ||||
|     it { is_expected.to have_many(:spam_logs).dependent(:destroy) } | ||||
|     it { is_expected.to have_many(:tasks).dependent(:destroy) } | ||||
|     it { is_expected.to have_many(:todos).dependent(:destroy) } | ||||
|   end | ||||
| 
 | ||||
|   describe 'validations' do | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ describe Issues::CloseService, services: true do | |||
|   let(:user2) { create(:user) } | ||||
|   let(:issue) { create(:issue, assignee: user2) } | ||||
|   let(:project) { issue.project } | ||||
|   let!(:pending_task) { create(:task, :assigned, user: user, project: project, target: issue, author: user2) } | ||||
|   let!(:todo) { create(:todo, :assigned, user: user, project: project, target: issue, author: user2) } | ||||
| 
 | ||||
|   before do | ||||
|     project.team << [user, :master] | ||||
|  | @ -34,8 +34,8 @@ describe Issues::CloseService, services: true do | |||
|         expect(note.note).to include "Status changed to closed" | ||||
|       end | ||||
| 
 | ||||
|       it 'marks pending tasks as done' do | ||||
|         expect(pending_task.reload).to be_done | ||||
|       it 'marks todos as done' do | ||||
|         expect(todo.reload).to be_done | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|  | @ -47,7 +47,7 @@ describe Issues::CloseService, services: true do | |||
| 
 | ||||
|       it { expect(@issue).to be_valid } | ||||
|       it { expect(@issue).to be_opened } | ||||
|       it { expect(pending_task.reload).to be_pending } | ||||
|       it { expect(todo.reload).to be_pending } | ||||
|     end | ||||
|   end | ||||
| end | ||||
|  |  | |||
|  | @ -24,17 +24,18 @@ describe Issues::CreateService, services: true do | |||
|       it { expect(@issue.title).to eq('Awesome issue') } | ||||
|       it { expect(@issue.assignee).to eq assignee } | ||||
| 
 | ||||
|       it 'creates a pending task for new assignee' do | ||||
|       it 'creates a pending todo for new assignee' do | ||||
|         attributes = { | ||||
|           project: project, | ||||
|           author: user, | ||||
|           user: assignee, | ||||
|           target: @issue, | ||||
|           action: Task::ASSIGNED, | ||||
|           target_id: @issue.id, | ||||
|           target_type: @issue.class.name, | ||||
|           action: Todo::ASSIGNED, | ||||
|           state: :pending | ||||
|         } | ||||
| 
 | ||||
|         expect(Task.where(attributes).count).to eq 1 | ||||
|         expect(Todo.where(attributes).count).to eq 1 | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|  |  | |||
|  | @ -80,16 +80,16 @@ describe Issues::UpdateService, services: true do | |||
|       end | ||||
|     end | ||||
| 
 | ||||
|     context 'task queue' do | ||||
|       let!(:pending_task) { create(:task, :assigned, user: user, project: project, target: issue, author: user2) } | ||||
|     context 'todos' do | ||||
|       let!(:todo) { create(:todo, :assigned, user: user, project: project, target: issue, author: user2) } | ||||
| 
 | ||||
|       context 'when the title change' do | ||||
|         before do | ||||
|           update_issue({ title: 'New title' }) | ||||
|         end | ||||
| 
 | ||||
|         it 'marks pending tasks as done' do | ||||
|           expect(pending_task.reload.done?).to eq true | ||||
|         it 'marks pending todos as done' do | ||||
|           expect(todo.reload.done?).to eq true | ||||
|         end | ||||
|       end | ||||
| 
 | ||||
|  | @ -98,8 +98,8 @@ describe Issues::UpdateService, services: true do | |||
|           update_issue({ description: 'Also please fix' }) | ||||
|         end | ||||
| 
 | ||||
|         it 'marks pending tasks as done' do | ||||
|           expect(pending_task.reload.done?).to eq true | ||||
|         it 'marks todos as done' do | ||||
|           expect(todo.reload.done?).to eq true | ||||
|         end | ||||
|       end | ||||
| 
 | ||||
|  | @ -108,21 +108,22 @@ describe Issues::UpdateService, services: true do | |||
|           update_issue({ assignee: user2 }) | ||||
|         end | ||||
| 
 | ||||
|         it 'marks previous assignee pending tasks as done' do | ||||
|           expect(pending_task.reload.done?).to eq true | ||||
|         it 'marks previous assignee todos as done' do | ||||
|           expect(todo.reload.done?).to eq true | ||||
|         end | ||||
| 
 | ||||
|         it 'creates a pending task for new assignee' do | ||||
|         it 'creates a todo for new assignee' do | ||||
|           attributes = { | ||||
|             project: project, | ||||
|             author: user, | ||||
|             user: user2, | ||||
|             target: issue, | ||||
|             action: Task::ASSIGNED, | ||||
|             target_id: issue.id, | ||||
|             target_type: issue.class.name, | ||||
|             action: Todo::ASSIGNED, | ||||
|             state: :pending | ||||
|           } | ||||
| 
 | ||||
|           expect(Task.where(attributes).count).to eq 1 | ||||
|           expect(Todo.where(attributes).count).to eq 1 | ||||
|         end | ||||
|       end | ||||
| 
 | ||||
|  | @ -131,8 +132,8 @@ describe Issues::UpdateService, services: true do | |||
|           update_issue({ milestone: create(:milestone) }) | ||||
|         end | ||||
| 
 | ||||
|         it 'marks pending tasks as done' do | ||||
|           expect(pending_task.reload.done?).to eq true | ||||
|         it 'marks todos as done' do | ||||
|           expect(todo.reload.done?).to eq true | ||||
|         end | ||||
|       end | ||||
| 
 | ||||
|  | @ -141,8 +142,8 @@ describe Issues::UpdateService, services: true do | |||
|           update_issue({ label_ids: [label.id] }) | ||||
|         end | ||||
| 
 | ||||
|         it 'marks pending tasks as done' do | ||||
|           expect(pending_task.reload.done?).to eq true | ||||
|         it 'marks todos as done' do | ||||
|           expect(todo.reload.done?).to eq true | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ describe MergeRequests::CloseService, services: true do | |||
|   let(:user2) { create(:user) } | ||||
|   let(:merge_request) { create(:merge_request, assignee: user2) } | ||||
|   let(:project) { merge_request.project } | ||||
|   let!(:pending_task) { create(:task, :assigned, user: user, project: project, target: merge_request, author: user2) } | ||||
|   let!(:todo) { create(:todo, :assigned, user: user, project: project, target: merge_request, author: user2) } | ||||
| 
 | ||||
|   before do | ||||
|     project.team << [user, :master] | ||||
|  | @ -43,8 +43,8 @@ describe MergeRequests::CloseService, services: true do | |||
|         expect(note.note).to include 'Status changed to closed' | ||||
|       end | ||||
| 
 | ||||
|       it 'marks pending tasks as done' do | ||||
|         expect(pending_task.reload).to be_done | ||||
|       it 'marks todos as done' do | ||||
|         expect(todo.reload).to be_done | ||||
|       end | ||||
|     end | ||||
|   end | ||||
|  |  | |||
|  | @ -34,13 +34,14 @@ describe MergeRequests::CreateService, services: true do | |||
|         expect(service).to have_received(:execute_hooks).with(@merge_request) | ||||
|       end | ||||
| 
 | ||||
|       it 'does not creates a pending task' do | ||||
|       it 'does not creates todos' do | ||||
|         attributes = { | ||||
|           project: project, | ||||
|           target: @merge_request | ||||
|           target_id: @merge_request.id, | ||||
|           target_type: @merge_request.class.name | ||||
|         } | ||||
| 
 | ||||
|         expect(Task.where(attributes).count).to be_zero | ||||
|         expect(Todo.where(attributes).count).to be_zero | ||||
|       end | ||||
| 
 | ||||
|       context 'when merge request is assigned to someone' do | ||||
|  | @ -56,17 +57,18 @@ describe MergeRequests::CreateService, services: true do | |||
| 
 | ||||
|         it { expect(@merge_request.assignee).to eq assignee } | ||||
| 
 | ||||
|         it 'creates a pending task for new assignee' do | ||||
|         it 'creates a todo for new assignee' do | ||||
|           attributes = { | ||||
|             project: project, | ||||
|             author: user, | ||||
|             user: assignee, | ||||
|             target: @merge_request, | ||||
|             action: Task::ASSIGNED, | ||||
|             target_id: @merge_request.id, | ||||
|             target_type: @merge_request.class.name, | ||||
|             action: Todo::ASSIGNED, | ||||
|             state: :pending | ||||
|           } | ||||
| 
 | ||||
|           expect(Task.where(attributes).count).to eq 1 | ||||
|           expect(Todo.where(attributes).count).to eq 1 | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|  |  | |||
|  | @ -98,16 +98,16 @@ describe MergeRequests::UpdateService, services: true do | |||
|       end | ||||
|     end | ||||
| 
 | ||||
|     context 'task queue' do | ||||
|       let!(:pending_task) { create(:task, :assigned, user: user, project: project, target: merge_request, author: user2) } | ||||
|     context 'todos' do | ||||
|       let!(:pending_todo) { create(:todo, :assigned, user: user, project: project, target: merge_request, author: user2) } | ||||
| 
 | ||||
|       context 'when the title change' do | ||||
|         before do | ||||
|           update_merge_request({ title: 'New title' }) | ||||
|         end | ||||
| 
 | ||||
|         it 'marks pending tasks as done' do | ||||
|           expect(pending_task.reload).to be_done | ||||
|         it 'marks pending todos as done' do | ||||
|           expect(pending_todo.reload).to be_done | ||||
|         end | ||||
|       end | ||||
| 
 | ||||
|  | @ -116,8 +116,8 @@ describe MergeRequests::UpdateService, services: true do | |||
|           update_merge_request({ description: 'Also please fix' }) | ||||
|         end | ||||
| 
 | ||||
|         it 'marks pending tasks as done' do | ||||
|           expect(pending_task.reload).to be_done | ||||
|         it 'marks pending todos as done' do | ||||
|           expect(pending_todo.reload).to be_done | ||||
|         end | ||||
|       end | ||||
| 
 | ||||
|  | @ -126,21 +126,22 @@ describe MergeRequests::UpdateService, services: true do | |||
|           update_merge_request({ assignee: user2 }) | ||||
|         end | ||||
| 
 | ||||
|         it 'marks previous assignee pending tasks as done' do | ||||
|           expect(pending_task.reload).to be_done | ||||
|         it 'marks previous assignee pending todos as done' do | ||||
|           expect(pending_todo.reload).to be_done | ||||
|         end | ||||
| 
 | ||||
|         it 'creates a pending task for new assignee' do | ||||
|         it 'creates a pending todo for new assignee' do | ||||
|           attributes = { | ||||
|             project: project, | ||||
|             author: user, | ||||
|             user: user2, | ||||
|             target: merge_request, | ||||
|             action: Task::ASSIGNED, | ||||
|             target_id: merge_request.id, | ||||
|             target_type: merge_request.class.name, | ||||
|             action: Todo::ASSIGNED, | ||||
|             state: :pending | ||||
|           } | ||||
| 
 | ||||
|           expect(Task.where(attributes).count).to eq 1 | ||||
|           expect(Todo.where(attributes).count).to eq 1 | ||||
|         end | ||||
|       end | ||||
| 
 | ||||
|  | @ -149,8 +150,8 @@ describe MergeRequests::UpdateService, services: true do | |||
|           update_merge_request({ milestone: create(:milestone) }) | ||||
|         end | ||||
| 
 | ||||
|         it 'marks pending tasks as done' do | ||||
|           expect(pending_task.reload).to be_done | ||||
|         it 'marks pending todos as done' do | ||||
|           expect(pending_todo.reload).to be_done | ||||
|         end | ||||
|       end | ||||
| 
 | ||||
|  | @ -159,8 +160,8 @@ describe MergeRequests::UpdateService, services: true do | |||
|           update_merge_request({ label_ids: [label.id] }) | ||||
|         end | ||||
| 
 | ||||
|         it 'marks pending tasks as done' do | ||||
|           expect(pending_task.reload).to be_done | ||||
|         it 'marks pending todos as done' do | ||||
|           expect(pending_todo.reload).to be_done | ||||
|         end | ||||
|       end | ||||
| 
 | ||||
|  | @ -169,8 +170,8 @@ describe MergeRequests::UpdateService, services: true do | |||
|           update_merge_request({ target_branch: 'target' }) | ||||
|         end | ||||
| 
 | ||||
|         it 'marks pending tasks as done' do | ||||
|           expect(pending_task.reload).to be_done | ||||
|         it 'marks pending todos as done' do | ||||
|           expect(pending_todo.reload).to be_done | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|  |  | |||
|  | @ -18,16 +18,16 @@ describe Notes::UpdateService, services: true do | |||
|       @note.reload | ||||
|     end | ||||
| 
 | ||||
|     context 'task queue' do | ||||
|       let!(:pending_task) { create(:task, :assigned, user: user, project: project, target: issue, author: user2) } | ||||
|     context 'todos' do | ||||
|       let!(:todo) { create(:todo, :assigned, user: user, project: project, target: issue, author: user2) } | ||||
| 
 | ||||
|       context 'when the note change' do | ||||
|         before do | ||||
|           update_note({ note: 'New note' }) | ||||
|         end | ||||
| 
 | ||||
|         it 'marks pending tasks as done' do | ||||
|           expect(pending_task.reload).to be_done | ||||
|         it 'marks todos as done' do | ||||
|           expect(todo.reload).to be_done | ||||
|         end | ||||
|       end | ||||
| 
 | ||||
|  | @ -36,8 +36,8 @@ describe Notes::UpdateService, services: true do | |||
|           update_note({ note: 'Old note' }) | ||||
|         end | ||||
| 
 | ||||
|         it 'keep pending tasks' do | ||||
|           expect(pending_task.reload).to be_pending | ||||
|         it 'keep todos' do | ||||
|           expect(todo.reload).to be_pending | ||||
|         end | ||||
|       end | ||||
|     end | ||||
|  |  | |||
|  | @ -1,264 +0,0 @@ | |||
| require 'spec_helper' | ||||
| 
 | ||||
| describe TaskService, services: true do | ||||
|   let(:author) { create(:user) } | ||||
|   let(:john_doe) { create(:user, username: 'john_doe') } | ||||
|   let(:michael) { create(:user, username: 'michael') } | ||||
|   let(:stranger) { create(:user, username: 'stranger') } | ||||
|   let(:project) { create(:project) } | ||||
|   let(:mentions) { [author.to_reference, john_doe.to_reference, michael.to_reference, stranger.to_reference].join(' ') } | ||||
|   let(:service) { described_class.new } | ||||
| 
 | ||||
|   before do | ||||
|     project.team << [author, :developer] | ||||
|     project.team << [john_doe, :developer] | ||||
|     project.team << [michael, :developer] | ||||
|   end | ||||
| 
 | ||||
|   describe 'Issues' do | ||||
|     let(:issue) { create(:issue, project: project, assignee: john_doe, author: author, description: mentions) } | ||||
|     let(:unassigned_issue) { create(:issue, project: project, assignee: nil) } | ||||
| 
 | ||||
|     describe '#new_issue' do | ||||
|       it 'creates a task if assigned' do | ||||
|         service.new_issue(issue, author) | ||||
| 
 | ||||
|         should_create_task(user: john_doe, target: issue, action: Task::ASSIGNED) | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create a task if unassigned' do | ||||
|         should_not_create_any_task { service.new_issue(unassigned_issue, author) } | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create a task if assignee is the current user' do | ||||
|         should_not_create_any_task { service.new_issue(unassigned_issue, john_doe) } | ||||
|       end | ||||
| 
 | ||||
|       it 'creates a task for each valid mentioned user' do | ||||
|         service.new_issue(issue, author) | ||||
| 
 | ||||
|         should_create_task(user: michael, target: issue, action: Task::MENTIONED) | ||||
|         should_not_create_task(user: author, target: issue, action: Task::MENTIONED) | ||||
|         should_not_create_task(user: john_doe, target: issue, action: Task::MENTIONED) | ||||
|         should_not_create_task(user: stranger, target: issue, action: Task::MENTIONED) | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     describe '#update_issue' do | ||||
|       it 'creates a task for each valid mentioned user' do | ||||
|         service.update_issue(issue, author) | ||||
| 
 | ||||
|         should_create_task(user: michael, target: issue, action: Task::MENTIONED) | ||||
|         should_create_task(user: john_doe, target: issue, action: Task::MENTIONED) | ||||
|         should_not_create_task(user: author, target: issue, action: Task::MENTIONED) | ||||
|         should_not_create_task(user: stranger, target: issue, action: Task::MENTIONED) | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create a task if user was already mentioned' do | ||||
|         create(:task, :mentioned, user: michael, project: project, target: issue, author: author) | ||||
| 
 | ||||
|         expect { service.update_issue(issue, author) }.not_to change(michael.tasks, :count) | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     describe '#close_issue' do | ||||
|       it 'marks related pending tasks to the target for the user as done' do | ||||
|         first_task = create(:task, :assigned, user: john_doe, project: project, target: issue, author: author) | ||||
|         second_task = create(:task, :assigned, user: john_doe, project: project, target: issue, author: author) | ||||
| 
 | ||||
|         service.close_issue(issue, john_doe) | ||||
| 
 | ||||
|         expect(first_task.reload).to be_done | ||||
|         expect(second_task.reload).to be_done | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     describe '#reassigned_issue' do | ||||
|       it 'creates a pending task for new assignee' do | ||||
|         unassigned_issue.update_attribute(:assignee, john_doe) | ||||
|         service.reassigned_issue(unassigned_issue, author) | ||||
| 
 | ||||
|         should_create_task(user: john_doe, target: unassigned_issue, action: Task::ASSIGNED) | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create a task if unassigned' do | ||||
|         issue.update_attribute(:assignee, nil) | ||||
| 
 | ||||
|         should_not_create_any_task { service.reassigned_issue(issue, author) } | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create a task if new assignee is the current user' do | ||||
|         unassigned_issue.update_attribute(:assignee, john_doe) | ||||
| 
 | ||||
|         should_not_create_any_task { service.reassigned_issue(unassigned_issue, john_doe) } | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     describe '#mark_pending_tasks_as_done' do | ||||
|       it 'marks related pending tasks to the target for the user as done' do | ||||
|         first_task = create(:task, :assigned, user: john_doe, project: project, target: issue, author: author) | ||||
|         second_task = create(:task, :assigned, user: john_doe, project: project, target: issue, author: author) | ||||
| 
 | ||||
|         service.mark_pending_tasks_as_done(issue, john_doe) | ||||
| 
 | ||||
|         expect(first_task.reload).to be_done | ||||
|         expect(second_task.reload).to be_done | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     describe '#new_note' do | ||||
|       let!(:first_task) { create(:task, :assigned, user: john_doe, project: project, target: issue, author: author) } | ||||
|       let!(:second_task) { create(:task, :assigned, user: john_doe, project: project, target: issue, author: author) } | ||||
|       let(:note) { create(:note, project: project, noteable: issue, author: john_doe, note: mentions) } | ||||
|       let(:award_note) { create(:note, :award, project: project, noteable: issue, author: john_doe, note: 'thumbsup') } | ||||
|       let(:system_note) { create(:system_note, project: project, noteable: issue) } | ||||
| 
 | ||||
|       it 'mark related pending tasks to the noteable for the note author as done' do | ||||
|         first_task = create(:task, :assigned, user: john_doe, project: project, target: issue, author: author) | ||||
|         second_task = create(:task, :assigned, user: john_doe, project: project, target: issue, author: author) | ||||
| 
 | ||||
|         service.new_note(note, john_doe) | ||||
| 
 | ||||
|         expect(first_task.reload).to be_done | ||||
|         expect(second_task.reload).to be_done | ||||
|       end | ||||
| 
 | ||||
|       it 'mark related pending tasks to the noteable for the award note author as done' do | ||||
|         service.new_note(award_note, john_doe) | ||||
| 
 | ||||
|         expect(first_task.reload).to be_done | ||||
|         expect(second_task.reload).to be_done | ||||
|       end | ||||
| 
 | ||||
|       it 'does not mark related pending tasks it is a system note' do | ||||
|         service.new_note(system_note, john_doe) | ||||
| 
 | ||||
|         expect(first_task.reload).to be_pending | ||||
|         expect(second_task.reload).to be_pending | ||||
|       end | ||||
| 
 | ||||
|       it 'creates a task for each valid mentioned user' do | ||||
|         service.new_note(note, john_doe) | ||||
| 
 | ||||
|         should_create_task(user: michael, target: issue, author: john_doe, action: Task::MENTIONED, note: note) | ||||
|         should_create_task(user: author, target: issue, author: john_doe, action: Task::MENTIONED, note: note) | ||||
|         should_not_create_task(user: john_doe, target: issue, author: john_doe, action: Task::MENTIONED, note: note) | ||||
|         should_not_create_task(user: stranger, target: issue, author: john_doe, action: Task::MENTIONED, note: note) | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe 'Merge Requests' do | ||||
|     let(:mr_assigned) { create(:merge_request, source_project: project, author: author, assignee: john_doe, description: mentions) } | ||||
|     let(:mr_unassigned) { create(:merge_request, source_project: project, author: author, assignee: nil) } | ||||
| 
 | ||||
|     describe '#new_merge_request' do | ||||
|       it 'creates a pending task if assigned' do | ||||
|         service.new_merge_request(mr_assigned, author) | ||||
| 
 | ||||
|         should_create_task(user: john_doe, target: mr_assigned, action: Task::ASSIGNED) | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create a task if unassigned' do | ||||
|         should_not_create_any_task { service.new_merge_request(mr_unassigned, author) } | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create a task if assignee is the current user' do | ||||
|         should_not_create_any_task { service.new_merge_request(mr_unassigned, john_doe) } | ||||
|       end | ||||
| 
 | ||||
|       it 'creates a task for each valid mentioned user' do | ||||
|         service.new_merge_request(mr_assigned, author) | ||||
| 
 | ||||
|         should_create_task(user: michael, target: mr_assigned, action: Task::MENTIONED) | ||||
|         should_not_create_task(user: author, target: mr_assigned, action: Task::MENTIONED) | ||||
|         should_not_create_task(user: john_doe, target: mr_assigned, action: Task::MENTIONED) | ||||
|         should_not_create_task(user: stranger, target: mr_assigned, action: Task::MENTIONED) | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     describe '#update_merge_request' do | ||||
|       it 'creates a task for each valid mentioned user' do | ||||
|         service.update_merge_request(mr_assigned, author) | ||||
| 
 | ||||
|         should_create_task(user: michael, target: mr_assigned, action: Task::MENTIONED) | ||||
|         should_create_task(user: john_doe, target: mr_assigned, action: Task::MENTIONED) | ||||
|         should_not_create_task(user: author, target: mr_assigned, action: Task::MENTIONED) | ||||
|         should_not_create_task(user: stranger, target: mr_assigned, action: Task::MENTIONED) | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create a task if user was already mentioned' do | ||||
|         create(:task, :mentioned, user: michael, project: project, target: mr_assigned, author: author) | ||||
| 
 | ||||
|         expect { service.update_merge_request(mr_assigned, author) }.not_to change(michael.tasks, :count) | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     describe '#close_merge_request' do | ||||
|       it 'marks related pending tasks to the target for the user as done' do | ||||
|         first_task = create(:task, :assigned, user: john_doe, project: project, target: mr_assigned, author: author) | ||||
|         second_task = create(:task, :assigned, user: john_doe, project: project, target: mr_assigned, author: author) | ||||
|         service.close_merge_request(mr_assigned, john_doe) | ||||
| 
 | ||||
|         expect(first_task.reload).to be_done | ||||
|         expect(second_task.reload).to be_done | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     describe '#reassigned_merge_request' do | ||||
|       it 'creates a pending task for new assignee' do | ||||
|         mr_unassigned.update_attribute(:assignee, john_doe) | ||||
|         service.reassigned_merge_request(mr_unassigned, author) | ||||
| 
 | ||||
|         should_create_task(user: john_doe, target: mr_unassigned, action: Task::ASSIGNED) | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create a task if unassigned' do | ||||
|         mr_assigned.update_attribute(:assignee, nil) | ||||
| 
 | ||||
|         should_not_create_any_task { service.reassigned_merge_request(mr_assigned, author) } | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create a task if new assignee is the current user' do | ||||
|         mr_assigned.update_attribute(:assignee, john_doe) | ||||
| 
 | ||||
|         should_not_create_any_task { service.reassigned_merge_request(mr_assigned, john_doe) } | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     describe '#merge_merge_request' do | ||||
|       it 'marks related pending tasks to the target for the user as done' do | ||||
|         first_task = create(:task, :assigned, user: john_doe, project: project, target: mr_assigned, author: author) | ||||
|         second_task = create(:task, :assigned, user: john_doe, project: project, target: mr_assigned, author: author) | ||||
|         service.merge_merge_request(mr_assigned, john_doe) | ||||
| 
 | ||||
|         expect(first_task.reload).to be_done | ||||
|         expect(second_task.reload).to be_done | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def should_create_task(attributes = {}) | ||||
|     attributes.reverse_merge!( | ||||
|       project: project, | ||||
|       author: author, | ||||
|       state: :pending | ||||
|     ) | ||||
| 
 | ||||
|     expect(Task.where(attributes).count).to eq 1 | ||||
|   end | ||||
| 
 | ||||
|   def should_not_create_task(attributes = {}) | ||||
|     attributes.reverse_merge!( | ||||
|       project: project, | ||||
|       author: author, | ||||
|       state: :pending | ||||
|     ) | ||||
| 
 | ||||
|     expect(Task.where(attributes).count).to eq 0 | ||||
|   end | ||||
| 
 | ||||
|   def should_not_create_any_task | ||||
|     expect { yield }.not_to change(Task, :count) | ||||
|   end | ||||
| end | ||||
|  | @ -0,0 +1,264 @@ | |||
| require 'spec_helper' | ||||
| 
 | ||||
| describe TodoService, services: true do | ||||
|   let(:author) { create(:user) } | ||||
|   let(:john_doe) { create(:user, username: 'john_doe') } | ||||
|   let(:michael) { create(:user, username: 'michael') } | ||||
|   let(:stranger) { create(:user, username: 'stranger') } | ||||
|   let(:project) { create(:project) } | ||||
|   let(:mentions) { [author.to_reference, john_doe.to_reference, michael.to_reference, stranger.to_reference].join(' ') } | ||||
|   let(:service) { described_class.new } | ||||
| 
 | ||||
|   before do | ||||
|     project.team << [author, :developer] | ||||
|     project.team << [john_doe, :developer] | ||||
|     project.team << [michael, :developer] | ||||
|   end | ||||
| 
 | ||||
|   describe 'Issues' do | ||||
|     let(:issue) { create(:issue, project: project, assignee: john_doe, author: author, description: mentions) } | ||||
|     let(:unassigned_issue) { create(:issue, project: project, assignee: nil) } | ||||
| 
 | ||||
|     describe '#new_issue' do | ||||
|       it 'creates a todo if assigned' do | ||||
|         service.new_issue(issue, author) | ||||
| 
 | ||||
|         should_create_todo(user: john_doe, target: issue, action: Todo::ASSIGNED) | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create a todo if unassigned' do | ||||
|         should_not_create_any_todo { service.new_issue(unassigned_issue, author) } | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create a todo if assignee is the current user' do | ||||
|         should_not_create_any_todo { service.new_issue(unassigned_issue, john_doe) } | ||||
|       end | ||||
| 
 | ||||
|       it 'creates a todo for each valid mentioned user' do | ||||
|         service.new_issue(issue, author) | ||||
| 
 | ||||
|         should_create_todo(user: michael, target: issue, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: author, target: issue, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: john_doe, target: issue, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: stranger, target: issue, action: Todo::MENTIONED) | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     describe '#update_issue' do | ||||
|       it 'creates a todo for each valid mentioned user' do | ||||
|         service.update_issue(issue, author) | ||||
| 
 | ||||
|         should_create_todo(user: michael, target: issue, action: Todo::MENTIONED) | ||||
|         should_create_todo(user: john_doe, target: issue, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: author, target: issue, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: stranger, target: issue, action: Todo::MENTIONED) | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create a todo if user was already mentioned' do | ||||
|         create(:todo, :mentioned, user: michael, project: project, target: issue, author: author) | ||||
| 
 | ||||
|         expect { service.update_issue(issue, author) }.not_to change(michael.todos, :count) | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     describe '#close_issue' do | ||||
|       it 'marks related pending todos to the target for the user as done' do | ||||
|         first_todo = create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author) | ||||
|         second_todo = create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author) | ||||
| 
 | ||||
|         service.close_issue(issue, john_doe) | ||||
| 
 | ||||
|         expect(first_todo.reload).to be_done | ||||
|         expect(second_todo.reload).to be_done | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     describe '#reassigned_issue' do | ||||
|       it 'creates a pending todo for new assignee' do | ||||
|         unassigned_issue.update_attribute(:assignee, john_doe) | ||||
|         service.reassigned_issue(unassigned_issue, author) | ||||
| 
 | ||||
|         should_create_todo(user: john_doe, target: unassigned_issue, action: Todo::ASSIGNED) | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create a todo if unassigned' do | ||||
|         issue.update_attribute(:assignee, nil) | ||||
| 
 | ||||
|         should_not_create_any_todo { service.reassigned_issue(issue, author) } | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create a todo if new assignee is the current user' do | ||||
|         unassigned_issue.update_attribute(:assignee, john_doe) | ||||
| 
 | ||||
|         should_not_create_any_todo { service.reassigned_issue(unassigned_issue, john_doe) } | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     describe '#mark_pending_todos_as_done' do | ||||
|       it 'marks related pending todos to the target for the user as done' do | ||||
|         first_todo = create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author) | ||||
|         second_todo = create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author) | ||||
| 
 | ||||
|         service.mark_pending_todos_as_done(issue, john_doe) | ||||
| 
 | ||||
|         expect(first_todo.reload).to be_done | ||||
|         expect(second_todo.reload).to be_done | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     describe '#new_note' do | ||||
|       let!(:first_todo) { create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author) } | ||||
|       let!(:second_todo) { create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author) } | ||||
|       let(:note) { create(:note, project: project, noteable: issue, author: john_doe, note: mentions) } | ||||
|       let(:award_note) { create(:note, :award, project: project, noteable: issue, author: john_doe, note: 'thumbsup') } | ||||
|       let(:system_note) { create(:system_note, project: project, noteable: issue) } | ||||
| 
 | ||||
|       it 'mark related pending todos to the noteable for the note author as done' do | ||||
|         first_todo = create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author) | ||||
|         second_todo = create(:todo, :assigned, user: john_doe, project: project, target: issue, author: author) | ||||
| 
 | ||||
|         service.new_note(note, john_doe) | ||||
| 
 | ||||
|         expect(first_todo.reload).to be_done | ||||
|         expect(second_todo.reload).to be_done | ||||
|       end | ||||
| 
 | ||||
|       it 'mark related pending todos to the noteable for the award note author as done' do | ||||
|         service.new_note(award_note, john_doe) | ||||
| 
 | ||||
|         expect(first_todo.reload).to be_done | ||||
|         expect(second_todo.reload).to be_done | ||||
|       end | ||||
| 
 | ||||
|       it 'does not mark related pending todos it is a system note' do | ||||
|         service.new_note(system_note, john_doe) | ||||
| 
 | ||||
|         expect(first_todo.reload).to be_pending | ||||
|         expect(second_todo.reload).to be_pending | ||||
|       end | ||||
| 
 | ||||
|       it 'creates a todo for each valid mentioned user' do | ||||
|         service.new_note(note, john_doe) | ||||
| 
 | ||||
|         should_create_todo(user: michael, target: issue, author: john_doe, action: Todo::MENTIONED, note: note) | ||||
|         should_create_todo(user: author, target: issue, author: john_doe, action: Todo::MENTIONED, note: note) | ||||
|         should_not_create_todo(user: john_doe, target: issue, author: john_doe, action: Todo::MENTIONED, note: note) | ||||
|         should_not_create_todo(user: stranger, target: issue, author: john_doe, action: Todo::MENTIONED, note: note) | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   describe 'Merge Requests' do | ||||
|     let(:mr_assigned) { create(:merge_request, source_project: project, author: author, assignee: john_doe, description: mentions) } | ||||
|     let(:mr_unassigned) { create(:merge_request, source_project: project, author: author, assignee: nil) } | ||||
| 
 | ||||
|     describe '#new_merge_request' do | ||||
|       it 'creates a pending todo if assigned' do | ||||
|         service.new_merge_request(mr_assigned, author) | ||||
| 
 | ||||
|         should_create_todo(user: john_doe, target: mr_assigned, action: Todo::ASSIGNED) | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create a todo if unassigned' do | ||||
|         should_not_create_any_todo { service.new_merge_request(mr_unassigned, author) } | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create a todo if assignee is the current user' do | ||||
|         should_not_create_any_todo { service.new_merge_request(mr_unassigned, john_doe) } | ||||
|       end | ||||
| 
 | ||||
|       it 'creates a todo for each valid mentioned user' do | ||||
|         service.new_merge_request(mr_assigned, author) | ||||
| 
 | ||||
|         should_create_todo(user: michael, target: mr_assigned, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: author, target: mr_assigned, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: john_doe, target: mr_assigned, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: stranger, target: mr_assigned, action: Todo::MENTIONED) | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     describe '#update_merge_request' do | ||||
|       it 'creates a todo for each valid mentioned user' do | ||||
|         service.update_merge_request(mr_assigned, author) | ||||
| 
 | ||||
|         should_create_todo(user: michael, target: mr_assigned, action: Todo::MENTIONED) | ||||
|         should_create_todo(user: john_doe, target: mr_assigned, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: author, target: mr_assigned, action: Todo::MENTIONED) | ||||
|         should_not_create_todo(user: stranger, target: mr_assigned, action: Todo::MENTIONED) | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create a todo if user was already mentioned' do | ||||
|         create(:todo, :mentioned, user: michael, project: project, target: mr_assigned, author: author) | ||||
| 
 | ||||
|         expect { service.update_merge_request(mr_assigned, author) }.not_to change(michael.todos, :count) | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     describe '#close_merge_request' do | ||||
|       it 'marks related pending todos to the target for the user as done' do | ||||
|         first_todo = create(:todo, :assigned, user: john_doe, project: project, target: mr_assigned, author: author) | ||||
|         second_todo = create(:todo, :assigned, user: john_doe, project: project, target: mr_assigned, author: author) | ||||
|         service.close_merge_request(mr_assigned, john_doe) | ||||
| 
 | ||||
|         expect(first_todo.reload).to be_done | ||||
|         expect(second_todo.reload).to be_done | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     describe '#reassigned_merge_request' do | ||||
|       it 'creates a pending todo for new assignee' do | ||||
|         mr_unassigned.update_attribute(:assignee, john_doe) | ||||
|         service.reassigned_merge_request(mr_unassigned, author) | ||||
| 
 | ||||
|         should_create_todo(user: john_doe, target: mr_unassigned, action: Todo::ASSIGNED) | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create a todo if unassigned' do | ||||
|         mr_assigned.update_attribute(:assignee, nil) | ||||
| 
 | ||||
|         should_not_create_any_todo { service.reassigned_merge_request(mr_assigned, author) } | ||||
|       end | ||||
| 
 | ||||
|       it 'does not create a todo if new assignee is the current user' do | ||||
|         mr_assigned.update_attribute(:assignee, john_doe) | ||||
| 
 | ||||
|         should_not_create_any_todo { service.reassigned_merge_request(mr_assigned, john_doe) } | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|     describe '#merge_merge_request' do | ||||
|       it 'marks related pending todos to the target for the user as done' do | ||||
|         first_todo = create(:todo, :assigned, user: john_doe, project: project, target: mr_assigned, author: author) | ||||
|         second_todo = create(:todo, :assigned, user: john_doe, project: project, target: mr_assigned, author: author) | ||||
|         service.merge_merge_request(mr_assigned, john_doe) | ||||
| 
 | ||||
|         expect(first_todo.reload).to be_done | ||||
|         expect(second_todo.reload).to be_done | ||||
|       end | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   def should_create_todo(attributes = {}) | ||||
|     attributes.reverse_merge!( | ||||
|       project: project, | ||||
|       author: author, | ||||
|       state: :pending | ||||
|     ) | ||||
| 
 | ||||
|     expect(Todo.where(attributes).count).to eq 1 | ||||
|   end | ||||
| 
 | ||||
|   def should_not_create_todo(attributes = {}) | ||||
|     attributes.reverse_merge!( | ||||
|       project: project, | ||||
|       author: author, | ||||
|       state: :pending | ||||
|     ) | ||||
| 
 | ||||
|     expect(Todo.where(attributes).count).to eq 0 | ||||
|   end | ||||
| 
 | ||||
|   def should_not_create_any_todo | ||||
|     expect { yield }.not_to change(Todo, :count) | ||||
|   end | ||||
| end | ||||
		Loading…
	
		Reference in New Issue