Commit fce8b459 authored by jplang's avatar jplang

* new report: project activity

* "start date" and "% done" fields added on issues
* project calendar added
* gantt chart added (exportable to pdf)
* multiple file upload for issues attachments
* user custom field displayed on account/show
* default configuration improved (default roles, trackers, status, permissions and workflows)
* fixed: project settings now displayed according to user's permissions

git-svn-id: https://svn.redmine.org/redmine/trunk@44 e93f8b46-1217-0410-a6f0-8f06a7374b81
parent 90287eaf
......@@ -27,6 +27,7 @@ class AccountController < ApplicationController
# Show user's account
def show
@user = User.find(params[:id])
@custom_values = @user.custom_values.find(:all, :include => :custom_field)
end
# Login request and validation
......
......@@ -81,6 +81,7 @@ class IssuesController < ApplicationController
@issue.status = @history.status
@issue.fixed_version_id = (params[:issue][:fixed_version_id])
@issue.assigned_to_id = (params[:issue][:assigned_to_id])
@issue.done_ratio = (params[:issue][:done_ratio])
@issue.lock_version = (params[:issue][:lock_version])
if @issue.save
flash[:notice] = l(:notice_successful_update)
......@@ -124,5 +125,6 @@ private
def find_project
@issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
@project = @issue.project
@html_title = "#{@project.name} - #{@issue.tracker.name} ##{@issue.id}"
end
end
......@@ -182,7 +182,8 @@ class ProjectsController < ApplicationController
@tracker = Tracker.find(params[:tracker_id])
@priorities = Enumeration::get_values('IPRI')
@issue = Issue.new(:project => @project, :tracker => @tracker)
if request.get?
if request.get?
@issue.start_date = Date.today
@custom_values = @project.custom_fields_for_issues(@tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue) }
else
@issue.attributes = params[:issue]
......@@ -214,7 +215,7 @@ class ProjectsController < ApplicationController
@results_per_page = params[:per_page].to_i
session[:results_per_page] = @results_per_page
else
@results_per_page = session[:results_per_page] || @results_per_page_options.first
@results_per_page = session[:results_per_page] || 25
end
@issue_count = Issue.count(:include => [:status, :project], :conditions => search_filter_clause)
......@@ -356,16 +357,22 @@ class ProjectsController < ApplicationController
end
def activity
@date_from = begin
params[:date_from].to_date
rescue
end || Date.today
@days_back = params[:days_back] ? params[:days_back].to_i : 15
@date_to = @date_from - @days_back
if params[:year] and params[:year].to_i > 1900
@year = params[:year].to_i
if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
@month = params[:month].to_i
end
end
@year ||= Date.today.year
@month ||= Date.today.month
@date_from = Date.civil(@year, @month, 1)
@date_to = (@date_from >> 1)-1
@events_by_day = {}
unless params[:show_issues] == "0"
@project.issues.find(:all, :include => [:author, :status], :conditions => ["issues.created_on<=? and issues.created_on>=?", @date_from+1, @date_to], :order => "issues.created_on asc" ).each { |i|
@project.issues.find(:all, :include => [:author, :status], :conditions => ["issues.created_on>=? and issues.created_on<=?", @date_from, @date_to] ).each { |i|
@events_by_day[i.created_on.to_date] ||= []
@events_by_day[i.created_on.to_date] << i
}
......@@ -373,7 +380,7 @@ class ProjectsController < ApplicationController
end
unless params[:show_news] == "0"
@project.news.find(:all, :conditions => ["news.created_on<=? and news.created_on>=?", @date_from+1, @date_to], :order => "news.created_on asc" ).each { |i|
@project.news.find(:all, :conditions => ["news.created_on>=? and news.created_on<=?", @date_from, @date_to] ).each { |i|
@events_by_day[i.created_on.to_date] ||= []
@events_by_day[i.created_on.to_date] << i
}
......@@ -381,7 +388,7 @@ class ProjectsController < ApplicationController
end
unless params[:show_files] == "0"
Attachment.find(:all, :joins => "LEFT JOIN versions ON versions.id = attachments.container_id", :conditions => ["attachments.container_type='Version' and versions.project_id=? and attachments.created_on<=? and attachments.created_on>=?", @project.id, @date_from+1, @date_to], :order => "attachments.created_on asc" ).each { |i|
Attachment.find(:all, :joins => "LEFT JOIN versions ON versions.id = attachments.container_id", :conditions => ["attachments.container_type='Version' and versions.project_id=? and attachments.created_on>=? and attachments.created_on<=?", @project.id, @date_from, @date_to] ).each { |i|
@events_by_day[i.created_on.to_date] ||= []
@events_by_day[i.created_on.to_date] << i
}
......@@ -389,7 +396,7 @@ class ProjectsController < ApplicationController
end
unless params[:show_documentss] == "0"
Attachment.find(:all, :joins => "LEFT JOIN documents ON documents.id = attachments.container_id", :conditions => ["attachments.container_type='Document' and documents.project_id=? and attachments.created_on<=? and attachments.created_on>=?", @project.id, @date_from+1, @date_to], :order => "attachments.created_on asc" ).each { |i|
Attachment.find(:all, :joins => "LEFT JOIN documents ON documents.id = attachments.container_id", :conditions => ["attachments.container_type='Document' and documents.project_id=? and attachments.created_on>=? and attachments.created_on<=?", @project.id, @date_from, @date_to] ).each { |i|
@events_by_day[i.created_on.to_date] ||= []
@events_by_day[i.created_on.to_date] << i
}
......@@ -397,12 +404,64 @@ class ProjectsController < ApplicationController
end
end
def calendar
if params[:year] and params[:year].to_i > 1900
@year = params[:year].to_i
if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
@month = params[:month].to_i
end
end
@year ||= Date.today.year
@month ||= Date.today.month
@date_from = Date.civil(@year, @month, 1)
@date_to = (@date_from >> 1)-1
# start on monday
@date_from = @date_from - (@date_from.cwday-1)
# finish on sunday
@date_to = @date_to + (7-@date_to.cwday)
@issues = @project.issues.find(:all, :include => :tracker, :conditions => ["((start_date>=? and start_date<=?) or (due_date>=? and due_date<=?))", @date_from, @date_to, @date_from, @date_to])
render :layout => false if request.xhr?
end
def gantt
if params[:year] and params[:year].to_i >0
@year_from = params[:year].to_i
if params[:month] and params[:month].to_i >=1 and params[:month].to_i <= 12
@month_from = params[:month].to_i
else
@month_from = 1
end
else
@month_from ||= (Date.today << 1).month
@year_from ||= (Date.today << 1).year
end
@zoom = (params[:zoom].to_i > 0 and params[:zoom].to_i < 5) ? params[:zoom].to_i : 2
@months = (params[:months].to_i > 0 and params[:months].to_i < 25) ? params[:months].to_i : 6
@date_from = Date.civil(@year_from, @month_from, 1)
@date_to = (@date_from >> @months) - 1
@issues = @project.issues.find(:all, :order => "start_date, due_date", :conditions => ["(((start_date>=? and start_date<=?) or (due_date>=? and due_date<=?) or (start_date<? and due_date>?)) and start_date is not null and due_date is not null)", @date_from, @date_to, @date_from, @date_to, @date_from, @date_to])
if params[:output]=='pdf'
@options_for_rfpdf ||= {}
@options_for_rfpdf[:file_name] = "gantt.pdf"
render :template => "projects/gantt.rfpdf", :layout => false
else
render :template => "projects/gantt.rhtml"
end
end
private
# Find project of id params[:id]
# if not found, redirect to project list
# Used as a before_filter
def find_project
@project = Project.find(params[:id])
@project = Project.find(params[:id])
@html_title = @project.name
rescue
redirect_to :action => 'list'
end
......
......@@ -51,14 +51,15 @@ class UsersController < ApplicationController
@user = User.new(params[:user])
@user.admin = params[:user][:admin] || false
@user.login = params[:user][:login]
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation]
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless @user.auth_source_id
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
@user.custom_values = @custom_values
if @user.save
flash[:notice] = l(:notice_successful_create)
redirect_to :action => 'list'
end
end
end
@auth_sources = AuthSource.find(:all)
end
def edit
......@@ -68,7 +69,7 @@ class UsersController < ApplicationController
else
@user.admin = params[:user][:admin] if params[:user][:admin]
@user.login = params[:user][:login] if params[:user][:login]
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless params[:password].nil? or params[:password].empty?
@user.password, @user.password_confirmation = params[:password], params[:password_confirmation] unless params[:password].nil? or params[:password].empty? or @user.auth_source_id
if params[:custom_fields]
@custom_values = UserCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @user, :value => params["custom_fields"][x.id.to_s]) }
@user.custom_values = @custom_values
......@@ -78,6 +79,7 @@ class UsersController < ApplicationController
redirect_to :action => 'list'
end
end
@auth_sources = AuthSource.find(:all)
end
def destroy
......
......@@ -57,6 +57,10 @@ module ApplicationHelper
def format_time(time)
l_datetime(time) if time
end
def day_name(day)
l(:general_day_names).split(',')[day-1]
end
def pagination_links_full(paginator, options={}, html_options={})
html = ''
......@@ -76,6 +80,10 @@ module ApplicationHelper
html
end
def textilizable(text)
$RDM_TEXTILE_DISABLED ? text : textilize(text)
end
def error_messages_for(object_name, options = {})
options = options.symbolize_keys
object = instance_variable_get("@#{object_name}")
......
......@@ -33,6 +33,7 @@ class Issue < ActiveRecord::Base
has_many :custom_fields, :through => :custom_values
validates_presence_of :subject, :description, :priority, :tracker, :author, :status
validates_inclusion_of :done_ratio, :in => 0..100
validates_associated :custom_values, :on => :update
# set default status for new issues
......@@ -44,6 +45,10 @@ class Issue < ActiveRecord::Base
if self.due_date.nil? && @attributes['due_date'] && !@attributes['due_date'].empty?
errors.add :due_date, :activerecord_error_not_a_date
end
if self.due_date and self.start_date and self.due_date < self.start_date
errors.add :due_date, :activerecord_error_greater_than_start_date
end
end
def before_create
......
<h2><%= @user.display_name %></h2>
<p>
<%= mail_to @user.mail %><br />
<%=l(:label_registered_on)%>: <%= format_date(@user.created_on) %>
<%= mail_to @user.mail %>
<ul>
<li><%=l(:label_registered_on)%>: <%= format_date(@user.created_on) %></li>
<% for custom_value in @custom_values %>
<% if !custom_value.value.empty? %>
<li><%= custom_value.custom_field.name%>: <%= show_value(custom_value) %></li>
<% end %>
<% end %>
</ul>
</p>
<h3><%=l(:label_project_plural)%></h3>
......
......@@ -14,6 +14,12 @@
<option value=""></option>
<%= options_from_collection_for_select @assignable_to, "id", "display_name", @issue.assigned_to_id %></p>
</select></p>
<p><label for="issue_done_ratio"><%=l(:field_done_ratio)%></label>
<%= select("issue", "done_ratio", ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) ) %>
</select></p>
<p><label for="issue_fixed_version"><%=l(:field_fixed_version)%></label>
<select name="issue[fixed_version_id]">
......
......@@ -4,14 +4,22 @@
<%= error_messages_for 'issue' %>
<div class="box">
<!--[form:issue]-->
<div class="splitcontentleft">
<p><label><%=l(:field_status)%></label> <%= @issue.status.name %></p>
<p><%= f.select :priority_id, (@priorities.collect {|p| [p.name, p.id]}), :required => true %></p>
<p><%= f.select :assigned_to_id, (@issue.project.members.collect {|m| [m.name, m.user_id]}), :include_blank => true %></p>
<p><%= f.select :category_id, (@project.issue_categories.collect {|c| [c.name, c.id]}) %></p>
</div>
<div class="splitcontentright">
<p><%= f.text_field :start_date, :size => 10 %><%= calendar_for('issue_start_date') %></p>
<p><%= f.text_field :due_date, :size => 10 %><%= calendar_for('issue_due_date') %></p>
<p><%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %></p>
</div>
<div class="clear">
<p><%= f.text_field :subject, :size => 80, :required => true %></p>
<p><%= f.text_area :description, :cols => 60, :rows => 10, :required => true %></p>
<p><%= f.text_field :due_date, :size => 10 %><%= calendar_for('issue_due_date') %></p>
<% for @custom_value in @custom_values %>
<p><%= custom_field_tag_with_label @custom_value %></p>
......@@ -19,36 +27,23 @@
<p><%= f.select :fixed_version_id, (@project.versions.collect {|v| [v.name, v.id]}), { :include_blank => true } %>
</select></p>
</div>
<!--[eoform:issue]-->
</div>
<%= f.hidden_field :lock_version %>
<%= submit_tag l(:button_save) %>
<% end %>
<% unless $RDM_TEXTILE_DISABLED %>
<%= javascript_include_tag 'jstoolbar' %>
<script type="text/javascript">
//<![CDATA[
jsToolBar.prototype.base_url = 'http://callmepep.org';
jsToolBar.prototype.legend_msg = 'You can use the following shortcuts to format your text.';
jsToolBar.prototype.elements.strong.title = 'Strong emphasis';
jsToolBar.prototype.elements.em.title = 'Emphasis';
jsToolBar.prototype.elements.ins.title = 'Inserted';
jsToolBar.prototype.elements.del.title = 'Deleted';
jsToolBar.prototype.elements.quote.title = 'Inline quote';
jsToolBar.prototype.elements.code.title = 'Code';
jsToolBar.prototype.elements.br.title = 'Line break';
jsToolBar.prototype.elements.ul.title = 'Unordered list';
jsToolBar.prototype.elements.ol.title = 'Ordered list';
jsToolBar.prototype.elements.link.title = 'Link';
jsToolBar.prototype.elements.link.href_prompt = 'URL?';
jsToolBar.prototype.elements.link.hreflang_prompt = 'Language?';
if (document.getElementById) {
if (document.getElementById('issue_description')) {
var commentTb = new jsToolBar(document.getElementById('issue_description'));
commentTb.draw();
}
}
//]]>
</script>
\ No newline at end of file
</script>
<% end %>
\ No newline at end of file
......@@ -12,16 +12,20 @@
<td width="15%"><b><%=l(:field_priority)%> :</b></td><td width="35%"><%= @issue.priority.name %></td>
</tr>
<tr>
<td><b><%=l(:field_author)%> :</b></td><td><%= link_to_user @issue.author %></td>
<td><b><%=l(:field_assigned_to)%> :</b></td><td><%= @issue.assigned_to ? @issue.assigned_to.name : "-" %></td>
<td><b><%=l(:field_category)%> :</b></td><td><%= @issue.category ? @issue.category.name : "-" %></td>
</tr>
<tr>
<td><b><%=l(:field_author)%> :</b></td><td><%= link_to_user @issue.author %></td>
<td><b><%=l(:field_start_date)%> :</b></td><td><%= format_date(@issue.start_date) %></td>
</tr>
<tr>
<td><b><%=l(:field_created_on)%> :</b></td><td><%= format_date(@issue.created_on) %></td>
<td><b><%=l(:field_assigned_to)%> :</b></td><td><%= @issue.assigned_to ? @issue.assigned_to.name : "-" %></td>
<td><b><%=l(:field_due_date)%> :</b></td><td><%= format_date(@issue.due_date) %></td>
</tr>
<tr>
<td><b><%=l(:field_updated_on)%> :</b></td><td><%= format_date(@issue.updated_on) %></td>
<td><b><%=l(:field_due_date)%> :</b></td><td><%= format_date(@issue.due_date) %></td>
<td><b><%=l(:field_done_ratio)%> :</b></td><td><%= @issue.done_ratio %> %</td>
</tr>
<tr>
<% n = 0
......@@ -39,7 +43,7 @@ end %>
<br />
<b><%=l(:field_description)%> :</b><br /><br />
<%= textilize @issue.description %>
<%= textilizable @issue.description %>
<p>
<% if authorize_for('issues', 'edit') %>
......@@ -98,7 +102,7 @@ end %>
<table width="100%">
<% for attachment in @issue.attachments %>
<tr>
<td><%= link_to attachment.filename, :action => 'download', :id => @issue, :attachment_id => attachment %> (<%= human_size(attachment.filesize) %>)</td>
<td><%= image_tag('attachment') %> <%= link_to attachment.filename, :action => 'download', :id => @issue, :attachment_id => attachment %> (<%= human_size(attachment.filesize) %>)</td>
<td><%= format_date(attachment.created_on) %></td>
<td><%= attachment.author.display_name %></td>
<% if authorize_for('issues', 'destroy_attachment') %>
......@@ -114,8 +118,8 @@ end %>
<br />
<% if authorize_for('issues', 'add_attachment') %>
<%= start_form_tag ({ :controller => 'issues', :action => 'add_attachment', :id => @issue }, :multipart => true, :class => "tabular") %>
<p id="attachments_p"><label><%=l(:label_attachment_new)%>
<%= link_to_function image_tag('add', :align => "top"), "addFileField()" %></label>
<p id="attachments_p"><label><%=l(:label_attachment_new)%>&nbsp;
<%= link_to_function image_tag('add'), "addFileField()" %></label>
<%= file_field_tag 'attachments[]', :size => 30 %></p>
<%= submit_tag l(:button_add) %>
<%= end_form_tag %>
......
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title><%= $RDM_HEADER_TITLE %></title>
<title><%= $RDM_HEADER_TITLE + (@html_title ? ": #{@html_title}" : "") %></title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="description" content="redMine" />
<meta name="keywords" content="issue,bug,tracker" />
......@@ -37,6 +37,7 @@ var menu_contenu=' \
\
<% unless @project.nil? || @project.id.nil? %> \
<div id="menuProject" class="menu" onmouseover="menuMouseover(event)"> \
<%= link_to l(:label_calendar), {:controller => 'projects', :action => 'calendar', :id => @project }, :class => "menuItem" %> \
<%= link_to l(:label_issue_plural), {:controller => 'projects', :action => 'list_issues', :id => @project }, :class => "menuItem" %> \
<%= link_to l(:label_report_plural), {:controller => 'reports', :action => 'issue_report', :id => @project }, :class => "menuItem" %> \
<%= link_to l(:label_activity), {:controller => 'projects', :action => 'activity', :id => @project }, :class => "menuItem" %> \
......@@ -101,6 +102,7 @@ var menu_contenu=' \
<h2><%= @project.name %></h2>
<ul class="menublock">
<li><%= link_to l(:label_overview), :controller => 'projects', :action => 'show', :id => @project %></li>
<li><%= link_to l(:label_calendar), :controller => 'projects', :action => 'calendar', :id => @project %></li>
<li><%= link_to l(:label_issue_plural), :controller => 'projects', :action => 'list_issues', :id => @project %></li>
<li><%= link_to l(:label_report_plural), :controller => 'reports', :action => 'issue_report', :id => @project %></li>
<li><%= link_to l(:label_activity), :controller => 'projects', :action => 'activity', :id => @project %></li>
......@@ -120,7 +122,7 @@ var menu_contenu=' \
<li><%= link_to membership.project.name, :controller => 'projects', :action => 'show', :id => membership.project %></li>
<% end %>
</ul>
<% end %>
<% end %>
</div>
<div id="content">
......
......@@ -3,4 +3,18 @@
<p><%= f.text_field :title, :required => true, :size => 60 %></p>
<p><%= f.text_area :summary, :cols => 60, :rows => 2 %></p>
<p><%= f.text_area :description, :required => true, :cols => 60, :rows => 10 %></p>
</div>
\ No newline at end of file
</div>
<% unless $RDM_TEXTILE_DISABLED %>
<%= javascript_include_tag 'jstoolbar' %>
<script type="text/javascript">
//<![CDATA[
if (document.getElementById) {
if (document.getElementById('news_description')) {
var commentTb = new jsToolBar(document.getElementById('news_description'));
commentTb.draw();
}
}
//]]>
</script>
<% end %>
\ No newline at end of file
......@@ -6,7 +6,7 @@
<b><%=l(:field_created_on)%></b>: <%= format_time(@news.created_on) %>
</p>
<%= simple_format auto_link @news.description %>
<%= textilizable auto_link @news.description %>
<% if authorize_for('news', 'edit') %>
<%= start_form_tag ({:controller => 'news', :action => 'edit', :id => @news}, :method => 'get' ) %>
......
......@@ -3,7 +3,7 @@
<!--[form:project]-->
<p><%= f.text_field :name, :required => true %></p>
<% if admin_loggedin? %>
<% if admin_loggedin? and !@root_projects.empty? %>
<p><%= f.select :parent_id, (@root_projects.collect {|p| [p.name, p.id]}), { :include_blank => true } %></p>
<% end %>
......@@ -14,11 +14,13 @@
<% for @custom_value in @custom_values %>
<p><%= custom_field_tag_with_label @custom_value %></p>
<% end %>
<p><label><%=l(:label_custom_field_plural)%></label>
<% unless @custom_fields.empty? %>
<p><label><%=l(:label_custom_field_plural)%></label>
<% for custom_field in @custom_fields %>
<%= check_box_tag "custom_field_ids[]", custom_field.id, (@project.custom_fields.include? custom_field) %>
<%= check_box_tag "custom_field_ids[]", custom_field.id, ((@project.custom_fields.include? custom_field) or custom_field.is_for_all?), (custom_field.is_for_all? ? {:disabled => "disabled"} : {}) %>
<%= custom_field.name %>
<% end %></p>
<% end %></p>
<% end %>
<!--[eoform:project]-->
</div>
......@@ -3,8 +3,8 @@
<div>
<div class="rightbox">
<%= start_form_tag %>
<p>From <%= text_field_tag 'date_from', @date_from, :size => 10, :class => 'button-small' %>
and <%= text_field_tag 'days_back', @days_back, :size => 2, :class => 'button-small' %> days back</p>
<p><%= select_month(@month, :prefix => "month", :discard_type => true) %>
<%= select_year(@year, :prefix => "year", :discard_type => true) %></p>
<%= check_box_tag 'show_issues', 1, @show_issues %><%= hidden_field_tag 'show_issues', 0 %> <%=l(:label_issue_plural)%><br />
<%= check_box_tag 'show_news', 1, @show_news %><%= hidden_field_tag 'show_news', 0 %> <%=l(:label_news_plural)%><br />
<%= check_box_tag 'show_files', 1, @show_files %><%= hidden_field_tag 'show_files', 0 %> <%=l(:label_attachment_plural)%><br />
......@@ -15,7 +15,7 @@
<% @events_by_day.keys.sort {|x,y| y <=> x }.each do |day| %>
<h3><%= format_date(day) %></h3>
<ul>
<% @events_by_day[day].each do |e| %>
<% @events_by_day[day].sort {|x,y| y.created_on <=> x.created_on }.each do |e| %>
<li><p>
<% if e.is_a? Issue %>
<%= e.created_on.strftime("%H:%M") %> <%= e.tracker.name %> <%= link_to e.long_id, :controller => 'issues', :action => 'show', :id => e %> (<%= e.status.name %>): <%= e.subject %><br />
......@@ -36,8 +36,6 @@
<% end %>
</ul>
<% end %>
<br />
<% if @events_by_day.empty? %><p><i><%= l(:label_no_data) %></i></p><% end %>
<br />
</div>
\ No newline at end of file
......@@ -5,23 +5,46 @@
<div class="box">
<!--[form:issue]-->
<%= hidden_field_tag 'tracker_id', @tracker.id %>
<div class="splitcontentleft">
<p><%= f.select :priority_id, (@priorities.collect {|p| [p.name, p.id]}), :required => true %></p>
<p><%= f.select :assigned_to_id, (@issue.project.members.collect {|m| [m.name, m.user_id]}), :include_blank => true %></p>
<p><%= f.select :category_id, (@project.issue_categories.collect {|c| [c.name, c.id]}), :include_blank => true %></p>
</div>
<div class="splitcontentright">
<p><%= f.text_field :start_date, :size => 10 %><%= calendar_for('issue_start_date') %></p>
<p><%= f.text_field :due_date, :size => 10 %><%= calendar_for('issue_due_date') %></p>
<p><%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %></p>
</div>
<div class="clear">
<p><%= f.text_field :subject, :size => 80, :required => true %></p>
<p><%= f.text_area :description, :cols => 60, :rows => 10, :required => true %></p>
<p><%= f.text_field :due_date, :size => 10 %><%= calendar_for('issue_due_date') %></p>
<% for @custom_value in @custom_values %>
<p><%= custom_field_tag_with_label @custom_value %></p>
<% end %>
<p id="attachments_p"><label for="attachment_file"><%=l(:label_attachment)%>
<%= link_to_function image_tag('add', :align => "top"), "addFileField()" %></label>
<p id="attachments_p"><label for="attachment_file"><%=l(:label_attachment)%>&nbsp;
<%= link_to_function image_tag('add'), "addFileField()" %></label>
<%= file_field_tag 'attachments[]', :size => 30 %></p>
<!--[eoform:issue]-->
</div>
</div>
<!--[eoform:issue]-->
</div>
<%= submit_tag l(:button_create) %>
<% end %>
<% unless $RDM_TEXTILE_DISABLED %>
<%= javascript_include_tag 'jstoolbar' %>
<script type="text/javascript">
//<![CDATA[
if (document.getElementById) {
if (document.getElementById('issue_description')) {
var commentTb = new jsToolBar(document.getElementById('issue_description'));
commentTb.draw();
}
}
//]]>
</script>
<% end %>
\ No newline at end of file
<h2><%= l(:label_calendar) %></h2>
<table width="100%">
<tr>
<td align="left">
<%= start_form_tag :action => 'calendar', :id => @project %>
<%=