Merged IssuesController #edit and #update into a single actions.
Users with 'edit issues' permission can now update any property including custom fields when adding a note or changing the status (#519, #581, #587). git-svn-id: http://redmine.rubyforge.org/svn/trunk@1129 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
6d109258c9
commit
43a6f312ed
|
@ -25,7 +25,7 @@ class IssuesController < ApplicationController
|
||||||
before_filter :find_optional_project, :only => [:index, :changes]
|
before_filter :find_optional_project, :only => [:index, :changes]
|
||||||
accept_key_auth :index, :changes
|
accept_key_auth :index, :changes
|
||||||
|
|
||||||
cache_sweeper :issue_sweeper, :only => [ :new, :edit, :update, :destroy ]
|
cache_sweeper :issue_sweeper, :only => [ :new, :edit, :destroy ]
|
||||||
|
|
||||||
helper :journals
|
helper :journals
|
||||||
helper :projects
|
helper :projects
|
||||||
|
@ -85,10 +85,12 @@ class IssuesController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@custom_values = @issue.custom_values.find(:all, :include => :custom_field, :order => "#{CustomField.table_name}.position")
|
@custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| @issue.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x, :customized => @issue) }
|
||||||
@journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
|
@journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
|
||||||
@status_options = @issue.new_statuses_allowed_to(User.current)
|
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
|
||||||
|
@edit_allowed = User.current.allowed_to?(:edit_issues, @project)
|
||||||
@activities = Enumeration::get_values('ACTI')
|
@activities = Enumeration::get_values('ACTI')
|
||||||
|
@priorities = Enumeration::get_values('IPRI')
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { render :template => 'issues/show.rhtml' }
|
format.html { render :template => 'issues/show.rhtml' }
|
||||||
format.pdf { send_data(render(:template => 'issues/show.rfpdf', :layout => false), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") }
|
format.pdf { send_data(render(:template => 'issues/show.rfpdf', :layout => false), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") }
|
||||||
|
@ -140,48 +142,33 @@ class IssuesController < ApplicationController
|
||||||
render :layout => !request.xhr?
|
render :layout => !request.xhr?
|
||||||
end
|
end
|
||||||
|
|
||||||
def edit
|
# Attributes that can be updated on workflow transition (without :edit permission)
|
||||||
@priorities = Enumeration::get_values('IPRI')
|
|
||||||
@custom_values = []
|
|
||||||
if request.get?
|
|
||||||
@custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| @issue.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x, :customized => @issue) }
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
journal = @issue.init_journal(User.current)
|
|
||||||
# Retrieve custom fields and values
|
|
||||||
if params["custom_fields"]
|
|
||||||
@custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
|
|
||||||
@issue.custom_values = @custom_values
|
|
||||||
end
|
|
||||||
@issue.attributes = params[:issue]
|
|
||||||
if @issue.save
|
|
||||||
flash[:notice] = l(:notice_successful_update)
|
|
||||||
Mailer.deliver_issue_edit(journal) if Setting.notified_events.include?('issue_updated')
|
|
||||||
redirect_to(params[:back_to] || {:action => 'show', :id => @issue})
|
|
||||||
end
|
|
||||||
rescue ActiveRecord::StaleObjectError
|
|
||||||
# Optimistic locking exception
|
|
||||||
flash[:error] = l(:notice_locking_conflict)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Attributes that can be updated on workflow transition
|
|
||||||
# TODO: make it configurable (at least per role)
|
# TODO: make it configurable (at least per role)
|
||||||
UPDATABLE_ATTRS_ON_TRANSITION = %w(status_id assigned_to_id fixed_version_id done_ratio) unless const_defined?(:UPDATABLE_ATTRS_ON_TRANSITION)
|
UPDATABLE_ATTRS_ON_TRANSITION = %w(status_id assigned_to_id fixed_version_id done_ratio) unless const_defined?(:UPDATABLE_ATTRS_ON_TRANSITION)
|
||||||
|
|
||||||
def update
|
def edit
|
||||||
@status_options = @issue.new_statuses_allowed_to(User.current)
|
@allowed_statuses = @issue.new_statuses_allowed_to(User.current)
|
||||||
@activities = Enumeration::get_values('ACTI')
|
@activities = Enumeration::get_values('ACTI')
|
||||||
journal = @issue.init_journal(User.current, params[:notes])
|
@priorities = Enumeration::get_values('IPRI')
|
||||||
# User can change issue attributes only if a workflow transition is allowed
|
@custom_values = []
|
||||||
if !@status_options.empty? && params[:issue]
|
@edit_allowed = User.current.allowed_to?(:edit_issues, @project)
|
||||||
attrs = params[:issue].dup
|
if request.get?
|
||||||
attrs.delete_if {|k,v| !UPDATABLE_ATTRS_ON_TRANSITION.include?(k) }
|
@custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| @issue.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x, :customized => @issue) }
|
||||||
attrs.delete(:status_id) unless @status_options.detect {|s| s.id.to_s == attrs[:status_id].to_s}
|
else
|
||||||
@issue.attributes = attrs
|
@notes = params[:notes]
|
||||||
end
|
journal = @issue.init_journal(User.current, @notes)
|
||||||
if request.post?
|
# User can change issue attributes only if he has :edit permission or if a workflow transition is allowed
|
||||||
|
if (@edit_allowed || !@allowed_statuses.empty?) && params[:issue]
|
||||||
|
attrs = params[:issue].dup
|
||||||
|
attrs.delete_if {|k,v| !UPDATABLE_ATTRS_ON_TRANSITION.include?(k) } unless @edit_allowed
|
||||||
|
attrs.delete(:status_id) unless @allowed_statuses.detect {|s| s.id.to_s == attrs[:status_id].to_s}
|
||||||
|
@issue.attributes = attrs
|
||||||
|
end
|
||||||
|
# Update custom fields if user has :edit permission
|
||||||
|
if @edit_allowed && params[:custom_fields]
|
||||||
|
@custom_values = @project.custom_fields_for_issues(@issue.tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
|
||||||
|
@issue.custom_values = @custom_values
|
||||||
|
end
|
||||||
attachments = attach_files(@issue, params[:attachments])
|
attachments = attach_files(@issue, params[:attachments])
|
||||||
attachments.each {|a| journal.details << JournalDetail.new(:property => 'attachment', :prop_key => a.id, :value => a.filename)}
|
attachments.each {|a| journal.details << JournalDetail.new(:property => 'attachment', :prop_key => a.id, :value => a.filename)}
|
||||||
if @issue.save
|
if @issue.save
|
||||||
|
@ -243,7 +230,7 @@ class IssuesController < ApplicationController
|
||||||
def preview
|
def preview
|
||||||
issue = Issue.find_by_id(params[:id])
|
issue = Issue.find_by_id(params[:id])
|
||||||
@attachements = issue.attachments if issue
|
@attachements = issue.attachments if issue
|
||||||
@text = (params[:issue] ? params[:issue][:description] : nil) || params[:notes]
|
@text = params[:notes] || (params[:issue] ? params[:issue][:description] : nil)
|
||||||
render :partial => 'common/preview'
|
render :partial => 'common/preview'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
<% labelled_tabular_form_for :issue, @issue,
|
||||||
|
:url => {:action => 'edit', :id => @issue},
|
||||||
|
:html => {:id => 'issue-form',
|
||||||
|
:multipart => true} do |f| %>
|
||||||
|
<%= error_messages_for 'issue' %>
|
||||||
|
<div class="box">
|
||||||
|
<% if @edit_allowed || !@allowed_statuses.empty? %>
|
||||||
|
<fieldset>
|
||||||
|
<legend><%= l(:label_change_properties) %>
|
||||||
|
<% if !@issue.new_record? && !@issue.errors.any? && @edit_allowed %>
|
||||||
|
<small>(<%= link_to l(:label_more), {}, :onclick => 'Effect.toggle("issue_descr_fields", "appear", {duration:0.3}); return false;' %>)</small>
|
||||||
|
<% end %>
|
||||||
|
</legend>
|
||||||
|
<%= render :partial => (@edit_allowed ? 'form' : 'form_update'), :locals => {:f => f} %>
|
||||||
|
</fieldset>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<fieldset><legend><%= l(:field_notes) %></legend>
|
||||||
|
<%= text_area_tag 'notes', @notes, :cols => 60, :rows => 10, :class => 'wiki-edit' %>
|
||||||
|
<%= wikitoolbar_for 'notes' %>
|
||||||
|
|
||||||
|
<p id="attachments_p"><label><%=l(:label_attachment_new)%>
|
||||||
|
<%= image_to_function 'add.png', 'addFileField();return false;' %></label>
|
||||||
|
<%= file_field_tag 'attachments[]', :size => 30 %> <em>(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)</em></p>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= f.hidden_field :lock_version %>
|
||||||
|
<%= submit_tag l(:button_submit) %>
|
||||||
|
<%= link_to_remote l(:label_preview),
|
||||||
|
{ :url => { :controller => 'issues', :action => 'preview', :id => @issue },
|
||||||
|
:method => 'post',
|
||||||
|
:update => 'preview',
|
||||||
|
:with => 'Form.serialize("issue-form")',
|
||||||
|
:complete => "location.hash='preview'"
|
||||||
|
}, :accesskey => accesskey(:preview) %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<div id="preview" class="wiki"></div>
|
|
@ -1,6 +1,3 @@
|
||||||
<%= error_messages_for 'issue' %>
|
|
||||||
<div class="box">
|
|
||||||
|
|
||||||
<% if @issue.new_record? %>
|
<% if @issue.new_record? %>
|
||||||
<p><%= f.select :tracker_id, @project.trackers.collect {|t| [t.name, t.id]}, :required => true %></p>
|
<p><%= f.select :tracker_id, @project.trackers.collect {|t| [t.name, t.id]}, :required => true %></p>
|
||||||
<%= observe_field :issue_tracker_id, :url => { :action => :new },
|
<%= observe_field :issue_tracker_id, :url => { :action => :new },
|
||||||
|
@ -8,15 +5,17 @@
|
||||||
:with => "Form.serialize('issue-form')" %>
|
:with => "Form.serialize('issue-form')" %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
<div id="issue_descr_fields" <%= 'style="display:none"' unless @issue.new_record? || @issue.errors.any? %>>
|
||||||
<p><%= f.text_field :subject, :size => 80, :required => true %></p>
|
<p><%= f.text_field :subject, :size => 80, :required => true %></p>
|
||||||
<p><%= f.text_area :description, :required => true,
|
<p><%= f.text_area :description, :required => true,
|
||||||
:cols => 60,
|
:cols => 60,
|
||||||
:rows => (@issue.description.blank? ? 10 : [[10, @issue.description.length / 50].max, 100].min),
|
:rows => (@issue.description.blank? ? 10 : [[10, @issue.description.length / 50].max, 100].min),
|
||||||
:accesskey => accesskey(:edit),
|
:accesskey => accesskey(:edit),
|
||||||
:class => 'wiki-edit' %></p>
|
:class => 'wiki-edit' %></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="splitcontentleft">
|
<div class="splitcontentleft">
|
||||||
<% if @issue.new_record? %>
|
<% if @issue.new_record? || @allowed_statuses %>
|
||||||
<p><%= f.select :status_id, (@allowed_statuses.collect {|p| [p.name, p.id]}), :required => true %></p>
|
<p><%= f.select :status_id, (@allowed_statuses.collect {|p| [p.name, p.id]}), :required => true %></p>
|
||||||
<% else %>
|
<% else %>
|
||||||
<p><label><%= l(:field_status) %></label> <%= @issue.status.name %></p>
|
<p><label><%= l(:field_status) %></label> <%= @issue.status.name %></p>
|
||||||
|
@ -49,7 +48,6 @@
|
||||||
<%= image_to_function "add.png", "addFileField();return false" %></label>
|
<%= image_to_function "add.png", "addFileField();return false" %></label>
|
||||||
<%= file_field_tag 'attachments[]', :size => 30 %> <em>(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)</em></p>
|
<%= file_field_tag 'attachments[]', :size => 30 %> <em>(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)</em></p>
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
|
||||||
|
|
||||||
<%= wikitoolbar_for 'issue_description' %>
|
<%= wikitoolbar_for 'issue_description' %>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
<div class="splitcontentleft">
|
||||||
|
<p><%= f.select :status_id, (@allowed_statuses.collect {|p| [p.name, p.id]}), :required => true %></p>
|
||||||
|
<p><%= f.select :assigned_to_id, (@issue.assignable_users.collect {|m| [m.name, m.id]}), :include_blank => true %></p>
|
||||||
|
</div>
|
||||||
|
<div class="splitcontentright">
|
||||||
|
<p><%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %></p>
|
||||||
|
<%= content_tag('p', f.select(:fixed_version_id,
|
||||||
|
(@project.versions.sort.collect {|v| [v.name, v.id]}),
|
||||||
|
{ :include_blank => true })) unless @project.versions.empty? %>
|
||||||
|
</div>
|
|
@ -1,54 +0,0 @@
|
||||||
<% labelled_tabular_form_for(:issue, @issue, :url => {:action => 'update', :id => @issue},
|
|
||||||
:html => {:multipart => true,
|
|
||||||
:id => 'issue-form'}) do |f| %>
|
|
||||||
|
|
||||||
<div class="box">
|
|
||||||
<% unless @status_options.empty? %>
|
|
||||||
<%= f.hidden_field :lock_version %>
|
|
||||||
<fieldset><legend><%= l(:label_change_properties) %></legend>
|
|
||||||
<div class="splitcontentleft">
|
|
||||||
<p><%= f.select :status_id, (@status_options.collect {|p| [p.name, p.id]}), :required => true %></p>
|
|
||||||
<p><%= f.select :assigned_to_id, (@issue.assignable_users.collect {|m| [m.name, m.id]}), :include_blank => true %></p>
|
|
||||||
</div>
|
|
||||||
<div class="splitcontentright">
|
|
||||||
<p><%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %></p>
|
|
||||||
<p><%= f.select :fixed_version_id, (@project.versions.sort.collect {|v| [v.name, v.id]}), { :include_blank => true } %></p>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
|
||||||
<% end%>
|
|
||||||
<% if authorize_for('timelog', 'edit') %>
|
|
||||||
<fieldset><legend><%= l(:button_log_time) %></legend>
|
|
||||||
<% fields_for :time_entry, @time_entry, { :builder => TabularFormBuilder, :lang => current_language} do |time_entry| %>
|
|
||||||
<div class="splitcontentleft">
|
|
||||||
<p><%= time_entry.text_field :hours, :size => 6, :label => :label_spent_time %> <%= l(:field_hours) %></p>
|
|
||||||
</div>
|
|
||||||
<div class="splitcontentright">
|
|
||||||
<p><%= time_entry.text_field :comments, :size => 40 %></p>
|
|
||||||
<p><%= time_entry.select :activity_id, (@activities.collect {|p| [p.name, p.id]}) %></p>
|
|
||||||
</div>
|
|
||||||
<% end %>
|
|
||||||
</fieldset>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<fieldset><legend><%= l(:field_notes) %></legend>
|
|
||||||
<%= text_area_tag 'notes', @notes, :cols => 60, :rows => 10, :class => 'wiki-edit' %>
|
|
||||||
<%= wikitoolbar_for 'notes' %>
|
|
||||||
|
|
||||||
<p id="attachments_p"><label><%=l(:label_attachment_new)%>
|
|
||||||
<%= image_to_function "add.png", "addFileField();return false" %></label>
|
|
||||||
<%= file_field_tag 'attachments[]', :size => 30 %> <em>(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)</em></p>
|
|
||||||
</fieldset>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<%= submit_tag l(:button_submit) %>
|
|
||||||
<%= link_to_remote l(:label_preview),
|
|
||||||
{ :url => { :controller => 'issues', :action => 'preview', :id => @issue },
|
|
||||||
:method => 'post',
|
|
||||||
:update => 'preview',
|
|
||||||
:with => "Form.serialize('issue-form')",
|
|
||||||
:complete => "window.location.hash='preview'"
|
|
||||||
}, :accesskey => accesskey(:preview) %> |
|
|
||||||
<%= toggle_link l(:button_cancel), 'update' %>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<div id="preview" class="wiki"></div>
|
|
|
@ -6,7 +6,7 @@
|
||||||
<a href="#" class="submenu" onclick="return false;"><%= l(:field_status) %></a>
|
<a href="#" class="submenu" onclick="return false;"><%= l(:field_status) %></a>
|
||||||
<ul>
|
<ul>
|
||||||
<% @statuses.each do |s| %>
|
<% @statuses.each do |s| %>
|
||||||
<li><%= context_menu_link s.name, {:controller => 'issues', :action => 'update', :id => @issue, :issue => {:status_id => s}},
|
<li><%= context_menu_link s.name, {:controller => 'issues', :action => 'edit', :id => @issue, :issue => {:status_id => s}},
|
||||||
:selected => (s == @issue.status), :disabled => !(@allowed_statuses.include?(s)) %></li>
|
:selected => (s == @issue.status), :disabled => !(@allowed_statuses.include?(s)) %></li>
|
||||||
<% end %>
|
<% end %>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -24,10 +24,10 @@
|
||||||
<a href="#" class="submenu"><%= l(:field_assigned_to) %></a>
|
<a href="#" class="submenu"><%= l(:field_assigned_to) %></a>
|
||||||
<ul>
|
<ul>
|
||||||
<% @assignables.each do |u| %>
|
<% @assignables.each do |u| %>
|
||||||
<li><%= context_menu_link u.name, {:controller => 'issues', :action => 'update', :id => @issue, :issue => {:assigned_to_id => u}, :back_to => back_to}, :method => :post,
|
<li><%= context_menu_link u.name, {:controller => 'issues', :action => 'edit', :id => @issue, :issue => {:assigned_to_id => u}, :back_to => back_to}, :method => :post,
|
||||||
:selected => (u == @issue.assigned_to), :disabled => !@can[:assign] %></li>
|
:selected => (u == @issue.assigned_to), :disabled => !@can[:assign] %></li>
|
||||||
<% end %>
|
<% end %>
|
||||||
<li><%= context_menu_link l(:label_nobody), {:controller => 'issues', :action => 'update', :id => @issue, :issue => {:assigned_to_id => nil}, :back_to => back_to}, :method => :post,
|
<li><%= context_menu_link l(:label_nobody), {:controller => 'issues', :action => 'edit', :id => @issue, :issue => {:assigned_to_id => nil}, :back_to => back_to}, :method => :post,
|
||||||
:selected => @issue.assigned_to.nil?, :disabled => !@can[:assign] %></li>
|
:selected => @issue.assigned_to.nil?, :disabled => !@can[:assign] %></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -1,19 +1,3 @@
|
||||||
<h2><%=h "#{@issue.tracker.name} ##{@issue.id}" %></h2>
|
<h2><%=h "#{@issue.tracker.name} ##{@issue.id}" %></h2>
|
||||||
|
|
||||||
<% labelled_tabular_form_for :issue, @issue,
|
<%= render :partial => 'edit' %>
|
||||||
:url => {:action => 'edit'},
|
|
||||||
:html => {:id => 'issue-form'} do |f| %>
|
|
||||||
<%= render :partial => 'form', :locals => {:f => f} %>
|
|
||||||
<%= f.hidden_field :lock_version %>
|
|
||||||
<%= submit_tag l(:button_save) %>
|
|
||||||
<%= link_to_remote l(:label_preview),
|
|
||||||
{ :url => { :controller => 'issues', :action => 'preview', :id => @issue },
|
|
||||||
:method => 'post',
|
|
||||||
:update => 'preview',
|
|
||||||
:with => "Form.serialize('issue-form')",
|
|
||||||
:complete => "location.href='#preview-top'"
|
|
||||||
}, :accesskey => accesskey(:preview) %>
|
|
||||||
<% end %>
|
|
||||||
|
|
||||||
<a name="preview-top"></a>
|
|
||||||
<div id="preview" class="wiki"></div>
|
|
||||||
|
|
|
@ -2,7 +2,10 @@
|
||||||
|
|
||||||
<% labelled_tabular_form_for :issue, @issue,
|
<% labelled_tabular_form_for :issue, @issue,
|
||||||
:html => {:multipart => true, :id => 'issue-form'} do |f| %>
|
:html => {:multipart => true, :id => 'issue-form'} do |f| %>
|
||||||
|
<%= error_messages_for 'issue' %>
|
||||||
|
<div class="box">
|
||||||
<%= render :partial => 'issues/form', :locals => {:f => f} %>
|
<%= render :partial => 'issues/form', :locals => {:f => f} %>
|
||||||
|
</div>
|
||||||
<%= submit_tag l(:button_create) %>
|
<%= submit_tag l(:button_create) %>
|
||||||
<%= link_to_remote l(:label_preview),
|
<%= link_to_remote l(:label_preview),
|
||||||
{ :url => { :controller => 'issues', :action => 'preview', :id => @issue },
|
{ :url => { :controller => 'issues', :action => 'preview', :id => @issue },
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
<div class="contextual">
|
<div class="contextual">
|
||||||
<%= show_and_goto_link(l(:button_update), 'update', :class => 'icon icon-note') if authorize_for('issues', 'update') %>
|
<%= show_and_goto_link(l(:button_update), 'update', :class => 'icon icon-edit', :accesskey => accesskey(:edit)) if authorize_for('issues', 'edit') %>
|
||||||
<%= link_to_if_authorized l(:button_edit), {:controller => 'issues', :action => 'edit', :id => @issue}, :class => 'icon icon-edit', :accesskey => accesskey(:edit) %>
|
|
||||||
<%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'edit', :issue_id => @issue}, :class => 'icon icon-time' %>
|
<%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'edit', :issue_id => @issue}, :class => 'icon icon-time' %>
|
||||||
<%= watcher_tag(@issue, User.current) %>
|
<%= watcher_tag(@issue, User.current) %>
|
||||||
<%= link_to_if_authorized l(:button_copy), {:controller => 'issues', :action => 'new', :project_id => @project, :copy_from => @issue }, :class => 'icon icon-copy' %>
|
<%= link_to_if_authorized l(:button_copy), {:controller => 'issues', :action => 'new', :project_id => @project, :copy_from => @issue }, :class => 'icon icon-copy' %>
|
||||||
|
@ -89,11 +88,11 @@ end %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<% if authorize_for('issues', 'update') %>
|
<% if authorize_for('issues', 'edit') %>
|
||||||
<a name="update-anchor"></a>
|
<a name="update-anchor"></a>
|
||||||
<div id="update" style="display:none;">
|
<div id="update" style="display:none;">
|
||||||
<h3><%= l(:button_update) %></h3>
|
<h3><%= l(:button_update) %></h3>
|
||||||
<%= render :partial => 'update' %>
|
<%= render :partial => 'edit' %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
<h2><%= @issue.tracker.name %> #<%= @issue.id %>: <%=h @issue.subject %></h2>
|
|
||||||
|
|
||||||
<%= error_messages_for 'issue' %>
|
|
||||||
<%= render :partial => 'update' %>
|
|
|
@ -567,3 +567,4 @@ label_repository_plural: Хранилища
|
||||||
label_associated_revisions: Асоциирани ревизии
|
label_associated_revisions: Асоциирани ревизии
|
||||||
setting_user_format: Потребителски формат
|
setting_user_format: Потребителски формат
|
||||||
text_status_changed_by_changeset: Applied in changeset %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
|
label_more: More
|
||||||
|
|
|
@ -567,3 +567,4 @@ label_repository_plural: Repositories
|
||||||
label_associated_revisions: Associated revisions
|
label_associated_revisions: Associated revisions
|
||||||
setting_user_format: Users display format
|
setting_user_format: Users display format
|
||||||
text_status_changed_by_changeset: Applied in changeset %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
|
label_more: More
|
||||||
|
|
|
@ -567,3 +567,4 @@ enumeration_issue_priorities: Ticket-Prioritäten
|
||||||
enumeration_doc_categories: Dokumentenkategorien
|
enumeration_doc_categories: Dokumentenkategorien
|
||||||
enumeration_activities: Aktivitäten (Zeiterfassung)
|
enumeration_activities: Aktivitäten (Zeiterfassung)
|
||||||
text_status_changed_by_changeset: Applied in changeset %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
|
label_more: More
|
||||||
|
|
|
@ -469,6 +469,7 @@ label_display_per_page: 'Per page: %s'
|
||||||
label_age: Age
|
label_age: Age
|
||||||
label_change_properties: Change properties
|
label_change_properties: Change properties
|
||||||
label_general: General
|
label_general: General
|
||||||
|
label_more: More
|
||||||
|
|
||||||
button_login: Login
|
button_login: Login
|
||||||
button_submit: Submit
|
button_submit: Submit
|
||||||
|
|
|
@ -570,3 +570,4 @@ label_repository_plural: Repositories
|
||||||
label_associated_revisions: Associated revisions
|
label_associated_revisions: Associated revisions
|
||||||
setting_user_format: Users display format
|
setting_user_format: Users display format
|
||||||
text_status_changed_by_changeset: Applied in changeset %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
|
label_more: More
|
||||||
|
|
|
@ -571,3 +571,4 @@ enumeration_activities: Aktiviteetit (ajan seuranta)
|
||||||
label_associated_revisions: Liittyvät versiot
|
label_associated_revisions: Liittyvät versiot
|
||||||
setting_user_format: Users display format
|
setting_user_format: Users display format
|
||||||
text_status_changed_by_changeset: Applied in changeset %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
|
label_more: More
|
||||||
|
|
|
@ -470,6 +470,7 @@ label_display_per_page: 'Par page: %s'
|
||||||
label_age: Age
|
label_age: Age
|
||||||
label_change_properties: Changer les propriétés
|
label_change_properties: Changer les propriétés
|
||||||
label_general: Général
|
label_general: Général
|
||||||
|
label_more: Plus
|
||||||
|
|
||||||
button_login: Connexion
|
button_login: Connexion
|
||||||
button_submit: Soumettre
|
button_submit: Soumettre
|
||||||
|
|
|
@ -567,3 +567,4 @@ label_repository_plural: Repositories
|
||||||
label_associated_revisions: Associated revisions
|
label_associated_revisions: Associated revisions
|
||||||
setting_user_format: Users display format
|
setting_user_format: Users display format
|
||||||
text_status_changed_by_changeset: Applied in changeset %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
|
label_more: More
|
||||||
|
|
|
@ -567,3 +567,4 @@ label_repository_plural: Repositories
|
||||||
label_associated_revisions: Associated revisions
|
label_associated_revisions: Associated revisions
|
||||||
setting_user_format: Users display format
|
setting_user_format: Users display format
|
||||||
text_status_changed_by_changeset: Applied in changeset %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
|
label_more: More
|
||||||
|
|
|
@ -568,3 +568,4 @@ label_repository_plural: Repositories
|
||||||
label_associated_revisions: Associated revisions
|
label_associated_revisions: Associated revisions
|
||||||
setting_user_format: Users display format
|
setting_user_format: Users display format
|
||||||
text_status_changed_by_changeset: Applied in changeset %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
|
label_more: More
|
||||||
|
|
|
@ -567,3 +567,4 @@ label_repository_plural: 저장소들
|
||||||
label_associated_revisions: Associated revisions
|
label_associated_revisions: Associated revisions
|
||||||
setting_user_format: Users display format
|
setting_user_format: Users display format
|
||||||
text_status_changed_by_changeset: Applied in changeset %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
|
label_more: More
|
||||||
|
|
|
@ -568,3 +568,4 @@ error_can_t_load_default_data: "Numatytoji konfiguracija negali būti užkrauta:
|
||||||
label_associated_revisions: susijusios revizijos
|
label_associated_revisions: susijusios revizijos
|
||||||
setting_user_format: Vartotojo atvaizdavimo formatas
|
setting_user_format: Vartotojo atvaizdavimo formatas
|
||||||
text_status_changed_by_changeset: Applied in changeset %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
|
label_more: More
|
||||||
|
|
|
@ -568,3 +568,4 @@ label_repository_plural: Repositories
|
||||||
label_associated_revisions: Associated revisions
|
label_associated_revisions: Associated revisions
|
||||||
setting_user_format: Users display format
|
setting_user_format: Users display format
|
||||||
text_status_changed_by_changeset: Applied in changeset %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
|
label_more: More
|
||||||
|
|
|
@ -567,3 +567,4 @@ label_repository_plural: Repozytoria
|
||||||
label_associated_revisions: Associated revisions
|
label_associated_revisions: Associated revisions
|
||||||
setting_user_format: Users display format
|
setting_user_format: Users display format
|
||||||
text_status_changed_by_changeset: Applied in changeset %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
|
label_more: More
|
||||||
|
|
|
@ -567,3 +567,4 @@ label_repository_plural: Repositories
|
||||||
label_associated_revisions: Associated revisions
|
label_associated_revisions: Associated revisions
|
||||||
setting_user_format: Users display format
|
setting_user_format: Users display format
|
||||||
text_status_changed_by_changeset: Applied in changeset %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
|
label_more: More
|
||||||
|
|
|
@ -567,3 +567,4 @@ label_repository_plural: Repositories
|
||||||
label_associated_revisions: Associated revisions
|
label_associated_revisions: Associated revisions
|
||||||
setting_user_format: Users display format
|
setting_user_format: Users display format
|
||||||
text_status_changed_by_changeset: Applied in changeset %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
|
label_more: More
|
||||||
|
|
|
@ -567,3 +567,4 @@ label_repository_plural: Repositories
|
||||||
label_associated_revisions: Associated revisions
|
label_associated_revisions: Associated revisions
|
||||||
setting_user_format: Users display format
|
setting_user_format: Users display format
|
||||||
text_status_changed_by_changeset: Applied in changeset %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
|
label_more: More
|
||||||
|
|
|
@ -568,3 +568,4 @@ enumeration_issue_priorities: Приоритеты задач
|
||||||
enumeration_doc_categories: Категории документов
|
enumeration_doc_categories: Категории документов
|
||||||
enumeration_activities: Действия (учет времени)
|
enumeration_activities: Действия (учет времени)
|
||||||
text_status_changed_by_changeset: Applied in changeset %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
|
label_more: More
|
||||||
|
|
|
@ -568,3 +568,4 @@ label_repository_plural: Repositories
|
||||||
label_associated_revisions: Associated revisions
|
label_associated_revisions: Associated revisions
|
||||||
setting_user_format: Users display format
|
setting_user_format: Users display format
|
||||||
text_status_changed_by_changeset: Applied in changeset %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
|
label_more: More
|
||||||
|
|
|
@ -568,3 +568,4 @@ label_repository_plural: Repositories
|
||||||
label_associated_revisions: Associated revisions
|
label_associated_revisions: Associated revisions
|
||||||
setting_user_format: Users display format
|
setting_user_format: Users display format
|
||||||
text_status_changed_by_changeset: Applied in changeset %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
|
label_more: More
|
||||||
|
|
|
@ -567,3 +567,4 @@ enumeration_issue_priorities: 項目重要性
|
||||||
enumeration_doc_categories: 文件分類
|
enumeration_doc_categories: 文件分類
|
||||||
enumeration_activities: 活動 (time tracking)
|
enumeration_activities: 活動 (time tracking)
|
||||||
text_status_changed_by_changeset: Applied in changeset %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
|
label_more: More
|
||||||
|
|
|
@ -570,3 +570,4 @@ label_repository_plural: 源代码库
|
||||||
label_associated_revisions: 相关的版本
|
label_associated_revisions: 相关的版本
|
||||||
setting_user_format: 用户显示格式
|
setting_user_format: 用户显示格式
|
||||||
text_status_changed_by_changeset: Applied in changeset %s.
|
text_status_changed_by_changeset: Applied in changeset %s.
|
||||||
|
label_more: More
|
||||||
|
|
|
@ -32,9 +32,9 @@ Redmine::AccessControl.map do |map|
|
||||||
:reports => :issue_report}, :public => true
|
:reports => :issue_report}, :public => true
|
||||||
map.permission :add_issues, {:issues => :new}
|
map.permission :add_issues, {:issues => :new}
|
||||||
map.permission :edit_issues, {:projects => :bulk_edit_issues,
|
map.permission :edit_issues, {:projects => :bulk_edit_issues,
|
||||||
:issues => [:edit, :update, :destroy_attachment]}
|
:issues => [:edit, :destroy_attachment]}
|
||||||
map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]}
|
map.permission :manage_issue_relations, {:issue_relations => [:new, :destroy]}
|
||||||
map.permission :add_issue_notes, {:issues => :update}
|
map.permission :add_issue_notes, {:issues => :edit}
|
||||||
map.permission :move_issues, {:projects => :move_issues}, :require => :loggedin
|
map.permission :move_issues, {:projects => :move_issues}, :require => :loggedin
|
||||||
map.permission :delete_issues, {:issues => :destroy}, :require => :member
|
map.permission :delete_issues, {:issues => :destroy}, :require => :member
|
||||||
# Queries
|
# Queries
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 469 B |
|
@ -512,7 +512,6 @@ vertical-align: middle;
|
||||||
.icon-reload { background-image: url(../images/reload.png); }
|
.icon-reload { background-image: url(../images/reload.png); }
|
||||||
.icon-lock { background-image: url(../images/locked.png); }
|
.icon-lock { background-image: url(../images/locked.png); }
|
||||||
.icon-unlock { background-image: url(../images/unlock.png); }
|
.icon-unlock { background-image: url(../images/unlock.png); }
|
||||||
.icon-note { background-image: url(../images/note.png); }
|
|
||||||
.icon-checked { background-image: url(../images/true.png); }
|
.icon-checked { background-image: url(../images/true.png); }
|
||||||
|
|
||||||
.icon22-projects { background-image: url(../images/22x22/projects.png); }
|
.icon22-projects { background-image: url(../images/22x22/projects.png); }
|
||||||
|
|
|
@ -217,18 +217,11 @@ class IssuesControllerTest < Test::Unit::TestCase
|
||||||
assert mail.body.include?("Subject changed from #{old_subject} to #{new_subject}")
|
assert mail.body.include?("Subject changed from #{old_subject} to #{new_subject}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_get_update
|
def test_post_edit_with_status_and_assignee_change
|
||||||
@request.session[:user_id] = 2
|
|
||||||
get :update, :id => 1
|
|
||||||
assert_response :success
|
|
||||||
assert_template 'update'
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_update_with_status_and_assignee_change
|
|
||||||
issue = Issue.find(1)
|
issue = Issue.find(1)
|
||||||
assert_equal 1, issue.status_id
|
assert_equal 1, issue.status_id
|
||||||
@request.session[:user_id] = 2
|
@request.session[:user_id] = 2
|
||||||
post :update,
|
post :edit,
|
||||||
:id => 1,
|
:id => 1,
|
||||||
:issue => { :status_id => 2, :assigned_to_id => 3 },
|
:issue => { :status_id => 2, :assigned_to_id => 3 },
|
||||||
:notes => 'Assigned to dlopper'
|
:notes => 'Assigned to dlopper'
|
||||||
|
@ -243,10 +236,10 @@ class IssuesControllerTest < Test::Unit::TestCase
|
||||||
assert mail.body.include?("Status changed from New to Assigned")
|
assert mail.body.include?("Status changed from New to Assigned")
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_update_with_note_only
|
def test_post_edit_with_note_only
|
||||||
notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
|
notes = 'Note added by IssuesControllerTest#test_update_with_note_only'
|
||||||
# anonymous user
|
# anonymous user
|
||||||
post :update,
|
post :edit,
|
||||||
:id => 1,
|
:id => 1,
|
||||||
:notes => notes
|
:notes => notes
|
||||||
assert_redirected_to 'issues/show/1'
|
assert_redirected_to 'issues/show/1'
|
||||||
|
@ -259,10 +252,10 @@ class IssuesControllerTest < Test::Unit::TestCase
|
||||||
assert mail.body.include?(notes)
|
assert mail.body.include?(notes)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_update_with_note_and_spent_time
|
def test_post_edit_with_note_and_spent_time
|
||||||
@request.session[:user_id] = 2
|
@request.session[:user_id] = 2
|
||||||
spent_hours_before = Issue.find(1).spent_hours
|
spent_hours_before = Issue.find(1).spent_hours
|
||||||
post :update,
|
post :edit,
|
||||||
:id => 1,
|
:id => 1,
|
||||||
:notes => '2.5 hours added',
|
:notes => '2.5 hours added',
|
||||||
:time_entry => { :hours => '2.5', :comments => '', :activity_id => Enumeration.get_values('ACTI').first }
|
:time_entry => { :hours => '2.5', :comments => '', :activity_id => Enumeration.get_values('ACTI').first }
|
||||||
|
@ -280,9 +273,9 @@ class IssuesControllerTest < Test::Unit::TestCase
|
||||||
assert_equal spent_hours_before + 2.5, issue.spent_hours
|
assert_equal spent_hours_before + 2.5, issue.spent_hours
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_update_with_attachment_only
|
def test_post_edit_with_attachment_only
|
||||||
# anonymous user
|
# anonymous user
|
||||||
post :update,
|
post :edit,
|
||||||
:id => 1,
|
:id => 1,
|
||||||
:notes => '',
|
:notes => '',
|
||||||
:attachments => [ test_uploaded_file('testfile.txt', 'text/plain') ]
|
:attachments => [ test_uploaded_file('testfile.txt', 'text/plain') ]
|
||||||
|
@ -297,12 +290,12 @@ class IssuesControllerTest < Test::Unit::TestCase
|
||||||
assert mail.body.include?('testfile.txt')
|
assert mail.body.include?('testfile.txt')
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_update_with_no_change
|
def test_post_edit_with_no_change
|
||||||
issue = Issue.find(1)
|
issue = Issue.find(1)
|
||||||
issue.journals.clear
|
issue.journals.clear
|
||||||
ActionMailer::Base.deliveries.clear
|
ActionMailer::Base.deliveries.clear
|
||||||
|
|
||||||
post :update,
|
post :edit,
|
||||||
:id => 1,
|
:id => 1,
|
||||||
:notes => ''
|
:notes => ''
|
||||||
assert_redirected_to 'issues/show/1'
|
assert_redirected_to 'issues/show/1'
|
||||||
|
|
|
@ -48,7 +48,7 @@ class IssuesTest < ActionController::IntegrationTest
|
||||||
def test_issue_attachements
|
def test_issue_attachements
|
||||||
log_user('jsmith', 'jsmith')
|
log_user('jsmith', 'jsmith')
|
||||||
|
|
||||||
post 'issues/update/1',
|
post 'issues/edit/1',
|
||||||
:notes => 'Some notes',
|
:notes => 'Some notes',
|
||||||
:attachments => ([] << ActionController::TestUploadedFile.new(Test::Unit::TestCase.fixture_path + '/files/testfile.txt', 'text/plain'))
|
:attachments => ([] << ActionController::TestUploadedFile.new(Test::Unit::TestCase.fixture_path + '/files/testfile.txt', 'text/plain'))
|
||||||
assert_redirected_to "issues/show/1"
|
assert_redirected_to "issues/show/1"
|
||||||
|
|
Loading…
Reference in New Issue