Merge pull request #271 from warpc/194-issue_page

#194 Управление назначением исполнителя и метками задачи
This commit is contained in:
Pasha 2012-03-06 11:54:45 -08:00
commit 2735b324ac
15 changed files with 152 additions and 72 deletions

View File

@ -119,8 +119,7 @@ $(document).ready(function() {
url: $(this).attr("action"),
data: $(this).serialize(),
success: function(data){
var tmp = $('#create_issue_'+ which +'_list');
$('#create_issue_'+ which +'_list').html(data);
$('#manage_issue_'+ which +'_list').html(data);
},
error: function(data){
alert('error') // TODO remove
@ -132,20 +131,23 @@ $(document).ready(function() {
function remExecutor(form) {
var el = form.find('.people.selected.remove_executor');
var id = el.attr('id');
$('#'+id+'.add_executor.people.selected').removeClass('select');
$('#manage_issue_users_list .add_executor.people.selected').removeClass('select');
el.remove();
}
$('.add_executor.people.selected').live('click', function() {
var form = $('.form.issue');
form.find('#people-span').fadeOut(0);
remExecutor(form);
form.find('#issue_executor').html($(this).clone().removeClass('add_executor').addClass('remove_executor'));
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'));
$(this).addClass('select');
});
$('.remove_executor.people.selected').live('click', function() {
var form = $('.form.issue');
var form = $('form.issue, form.edit_form issue');
form.find('#people-span').fadeIn(0);
remExecutor(form);
});
@ -165,23 +167,28 @@ $(document).ready(function() {
var style = $(this).find('.flag').attr('style');
$(this).find('.flag').fadeOut(0);
$(this).find('.labeltext.selected').attr('style', style);
var form = $('.form.issue');
form.find('#flag-span').fadeOut(0);
form.find('#issue_labels').append($(this).clone());
var form_new = $('form.form.issue');
var clone = $(this).clone();
form_new.find('#flag-span').fadeOut(0);
form_new.find('#issue_labels').append(clone);
var labels = $('#active_labels');
labels.find('#'+$(this).attr('id')).remove();
labels.append(clone);
});
$('.remove_label.label.selected').live('click', function() {
var id = $(this).attr('id');
$('.current_labels, #active_labels').find('#'+id+'.label.selected.remove_label').remove();
var form = $('.form.issue');
if(form.find('.remove_label.label.selected').length == 1) {
form.find('#flag-span').fadeIn(0);
}
var str = '.label.remove_label'+'#'+$(this).attr('id');
var str = '.label.remove_label'+'#'+id;
form.find(str).remove();
var label = $(str);
label.removeClass('selected').addClass('add_label').removeClass('remove_label');
label.find('.labeltext.selected').attr('style', '').removeClass('selected');
label.find('.flag').fadeIn(0);
});
$('.issue_status.switch_issue_status').live('click', function () {
@ -228,10 +235,57 @@ $(document).ready(function() {
$('.fulltext.view.issue_body').html(form.find('#issue_body').attr('value'));
},
error: function(data){
alert('error') // TODO remove
alert('error'); // TODO remove
}
});
return false;
});
$('.button.manage_executor').live('click', function() {
$('form#search_user, .button.update_executor').fadeIn(0);
$('.current_executor .people').addClass('remove_executor selected');
$(this).fadeOut(0);
});
$('.button.manage_labels').live('click', function() {
$('form#search_labels, .button.update_labels').fadeIn(0);
$(this).fadeOut(0);
});
$('.button.update_executor').live('click', function() {
var form = $('form.edit_executor.issue');
$.ajax({
type: 'POST',
url: form.attr("action"),
data: form.serialize(),
success: function(data){
$('form#search_user, .button.update_executor').fadeOut(0);
$('.button.manage_executor').fadeIn(0);
$('#manage_issue_users_list').html('');
},
error: function(data){
alert('error'); // TODO remove
}
});
return false;
});
$('.button.update_labels').live('click', function() {
var form = $('form.edit_labels.issue');
$.ajax({
type: 'POST',
url: form.attr("action"),
data: form.serialize(),
success: function(data){
$('form#search_labels, .button.update_labels').fadeOut(0);
$('.button.manage_labels').fadeIn(0);
$('#manage_issue_labels_list').html('');
},
error: function(data){
alert('error'); // TODO remove
}
});
return false;
});
});

View File

@ -57,15 +57,18 @@ class IssuesController < ApplicationController
end
def update
if status = params[:issue][:status]
if params[:issue] && status = params[:issue][:status]
action = 'issues/_status'
@issue.set_close(current_user) if status == 'closed'
@issue.set_open if status == 'open'
status = 200 if @issue.save
render action, :status => (status || 500), :layout => false
else
elsif params[:issue]
@issue.labelings.destroy_all if params[:issue][:labelings_attributes] # FIXME
status = 200 if @issue.update_attributes(params[:issue])
render :nothing => true, :status => (status || 500), :layout => false
else
render :nothing => true, :status => 200, :layout => false
end
end

View File

@ -9,7 +9,7 @@ class Issue < ActiveRecord::Base
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 :labels, :through => :labelings
has_many :labels, :through => :labelings, :uniq => true
has_many :labelings
validates :title, :body, :project_id, :presence => true
@ -20,7 +20,7 @@ class Issue < ActiveRecord::Base
after_create :subscribe_users
after_update :subscribe_issue_assigned_user
attr_accessible :labelings_attributes, :title, :body
attr_accessible :labelings_attributes, :title, :body, :user_id
accepts_nested_attributes_for :labelings, :allow_destroy => true
scope :opened, where(:status => 'open', :closed_by => nil, :closed_at => nil)

View File

@ -50,7 +50,7 @@ class CommentPresenter < ApplicationPresenter
end
def header
res = link_to @user.uname, user_path(@user.uname)
res = link_to "#{@user.uname} (#{@user.name})", user_path(@user.uname)
res += ' ' + t("layout.comments.has_commented")
end

View File

@ -1,39 +0,0 @@
-content_for :sidebar do
- if @issue.persisted?
.bordered.nopadding
%h3=t('activerecord.attributes.issue.status')
#switcher.issue_status{:class => "#{@issue.closed? ? 'switcher-off' : 'switcher'} #{can?(:write, @issue.project) ? "switch_issue_status" : ''}"}
.swleft=t('layout.issues.status.open')
.swright=t('layout.issues.status.closed')
- if can? :write, @issue.project
=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')
- if @issue.persisted? && @issue.user
.bordered.nopadding
.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 => 'user_id'
.both
- else
=form_tag search_collaborators_project_issues_path(@project), :id => 'search_user', :method => :get do
=tracker_search_field(:search_user, t('layout.issues.search_user'))
#create_issue_users_list
=render 'issues/search_collaborators'
.block
%h3=t('layout.issues.labels')
- if @issue.new_record?
=form_tag search_labels_project_issues_path(@project), :id => 'search_labels', :method => :get do
=tracker_search_field(:search_labels, t('layout.issues.search_labels'))
#create_issue_labels_list
=render 'issues/search_labels'
- else
- (@issue.labels || []).each_with_index do |label|
.label.selected.nopointer
.labeltext.selected{:style => "background: ##{label.color};"}
=label.name
.both

View File

@ -14,7 +14,8 @@
=form_tag project_issues_path(@project), :id => 'search_issue', :method => :get do
.bordered.bpadding20
=tracker_search_field(:search_issue, t('layout.issues.search'))
.bordered.nopadding
%h3.bmargin10=t('layout.issues.new')
= link_to t("layout.add"), new_project_issue_path(@project), :class => 'button' if can? :new, @project.issues.new
- if can? :new, @project.issues.new
.bordered.nopadding
%h3.bmargin10=t('layout.issues.new')
= link_to t("layout.add"), new_project_issue_path(@project), :class => 'button'
=render :partial => 'labels'

View File

@ -7,7 +7,7 @@
%div.issue_title=issue.title
.smalltext
=issue.created_at.to_s(:long)
=t("layout.issues.by") if issue.creator
=t("layout.by") if issue.creator
=link_to(issue.creator.uname, user_path(issue.creator)) if issue.creator
.label.selected.tracker
-issue.labels.each do |label|

View File

@ -0,0 +1,61 @@
-content_for :sidebar do
- can_manage = can? :write, @issue.project
- if @issue.persisted?
.bordered.nopadding
%h3=t('activerecord.attributes.issue.status')
#switcher.issue_status{:class => "#{@issue.closed? ? 'switcher-off' : 'switcher'} #{can_manage ? "switch_issue_status" : ''}"}
.swleft=t('layout.issues.status.open')
.swright=t('layout.issues.status.closed')
- if can_manage
=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')
- if @issue.persisted?
-if can_manage
=form_for :issue, :url => [@project, @issue], :method => :put, :html => { :class => 'edit_executor issue'} do |f|
.current_executor
- if @issue.user
#user-0.people
.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]'
.both
- else
.people.nopointer
.avatar=image_tag(@issue.user.avatar(25), :alt => 'avatar')
.name="#{@issue.user.uname} (#{@issue.user.name})"
.both
=link_to(t('layout.issues.label_manage'), '#', :class => "button tmargin10 manage_executor") 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
.block
%h3=t('layout.issues.labels')
- if @issue.persisted?
- if can_manage
=form_for :issue, :url => [@project, @issue], :method => :put, :html => { :class => 'edit_labels issue'} do |f|
.current_labels
- (@issue.labels || []).each do |label|
.label.selected{:id => "flag#{label.id}"}
.flag{:style => "display:none; background: ##{label.color}"}
.labeltext.selected{:style => "background: ##{label.color}"}=label.name
=hidden_field_tag "label-#{label.id}", label.id, :name => "issue[labelings_attributes][#{label.id}][label_id]"
.both
- else
- (@issue.labels || []).each do |label|
.label.nopointer
.labeltext.selected{:style => "background: ##{label.color};"}
=label.name
.both
=link_to(t('layout.issues.label_manage'), '#', :class => "button tmargin10 manage_labels") if can_manage
- if can_manage
=form_tag search_labels_project_issues_path(@project), :id => 'search_labels', :method => :get, :style => @issue.persisted? ? 'display:none' : '' do
=tracker_search_field(:search_labels, t('layout.issues.search_labels'))
#manage_issue_labels_list
=render 'issues/search_labels'
=link_to(t('layout.issues.done'), '#', :class => "button tmargin10 update_labels", :style => 'display:none') if can_manage

View File

@ -2,5 +2,5 @@
.people.selected{:id => "user-#{index}", :class => 'add_executor'}
.avatar= image_tag(avatar_url(user), :alt => 'avatar')
.name="#{user.uname} (#{user.name})"
=hidden_field_tag "user-#{index}", user.id, :name => 'user_id'
=hidden_field_tag "user-#{index}", user.id, :name => 'issue[user_id]'
.both

View File

@ -1,6 +1,6 @@
- (@labels || []).each_with_index do |label, index|
.add_label.label{:id => "flag#{index}"}
- (@labels || []).each do |label|
.add_label.label{:id => "flag#{label.id}"}
.flag{:style => "background: ##{label.color};"}
.labeltext=label.name
=hidden_field_tag "label-#{index}", label.id, :name => "issue[labelings_attributes][#{index}][label_id]"
=hidden_field_tag "label-#{label.id}", label.id, :name => "issue[labelings_attributes][#{label.id}][label_id]"
.both

View File

@ -1,5 +1,5 @@
-render :partial => 'projects/submenu'
-render :partial => 'issues/create_sidebar'
-render :partial => 'issues/manage_sidebar'
%h3.bpadding10= t("layout.issues.create_header")
= form_for :issue, :url => project_issues_path(@project), :html => { :class => 'form issue' } do |f|

View File

@ -1,5 +1,5 @@
-render :partial => 'projects/submenu'
-render :partial => 'issues/create_sidebar'
-render :partial => 'issues/manage_sidebar'
-content_for :right_nopadding do
dummy
%h3.issue_title=@issue.title
@ -8,7 +8,7 @@
.image
=image_tag(avatar_url(@issue.creator, :medium), :alt => 'avatar') if @issue.creator
.text
%span.name=link_to(@issue.creator.uname, user_path(@issue.creator)) if @issue.creator
%span.name=link_to("#{@issue.creator.uname} (#{@issue.creator.name})", user_path(@issue.creator)) if @issue.creator
%br/
%span.date=@issue.created_at.to_s(:long)
%br/

View File

@ -8,7 +8,7 @@
- if @project.is_rpm and can?(:create, @project => BuildList)
%li= link_to t("project_menu.builds"), project_build_lists_path(@project), :class => (contr == :build_lists ? 'active' : nil)
- if @project.has_issues
%li= link_to t("project_menu.tracker"), project_issues_path(@project), :class => (act == :index && contr == :issues ? 'active' : nil)
%li= link_to t("project_menu.tracker"), project_issues_path(@project), :class => (contr == :issues ? 'active' : nil)
- if @project.has_wiki
%li= link_to t("project_menu.wiki"), project_wiki_index_path(@project), :class => (contr == :wiki ? 'active' : nil)
%li= link_to t("project_menu.readme"), "#" #pending

View File

@ -35,7 +35,6 @@ en:
unsubscribe_btn: Unsubscribe
number: Number
description: Description
by: by
labels: Labels
invalid_labels: Invalid hex color code
new_label: New label name
@ -49,6 +48,7 @@ en:
choose_labels_on_left: Choose labels on the left
at: at
cancel_button: Cancel
done: Done
flash:
issue:

View File

@ -35,7 +35,6 @@ ru:
unsubscribe_btn: Отписаться
number: Номер
description: Описание
by: ' '
labels: Метки
invalid_labels: Неверный hex код
new_label: Название новой метки
@ -49,6 +48,7 @@ ru:
choose_labels_on_left: выберите метки слева
at: в
cancel_button: Отменить
done: Обновить
flash:
issue: