Create a pending task when a user is mentioned on a note
This commit is contained in:
parent
14fc05ebfd
commit
1d476b0656
|
@ -59,6 +59,15 @@
|
|||
.task-note {
|
||||
word-wrap: break-word;
|
||||
|
||||
.md {
|
||||
color: #7f8fa4;
|
||||
font-size: $gl-font-size;
|
||||
|
||||
p {
|
||||
color: #5c5d5e;
|
||||
}
|
||||
}
|
||||
|
||||
pre {
|
||||
border: none;
|
||||
background: #f9f9f9;
|
||||
|
@ -68,10 +77,25 @@
|
|||
overflow: hidden;
|
||||
}
|
||||
|
||||
.note-image-attach {
|
||||
margin-top: 4px;
|
||||
margin-left: 0px;
|
||||
max-width: 200px;
|
||||
float: none;
|
||||
}
|
||||
|
||||
p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.task-note-icon {
|
||||
color: #777;
|
||||
float: left;
|
||||
font-size: $gl-font-size;
|
||||
line-height: 16px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
&:last-child { border:none }
|
||||
|
|
|
@ -22,4 +22,20 @@ module TasksHelper
|
|||
|
||||
[task.action_name, target].join(" ")
|
||||
end
|
||||
|
||||
def task_note_link_html(task)
|
||||
link_to task_note_target_path(task) do
|
||||
"##{task.target_iid}"
|
||||
end
|
||||
end
|
||||
|
||||
def task_note_target_path(task)
|
||||
polymorphic_path([task.project.namespace.becomes(Namespace),
|
||||
task.project, task.target], anchor: dom_id(task.note))
|
||||
end
|
||||
|
||||
def task_note(text, options = {})
|
||||
text = first_line_in_markdown(text, 150, options)
|
||||
sanitize(text, tags: %w(a img b pre code p span))
|
||||
end
|
||||
end
|
||||
|
|
|
@ -37,6 +37,8 @@ class Note < ActiveRecord::Base
|
|||
belongs_to :author, class_name: "User"
|
||||
belongs_to :updated_by, class_name: "User"
|
||||
|
||||
has_many :tasks, dependent: :delete_all
|
||||
|
||||
delegate :name, to: :project, prefix: true
|
||||
delegate :name, :email, to: :author, prefix: true
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
# target_id :integer not null
|
||||
# target_type :string not null
|
||||
# author_id :integer
|
||||
# note_id :integer
|
||||
# action :integer
|
||||
# state :string not null
|
||||
# created_at :datetime
|
||||
|
@ -19,6 +20,7 @@ class Task < ActiveRecord::Base
|
|||
MENTIONED = 2
|
||||
|
||||
belongs_to :author, class_name: "User"
|
||||
belongs_to :note
|
||||
belongs_to :project
|
||||
belongs_to :target, polymorphic: true, touch: true
|
||||
belongs_to :user
|
||||
|
@ -52,6 +54,10 @@ class Task < ActiveRecord::Base
|
|||
target.respond_to? :title
|
||||
end
|
||||
|
||||
def note_text
|
||||
note.try(:note)
|
||||
end
|
||||
|
||||
def target_iid
|
||||
target.respond_to?(:iid) ? target.iid : target_id
|
||||
end
|
||||
|
|
|
@ -77,7 +77,17 @@ class TaskService
|
|||
def new_note(note)
|
||||
# Skip system notes, like status changes and cross-references
|
||||
unless note.system
|
||||
mark_pending_tasks_as_done(note.noteable, note.author)
|
||||
project = note.project
|
||||
target = note.noteable
|
||||
author = note.author
|
||||
|
||||
mark_pending_tasks_as_done(target, author)
|
||||
|
||||
mentioned_users = build_mentioned_users(project, note, author)
|
||||
|
||||
mentioned_users.each do |user|
|
||||
create_task(project, target, author, user, Task::MENTIONED, note)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -94,14 +104,15 @@ class TaskService
|
|||
|
||||
private
|
||||
|
||||
def create_task(project, target, author, user, action)
|
||||
def create_task(project, target, author, user, action, note = nil)
|
||||
attributes = {
|
||||
project: project,
|
||||
user_id: user.id,
|
||||
author_id: author.id,
|
||||
target_id: target.id,
|
||||
target_type: target.class.name,
|
||||
action: action
|
||||
action: action,
|
||||
note: note
|
||||
}
|
||||
|
||||
Task.create(attributes)
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
.task-title
|
||||
%span.author_name= link_to_author task
|
||||
%span.task_label{class: task.action_name}
|
||||
= task_action_name(task)
|
||||
|
||||
%strong= link_to "##{task.target_iid}", [task.project.namespace.becomes(Namespace), task.project, task.target]
|
||||
|
||||
· #{time_ago_with_tooltip(task.created_at)}
|
||||
|
||||
- if task.pending?
|
||||
.task-actions.pull-right
|
||||
= link_to 'Done', [:dashboard, task], method: :delete, class: 'btn'
|
||||
|
||||
- if task.body?
|
||||
.task-body
|
||||
.task-note
|
||||
= task.target.title
|
|
@ -0,0 +1,26 @@
|
|||
.task-title
|
||||
%span.author_name
|
||||
= link_to_author task
|
||||
%span.task_label{class: task.action_name}
|
||||
= task_action_name(task)
|
||||
= task_note_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
|
||||
= task_note(task.note_text, project: task.project)
|
||||
- note = task.note
|
||||
- if note.attachment.url
|
||||
- if note.attachment.image?
|
||||
= link_to note.attachment.url, target: '_blank' do
|
||||
= image_tag note.attachment.url, class: 'note-image-attach'
|
||||
- else
|
||||
= link_to note.attachment.url, target: "_blank", class: 'note-file-attach' do
|
||||
%i.fa.fa-paperclip
|
||||
= note.attachment_identifier
|
|
@ -2,20 +2,7 @@
|
|||
.task-item{class: "#{task.body? ? 'task-block' : 'task-inline' }"}
|
||||
= image_tag avatar_icon(task.author_email, 40), class: "avatar s40", alt:''
|
||||
|
||||
.task-title
|
||||
%span.author_name= link_to_author task
|
||||
%span.task_label{class: task.action_name}
|
||||
= task_action_name(task)
|
||||
|
||||
%strong= link_to "##{task.target_iid}", [task.project.namespace.becomes(Namespace), task.project, task.target]
|
||||
|
||||
· #{time_ago_with_tooltip(task.created_at)}
|
||||
|
||||
- if task.pending?
|
||||
.task-actions.pull-right
|
||||
= link_to 'Done', [:dashboard, task], method: :delete, class: 'btn'
|
||||
|
||||
- if task.body?
|
||||
.task-body
|
||||
.task-note
|
||||
= task.target.title
|
||||
- if task.note.present?
|
||||
= render 'note', task: task
|
||||
- else
|
||||
= render 'common', task: task
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
class AddNoteToTasks < ActiveRecord::Migration
|
||||
def change
|
||||
add_reference :tasks, :note, index: true
|
||||
end
|
||||
end
|
|
@ -11,7 +11,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20160217100506) do
|
||||
ActiveRecord::Schema.define(version: 20160217174422) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
@ -834,9 +834,11 @@ ActiveRecord::Schema.define(version: 20160217100506) do
|
|||
t.string "state", null: false
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
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
|
||||
|
|
|
@ -26,6 +26,8 @@ describe Note, models: true do
|
|||
it { is_expected.to belong_to(:project) }
|
||||
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(:delete_all) }
|
||||
end
|
||||
|
||||
describe 'validation' do
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
# target_id :integer not null
|
||||
# target_type :string not null
|
||||
# author_id :integer
|
||||
# note_id :integer
|
||||
# action :integer
|
||||
# state :string not null
|
||||
# created_at :datetime
|
||||
|
@ -19,6 +20,7 @@ require 'spec_helper'
|
|||
describe Task, models: true do
|
||||
describe 'relationships' do
|
||||
it { is_expected.to belong_to(:author).class_name("User") }
|
||||
it { is_expected.to belong_to(:note) }
|
||||
it { is_expected.to belong_to(:project) }
|
||||
it { is_expected.to belong_to(:target).touch(true) }
|
||||
it { is_expected.to belong_to(:user) }
|
||||
|
@ -48,6 +50,20 @@ describe Task, models: true do
|
|||
it 'returns false when target does not respond to title'
|
||||
end
|
||||
|
||||
describe '#note_text' do
|
||||
it 'returns nil when note is blank' do
|
||||
subject.note = nil
|
||||
|
||||
expect(subject.note_text).to be_nil
|
||||
end
|
||||
|
||||
it 'returns note when note is present' do
|
||||
subject.note = build(:note, note: 'quick fix')
|
||||
|
||||
expect(subject.note_text).to eq 'quick fix'
|
||||
end
|
||||
end
|
||||
|
||||
describe '#target_iid' do
|
||||
it 'returns target.iid when target respond to iid'
|
||||
it 'returns target_id when target does not respond to iid'
|
||||
|
|
|
@ -128,6 +128,17 @@ describe TaskService, services: true do
|
|||
expect(first_pending_task.reload).to be_pending
|
||||
expect(second_pending_task.reload).to be_pending
|
||||
end
|
||||
|
||||
it 'creates a task for each valid mentioned user' do
|
||||
note.update_attribute(:note, mentions)
|
||||
|
||||
service.new_note(note)
|
||||
|
||||
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
|
||||
|
||||
|
|
Loading…
Reference in New Issue