##// END OF EJS Templates
Added preview on add/edit issue form....
Jean-Philippe Lang -
r801:5259dec0611a
parent child
Show More
@@ -1,197 +1,204
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 class IssuesController < ApplicationController
18 class IssuesController < ApplicationController
19 layout 'base', :except => :export_pdf
19 layout 'base', :except => :export_pdf
20 before_filter :find_project, :authorize, :except => :index
20 before_filter :find_project, :authorize, :except => [:index, :preview]
21 accept_key_auth :index
21 accept_key_auth :index
22
22
23 cache_sweeper :issue_sweeper, :only => [ :edit, :change_status, :destroy ]
23 cache_sweeper :issue_sweeper, :only => [ :edit, :change_status, :destroy ]
24
24
25 helper :projects
25 helper :projects
26 include ProjectsHelper
26 include ProjectsHelper
27 helper :custom_fields
27 helper :custom_fields
28 include CustomFieldsHelper
28 include CustomFieldsHelper
29 helper :ifpdf
29 helper :ifpdf
30 include IfpdfHelper
30 include IfpdfHelper
31 helper :issue_relations
31 helper :issue_relations
32 include IssueRelationsHelper
32 include IssueRelationsHelper
33 helper :watchers
33 helper :watchers
34 include WatchersHelper
34 include WatchersHelper
35 helper :attachments
35 helper :attachments
36 include AttachmentsHelper
36 include AttachmentsHelper
37 helper :queries
37 helper :queries
38 helper :sort
38 helper :sort
39 include SortHelper
39 include SortHelper
40
40
41 def index
41 def index
42 sort_init "#{Issue.table_name}.id", "desc"
42 sort_init "#{Issue.table_name}.id", "desc"
43 sort_update
43 sort_update
44 retrieve_query
44 retrieve_query
45 if @query.valid?
45 if @query.valid?
46 @issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
46 @issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
47 @issue_pages = Paginator.new self, @issue_count, 25, params['page']
47 @issue_pages = Paginator.new self, @issue_count, 25, params['page']
48 @issues = Issue.find :all, :order => sort_clause,
48 @issues = Issue.find :all, :order => sort_clause,
49 :include => [ :assigned_to, :status, :tracker, :project, :priority, :category ],
49 :include => [ :assigned_to, :status, :tracker, :project, :priority, :category ],
50 :conditions => @query.statement,
50 :conditions => @query.statement,
51 :limit => @issue_pages.items_per_page,
51 :limit => @issue_pages.items_per_page,
52 :offset => @issue_pages.current.offset
52 :offset => @issue_pages.current.offset
53 end
53 end
54 respond_to do |format|
54 respond_to do |format|
55 format.html { render :layout => false if request.xhr? }
55 format.html { render :layout => false if request.xhr? }
56 format.atom { render_feed(@issues, :title => l(:label_issue_plural)) }
56 format.atom { render_feed(@issues, :title => l(:label_issue_plural)) }
57 end
57 end
58 end
58 end
59
59
60 def show
60 def show
61 @custom_values = @issue.custom_values.find(:all, :include => :custom_field)
61 @custom_values = @issue.custom_values.find(:all, :include => :custom_field)
62 @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
62 @journals = @issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
63
63
64 if params[:format]=='pdf'
64 if params[:format]=='pdf'
65 @options_for_rfpdf ||= {}
65 @options_for_rfpdf ||= {}
66 @options_for_rfpdf[:file_name] = "#{@project.identifier}-#{@issue.id}.pdf"
66 @options_for_rfpdf[:file_name] = "#{@project.identifier}-#{@issue.id}.pdf"
67 render :template => 'issues/show.rfpdf', :layout => false
67 render :template => 'issues/show.rfpdf', :layout => false
68 else
68 else
69 @status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
69 @status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
70 render :template => 'issues/show.rhtml'
70 render :template => 'issues/show.rhtml'
71 end
71 end
72 end
72 end
73
73
74 def edit
74 def edit
75 @priorities = Enumeration::get_values('IPRI')
75 @priorities = Enumeration::get_values('IPRI')
76 if request.get?
76 if request.get?
77 @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) }
77 @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) }
78 else
78 else
79 begin
79 begin
80 @issue.init_journal(self.logged_in_user)
80 @issue.init_journal(self.logged_in_user)
81 # Retrieve custom fields and values
81 # Retrieve custom fields and values
82 @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]) }
82 @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]) }
83 @issue.custom_values = @custom_values
83 @issue.custom_values = @custom_values
84 @issue.attributes = params[:issue]
84 @issue.attributes = params[:issue]
85 if @issue.save
85 if @issue.save
86 flash[:notice] = l(:notice_successful_update)
86 flash[:notice] = l(:notice_successful_update)
87 redirect_to :action => 'show', :id => @issue
87 redirect_to :action => 'show', :id => @issue
88 end
88 end
89 rescue ActiveRecord::StaleObjectError
89 rescue ActiveRecord::StaleObjectError
90 # Optimistic locking exception
90 # Optimistic locking exception
91 flash[:error] = l(:notice_locking_conflict)
91 flash[:error] = l(:notice_locking_conflict)
92 end
92 end
93 end
93 end
94 end
94 end
95
95
96 def add_note
96 def add_note
97 unless params[:notes].empty?
97 unless params[:notes].empty?
98 journal = @issue.init_journal(self.logged_in_user, params[:notes])
98 journal = @issue.init_journal(self.logged_in_user, params[:notes])
99 if @issue.save
99 if @issue.save
100 params[:attachments].each { |file|
100 params[:attachments].each { |file|
101 next unless file.size > 0
101 next unless file.size > 0
102 a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user)
102 a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user)
103 journal.details << JournalDetail.new(:property => 'attachment',
103 journal.details << JournalDetail.new(:property => 'attachment',
104 :prop_key => a.id,
104 :prop_key => a.id,
105 :value => a.filename) unless a.new_record?
105 :value => a.filename) unless a.new_record?
106 } if params[:attachments] and params[:attachments].is_a? Array
106 } if params[:attachments] and params[:attachments].is_a? Array
107 flash[:notice] = l(:notice_successful_update)
107 flash[:notice] = l(:notice_successful_update)
108 Mailer.deliver_issue_edit(journal) if Setting.notified_events.include?('issue_updated')
108 Mailer.deliver_issue_edit(journal) if Setting.notified_events.include?('issue_updated')
109 redirect_to :action => 'show', :id => @issue
109 redirect_to :action => 'show', :id => @issue
110 return
110 return
111 end
111 end
112 end
112 end
113 show
113 show
114 render :action => 'show'
114 render :action => 'show'
115 end
115 end
116
116
117 def change_status
117 def change_status
118 @status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
118 @status_options = @issue.status.find_new_statuses_allowed_to(logged_in_user.role_for_project(@project), @issue.tracker) if logged_in_user
119 @new_status = IssueStatus.find(params[:new_status_id])
119 @new_status = IssueStatus.find(params[:new_status_id])
120 if params[:confirm]
120 if params[:confirm]
121 begin
121 begin
122 journal = @issue.init_journal(self.logged_in_user, params[:notes])
122 journal = @issue.init_journal(self.logged_in_user, params[:notes])
123 @issue.status = @new_status
123 @issue.status = @new_status
124 if @issue.update_attributes(params[:issue])
124 if @issue.update_attributes(params[:issue])
125 # Save attachments
125 # Save attachments
126 params[:attachments].each { |file|
126 params[:attachments].each { |file|
127 next unless file.size > 0
127 next unless file.size > 0
128 a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user)
128 a = Attachment.create(:container => @issue, :file => file, :author => logged_in_user)
129 journal.details << JournalDetail.new(:property => 'attachment',
129 journal.details << JournalDetail.new(:property => 'attachment',
130 :prop_key => a.id,
130 :prop_key => a.id,
131 :value => a.filename) unless a.new_record?
131 :value => a.filename) unless a.new_record?
132 } if params[:attachments] and params[:attachments].is_a? Array
132 } if params[:attachments] and params[:attachments].is_a? Array
133
133
134 # Log time
134 # Log time
135 if current_role.allowed_to?(:log_time)
135 if current_role.allowed_to?(:log_time)
136 @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => logged_in_user, :spent_on => Date.today)
136 @time_entry ||= TimeEntry.new(:project => @project, :issue => @issue, :user => logged_in_user, :spent_on => Date.today)
137 @time_entry.attributes = params[:time_entry]
137 @time_entry.attributes = params[:time_entry]
138 @time_entry.save
138 @time_entry.save
139 end
139 end
140
140
141 flash[:notice] = l(:notice_successful_update)
141 flash[:notice] = l(:notice_successful_update)
142 Mailer.deliver_issue_edit(journal) if Setting.notified_events.include?('issue_updated')
142 Mailer.deliver_issue_edit(journal) if Setting.notified_events.include?('issue_updated')
143 redirect_to :action => 'show', :id => @issue
143 redirect_to :action => 'show', :id => @issue
144 end
144 end
145 rescue ActiveRecord::StaleObjectError
145 rescue ActiveRecord::StaleObjectError
146 # Optimistic locking exception
146 # Optimistic locking exception
147 flash[:error] = l(:notice_locking_conflict)
147 flash[:error] = l(:notice_locking_conflict)
148 end
148 end
149 end
149 end
150 @assignable_to = @project.members.find(:all, :include => :user).collect{ |m| m.user }
150 @assignable_to = @project.members.find(:all, :include => :user).collect{ |m| m.user }
151 @activities = Enumeration::get_values('ACTI')
151 @activities = Enumeration::get_values('ACTI')
152 end
152 end
153
153
154 def destroy
154 def destroy
155 @issue.destroy
155 @issue.destroy
156 redirect_to :controller => 'projects', :action => 'list_issues', :id => @project
156 redirect_to :controller => 'projects', :action => 'list_issues', :id => @project
157 end
157 end
158
158
159 def destroy_attachment
159 def destroy_attachment
160 a = @issue.attachments.find(params[:attachment_id])
160 a = @issue.attachments.find(params[:attachment_id])
161 a.destroy
161 a.destroy
162 journal = @issue.init_journal(self.logged_in_user)
162 journal = @issue.init_journal(self.logged_in_user)
163 journal.details << JournalDetail.new(:property => 'attachment',
163 journal.details << JournalDetail.new(:property => 'attachment',
164 :prop_key => a.id,
164 :prop_key => a.id,
165 :old_value => a.filename)
165 :old_value => a.filename)
166 journal.save
166 journal.save
167 redirect_to :action => 'show', :id => @issue
167 redirect_to :action => 'show', :id => @issue
168 end
168 end
169
169
170 def preview
171 issue = Issue.find_by_id(params[:id])
172 @attachements = issue.attachments if issue
173 @text = params[:issue][:description]
174 render :partial => 'common/preview'
175 end
176
170 private
177 private
171 def find_project
178 def find_project
172 @issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
179 @issue = Issue.find(params[:id], :include => [:project, :tracker, :status, :author, :priority, :category])
173 @project = @issue.project
180 @project = @issue.project
174 rescue ActiveRecord::RecordNotFound
181 rescue ActiveRecord::RecordNotFound
175 render_404
182 render_404
176 end
183 end
177
184
178 # Retrieve query from session or build a new query
185 # Retrieve query from session or build a new query
179 def retrieve_query
186 def retrieve_query
180 if params[:set_filter] or !session[:query] or session[:query].project_id
187 if params[:set_filter] or !session[:query] or session[:query].project_id
181 # Give it a name, required to be valid
188 # Give it a name, required to be valid
182 @query = Query.new(:name => "_", :executed_by => logged_in_user)
189 @query = Query.new(:name => "_", :executed_by => logged_in_user)
183 if params[:fields] and params[:fields].is_a? Array
190 if params[:fields] and params[:fields].is_a? Array
184 params[:fields].each do |field|
191 params[:fields].each do |field|
185 @query.add_filter(field, params[:operators][field], params[:values][field])
192 @query.add_filter(field, params[:operators][field], params[:values][field])
186 end
193 end
187 else
194 else
188 @query.available_filters.keys.each do |field|
195 @query.available_filters.keys.each do |field|
189 @query.add_short_filter(field, params[field]) if params[field]
196 @query.add_short_filter(field, params[field]) if params[field]
190 end
197 end
191 end
198 end
192 session[:query] = @query
199 session[:query] = @query
193 else
200 else
194 @query = session[:query]
201 @query = session[:query]
195 end
202 end
196 end
203 end
197 end
204 end
@@ -1,175 +1,175
1 # redMine - project management software
1 # redMine - project management software
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
2 # Copyright (C) 2006-2007 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require 'diff'
18 require 'diff'
19
19
20 class WikiController < ApplicationController
20 class WikiController < ApplicationController
21 layout 'base'
21 layout 'base'
22 before_filter :find_wiki, :authorize
22 before_filter :find_wiki, :authorize
23
23
24 verify :method => :post, :only => [:destroy, :destroy_attachment], :redirect_to => { :action => :index }
24 verify :method => :post, :only => [:destroy, :destroy_attachment], :redirect_to => { :action => :index }
25
25
26 helper :attachments
26 helper :attachments
27 include AttachmentsHelper
27 include AttachmentsHelper
28
28
29 # display a page (in editing mode if it doesn't exist)
29 # display a page (in editing mode if it doesn't exist)
30 def index
30 def index
31 page_title = params[:page]
31 page_title = params[:page]
32 @page = @wiki.find_or_new_page(page_title)
32 @page = @wiki.find_or_new_page(page_title)
33 if @page.new_record?
33 if @page.new_record?
34 edit
34 edit
35 render :action => 'edit' and return
35 render :action => 'edit' and return
36 end
36 end
37 @content = @page.content_for_version(params[:version])
37 @content = @page.content_for_version(params[:version])
38 if params[:export] == 'html'
38 if params[:export] == 'html'
39 export = render_to_string :action => 'export', :layout => false
39 export = render_to_string :action => 'export', :layout => false
40 send_data(export, :type => 'text/html', :filename => "#{@page.title}.html")
40 send_data(export, :type => 'text/html', :filename => "#{@page.title}.html")
41 return
41 return
42 elsif params[:export] == 'txt'
42 elsif params[:export] == 'txt'
43 send_data(@content.text, :type => 'text/plain', :filename => "#{@page.title}.txt")
43 send_data(@content.text, :type => 'text/plain', :filename => "#{@page.title}.txt")
44 return
44 return
45 end
45 end
46 render :action => 'show'
46 render :action => 'show'
47 end
47 end
48
48
49 # edit an existing page or a new one
49 # edit an existing page or a new one
50 def edit
50 def edit
51 @page = @wiki.find_or_new_page(params[:page])
51 @page = @wiki.find_or_new_page(params[:page])
52 @page.content = WikiContent.new(:page => @page) if @page.new_record?
52 @page.content = WikiContent.new(:page => @page) if @page.new_record?
53
53
54 @content = @page.content_for_version(params[:version])
54 @content = @page.content_for_version(params[:version])
55 @content.text = "h1. #{@page.pretty_title}" if @content.text.blank?
55 @content.text = "h1. #{@page.pretty_title}" if @content.text.blank?
56 # don't keep previous comment
56 # don't keep previous comment
57 @content.comments = nil
57 @content.comments = nil
58 if request.post?
58 if request.post?
59 if !@page.new_record? && @content.text == params[:content][:text]
59 if !@page.new_record? && @content.text == params[:content][:text]
60 # don't save if text wasn't changed
60 # don't save if text wasn't changed
61 redirect_to :action => 'index', :id => @project, :page => @page.title
61 redirect_to :action => 'index', :id => @project, :page => @page.title
62 return
62 return
63 end
63 end
64 #@content.text = params[:content][:text]
64 #@content.text = params[:content][:text]
65 #@content.comments = params[:content][:comments]
65 #@content.comments = params[:content][:comments]
66 @content.attributes = params[:content]
66 @content.attributes = params[:content]
67 @content.author = logged_in_user
67 @content.author = logged_in_user
68 # if page is new @page.save will also save content, but not if page isn't a new record
68 # if page is new @page.save will also save content, but not if page isn't a new record
69 if (@page.new_record? ? @page.save : @content.save)
69 if (@page.new_record? ? @page.save : @content.save)
70 redirect_to :action => 'index', :id => @project, :page => @page.title
70 redirect_to :action => 'index', :id => @project, :page => @page.title
71 end
71 end
72 end
72 end
73 rescue ActiveRecord::StaleObjectError
73 rescue ActiveRecord::StaleObjectError
74 # Optimistic locking exception
74 # Optimistic locking exception
75 flash[:error] = l(:notice_locking_conflict)
75 flash[:error] = l(:notice_locking_conflict)
76 end
76 end
77
77
78 # rename a page
78 # rename a page
79 def rename
79 def rename
80 @page = @wiki.find_page(params[:page])
80 @page = @wiki.find_page(params[:page])
81 @page.redirect_existing_links = true
81 @page.redirect_existing_links = true
82 # used to display the *original* title if some AR validation errors occur
82 # used to display the *original* title if some AR validation errors occur
83 @original_title = @page.pretty_title
83 @original_title = @page.pretty_title
84 if request.post? && @page.update_attributes(params[:wiki_page])
84 if request.post? && @page.update_attributes(params[:wiki_page])
85 flash[:notice] = l(:notice_successful_update)
85 flash[:notice] = l(:notice_successful_update)
86 redirect_to :action => 'index', :id => @project, :page => @page.title
86 redirect_to :action => 'index', :id => @project, :page => @page.title
87 end
87 end
88 end
88 end
89
89
90 # show page history
90 # show page history
91 def history
91 def history
92 @page = @wiki.find_page(params[:page])
92 @page = @wiki.find_page(params[:page])
93
93
94 @version_count = @page.content.versions.count
94 @version_count = @page.content.versions.count
95 @version_pages = Paginator.new self, @version_count, 25, params['p']
95 @version_pages = Paginator.new self, @version_count, 25, params['p']
96 # don't load text
96 # don't load text
97 @versions = @page.content.versions.find :all,
97 @versions = @page.content.versions.find :all,
98 :select => "id, author_id, comments, updated_on, version",
98 :select => "id, author_id, comments, updated_on, version",
99 :order => 'version DESC',
99 :order => 'version DESC',
100 :limit => @version_pages.items_per_page + 1,
100 :limit => @version_pages.items_per_page + 1,
101 :offset => @version_pages.current.offset
101 :offset => @version_pages.current.offset
102
102
103 render :layout => false if request.xhr?
103 render :layout => false if request.xhr?
104 end
104 end
105
105
106 def diff
106 def diff
107 @page = @wiki.find_page(params[:page])
107 @page = @wiki.find_page(params[:page])
108 @diff = @page.diff(params[:version], params[:version_from])
108 @diff = @page.diff(params[:version], params[:version_from])
109 render_404 unless @diff
109 render_404 unless @diff
110 end
110 end
111
111
112 # remove a wiki page and its history
112 # remove a wiki page and its history
113 def destroy
113 def destroy
114 @page = @wiki.find_page(params[:page])
114 @page = @wiki.find_page(params[:page])
115 @page.destroy if @page
115 @page.destroy if @page
116 redirect_to :action => 'special', :id => @project, :page => 'Page_index'
116 redirect_to :action => 'special', :id => @project, :page => 'Page_index'
117 end
117 end
118
118
119 # display special pages
119 # display special pages
120 def special
120 def special
121 page_title = params[:page].downcase
121 page_title = params[:page].downcase
122 case page_title
122 case page_title
123 # show pages index, sorted by title
123 # show pages index, sorted by title
124 when 'page_index', 'date_index'
124 when 'page_index', 'date_index'
125 # eager load information about last updates, without loading text
125 # eager load information about last updates, without loading text
126 @pages = @wiki.pages.find :all, :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on",
126 @pages = @wiki.pages.find :all, :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on",
127 :joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id",
127 :joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id",
128 :order => 'title'
128 :order => 'title'
129 @pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
129 @pages_by_date = @pages.group_by {|p| p.updated_on.to_date}
130 # export wiki to a single html file
130 # export wiki to a single html file
131 when 'export'
131 when 'export'
132 @pages = @wiki.pages.find :all, :order => 'title'
132 @pages = @wiki.pages.find :all, :order => 'title'
133 export = render_to_string :action => 'export_multiple', :layout => false
133 export = render_to_string :action => 'export_multiple', :layout => false
134 send_data(export, :type => 'text/html', :filename => "wiki.html")
134 send_data(export, :type => 'text/html', :filename => "wiki.html")
135 return
135 return
136 else
136 else
137 # requested special page doesn't exist, redirect to default page
137 # requested special page doesn't exist, redirect to default page
138 redirect_to :action => 'index', :id => @project, :page => nil and return
138 redirect_to :action => 'index', :id => @project, :page => nil and return
139 end
139 end
140 render :action => "special_#{page_title}"
140 render :action => "special_#{page_title}"
141 end
141 end
142
142
143 def preview
143 def preview
144 page = @wiki.find_page(params[:page])
144 page = @wiki.find_page(params[:page])
145 @attachements = page.attachments if page
145 @attachements = page.attachments if page
146 @text = params[:content][:text]
146 @text = params[:content][:text]
147 render :partial => 'preview'
147 render :partial => 'common/preview'
148 end
148 end
149
149
150 def add_attachment
150 def add_attachment
151 @page = @wiki.find_page(params[:page])
151 @page = @wiki.find_page(params[:page])
152 # Save the attachments
152 # Save the attachments
153 params[:attachments].each { |file|
153 params[:attachments].each { |file|
154 next unless file.size > 0
154 next unless file.size > 0
155 a = Attachment.create(:container => @page, :file => file, :author => logged_in_user)
155 a = Attachment.create(:container => @page, :file => file, :author => logged_in_user)
156 } if params[:attachments] and params[:attachments].is_a? Array
156 } if params[:attachments] and params[:attachments].is_a? Array
157 redirect_to :action => 'index', :page => @page.title
157 redirect_to :action => 'index', :page => @page.title
158 end
158 end
159
159
160 def destroy_attachment
160 def destroy_attachment
161 @page = @wiki.find_page(params[:page])
161 @page = @wiki.find_page(params[:page])
162 @page.attachments.find(params[:attachment_id]).destroy
162 @page.attachments.find(params[:attachment_id]).destroy
163 redirect_to :action => 'index', :page => @page.title
163 redirect_to :action => 'index', :page => @page.title
164 end
164 end
165
165
166 private
166 private
167
167
168 def find_wiki
168 def find_wiki
169 @project = Project.find(params[:id])
169 @project = Project.find(params[:id])
170 @wiki = @project.wiki
170 @wiki = @project.wiki
171 render_404 unless @wiki
171 render_404 unless @wiki
172 rescue ActiveRecord::RecordNotFound
172 rescue ActiveRecord::RecordNotFound
173 render_404
173 render_404
174 end
174 end
175 end
175 end
1 NO CONTENT: file renamed from app/views/wiki/_preview.rhtml to app/views/common/_preview.rhtml
NO CONTENT: file renamed from app/views/wiki/_preview.rhtml to app/views/common/_preview.rhtml
@@ -1,48 +1,52
1 <%= error_messages_for 'issue' %>
1 <%= error_messages_for 'issue' %>
2 <div class="box">
2 <div class="box">
3
3
4 <div class="splitcontentleft">
4 <div class="splitcontentleft">
5 <% if @issue.new_record? %>
5 <% if @issue.new_record? %>
6 <p><%= f.select :status_id, (@allowed_statuses.collect {|p| [p.name, p.id]}), :required => true %></p>
6 <p><%= f.select :status_id, (@allowed_statuses.collect {|p| [p.name, p.id]}), :required => true %></p>
7 <% else %>
7 <% else %>
8 <p><label><%= l(:field_status) %></label> <%= @issue.status.name %></p>
8 <p><label><%= l(:field_status) %></label> <%= @issue.status.name %></p>
9 <% end %>
9 <% end %>
10
10
11 <p><%= f.select :priority_id, (@priorities.collect {|p| [p.name, p.id]}), :required => true %></p>
11 <p><%= f.select :priority_id, (@priorities.collect {|p| [p.name, p.id]}), :required => true %></p>
12 <p><%= f.select :assigned_to_id, (@issue.assignable_users.collect {|m| [m.name, m.id]}), :include_blank => true %></p>
12 <p><%= f.select :assigned_to_id, (@issue.assignable_users.collect {|m| [m.name, m.id]}), :include_blank => true %></p>
13 <p><%= f.select :category_id, (@project.issue_categories.collect {|c| [c.name, c.id]}), :include_blank => true %>
13 <p><%= f.select :category_id, (@project.issue_categories.collect {|c| [c.name, c.id]}), :include_blank => true %>
14 <%= prompt_to_remote(l(:label_issue_category_new),
14 <%= prompt_to_remote(l(:label_issue_category_new),
15 l(:label_issue_category_new), 'category[name]',
15 l(:label_issue_category_new), 'category[name]',
16 {:controller => 'projects', :action => 'add_issue_category', :id => @project},
16 {:controller => 'projects', :action => 'add_issue_category', :id => @project},
17 :class => 'small') if authorize_for('projects', 'add_issue_category') %></p>
17 :class => 'small') if authorize_for('projects', 'add_issue_category') %></p>
18 </div>
18 </div>
19
19
20 <div class="splitcontentright">
20 <div class="splitcontentright">
21 <p><%= f.text_field :start_date, :size => 10 %><%= calendar_for('issue_start_date') %></p>
21 <p><%= f.text_field :start_date, :size => 10 %><%= calendar_for('issue_start_date') %></p>
22 <p><%= f.text_field :due_date, :size => 10 %><%= calendar_for('issue_due_date') %></p>
22 <p><%= f.text_field :due_date, :size => 10 %><%= calendar_for('issue_due_date') %></p>
23 <p><%= f.text_field :estimated_hours, :size => 3 %> <%= l(:field_hours) %></p>
23 <p><%= f.text_field :estimated_hours, :size => 3 %> <%= l(:field_hours) %></p>
24 <p><%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %></p>
24 <p><%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %></p>
25 </div>
25 </div>
26
26
27 <p><%= f.text_field :subject, :size => 80, :required => true %></p>
27 <p><%= f.text_field :subject, :size => 80, :required => true %></p>
28 <p><%= f.text_area :description, :required => true, :cols => 60, :rows => (@issue.description.blank? ? 10 : [[10, @issue.description.length / 50].max, 100].min), :class => 'wiki-edit' %></p>
28 <p><%= f.text_area :description, :required => true,
29 :cols => 60,
30 :rows => (@issue.description.blank? ? 10 : [[10, @issue.description.length / 50].max, 100].min),
31 :accesskey => accesskey(:edit),
32 :class => 'wiki-edit' %></p>
29 <p><%= f.select :fixed_version_id, (@project.versions.sort.collect {|v| [v.name, v.id]}), { :include_blank => true } %></p>
33 <p><%= f.select :fixed_version_id, (@project.versions.sort.collect {|v| [v.name, v.id]}), { :include_blank => true } %></p>
30 <% for @custom_value in @custom_values %>
34 <% for @custom_value in @custom_values %>
31 <p><%= custom_field_tag_with_label @custom_value %></p>
35 <p><%= custom_field_tag_with_label @custom_value %></p>
32 <% end %>
36 <% end %>
33
37
34 <% if @issue.new_record? %>
38 <% if @issue.new_record? %>
35 <p id="attachments_p"><label for="attachment_file"><%=l(:label_attachment)%>
39 <p id="attachments_p"><label for="attachment_file"><%=l(:label_attachment)%>
36 <%= image_to_function "add.png", "addFileField();return false" %></label>
40 <%= image_to_function "add.png", "addFileField();return false" %></label>
37 <%= file_field_tag 'attachments[]', :size => 30 %> <em>(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)</em></p>
41 <%= file_field_tag 'attachments[]', :size => 30 %> <em>(<%= l(:label_max_size) %>: <%= number_to_human_size(Setting.attachment_max_size.to_i.kilobytes) %>)</em></p>
38 <% end %>
42 <% end %>
39 </div>
43 </div>
40
44
41 <%= wikitoolbar_for 'issue_description' %>
45 <%= wikitoolbar_for 'issue_description' %>
42
46
43 <% content_for :header_tags do %>
47 <% content_for :header_tags do %>
44 <%= javascript_include_tag 'calendar/calendar' %>
48 <%= javascript_include_tag 'calendar/calendar' %>
45 <%= javascript_include_tag "calendar/lang/calendar-#{current_language}.js" %>
49 <%= javascript_include_tag "calendar/lang/calendar-#{current_language}.js" %>
46 <%= javascript_include_tag 'calendar/calendar-setup' %>
50 <%= javascript_include_tag 'calendar/calendar-setup' %>
47 <%= stylesheet_link_tag 'calendar' %>
51 <%= stylesheet_link_tag 'calendar' %>
48 <% end %>
52 <% end %>
@@ -1,7 +1,19
1 <h2><%=h "#{@issue.tracker.name} ##{@issue.id}" %></h2>
1 <h2><%=h "#{@issue.tracker.name} ##{@issue.id}" %></h2>
2
2
3 <% labelled_tabular_form_for :issue, @issue, :url => {:action => 'edit'} do |f| %>
3 <% labelled_tabular_form_for :issue, @issue,
4 :url => {:action => 'edit'},
5 :html => {:id => 'issue-form'} do |f| %>
4 <%= render :partial => 'form', :locals => {:f => f} %>
6 <%= render :partial => 'form', :locals => {:f => f} %>
5 <%= f.hidden_field :lock_version %>
7 <%= f.hidden_field :lock_version %>
6 <%= submit_tag l(:button_save) %>
8 <%= submit_tag l(:button_save) %>
9 <%= link_to_remote l(:label_preview),
10 { :url => { :controller => 'issues', :action => 'preview', :id => @issue },
11 :method => 'post',
12 :update => 'preview',
13 :with => "Form.serialize('issue-form')",
14 :complete => "location.href='#preview-top'"
15 }, :accesskey => accesskey(:preview) %>
7 <% end %>
16 <% end %>
17
18 <a name="preview-top"></a>
19 <div id="preview" class="wiki"></div>
@@ -1,7 +1,19
1 <h2><%=l(:label_issue_new)%>: <%= @tracker.name %></h2>
1 <h2><%=l(:label_issue_new)%>: <%= @tracker.name %></h2>
2
2
3 <% labelled_tabular_form_for :issue, @issue, :url => {:action => 'add_issue'}, :html => {:multipart => true} do |f| %>
3 <% labelled_tabular_form_for :issue, @issue,
4 :url => {:action => 'add_issue'},
5 :html => {:multipart => true, :id => 'issue-form'} do |f| %>
4 <%= hidden_field_tag 'tracker_id', @tracker.id %>
6 <%= hidden_field_tag 'tracker_id', @tracker.id %>
5 <%= render :partial => 'issues/form', :locals => {:f => f} %>
7 <%= render :partial => 'issues/form', :locals => {:f => f} %>
6 <%= submit_tag l(:button_create) %>
8 <%= submit_tag l(:button_create) %>
9 <%= link_to_remote l(:label_preview),
10 { :url => { :controller => 'issues', :action => 'preview', :id => @issue },
11 :method => 'post',
12 :update => 'preview',
13 :with => "Form.serialize('issue-form')",
14 :complete => "location.href='#preview-top'"
15 }, :accesskey => accesskey(:preview) %>
7 <% end %>
16 <% end %>
17
18 <a name="preview-top"></a>
19 <div id="preview" class="wiki"></div>
@@ -1,465 +1,467
1 body { font-family: Verdana, sans-serif; font-size: 12px; color:#484848; margin: 0; padding: 0; min-width: 900px; }
1 body { font-family: Verdana, sans-serif; font-size: 12px; color:#484848; margin: 0; padding: 0; min-width: 900px; }
2
2
3 h1, h2, h3, h4 { font-family: "Trebuchet MS", Verdana, sans-serif;}
3 h1, h2, h3, h4 { font-family: "Trebuchet MS", Verdana, sans-serif;}
4 h1 {margin:0; padding:0; font-size: 24px;}
4 h1 {margin:0; padding:0; font-size: 24px;}
5 h2, .wiki h1 {font-size: 20px;padding: 2px 10px 1px 0px;margin: 0 0 10px 0; border-bottom: 1px solid #bbbbbb; color: #444;}
5 h2, .wiki h1 {font-size: 20px;padding: 2px 10px 1px 0px;margin: 0 0 10px 0; border-bottom: 1px solid #bbbbbb; color: #444;}
6 h3, .wiki h2 {font-size: 16px;padding: 2px 10px 1px 0px;margin: 0 0 10px 0; border-bottom: 1px solid #bbbbbb; color: #444;}
6 h3, .wiki h2 {font-size: 16px;padding: 2px 10px 1px 0px;margin: 0 0 10px 0; border-bottom: 1px solid #bbbbbb; color: #444;}
7 h4, .wiki h3 {font-size: 12px;padding: 2px 10px 1px 0px;margin-bottom: 5px; border-bottom: 1px dotted #bbbbbb; color: #444;}
7 h4, .wiki h3 {font-size: 12px;padding: 2px 10px 1px 0px;margin-bottom: 5px; border-bottom: 1px dotted #bbbbbb; color: #444;}
8
8
9 /***** Layout *****/
9 /***** Layout *****/
10 #top-menu {background: #2C4056;color: #fff;height:1.5em; padding: 2px 6px 0px 6px;}
10 #top-menu {background: #2C4056;color: #fff;height:1.5em; padding: 2px 6px 0px 6px;}
11 #top-menu a {color: #fff; padding-right: 4px;}
11 #top-menu a {color: #fff; padding-right: 4px;}
12 #account {float:right;}
12 #account {float:right;}
13
13
14 #header {height:5.3em;margin:0;background-color:#507AAA;color:#f8f8f8; padding: 4px 8px 0px 6px;}
14 #header {height:5.3em;margin:0;background-color:#507AAA;color:#f8f8f8; padding: 4px 8px 0px 6px;}
15 #header a {color:#f8f8f8;}
15 #header a {color:#f8f8f8;}
16 #quick-search {float:right;}
16 #quick-search {float:right;}
17
17
18 #main-menu {position: absolute; top: 5.5em; left:6px;}
18 #main-menu {position: absolute; top: 5.5em; left:6px;}
19 #main-menu ul {margin: 0; padding: 0;}
19 #main-menu ul {margin: 0; padding: 0;}
20 #main-menu li {
20 #main-menu li {
21 float:left;
21 float:left;
22 list-style-type:none;
22 list-style-type:none;
23 margin: 0px 10px 0px 0px;
23 margin: 0px 10px 0px 0px;
24 padding: 0px 0px 0px 0px;
24 padding: 0px 0px 0px 0px;
25 white-space:nowrap;
25 white-space:nowrap;
26 }
26 }
27 #main-menu li a {
27 #main-menu li a {
28 display: block;
28 display: block;
29 color: #fff;
29 color: #fff;
30 text-decoration: none;
30 text-decoration: none;
31 margin: 0;
31 margin: 0;
32 padding: 4px 4px 4px 4px;
32 padding: 4px 4px 4px 4px;
33 background: #2C4056;
33 background: #2C4056;
34 }
34 }
35 #main-menu li a:hover {background:#759FCF;}
35 #main-menu li a:hover {background:#759FCF;}
36
36
37 #main {background: url(../images/mainbg.png) repeat-x; background-color:#EEEEEE;}
37 #main {background: url(../images/mainbg.png) repeat-x; background-color:#EEEEEE;}
38
38
39 #sidebar{ float: right; width: 17%; position: relative; z-index: 9; min-height: 600px; padding: 0; margin: 0;}
39 #sidebar{ float: right; width: 17%; position: relative; z-index: 9; min-height: 600px; padding: 0; margin: 0;}
40 * html #sidebar{ width: 17%; }
40 * html #sidebar{ width: 17%; }
41 #sidebar h3{ font-size: 14px; margin-top:14px; color: #666; }
41 #sidebar h3{ font-size: 14px; margin-top:14px; color: #666; }
42 #sidebar hr{ width: 100%; margin: 0 auto; height: 1px; background: #ccc; border: 0; }
42 #sidebar hr{ width: 100%; margin: 0 auto; height: 1px; background: #ccc; border: 0; }
43 * html #sidebar hr{ width: 95%; position: relative; left: -6px; color: #ccc; }
43 * html #sidebar hr{ width: 95%; position: relative; left: -6px; color: #ccc; }
44
44
45 #content { width: 80%; background: url(../images/contentbg.png) repeat-x; background-color: #fff; margin: 0px; border-right: 1px solid #ddd; padding: 6px 10px 10px 10px; position: relative; z-index: 10; height:600px; min-height: 600px;}
45 #content { width: 80%; background: url(../images/contentbg.png) repeat-x; background-color: #fff; margin: 0px; border-right: 1px solid #ddd; padding: 6px 10px 10px 10px; position: relative; z-index: 10; height:600px; min-height: 600px;}
46 * html #content{ width: 80%; padding-left: 0; margin-top: 0px; padding: 6px 10px 10px 10px;}
46 * html #content{ width: 80%; padding-left: 0; margin-top: 0px; padding: 6px 10px 10px 10px;}
47 html>body #content {
47 html>body #content {
48 height: auto;
48 height: auto;
49 min-height: 600px;
49 min-height: 600px;
50 }
50 }
51
51
52 #main.nosidebar #sidebar{ display: none; }
52 #main.nosidebar #sidebar{ display: none; }
53 #main.nosidebar #content{ width: auto; border-right: 0; }
53 #main.nosidebar #content{ width: auto; border-right: 0; }
54
54
55 #footer {clear: both; border-top: 1px solid #bbb; font-size: 0.9em; color: #aaa; padding: 5px; text-align:center; background:#fff;}
55 #footer {clear: both; border-top: 1px solid #bbb; font-size: 0.9em; color: #aaa; padding: 5px; text-align:center; background:#fff;}
56
56
57 #login-form table {margin-top:5em; padding:1em; margin-left: auto; margin-right: auto; border: 2px solid #FDBF3B; background-color:#FFEBC1; }
57 #login-form table {margin-top:5em; padding:1em; margin-left: auto; margin-right: auto; border: 2px solid #FDBF3B; background-color:#FFEBC1; }
58 #login-form table td {padding: 6px;}
58 #login-form table td {padding: 6px;}
59 #login-form label {font-weight: bold;}
59 #login-form label {font-weight: bold;}
60
60
61 .clear:after{ content: "."; display: block; height: 0; clear: both; visibility: hidden; }
61 .clear:after{ content: "."; display: block; height: 0; clear: both; visibility: hidden; }
62
62
63 /***** Links *****/
63 /***** Links *****/
64 a, a:link, a:visited{ color: #2A5685; text-decoration: none; }
64 a, a:link, a:visited{ color: #2A5685; text-decoration: none; }
65 a:hover, a:active{ color: #c61a1a; text-decoration: underline;}
65 a:hover, a:active{ color: #c61a1a; text-decoration: underline;}
66 a img{ border: 0; }
66 a img{ border: 0; }
67
67
68 /***** Tables *****/
68 /***** Tables *****/
69 table.list { border: 1px solid #e4e4e4; border-collapse: collapse; width: 100%; margin-bottom: 4px; }
69 table.list { border: 1px solid #e4e4e4; border-collapse: collapse; width: 100%; margin-bottom: 4px; }
70 table.list th { background-color:#EEEEEE; padding: 4px; white-space:nowrap; }
70 table.list th { background-color:#EEEEEE; padding: 4px; white-space:nowrap; }
71 table.list td { overflow: hidden; text-overflow: ellipsis; vertical-align: top;}
71 table.list td { overflow: hidden; text-overflow: ellipsis; vertical-align: top;}
72 table.list td.id { width: 2%; text-align: center;}
72 table.list td.id { width: 2%; text-align: center;}
73 table.list td.checkbox { width: 15px; padding: 0px;}
73 table.list td.checkbox { width: 15px; padding: 0px;}
74
74
75 tr.issue { text-align: center; white-space: nowrap; }
75 tr.issue { text-align: center; white-space: nowrap; }
76 tr.issue td.subject, tr.issue td.category { white-space: normal; }
76 tr.issue td.subject, tr.issue td.category { white-space: normal; }
77 tr.issue td.subject { text-align: left; }
77 tr.issue td.subject { text-align: left; }
78
78
79 table.list tbody tr:hover { background-color:#ffffdd; }
79 table.list tbody tr:hover { background-color:#ffffdd; }
80 table td {padding:2px;}
80 table td {padding:2px;}
81 table p {margin:0;}
81 table p {margin:0;}
82 .odd {background-color:#f6f7f8;}
82 .odd {background-color:#f6f7f8;}
83 .even {background-color: #fff;}
83 .even {background-color: #fff;}
84
84
85 .highlight { background-color: #FCFD8D;}
85 .highlight { background-color: #FCFD8D;}
86
86
87 .box{
87 .box{
88 padding:6px;
88 padding:6px;
89 margin-bottom: 10px;
89 margin-bottom: 10px;
90 background-color:#f6f6f6;
90 background-color:#f6f6f6;
91 color:#505050;
91 color:#505050;
92 line-height:1.5em;
92 line-height:1.5em;
93 border: 1px solid #e4e4e4;
93 border: 1px solid #e4e4e4;
94 }
94 }
95
95
96 div.square {
96 div.square {
97 border: 1px solid #999;
97 border: 1px solid #999;
98 float: left;
98 float: left;
99 margin: .3em .4em 0 .4em;
99 margin: .3em .4em 0 .4em;
100 overflow: hidden;
100 overflow: hidden;
101 width: .6em; height: .6em;
101 width: .6em; height: .6em;
102 }
102 }
103
103
104 .contextual {float:right; white-space: nowrap; line-height:1.4em;margin-top:5px;font-size:0.9em;}
104 .contextual {float:right; white-space: nowrap; line-height:1.4em;margin-top:5px;font-size:0.9em;}
105 .splitcontentleft{float:left; width:49%;}
105 .splitcontentleft{float:left; width:49%;}
106 .splitcontentright{float:right; width:49%;}
106 .splitcontentright{float:right; width:49%;}
107 form {display: inline;}
107 form {display: inline;}
108 input, select {vertical-align: middle; margin-top: 1px; margin-bottom: 1px;}
108 input, select {vertical-align: middle; margin-top: 1px; margin-bottom: 1px;}
109 fieldset {border: 1px solid #e4e4e4; margin:0;}
109 fieldset {border: 1px solid #e4e4e4; margin:0;}
110 legend {color: #484848;}
110 legend {color: #484848;}
111 hr { width: 100%; height: 1px; background: #ccc; border: 0;}
111 hr { width: 100%; height: 1px; background: #ccc; border: 0;}
112 textarea.wiki-edit { width: 99%; }
112 textarea.wiki-edit { width: 99%; }
113 li p {margin-top: 0;}
113 li p {margin-top: 0;}
114 div.issue {background:#ffffdd; padding:6px; margin-bottom:6px;border: 1px solid #d7d7d7;}
114 div.issue {background:#ffffdd; padding:6px; margin-bottom:6px;border: 1px solid #d7d7d7;}
115 .autoscroll {overflow-x: auto; padding:1px; width:100%;}
115 .autoscroll {overflow-x: auto; padding:1px; width:100%;}
116
116
117 /***** Tabular forms ******/
117 /***** Tabular forms ******/
118 .tabular p{
118 .tabular p{
119 margin: 0;
119 margin: 0;
120 padding: 5px 0 8px 0;
120 padding: 5px 0 8px 0;
121 padding-left: 180px; /*width of left column containing the label elements*/
121 padding-left: 180px; /*width of left column containing the label elements*/
122 height: 1%;
122 height: 1%;
123 clear:left;
123 clear:left;
124 }
124 }
125
125
126 .tabular label{
126 .tabular label{
127 font-weight: bold;
127 font-weight: bold;
128 float: left;
128 float: left;
129 text-align: right;
129 text-align: right;
130 margin-left: -180px; /*width of left column*/
130 margin-left: -180px; /*width of left column*/
131 width: 175px; /*width of labels. Should be smaller than left column to create some right
131 width: 175px; /*width of labels. Should be smaller than left column to create some right
132 margin*/
132 margin*/
133 }
133 }
134
134
135 .tabular label.floating{
135 .tabular label.floating{
136 font-weight: normal;
136 font-weight: normal;
137 margin-left: 0px;
137 margin-left: 0px;
138 text-align: left;
138 text-align: left;
139 width: 200px;
139 width: 200px;
140 }
140 }
141
141
142 #preview fieldset {margin-top: 1em; background: url(../images/draft.png)}
143
142 #settings .tabular p{ padding-left: 300px; }
144 #settings .tabular p{ padding-left: 300px; }
143 #settings .tabular label{ margin-left: -300px; width: 295px; }
145 #settings .tabular label{ margin-left: -300px; width: 295px; }
144
146
145 .required {color: #bb0000;}
147 .required {color: #bb0000;}
146 .summary {font-style: italic;}
148 .summary {font-style: italic;}
147
149
148 div.attachments p { margin:4px 0 2px 0; }
150 div.attachments p { margin:4px 0 2px 0; }
149
151
150 /***** Flash & error messages ****/
152 /***** Flash & error messages ****/
151 #flash div, #errorExplanation, .nodata {
153 #flash div, #errorExplanation, .nodata {
152 padding: 4px 4px 4px 30px;
154 padding: 4px 4px 4px 30px;
153 margin-bottom: 12px;
155 margin-bottom: 12px;
154 font-size: 1.1em;
156 font-size: 1.1em;
155 border: 2px solid;
157 border: 2px solid;
156 }
158 }
157
159
158 #flash div {margin-top: 6px;}
160 #flash div {margin-top: 6px;}
159
161
160 #flash div.error, #errorExplanation {
162 #flash div.error, #errorExplanation {
161 background: url(../images/false.png) 8px 5px no-repeat;
163 background: url(../images/false.png) 8px 5px no-repeat;
162 background-color: #ffe3e3;
164 background-color: #ffe3e3;
163 border-color: #dd0000;
165 border-color: #dd0000;
164 color: #550000;
166 color: #550000;
165 }
167 }
166
168
167 #flash div.notice {
169 #flash div.notice {
168 background: url(../images/true.png) 8px 5px no-repeat;
170 background: url(../images/true.png) 8px 5px no-repeat;
169 background-color: #dfffdf;
171 background-color: #dfffdf;
170 border-color: #9fcf9f;
172 border-color: #9fcf9f;
171 color: #005f00;
173 color: #005f00;
172 }
174 }
173
175
174 .nodata {
176 .nodata {
175 text-align: center;
177 text-align: center;
176 background-color: #FFEBC1;
178 background-color: #FFEBC1;
177 border-color: #FDBF3B;
179 border-color: #FDBF3B;
178 color: #A6750C;
180 color: #A6750C;
179 }
181 }
180
182
181 #errorExplanation ul { font-size: 0.9em;}
183 #errorExplanation ul { font-size: 0.9em;}
182
184
183 /***** Ajax indicator ******/
185 /***** Ajax indicator ******/
184 #ajax-indicator {
186 #ajax-indicator {
185 position: absolute; /* fixed not supported by IE */
187 position: absolute; /* fixed not supported by IE */
186 background-color:#eee;
188 background-color:#eee;
187 border: 1px solid #bbb;
189 border: 1px solid #bbb;
188 top:35%;
190 top:35%;
189 left:40%;
191 left:40%;
190 width:20%;
192 width:20%;
191 font-weight:bold;
193 font-weight:bold;
192 text-align:center;
194 text-align:center;
193 padding:0.6em;
195 padding:0.6em;
194 z-index:100;
196 z-index:100;
195 filter:alpha(opacity=50);
197 filter:alpha(opacity=50);
196 -moz-opacity:0.5;
198 -moz-opacity:0.5;
197 opacity: 0.5;
199 opacity: 0.5;
198 -khtml-opacity: 0.5;
200 -khtml-opacity: 0.5;
199 }
201 }
200
202
201 html>body #ajax-indicator { position: fixed; }
203 html>body #ajax-indicator { position: fixed; }
202
204
203 #ajax-indicator span {
205 #ajax-indicator span {
204 background-position: 0% 40%;
206 background-position: 0% 40%;
205 background-repeat: no-repeat;
207 background-repeat: no-repeat;
206 background-image: url(../images/loading.gif);
208 background-image: url(../images/loading.gif);
207 padding-left: 26px;
209 padding-left: 26px;
208 vertical-align: bottom;
210 vertical-align: bottom;
209 }
211 }
210
212
211 /***** Calendar *****/
213 /***** Calendar *****/
212 table.cal {border-collapse: collapse; width: 100%; margin: 8px 0 6px 0;border: 1px solid #d7d7d7;}
214 table.cal {border-collapse: collapse; width: 100%; margin: 8px 0 6px 0;border: 1px solid #d7d7d7;}
213 table.cal th { background-color:#EEEEEE; padding: 4px; }
215 table.cal th { background-color:#EEEEEE; padding: 4px; }
214 table.cal td {border: 1px solid #d7d7d7;}
216 table.cal td {border: 1px solid #d7d7d7;}
215 table.cal td.today {background:#ffffdd;}
217 table.cal td.today {background:#ffffdd;}
216
218
217 /***** Tooltips ******/
219 /***** Tooltips ******/
218 .tooltip{position:relative;z-index:24;}
220 .tooltip{position:relative;z-index:24;}
219 .tooltip:hover{z-index:25;color:#000;}
221 .tooltip:hover{z-index:25;color:#000;}
220 .tooltip span.tip{display: none; text-align:left;}
222 .tooltip span.tip{display: none; text-align:left;}
221
223
222 div.tooltip:hover span.tip{
224 div.tooltip:hover span.tip{
223 display:block;
225 display:block;
224 position:absolute;
226 position:absolute;
225 top:12px; left:24px; width:270px;
227 top:12px; left:24px; width:270px;
226 border:1px solid #555;
228 border:1px solid #555;
227 background-color:#fff;
229 background-color:#fff;
228 padding: 4px;
230 padding: 4px;
229 font-size: 0.8em;
231 font-size: 0.8em;
230 color:#505050;
232 color:#505050;
231 }
233 }
232
234
233 /***** Progress bar *****/
235 /***** Progress bar *****/
234 .progress {
236 .progress {
235 border: 1px solid #D7D7D7;
237 border: 1px solid #D7D7D7;
236 border-collapse: collapse;
238 border-collapse: collapse;
237 border-spacing: 0pt;
239 border-spacing: 0pt;
238 empty-cells: show;
240 empty-cells: show;
239 padding: 3px;
241 padding: 3px;
240 width: 40em;
242 width: 40em;
241 text-align: center;
243 text-align: center;
242 }
244 }
243
245
244 .progress td { height: 1em; }
246 .progress td { height: 1em; }
245 .progress .closed { background: #BAE0BA none repeat scroll 0%; }
247 .progress .closed { background: #BAE0BA none repeat scroll 0%; }
246 .progress .open { background: #FFF none repeat scroll 0%; }
248 .progress .open { background: #FFF none repeat scroll 0%; }
247
249
248 /***** Tabs *****/
250 /***** Tabs *****/
249 #content .tabs{height: 2.6em;}
251 #content .tabs{height: 2.6em;}
250 #content .tabs ul{margin:0;}
252 #content .tabs ul{margin:0;}
251 #content .tabs ul li{
253 #content .tabs ul li{
252 float:left;
254 float:left;
253 list-style-type:none;
255 list-style-type:none;
254 white-space:nowrap;
256 white-space:nowrap;
255 margin-right:8px;
257 margin-right:8px;
256 background:#fff;
258 background:#fff;
257 }
259 }
258 #content .tabs ul li a{
260 #content .tabs ul li a{
259 display:block;
261 display:block;
260 font-size: 0.9em;
262 font-size: 0.9em;
261 text-decoration:none;
263 text-decoration:none;
262 line-height:1em;
264 line-height:1em;
263 padding:4px;
265 padding:4px;
264 border: 1px solid #c0c0c0;
266 border: 1px solid #c0c0c0;
265 }
267 }
266
268
267 #content .tabs ul li a.selected, #content .tabs ul li a:hover{
269 #content .tabs ul li a.selected, #content .tabs ul li a:hover{
268 background-color: #507AAA;
270 background-color: #507AAA;
269 border: 1px solid #507AAA;
271 border: 1px solid #507AAA;
270 color: #fff;
272 color: #fff;
271 text-decoration:none;
273 text-decoration:none;
272 }
274 }
273
275
274 /***** Diff *****/
276 /***** Diff *****/
275 .diff_out { background: #fcc; }
277 .diff_out { background: #fcc; }
276 .diff_in { background: #cfc; }
278 .diff_in { background: #cfc; }
277
279
278 /***** Wiki *****/
280 /***** Wiki *****/
279 div.wiki table {
281 div.wiki table {
280 border: 1px solid #505050;
282 border: 1px solid #505050;
281 border-collapse: collapse;
283 border-collapse: collapse;
282 }
284 }
283
285
284 div.wiki table, div.wiki td, div.wiki th {
286 div.wiki table, div.wiki td, div.wiki th {
285 border: 1px solid #bbb;
287 border: 1px solid #bbb;
286 padding: 4px;
288 padding: 4px;
287 }
289 }
288
290
289 div.wiki .external {
291 div.wiki .external {
290 background-position: 0% 60%;
292 background-position: 0% 60%;
291 background-repeat: no-repeat;
293 background-repeat: no-repeat;
292 padding-left: 12px;
294 padding-left: 12px;
293 background-image: url(../images/external.png);
295 background-image: url(../images/external.png);
294 }
296 }
295
297
296 div.wiki a.new {
298 div.wiki a.new {
297 color: #b73535;
299 color: #b73535;
298 }
300 }
299
301
300 div.wiki pre {
302 div.wiki pre {
301 margin: 1em 1em 1em 1.6em;
303 margin: 1em 1em 1em 1.6em;
302 padding: 2px;
304 padding: 2px;
303 background-color: #fafafa;
305 background-color: #fafafa;
304 border: 1px solid #dadada;
306 border: 1px solid #dadada;
305 width:95%;
307 width:95%;
306 overflow-x: auto;
308 overflow-x: auto;
307 }
309 }
308
310
309 div.wiki div.toc {
311 div.wiki div.toc {
310 background-color: #ffffdd;
312 background-color: #ffffdd;
311 border: 1px solid #e4e4e4;
313 border: 1px solid #e4e4e4;
312 padding: 4px;
314 padding: 4px;
313 line-height: 1.2em;
315 line-height: 1.2em;
314 margin-bottom: 12px;
316 margin-bottom: 12px;
315 margin-right: 12px;
317 margin-right: 12px;
316 display: table
318 display: table
317 }
319 }
318 * html div.wiki div.toc { width: 50%; } /* IE6 doesn't autosize div */
320 * html div.wiki div.toc { width: 50%; } /* IE6 doesn't autosize div */
319
321
320 div.wiki div.toc.right { float: right; margin-left: 12px; margin-right: 0; width: auto; }
322 div.wiki div.toc.right { float: right; margin-left: 12px; margin-right: 0; width: auto; }
321 div.wiki div.toc.left { float: left; margin-right: 12px; margin-left: 0; width: auto; }
323 div.wiki div.toc.left { float: left; margin-right: 12px; margin-left: 0; width: auto; }
322
324
323 div.wiki div.toc a {
325 div.wiki div.toc a {
324 display: block;
326 display: block;
325 font-size: 0.9em;
327 font-size: 0.9em;
326 font-weight: normal;
328 font-weight: normal;
327 text-decoration: none;
329 text-decoration: none;
328 color: #606060;
330 color: #606060;
329 }
331 }
330 div.wiki div.toc a:hover { color: #c61a1a; text-decoration: underline;}
332 div.wiki div.toc a:hover { color: #c61a1a; text-decoration: underline;}
331
333
332 div.wiki div.toc a.heading2 { margin-left: 6px; }
334 div.wiki div.toc a.heading2 { margin-left: 6px; }
333 div.wiki div.toc a.heading3 { margin-left: 12px; font-size: 0.8em; }
335 div.wiki div.toc a.heading3 { margin-left: 12px; font-size: 0.8em; }
334
336
335 /***** My page layout *****/
337 /***** My page layout *****/
336 .block-receiver {
338 .block-receiver {
337 border:1px dashed #c0c0c0;
339 border:1px dashed #c0c0c0;
338 margin-bottom: 20px;
340 margin-bottom: 20px;
339 padding: 15px 0 15px 0;
341 padding: 15px 0 15px 0;
340 }
342 }
341
343
342 .mypage-box {
344 .mypage-box {
343 margin:0 0 20px 0;
345 margin:0 0 20px 0;
344 color:#505050;
346 color:#505050;
345 line-height:1.5em;
347 line-height:1.5em;
346 }
348 }
347
349
348 .handle {
350 .handle {
349 cursor: move;
351 cursor: move;
350 }
352 }
351
353
352 a.close-icon {
354 a.close-icon {
353 display:block;
355 display:block;
354 margin-top:3px;
356 margin-top:3px;
355 overflow:hidden;
357 overflow:hidden;
356 width:12px;
358 width:12px;
357 height:12px;
359 height:12px;
358 background-repeat: no-repeat;
360 background-repeat: no-repeat;
359 cursor:pointer;
361 cursor:pointer;
360 background-image:url('../images/close.png');
362 background-image:url('../images/close.png');
361 }
363 }
362
364
363 a.close-icon:hover {
365 a.close-icon:hover {
364 background-image:url('../images/close_hl.png');
366 background-image:url('../images/close_hl.png');
365 }
367 }
366
368
367 /***** Gantt chart *****/
369 /***** Gantt chart *****/
368 .gantt_hdr {
370 .gantt_hdr {
369 position:absolute;
371 position:absolute;
370 top:0;
372 top:0;
371 height:16px;
373 height:16px;
372 border-top: 1px solid #c0c0c0;
374 border-top: 1px solid #c0c0c0;
373 border-bottom: 1px solid #c0c0c0;
375 border-bottom: 1px solid #c0c0c0;
374 border-right: 1px solid #c0c0c0;
376 border-right: 1px solid #c0c0c0;
375 text-align: center;
377 text-align: center;
376 overflow: hidden;
378 overflow: hidden;
377 }
379 }
378
380
379 .task {
381 .task {
380 position: absolute;
382 position: absolute;
381 height:8px;
383 height:8px;
382 font-size:0.8em;
384 font-size:0.8em;
383 color:#888;
385 color:#888;
384 padding:0;
386 padding:0;
385 margin:0;
387 margin:0;
386 line-height:0.8em;
388 line-height:0.8em;
387 }
389 }
388
390
389 .task_late { background:#f66 url(../images/task_late.png); border: 1px solid #f66; }
391 .task_late { background:#f66 url(../images/task_late.png); border: 1px solid #f66; }
390 .task_done { background:#66f url(../images/task_done.png); border: 1px solid #66f; }
392 .task_done { background:#66f url(../images/task_done.png); border: 1px solid #66f; }
391 .task_todo { background:#aaa url(../images/task_todo.png); border: 1px solid #aaa; }
393 .task_todo { background:#aaa url(../images/task_todo.png); border: 1px solid #aaa; }
392 .milestone { background-image:url(../images/milestone.png); background-repeat: no-repeat; border: 0; }
394 .milestone { background-image:url(../images/milestone.png); background-repeat: no-repeat; border: 0; }
393
395
394 /***** Icons *****/
396 /***** Icons *****/
395 .icon {
397 .icon {
396 background-position: 0% 40%;
398 background-position: 0% 40%;
397 background-repeat: no-repeat;
399 background-repeat: no-repeat;
398 padding-left: 20px;
400 padding-left: 20px;
399 padding-top: 2px;
401 padding-top: 2px;
400 padding-bottom: 3px;
402 padding-bottom: 3px;
401 }
403 }
402
404
403 .icon22 {
405 .icon22 {
404 background-position: 0% 40%;
406 background-position: 0% 40%;
405 background-repeat: no-repeat;
407 background-repeat: no-repeat;
406 padding-left: 26px;
408 padding-left: 26px;
407 line-height: 22px;
409 line-height: 22px;
408 vertical-align: middle;
410 vertical-align: middle;
409 }
411 }
410
412
411 .icon-add { background-image: url(../images/add.png); }
413 .icon-add { background-image: url(../images/add.png); }
412 .icon-edit { background-image: url(../images/edit.png); }
414 .icon-edit { background-image: url(../images/edit.png); }
413 .icon-del { background-image: url(../images/delete.png); }
415 .icon-del { background-image: url(../images/delete.png); }
414 .icon-move { background-image: url(../images/move.png); }
416 .icon-move { background-image: url(../images/move.png); }
415 .icon-save { background-image: url(../images/save.png); }
417 .icon-save { background-image: url(../images/save.png); }
416 .icon-cancel { background-image: url(../images/cancel.png); }
418 .icon-cancel { background-image: url(../images/cancel.png); }
417 .icon-pdf { background-image: url(../images/pdf.png); }
419 .icon-pdf { background-image: url(../images/pdf.png); }
418 .icon-csv { background-image: url(../images/csv.png); }
420 .icon-csv { background-image: url(../images/csv.png); }
419 .icon-html { background-image: url(../images/html.png); }
421 .icon-html { background-image: url(../images/html.png); }
420 .icon-image { background-image: url(../images/image.png); }
422 .icon-image { background-image: url(../images/image.png); }
421 .icon-txt { background-image: url(../images/txt.png); }
423 .icon-txt { background-image: url(../images/txt.png); }
422 .icon-file { background-image: url(../images/file.png); }
424 .icon-file { background-image: url(../images/file.png); }
423 .icon-folder { background-image: url(../images/folder.png); }
425 .icon-folder { background-image: url(../images/folder.png); }
424 .icon-package { background-image: url(../images/package.png); }
426 .icon-package { background-image: url(../images/package.png); }
425 .icon-home { background-image: url(../images/home.png); }
427 .icon-home { background-image: url(../images/home.png); }
426 .icon-user { background-image: url(../images/user.png); }
428 .icon-user { background-image: url(../images/user.png); }
427 .icon-mypage { background-image: url(../images/user_page.png); }
429 .icon-mypage { background-image: url(../images/user_page.png); }
428 .icon-admin { background-image: url(../images/admin.png); }
430 .icon-admin { background-image: url(../images/admin.png); }
429 .icon-projects { background-image: url(../images/projects.png); }
431 .icon-projects { background-image: url(../images/projects.png); }
430 .icon-logout { background-image: url(../images/logout.png); }
432 .icon-logout { background-image: url(../images/logout.png); }
431 .icon-help { background-image: url(../images/help.png); }
433 .icon-help { background-image: url(../images/help.png); }
432 .icon-attachment { background-image: url(../images/attachment.png); }
434 .icon-attachment { background-image: url(../images/attachment.png); }
433 .icon-index { background-image: url(../images/index.png); }
435 .icon-index { background-image: url(../images/index.png); }
434 .icon-history { background-image: url(../images/history.png); }
436 .icon-history { background-image: url(../images/history.png); }
435 .icon-feed { background-image: url(../images/feed.png); }
437 .icon-feed { background-image: url(../images/feed.png); }
436 .icon-time { background-image: url(../images/time.png); }
438 .icon-time { background-image: url(../images/time.png); }
437 .icon-stats { background-image: url(../images/stats.png); }
439 .icon-stats { background-image: url(../images/stats.png); }
438 .icon-warning { background-image: url(../images/warning.png); }
440 .icon-warning { background-image: url(../images/warning.png); }
439 .icon-fav { background-image: url(../images/fav.png); }
441 .icon-fav { background-image: url(../images/fav.png); }
440 .icon-fav-off { background-image: url(../images/fav_off.png); }
442 .icon-fav-off { background-image: url(../images/fav_off.png); }
441 .icon-reload { background-image: url(../images/reload.png); }
443 .icon-reload { background-image: url(../images/reload.png); }
442 .icon-lock { background-image: url(../images/locked.png); }
444 .icon-lock { background-image: url(../images/locked.png); }
443 .icon-unlock { background-image: url(../images/unlock.png); }
445 .icon-unlock { background-image: url(../images/unlock.png); }
444 .icon-note { background-image: url(../images/note.png); }
446 .icon-note { background-image: url(../images/note.png); }
445
447
446 .icon22-projects { background-image: url(../images/22x22/projects.png); }
448 .icon22-projects { background-image: url(../images/22x22/projects.png); }
447 .icon22-users { background-image: url(../images/22x22/users.png); }
449 .icon22-users { background-image: url(../images/22x22/users.png); }
448 .icon22-tracker { background-image: url(../images/22x22/tracker.png); }
450 .icon22-tracker { background-image: url(../images/22x22/tracker.png); }
449 .icon22-role { background-image: url(../images/22x22/role.png); }
451 .icon22-role { background-image: url(../images/22x22/role.png); }
450 .icon22-workflow { background-image: url(../images/22x22/workflow.png); }
452 .icon22-workflow { background-image: url(../images/22x22/workflow.png); }
451 .icon22-options { background-image: url(../images/22x22/options.png); }
453 .icon22-options { background-image: url(../images/22x22/options.png); }
452 .icon22-notifications { background-image: url(../images/22x22/notifications.png); }
454 .icon22-notifications { background-image: url(../images/22x22/notifications.png); }
453 .icon22-authent { background-image: url(../images/22x22/authent.png); }
455 .icon22-authent { background-image: url(../images/22x22/authent.png); }
454 .icon22-info { background-image: url(../images/22x22/info.png); }
456 .icon22-info { background-image: url(../images/22x22/info.png); }
455 .icon22-comment { background-image: url(../images/22x22/comment.png); }
457 .icon22-comment { background-image: url(../images/22x22/comment.png); }
456 .icon22-package { background-image: url(../images/22x22/package.png); }
458 .icon22-package { background-image: url(../images/22x22/package.png); }
457 .icon22-settings { background-image: url(../images/22x22/settings.png); }
459 .icon22-settings { background-image: url(../images/22x22/settings.png); }
458 .icon22-plugin { background-image: url(../images/22x22/plugin.png); }
460 .icon22-plugin { background-image: url(../images/22x22/plugin.png); }
459
461
460 /***** Media print specific styles *****/
462 /***** Media print specific styles *****/
461 @media print {
463 @media print {
462 #top-menu, #header, #main-menu, #sidebar, #footer, .contextual { display:none; }
464 #top-menu, #header, #main-menu, #sidebar, #footer, .contextual { display:none; }
463 #main { background: #fff; }
465 #main { background: #fff; }
464 #content { width: 99%; margin: 0; padding: 0; border: 0; background: #fff; }
466 #content { width: 99%; margin: 0; padding: 0; border: 0; background: #fff; }
465 }
467 }
General Comments 0
You need to be logged in to leave comments. Login now