[refs #194] assignee & user

This commit is contained in:
Alexander Machehin 2012-04-14 01:44:04 +06:00
parent ba9184cc49
commit 2dedbd92d0
17 changed files with 91 additions and 82 deletions

View File

@ -128,28 +128,28 @@ $(document).ready(function() {
return false;
});
function remExecutor(form) {
var el = form.find('.people.selected.remove_executor');
function remAssignee(form) {
var el = form.find('.people.selected.remove_assignee');
var id = el.attr('id');
$('#manage_issue_users_list .add_executor.people.selected').removeClass('select');
$('#manage_issue_users_list .add_assignee.people.selected').removeClass('select');
el.remove();
}
$('.add_executor.people.selected').live('click', function() {
$('.add_assignee.people.selected').live('click', function() {
var form_new = $('form.issue');
var form_edit = $('form.edit_form.issue');
form_new.find('#people-span').fadeOut(0);
remExecutor(form_new);
var clone = $(this).clone().removeClass('add_executor').addClass('remove_executor');
form_new.find('#issue_executor').html(clone);
$('.current_executor').html(clone.removeClass('select'));
remAssignee(form_new);
var clone = $(this).clone().removeClass('add_assignee').addClass('remove_assignee');
form_new.find('#issue_assignee').html(clone);
$('.current_assignee').html(clone.removeClass('select'));
$(this).addClass('select');
});
$('.remove_executor.people.selected').live('click', function() {
$('.remove_assignee.people.selected').live('click', function() {
var form = $('form.issue, form.edit_form issue');
form.find('#people-span').fadeIn(0);
remExecutor(form);
remAssignee(form);
});
function remLabel(form, id) {
@ -241,9 +241,9 @@ $(document).ready(function() {
return false;
});
$('.button.manage_executor').live('click', function() {
$('form#search_user, .button.update_executor').fadeIn(0);
$('.current_executor .people').addClass('remove_executor selected').removeClass('nopointer');
$('.button.manage_assignee').live('click', function() {
$('form#search_user, .button.update_assignee').fadeIn(0);
$('.current_assignee .people').addClass('remove_assignee selected').removeClass('nopointer');
$(this).fadeOut(0);
});
@ -254,16 +254,16 @@ $(document).ready(function() {
$(this).fadeOut(0);
});
$('.button.update_executor').live('click', function() {
var form = $('form.edit_executor.issue');
$('.button.update_assignee').live('click', function() {
var form = $('form.edit_assignee.issue');
$.ajax({
type: 'POST',
url: form.attr("action"),
data: form.serialize(),
success: function(data){
$('.current_executor .people').removeClass('remove_executor selected').addClass('nopointer');
$('form#search_user, .button.update_executor').fadeOut(0);
$('.button.manage_executor').fadeIn(0);
$('.current_assignee .people').removeClass('remove_assignee selected').addClass('nopointer');
$('form#search_user, .button.update_assignee').fadeOut(0);
$('.button.manage_assignee').fadeIn(0);
$('#manage_issue_users_list').html('');
},
error: function(data){

View File

@ -14,7 +14,7 @@ class IssuesController < ApplicationController
@status = params[:status] == 'closed' ? 'closed' : 'open'
@labels = params[:labels] || []
@issues = @project.issues
@issues = @issues.where(:user_id => current_user.id) if @is_assigned_to_me
@issues = @issues.where(:assignee_id => current_user.id) if @is_assigned_to_me
@issues = @issues.joins(:labels).where(:labels => {:name => @labels}) unless @labels == []
if params[:search_issue]
@ -25,7 +25,7 @@ class IssuesController < ApplicationController
@issues = @issues.where(:status => @status)
@issues = @issues.includes(:creator, :user).order('serial_id desc').uniq.paginate :per_page => 10, :page => params[:page]
@issues = @issues.includes(:assignee, :user).order('serial_id desc').uniq.paginate :per_page => 10, :page => params[:page]
if status == 200
render 'index', :layout => request.format == '*/*' ? 'issues' : 'application' # maybe FIXME '*/*'?
else
@ -38,9 +38,9 @@ class IssuesController < ApplicationController
end
def create
@user_uname = params[:user_uname]
@assignee_uname = params[:assignee_uname]
@issue = @project.issues.new(params[:issue])
@issue.creator_id = current_user.id
@issue.user_id = current_user.id
if @issue.save
@issue.subscribe_creator(current_user.id)

View File

@ -19,17 +19,17 @@ class ActivityFeedObserver < ActiveRecord::Observer
ActivityFeed.create(
:user => recipient,
:kind => 'new_issue_notification',
:data => {:user_name => record.creator.name, :user_email => record.creator.email, :user_id => record.creator_id,:issue_serial_id => record.serial_id,
:data => {:user_name => record.user.name, :user_email => record.user.email, :user_id => record.user_id,:issue_serial_id => record.serial_id,
:issue_title => record.title, :project_id => record.project.id, :project_name => record.project.name, :project_owner => record.project.owner.uname}
)
end
if record.user_id_changed?
UserMailer.delay.issue_assign_notification(record, record.user) if record.user.notifier.issue_assign && record.user.notifier.can_notify
if record.assignee_id_changed?
UserMailer.delay.issue_assign_notification(record, record.assignee) if record.assignee.notifier.issue_assign && record.assignee.notifier.can_notify
ActivityFeed.create(
:user => record.user,
:kind => 'issue_assign_notification',
:data => {:user_name => record.creator.name, :user_email => record.creator.email, :user_id => record.creator_id, :issue_serial_id => record.serial_id,
:data => {:user_name => record.user.name, :user_email => record.user.email, :user_id => record.user_id, :issue_serial_id => record.serial_id,
:project_id => record.project.id, :issue_title => record.title, :project_name => record.project.name, :project_owner => record.project.owner.uname}
)
end
@ -121,12 +121,12 @@ class ActivityFeedObserver < ActiveRecord::Observer
def after_update(record)
case record.class.to_s
when 'Issue'
if record.user_id && record.user_id_changed?
UserMailer.delay.issue_assign_notification(record, record.user) if record.user.notifier.issue_assign && record.user.notifier.can_notify
if record.assignee_id && record.assignee_id_changed?
UserMailer.delay.issue_assign_notification(record, record.assignee) if record.assignee.notifier.issue_assign && record.assignee.notifier.can_notify
ActivityFeed.create(
:user => record.user,
:user => record.assignee,
:kind => 'issue_assign_notification',
:data => {:user_name => record.user.name, :user_email => record.user.email, :issue_serial_id => record.serial_id, :issue_title => record.title,
:data => {:user_name => record.assignee.name, :user_email => record.assignee.email, :issue_serial_id => record.serial_id, :issue_title => record.title,
:project_id => record.project.id, :project_name => record.project.name, :project_owner => record.project.owner.uname}
)
end

View File

@ -4,30 +4,28 @@ class Issue < ActiveRecord::Base
belongs_to :project
belongs_to :user
belongs_to :creator, :class_name => 'User', :foreign_key => 'creator_id'
belongs_to :assignee, :class_name => 'User', :foreign_key => 'assignee_id'
belongs_to :closer, :class_name => 'User', :foreign_key => 'closed_by'
has_many :comments, :as => :commentable, :dependent => :destroy #, :finder_sql => proc { "comments.commentable_id = '#{self.id}' AND comments.commentable_type = '#{self.class.name}'"}
has_many :subscribes, :as => :subscribeable, :dependent => :destroy #, :finder_sql => proc { "subscribes.subscribeable_id = '#{self.id}' AND subscribes.subscribeable_type = '#{self.class.name}'"}
has_many :comments, :as => :commentable, :dependent => :destroy
has_many :subscribes, :as => :subscribeable, :dependent => :destroy
has_many :labels, :through => :labelings, :uniq => true
has_many :labelings
validates :title, :body, :project_id, :presence => true
#attr_readonly :serial_id
after_create :set_serial_id
after_create :subscribe_users
after_update :subscribe_issue_assigned_user
attr_accessible :labelings_attributes, :title, :body, :user_id
attr_accessible :labelings_attributes, :title, :body, :assignee_id
accepts_nested_attributes_for :labelings, :allow_destroy => true
scope :opened, where(:status => 'open', :closed_by => nil, :closed_at => nil)
scope :closed, where(:status => 'closed').where("closed_by is not null and closed_at is not null")
def assign_uname
user.uname if user
assignee.uname if assignee
end
def to_param
@ -57,7 +55,7 @@ class Issue < ActiveRecord::Base
def collect_recipient_ids
recipients = self.project.relations.by_role('admin').where(:object_type => 'User').map { |rel| rel.read_attribute(:object_id) }
recipients = recipients | [self.user_id] if self.user_id
recipients = recipients | [self.assignee_id] if self.assignee_id
recipients = recipients | [self.project.owner_id] if self.project.owner_type == 'User'
recipients
@ -80,10 +78,10 @@ class Issue < ActiveRecord::Base
end
def subscribe_issue_assigned_user
if self.user_id && self.user_id_changed?
self.subscribes.where(:user_id => self.user_id_was).first.destroy unless self.user_id_was.blank?
if self.user.notifier.issue_assign && !self.subscribes.exists?(:user_id => self.user_id)
self.subscribes.create(:user_id => self.user_id)
if self.assignee_id && self.assignee_id_changed?
self.subscribes.where(:user_id => self.assignee_id_was).first.destroy unless self.assignee_id_was.blank?
if self.assignee.notifier.issue_assign && !self.subscribes.exists?(:user_id => self.assignee_id)
self.subscribes.create(:user_id => self.assignee_id)
end
end
end

View File

@ -3,12 +3,12 @@
.leftlist= t('activerecord.attributes.issue.body') + ':'
.rightlist= f.text_area :body
.both
.leftlist= t('activerecord.attributes.issue.user') + ':'
.leftlist= t('activerecord.attributes.issue.assignee') + ':'
.rightlist
%span#people-span.small-text= t('layout.issues.choose_user_on_left')
#issue_executor
#issue_assignee
.both
.leftlist= t('layout.issues.labels')
.leftlist= t('layout.issues.labels') + ':'
.rightlist
%span#flag-span.small-text= t('layout.issues.choose_labels_on_left')
#issue_labels

View File

@ -11,7 +11,7 @@
%tr
%td=radio_button_tag :myradio, 'to_me', @is_assigned_to_me, {:id => 'myradio1', :class => 'niceRadio', :name => 'filter'}
%td=t("layout.issues.to_me")
%td.width30.right=@project.issues.where(:user_id => current_user).count
%td.width30.right=@project.issues.where(:assignee_id => current_user.id).count
=form_tag project_issues_path(@project), :id => 'search_issue', :method => :get do
.bordered.bpadding20
=tracker_search_field(:search_issue, t('layout.issues.search'))

View File

@ -7,15 +7,15 @@
%div.issue_title=issue.title
.smalltext
=issue.created_at.to_s(:long)
=t("layout.by") if issue.creator
=link_to(issue.creator.uname, user_path(issue.creator)) if issue.creator
=t("layout.by") if issue.user
=link_to(issue.user.uname, user_path(issue.user)) if issue.user
-issue.labels.each do |label|
.left.nomargin
.label.selected.tracker.left
.labeltext.selected{:style => "background: ##{label.color};"}=label.name
%td.td3
.avatar
=link_to image_tag(avatar_url(issue.user), :alt => 'avatar'), user_path(issue.user) if issue.user
=link_to image_tag(avatar_url(issue.assignee), :alt => 'avatar'), user_path(issue.assignee) if issue.assignee
%a{:href => "#{project_issue_path @project, issue}#block-list"}
.answers
.pic= image_tag 'answers.png'

View File

@ -10,30 +10,30 @@
=form_tag [@project, @issue], :id => 'update_issue_status', :method => :put do
=hidden_field_tag "issue_status", @issue.closed? ? 'closed' : 'open', :name => "issue[status]"
.bordered.nopadding
%h3=t('layout.issues.executor')
%h3=t('layout.issues.assignee')
- if @issue.persisted?
-if can_manage
=form_for :issue, :url => [@project, @issue], :method => :put, :html => { :class => 'edit_executor issue'} do |f|
=hidden_field_tag "user-default_executor", nil, :name => 'issue[user_id]'
.current_executor
- if @issue.user
=form_for :issue, :url => [@project, @issue], :method => :put, :html => { :class => 'edit_assignee issue'} do |f|
=hidden_field_tag "user-default_assignee", nil, :name => 'issue[assignee_id]'
.current_assignee
- if @issue.assignee
#user-0.people.nopointer
.avatar=image_tag avatar_url(@issue.user), :alt => 'avatar'
.name="#{@issue.user.uname} (#{@issue.user.name})"
=hidden_field_tag "user-0", @issue.user.id, :name => 'issue[user_id]'
.avatar=image_tag avatar_url(@issue.assignee), :alt => 'avatar'
.name="#{@issue.user.uname} (#{@issue.assignee.name})"
=hidden_field_tag "user-0", @issue.assignee.id, :name => 'issue[assignee_id]'
.both
- elsif @issue.user
- elsif @issue.assignee
.people.nopointer
.avatar=image_tag avatar_url(@issue.user), :alt => 'avatar'
.name="#{@issue.user.uname} (#{@issue.user.name})"
.avatar=image_tag avatar_url(@issue.assignee), :alt => 'avatar'
.name="#{@issue.assignee.uname} (#{@issue.assignee.name})"
.both
=link_to(t('layout.issues.label_manage'), '#', :class => "button tmargin10 manage_executor") if can_manage
=link_to(t('layout.issues.label_manage'), '#', :class => "button tmargin10 manage_assignee") if can_manage
- if can_manage
=form_tag search_collaborators_project_issues_path(@project), :id => 'search_user', :method => :get, :style => @issue.persisted? ? 'display:none' : '' do
=tracker_search_field(:search_user, t('layout.issues.search_user'))
#manage_issue_users_list
=render 'issues/search_collaborators'
=link_to(t('layout.issues.done'), '#', :class => "button tmargin10 update_executor", :style => 'display:none') if can_manage
=link_to(t('layout.issues.done'), '#', :class => "button tmargin10 update_assignee", :style => 'display:none') if can_manage
.block
%h3=t('layout.issues.labels')

View File

@ -1,6 +1,6 @@
- (@users || []).each_with_index do |user, index|
.people.selected{:id => "user-#{index}", :class => 'add_executor'}
.people.selected{:id => "user-#{index}", :class => 'add_assignee'}
.avatar= image_tag(avatar_url(user), :alt => 'avatar')
.name="#{user.uname} (#{user.name})"
=hidden_field_tag "user-#{index}", user.id, :name => 'issue[user_id]'
=hidden_field_tag "user-#{index}", user.id, :name => 'issue[assignee_id]'
.both

View File

@ -7,9 +7,9 @@
.activity
.top
.image
=image_tag(avatar_url(@issue.creator, :medium), :alt => 'avatar') if @issue.creator
=image_tag(avatar_url(@issue.user, :medium), :alt => 'avatar') if @issue.user
.text
%span.name=link_to("#{@issue.creator.uname} (#{@issue.creator.name})", user_path(@issue.creator)) if @issue.creator
%span.name=link_to("#{@issue.user.uname} (#{@issue.user.name})", user_path(@issue.user)) if @issue.user
%br/
%span.date=@issue.created_at.to_s(:long)
%br/

View File

@ -4,8 +4,8 @@ en:
issue:
title: Name
body: Description
user: Assigned
user_id: Assigned
assignee: Assigned
assignee_id: Assigned
project: Project
status: Status
@ -41,10 +41,10 @@ en:
update_label: Update label
label_custom_color: Custom color
label_manage: Manage labels
executor: Executor
assignee: Assignee
search_user: Find user...
search_labels: Find labels...
choose_user_on_left: Choose executor on the left
choose_user_on_left: Choose assignee on the left
choose_labels_on_left: Choose labels on the left
at: at
cancel_button: Cancel

View File

@ -4,8 +4,8 @@ ru:
issue:
title: Название
body: Описание
user: Назначена
user_id: Назначена
assignee: Назначена
assignee_id: Назначена
project: Проект
status: Статус
@ -41,7 +41,7 @@ ru:
update_label: Обновить метку
label_custom_color: Свой цвет
label_manage: Управление
executor: Исполнитель
assignee: Исполнитель
search_user: Найти пользователя...
search_labels: Найти метки...
choose_user_on_left: выберите исполнителя слева

View File

@ -0,0 +1,11 @@
class AddAssigneeToIssues < ActiveRecord::Migration
def up
rename_column :issues, :user_id, :assignee_id
rename_column :issues, :creator_id, :user_id
end
def down
rename_column :issues, :user_id, :creator_id
rename_column :issues, :assignee_id, :user_id
end
end

View File

@ -80,7 +80,7 @@ describe IssuesController do
any_instance_of(Project, :versions => ['v1.0', 'v2.0'])
@issue = FactoryGirl.create(:issue, :project_id => @project.id, :user_id => @issue_user.id)
@issue = FactoryGirl.create(:issue, :project_id => @project.id, :assignee_id => @issue_user.id)
@create_params = {
:project_id => @project.id,
:issue => {
@ -88,8 +88,8 @@ describe IssuesController do
:body => "issue body",
:project_id => @project.id
},
:user_id => @issue_user.id,
:user_uname => @issue_user.uname
:assignee_id => @issue_user.id,
:assignee_uname => @issue_user.uname
}
@update_params = {
:project_id => @project.id,
@ -99,7 +99,7 @@ describe IssuesController do
}
@project_with_turned_off_issues = FactoryGirl.create(:project, :has_issues => false)
@turned_of_issue = FactoryGirl.create(:issue, :project_id => @project_with_turned_off_issues.id, :user_id => @issue_user.id)
@turned_of_issue = FactoryGirl.create(:issue, :project_id => @project_with_turned_off_issues.id, :assignee_id => @issue_user.id)
end
context 'for global admin user' do

View File

@ -5,7 +5,7 @@ FactoryGirl.define do
body { FactoryGirl.generate(:string) }
association :project, :factory => :project
association :user, :factory => :user
association :creator, :factory => :user
association :assignee, :factory => :user
status "open"
end
end

View File

@ -13,7 +13,7 @@ describe UserMailer do
any_instance_of(Project, :versions => ['v1.0', 'v2.0'])
@issue = FactoryGirl.create(:issue, :project_id => @project.id, :user_id => @issue_user.id, :creator => @issue_user)
@issue = FactoryGirl.create(:issue, :project_id => @project.id, :assignee_id => @issue_user.id, :user => @issue_user)
@email = UserMailer.new_issue_notification(@issue, @issue_user).deliver
end
@ -52,7 +52,7 @@ describe UserMailer do
any_instance_of(Project, :versions => ['v1.0', 'v2.0'])
@issue = FactoryGirl.create(:issue, :project_id => @project.id, :user_id => @issue_user.id, :creator => @issue_user)
@issue = FactoryGirl.create(:issue, :project_id => @project.id, :assignee_id => @issue_user.id, :user => @issue_user)
@email = UserMailer.issue_assign_notification(@issue, @user).deliver
end
@ -88,7 +88,7 @@ describe UserMailer do
any_instance_of(Project, :versions => ['v1.0', 'v2.0'])
@issue = FactoryGirl.create(:issue, :project_id => @project.id, :user_id => @issue_user.id, :creator => @issue_user)
@issue = FactoryGirl.create(:issue, :project_id => @project.id, :assignee_id => @issue_user.id, :user => @issue_user)
@comment = FactoryGirl.create(:comment, :commentable => @issue, :user_id => @user.id, :project => @project)
@email = UserMailer.new_comment_notification(@comment, @issue_user).deliver
end

View File

@ -6,7 +6,7 @@ def set_commentable_data
@ability = Ability.new(@user)
@project = FactoryGirl.create(:project)
@issue = FactoryGirl.create(:issue, :project_id => @project.id, :creator => @user)
@issue = FactoryGirl.create(:issue, :project_id => @project.id, :user => @user)
@comment = FactoryGirl.create(:comment, :commentable => @issue, :user => @user, :project => @project)
@stranger_comment = FactoryGirl.create(:comment, :commentable => @issue, :user => @stranger, :project => @project)