##// END OF EJS Templates
query model/controller added...
Jean-Philippe Lang -
r76:da91e5e95a54
parent child
Show More
@@ -0,0 +1,55
1 class QueriesController < ApplicationController
2 layout 'base'
3
4 def index
5 list
6 render :action => 'list'
7 end
8
9 # GETs should be safe (see http://www.w3.org/2001/tag/doc/whenToUseGet.html)
10 verify :method => :post, :only => [ :destroy, :create, :update ],
11 :redirect_to => { :action => :list }
12
13 def list
14 @query_pages, @queries = paginate :queries, :per_page => 10
15 end
16
17 def show
18 @query = Query.find(params[:id])
19 end
20
21 def new
22 @query = Query.new(params[:query])
23
24 params[:fields].each do |field|
25 @query.add_filter(field, params[:operators][field], params[:values][field])
26 end if params[:fields]
27
28 if request.post? and @query.save
29 flash[:notice] = 'Query was successfully created.'
30 redirect_to :action => 'list'
31 end
32 end
33
34 def edit
35 @query = Query.find(params[:id])
36
37 if request.post?
38 @query.filters = {}
39 params[:fields].each do |field|
40 @query.add_filter(field, params[:operators][field], params[:values][field])
41 end if params[:fields]
42 @query.attributes = params[:query]
43
44 if @query.save
45 flash[:notice] = 'Query was successfully updated.'
46 redirect_to :action => 'show', :id => @query
47 end
48 end
49 end
50
51 def destroy
52 Query.find(params[:id]).destroy
53 redirect_to :action => 'list'
54 end
55 end
@@ -0,0 +1,2
1 module QueriesHelper
2 end
@@ -0,0 +1,123
1 class Query < ActiveRecord::Base
2 serialize :filters
3
4 validates_presence_of :name
5
6 @@operators = { "=" => "Egal",
7 "!" => "Different",
8 "o" => "Ouvert",
9 "c" => "Ferme",
10 "!*" => "Aucun",
11 "*" => "Tous",
12 "<t+" => "Dans moins de",
13 ">t+" => "Dans plus de",
14 "t+" => "Dans exactement",
15 "t" => "Aujourd'hui",
16 ">t-" => "Il y a moins de",
17 "<t-" => "Il y a plus de",
18 "t-" => "Il y a exactement" }
19
20 @@operators_by_filter_type = { :list => [ "=", "!" ],
21 :list_status => [ "o", "=", "!", "c" ],
22 :list_optional => [ "=", "!", "!*", "*" ],
23 :date => [ "<t+", ">t+", "t+", "t", ">t-", "<t-", "t-" ],
24 :date_past => [ ">t-", "<t-", "t-", "t" ] }
25
26 @@available_filters = { "status_id" => { :type => :list_status, :order => 1,
27 :values => IssueStatus.find(:all).collect{|s| [s.name, s.id.to_s] } },
28 "tracker_id" => { :type => :list, :order => 2,
29 :values => Tracker.find(:all).collect{|s| [s.name, s.id.to_s] } },
30 "assigned_to_id" => { :type => :list_optional, :order => 3,
31 :values => User.find(:all).collect{|s| [s.display_name, s.id.to_s] } },
32 "priority_id" => { :type => :list, :order => 4,
33 :values => Enumeration.find(:all, :conditions => ['opt=?','IPRI']).collect{|s| [s.name, s.id.to_s] } },
34 "created_on" => { :type => :date_past, :order => 5 },
35 "updated_on" => { :type => :date_past, :order => 6 },
36 "start_date" => { :type => :date, :order => 7 },
37 "due_date" => { :type => :date, :order => 8 } }
38
39 cattr_accessor :available_filters
40
41 def initialize(attributes = nil)
42 super
43 self.filters ||= { 'status_id' => {:operator => "o"} }
44 end
45
46 def validate
47 errors.add_to_base "Au moins un critere doit etre selectionne" unless filters && !filters.empty?
48 filters.each_key do |field|
49 errors.add field.gsub(/\_id$/, ""), "doit etre renseigne" unless
50 # filter requires one or more values
51 (values_for(field) and !values_for(field).first.empty?) or
52 # filter doesn't require any value
53 ["o", "c", "!*", "*", "t"].include? operator_for(field)
54 end if filters
55 end
56
57 def add_filter(field, operator, values)
58 # values must be an array
59 return unless values and values.is_a? Array
60 # check if field is defined as an available filter
61 if @@available_filters.has_key? field
62 filter_options = @@available_filters[field]
63 # check if operator is allowed for that filter
64 if @@operators_by_filter_type[filter_options[:type]].include? operator
65 filters[field] = {:operator => operator, :values => values }
66 end
67 end
68 end
69
70 def has_filter?(field)
71 filters and filters[field]
72 end
73
74 def operator_for(field)
75 has_filter?(field) ? filters[field][:operator] : nil
76 end
77
78 def values_for(field)
79 has_filter?(field) ? filters[field][:values] : nil
80 end
81
82 def statement
83 sql = "1=1"
84 filters.each_key do |field|
85 sql = sql + " AND " unless sql.empty?
86 v = values_for field
87 case operator_for field
88 when "="
89 sql = sql + "issues.#{field} IN (" + v.each(&:to_i).join(",") + ")"
90 when "!"
91 sql = sql + "issues.#{field} NOT IN (" + v.each(&:to_i).join(",") + ")"
92 when "!*"
93 sql = sql + "issues.#{field} IS NULL"
94 when "*"
95 sql = sql + "issues.#{field} IS NOT NULL"
96 when "o"
97 sql = sql + "issue_statuses.is_closed=#{connection.quoted_false}" if field == "status_id"
98 when "c"
99 sql = sql + "issue_statuses.is_closed=#{connection.quoted_true}" if field == "status_id"
100 when ">t-"
101 sql = sql + "issues.#{field} >= '%s'" % connection.quoted_date(Date.today - v.first.to_i)
102 when "<t-"
103 sql = sql + "issues.#{field} <= '" + (Date.today - v.first.to_i).strftime("%Y-%m-%d") + "'"
104 when "t-"
105 sql = sql + "issues.#{field} = '" + (Date.today - v.first.to_i).strftime("%Y-%m-%d") + "'"
106 when ">t+"
107 sql = sql + "issues.#{field} >= '" + (Date.today + v.first.to_i).strftime("%Y-%m-%d") + "'"
108 when "<t+"
109 sql = sql + "issues.#{field} <= '" + (Date.today + v.first.to_i).strftime("%Y-%m-%d") + "'"
110 when "t+"
111 sql = sql + "issues.#{field} = '" + (Date.today + v.first.to_i).strftime("%Y-%m-%d") + "'"
112 when "t"
113 sql = sql + "issues.#{field} = '%s'" % connection.quoted_date(Date.today)
114 end
115 end if filters
116 sql
117 end
118
119 def self.operators_for_select(filter_type)
120 @@operators_by_filter_type[filter_type].collect {|o| [@@operators[o], o]}
121 end
122
123 end
@@ -0,0 +1,72
1 <script>
2
3 function toggle_filter(field) {
4 check_box = $('cb_' + field);
5
6 if (check_box.checked) {
7 Element.show("operators[" + field + "]");
8 toggle_operator(field);
9 } else {
10 Element.hide("operators[" + field + "]");
11 Element.hide("values_div[" + field + "]");
12 }
13 }
14
15 function toggle_operator(field) {
16 operator = $("operators[" + field + "]");
17 switch (operator.value) {
18 case "!*":
19 case "*":
20 case "t":
21 case "o":
22 case "c":
23 Element.hide("values_div[" + field + "]");
24 break;
25 default:
26 Element.show("values_div[" + field + "]");
27 break;
28 }
29 }
30
31 function toggle_multi_select(field) {
32 select = $('values[' + field + '][]');
33 if (select.multiple == true) {
34 select.multiple = false;
35 } else {
36 select.multiple = true;
37 }
38 }
39
40 </script>
41
42 <fieldset><legend>Filtres</legend>
43 <table>
44 <% Query.available_filters.sort{|a,b| a[1][:order]<=>b[1][:order]}.each do |filter| %>
45 <% field = filter[0]
46 options = filter[1] %>
47 <tr>
48 <td valign="top" width="200">
49 <%= check_box_tag 'fields[]', field, query.has_filter?(field), :onclick => "toggle_filter('#{field}');", :id => "cb_#{field}" %>
50 <label for="cb_<%= field %>"><%= l(("field_"+field.to_s.gsub(/\_id$/, "")).to_sym) %></label>
51 </td>
52 <td valign="top" width="150">
53 <%= select_tag "operators[#{field}]", options_for_select(Query.operators_for_select(options[:type]), query.operator_for(field)), :onchange => "toggle_operator('#{field}');", :class => "select-small", :style => "vertical-align: top;" %>
54 </td>
55 <td valign="top">
56 <div id="values_div[<%= field %>]">
57 <% case options[:type]
58 when :list, :list_optional, :list_status %>
59 <select <%= "multiple=true" if query.values_for(field) and query.values_for(field).length > 1 %>" name="values[<%= field %>][]" id="values[<%= field %>][]" class="select-small" style="vertical-align: top;">
60 <%= options_for_select options[:values], query.values_for(field) %>
61 </select>
62 <%= link_to_function '+', "toggle_multi_select('#{field}');" %>
63 <% when :date, :date_past %>
64 <%= text_field_tag "values[#{field}][]", query.values_for(field), :size => 3, :class => "select-small" %> jours
65 <% end %>
66 </div>
67 </td>
68 </tr>
69 <script>toggle_filter('<%= field %>');</script>
70 <% end %>
71 </table>
72 </fieldset> No newline at end of file
@@ -0,0 +1,18
1 <%= error_messages_for 'query' %>
2
3 <!--[form:query]-->
4 <div class="box">
5
6 <div class="tabular">
7 <p><label for="query_name">Name</label>
8 <%= text_field 'query', 'name', :size => 80 %></p>
9
10 <p><label for="query_is_public">Public</label>
11 <%= check_box 'query', 'is_public' %></p>
12 </div>
13
14 <%= render :partial => 'filters', :locals => {:query => query}%>
15
16 </div>
17 <!--[eoform:query]-->
18
@@ -0,0 +1,8
1 <h1>Editing query</h1>
2
3 <%= start_form_tag :action => 'edit', :id => @query %>
4 <%= render :partial => 'form', :locals => {:query => @query} %>
5 <%= submit_tag 'Edit' %>
6 <%= end_form_tag %>
7
8 <%= debug @query.statement %> No newline at end of file
@@ -0,0 +1,27
1 <h1>Listing queries</h1>
2
3 <table>
4 <tr>
5 <% for column in Query.content_columns %>
6 <th><%= column.human_name %></th>
7 <% end %>
8 </tr>
9
10 <% for query in @queries %>
11 <tr>
12 <% for column in Query.content_columns %>
13 <td><%=h query.send(column.name) %></td>
14 <% end %>
15 <td><%= link_to 'Show', :action => 'show', :id => query %></td>
16 <td><%= link_to 'Edit', :action => 'edit', :id => query %></td>
17 <td><%= link_to 'Destroy', { :action => 'destroy', :id => query }, :confirm => 'Are you sure?', :post => true %></td>
18 </tr>
19 <% end %>
20 </table>
21
22 <%= link_to 'Previous page', { :page => @query_pages.current.previous } if @query_pages.current.previous %>
23 <%= link_to 'Next page', { :page => @query_pages.current.next } if @query_pages.current.next %>
24
25 <br />
26
27 <%= link_to 'New query', :action => 'new' %>
@@ -0,0 +1,9
1 <h1>New query</h1>
2
3 <%= start_form_tag :action => 'new' %>
4 <%= render :partial => 'form', :locals => {:query => @query} %>
5 <%= submit_tag "Create" %>
6 <%= end_form_tag %>
7
8 <%= debug @query %>
9 <%= debug params %>
@@ -0,0 +1,8
1 <% for column in Query.content_columns %>
2 <p>
3 <b><%= column.human_name %>:</b> <%=h @query.send(column.name) %>
4 </p>
5 <% end %>
6
7 <%= link_to 'Edit', :action => 'edit', :id => @query %> |
8 <%= link_to 'Back', :action => 'list' %>
@@ -1,470 +1,472
1 1 # redMine - project management software
2 2 # Copyright (C) 2006 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 class ProjectsController < ApplicationController
19 19 layout 'base', :except => :export_issues_pdf
20 20 before_filter :find_project, :authorize, :except => [ :index, :list, :add ]
21 21 before_filter :require_admin, :only => [ :add, :destroy ]
22 22
23 23 helper :sort
24 24 include SortHelper
25 25 helper :search_filter
26 26 include SearchFilterHelper
27 27 helper :custom_fields
28 28 include CustomFieldsHelper
29 29 helper :ifpdf
30 30 include IfpdfHelper
31 31 helper IssuesHelper
32 32
33 33 def index
34 34 list
35 35 render :action => 'list' unless request.xhr?
36 36 end
37 37
38 38 # Lists public projects
39 39 def list
40 40 sort_init 'name', 'asc'
41 41 sort_update
42 42 @project_count = Project.count(["is_public=?", true])
43 43 @project_pages = Paginator.new self, @project_count,
44 44 15,
45 45 @params['page']
46 46 @projects = Project.find :all, :order => sort_clause,
47 47 :conditions => ["is_public=?", true],
48 48 :limit => @project_pages.items_per_page,
49 49 :offset => @project_pages.current.offset
50 50
51 51 render :action => "list", :layout => false if request.xhr?
52 52 end
53 53
54 54 # Add a new project
55 55 def add
56 56 @custom_fields = IssueCustomField.find(:all)
57 57 @root_projects = Project.find(:all, :conditions => "parent_id is null")
58 58 @project = Project.new(params[:project])
59 59 if request.get?
60 60 @custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project) }
61 61 else
62 62 @project.custom_fields = CustomField.find(@params[:custom_field_ids]) if @params[:custom_field_ids]
63 63 @custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => params["custom_fields"][x.id.to_s]) }
64 64 @project.custom_values = @custom_values
65 65 if @project.save
66 66 flash[:notice] = l(:notice_successful_create)
67 67 redirect_to :controller => 'admin', :action => 'projects'
68 68 end
69 69 end
70 70 end
71 71
72 72 # Show @project
73 73 def show
74 74 @custom_values = @project.custom_values.find(:all, :include => :custom_field)
75 75 @members = @project.members.find(:all, :include => [:user, :role])
76 76 @subprojects = @project.children if @project.children_count > 0
77 77 @news = @project.news.find(:all, :limit => 5, :include => [ :author, :project ], :order => "news.created_on DESC")
78 78 @trackers = Tracker.find(:all)
79 79 end
80 80
81 81 def settings
82 82 @root_projects = Project::find(:all, :conditions => ["parent_id is null and id <> ?", @project.id])
83 83 @custom_fields = IssueCustomField::find_all
84 84 @issue_category ||= IssueCategory.new
85 85 @member ||= @project.members.new
86 86 @roles = Role.find_all
87 87 @users = User.find_all - @project.members.find(:all, :include => :user).collect{|m| m.user }
88 88 @custom_values ||= ProjectCustomField.find(:all).collect { |x| @project.custom_values.find_by_custom_field_id(x.id) || CustomValue.new(:custom_field => x) }
89 89 end
90 90
91 91 # Edit @project
92 92 def edit
93 93 if request.post?
94 94 @project.custom_fields = IssueCustomField.find(@params[:custom_field_ids]) if @params[:custom_field_ids]
95 95 if params[:custom_fields]
96 96 @custom_values = ProjectCustomField.find(:all).collect { |x| CustomValue.new(:custom_field => x, :customized => @project, :value => params["custom_fields"][x.id.to_s]) }
97 97 @project.custom_values = @custom_values
98 98 end
99 99 if @project.update_attributes(params[:project])
100 100 flash[:notice] = l(:notice_successful_update)
101 101 redirect_to :action => 'settings', :id => @project
102 102 else
103 103 settings
104 104 render :action => 'settings'
105 105 end
106 106 end
107 107 end
108 108
109 109 # Delete @project
110 110 def destroy
111 111 if request.post? and params[:confirm]
112 112 @project.destroy
113 113 redirect_to :controller => 'admin', :action => 'projects'
114 114 end
115 115 end
116 116
117 117 # Add a new issue category to @project
118 118 def add_issue_category
119 119 if request.post?
120 120 @issue_category = @project.issue_categories.build(params[:issue_category])
121 121 if @issue_category.save
122 122 flash[:notice] = l(:notice_successful_create)
123 123 redirect_to :action => 'settings', :id => @project
124 124 else
125 125 settings
126 126 render :action => 'settings'
127 127 end
128 128 end
129 129 end
130 130
131 131 # Add a new version to @project
132 132 def add_version
133 133 @version = @project.versions.build(params[:version])
134 134 if request.post? and @version.save
135 135 flash[:notice] = l(:notice_successful_create)
136 136 redirect_to :action => 'settings', :id => @project
137 137 end
138 138 end
139 139
140 140 # Add a new member to @project
141 141 def add_member
142 142 @member = @project.members.build(params[:member])
143 143 if request.post?
144 144 if @member.save
145 145 flash[:notice] = l(:notice_successful_create)
146 146 redirect_to :action => 'settings', :id => @project
147 147 else
148 148 settings
149 149 render :action => 'settings'
150 150 end
151 151 end
152 152 end
153 153
154 154 # Show members list of @project
155 155 def list_members
156 156 @members = @project.members
157 157 end
158 158
159 159 # Add a new document to @project
160 160 def add_document
161 161 @categories = Enumeration::get_values('DCAT')
162 162 @document = @project.documents.build(params[:document])
163 163 if request.post?
164 164 # Save the attachment
165 165 if params[:attachment][:file].size > 0
166 166 @attachment = @document.attachments.build(params[:attachment])
167 167 @attachment.author_id = self.logged_in_user.id if self.logged_in_user
168 168 end
169 169 if @document.save
170 170 flash[:notice] = l(:notice_successful_create)
171 171 redirect_to :action => 'list_documents', :id => @project
172 172 end
173 173 end
174 174 end
175 175
176 176 # Show documents list of @project
177 177 def list_documents
178 178 @documents = @project.documents
179 179 end
180 180
181 181 # Add a new issue to @project
182 182 def add_issue
183 183 @tracker = Tracker.find(params[:tracker_id])
184 184 @priorities = Enumeration::get_values('IPRI')
185 185 @issue = Issue.new(:project => @project, :tracker => @tracker)
186 186 if request.get?
187 187 @issue.start_date = Date.today
188 188 @custom_values = @project.custom_fields_for_issues(@tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue) }
189 189 else
190 190 @issue.attributes = params[:issue]
191 191 @issue.author_id = self.logged_in_user.id if self.logged_in_user
192 192 # Multiple file upload
193 193 params[:attachments].each { |a|
194 194 @attachment = @issue.attachments.build(:file => a, :author => self.logged_in_user) unless a.size == 0
195 195 } if params[:attachments] and params[:attachments].is_a? Array
196 196 @custom_values = @project.custom_fields_for_issues(@tracker).collect { |x| CustomValue.new(:custom_field => x, :customized => @issue, :value => params["custom_fields"][x.id.to_s]) }
197 197 @issue.custom_values = @custom_values
198 198 if @issue.save
199 199 flash[:notice] = l(:notice_successful_create)
200 200 Mailer.deliver_issue_add(@issue) if Permission.find_by_controller_and_action(@params[:controller], @params[:action]).mail_enabled?
201 201 redirect_to :action => 'list_issues', :id => @project
202 202 end
203 203 end
204 204 end
205 205
206 206 # Show filtered/sorted issues list of @project
207 207 def list_issues
208 208 sort_init 'issues.id', 'desc'
209 209 sort_update
210 210
211 search_filter_init_list_issues
212 search_filter_update if params[:set_filter]
211 @query = Query.new
212 params[:fields].each do |field|
213 @query.add_filter(field, params[:operators][field], params[:values][field])
214 end if params[:fields]
213 215
214 216 @results_per_page_options = [ 15, 25, 50, 100 ]
215 217 if params[:per_page] and @results_per_page_options.include? params[:per_page].to_i
216 218 @results_per_page = params[:per_page].to_i
217 219 session[:results_per_page] = @results_per_page
218 220 else
219 221 @results_per_page = session[:results_per_page] || 25
220 222 end
221 223
222 @issue_count = Issue.count(:include => [:status, :project], :conditions => search_filter_clause)
224 @issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
223 225 @issue_pages = Paginator.new self, @issue_count, @results_per_page, @params['page']
224 226 @issues = Issue.find :all, :order => sort_clause,
225 227 :include => [ :author, :status, :tracker, :project ],
226 :conditions => search_filter_clause,
228 :conditions => @query.statement,
227 229 :limit => @issue_pages.items_per_page,
228 230 :offset => @issue_pages.current.offset
229 231
230 232 render :layout => false if request.xhr?
231 233 end
232 234
233 235 # Export filtered/sorted issues list to CSV
234 236 def export_issues_csv
235 237 sort_init 'issues.id', 'desc'
236 238 sort_update
237 239
238 240 search_filter_init_list_issues
239 241
240 242 @issues = Issue.find :all, :order => sort_clause,
241 243 :include => [ :author, :status, :tracker, :project, :custom_values ],
242 244 :conditions => search_filter_clause
243 245
244 246 ic = Iconv.new('ISO-8859-1', 'UTF-8')
245 247 export = StringIO.new
246 248 CSV::Writer.generate(export, l(:general_csv_separator)) do |csv|
247 249 # csv header fields
248 250 headers = [ "#", l(:field_status), l(:field_tracker), l(:field_subject), l(:field_author), l(:field_created_on), l(:field_updated_on) ]
249 251 for custom_field in @project.all_custom_fields
250 252 headers << custom_field.name
251 253 end
252 254 csv << headers.collect {|c| ic.iconv(c) }
253 255 # csv lines
254 256 @issues.each do |issue|
255 257 fields = [issue.id, issue.status.name, issue.tracker.name, issue.subject, issue.author.display_name, l_datetime(issue.created_on), l_datetime(issue.updated_on)]
256 258 for custom_field in @project.all_custom_fields
257 259 fields << (show_value issue.custom_value_for(custom_field))
258 260 end
259 261 csv << fields.collect {|c| ic.iconv(c.to_s) }
260 262 end
261 263 end
262 264 export.rewind
263 265 send_data(export.read, :type => 'text/csv; header=present', :filename => 'export.csv')
264 266 end
265 267
266 268 # Export filtered/sorted issues to PDF
267 269 def export_issues_pdf
268 270 sort_init 'issues.id', 'desc'
269 271 sort_update
270 272
271 273 search_filter_init_list_issues
272 274
273 275 @issues = Issue.find :all, :order => sort_clause,
274 276 :include => [ :author, :status, :tracker, :project, :custom_values ],
275 277 :conditions => search_filter_clause
276 278
277 279 @options_for_rfpdf ||= {}
278 280 @options_for_rfpdf[:file_name] = "export.pdf"
279 281 end
280 282
281 283 def move_issues
282 284 @issues = @project.issues.find(params[:issue_ids]) if params[:issue_ids]
283 285 redirect_to :action => 'list_issues', :id => @project and return unless @issues
284 286 @projects = []
285 287 # find projects to which the user is allowed to move the issue
286 288 @logged_in_user.memberships.each {|m| @projects << m.project if Permission.allowed_to_role("projects/move_issues", m.role_id)}
287 289 # issue can be moved to any tracker
288 290 @trackers = Tracker.find(:all)
289 291 if request.post? and params[:new_project_id] and params[:new_tracker_id]
290 292 new_project = Project.find(params[:new_project_id])
291 293 new_tracker = Tracker.find(params[:new_tracker_id])
292 294 @issues.each { |i|
293 295 # category is project dependent
294 296 i.category = nil unless i.project_id == new_project.id
295 297 # move the issue
296 298 i.project = new_project
297 299 i.tracker = new_tracker
298 300 i.save
299 301 }
300 302 flash[:notice] = l(:notice_successful_update)
301 303 redirect_to :action => 'list_issues', :id => @project
302 304 end
303 305 end
304 306
305 307 # Add a news to @project
306 308 def add_news
307 309 @news = News.new(:project => @project)
308 310 if request.post?
309 311 @news.attributes = params[:news]
310 312 @news.author_id = self.logged_in_user.id if self.logged_in_user
311 313 if @news.save
312 314 flash[:notice] = l(:notice_successful_create)
313 315 redirect_to :action => 'list_news', :id => @project
314 316 end
315 317 end
316 318 end
317 319
318 320 # Show news list of @project
319 321 def list_news
320 322 @news_pages, @news = paginate :news, :per_page => 10, :conditions => ["project_id=?", @project.id], :include => :author, :order => "news.created_on DESC"
321 323 render :action => "list_news", :layout => false if request.xhr?
322 324 end
323 325
324 326 def add_file
325 327 if request.post?
326 328 # Save the attachment
327 329 if params[:attachment][:file].size > 0
328 330 @attachment = @project.versions.find(params[:version_id]).attachments.build(params[:attachment])
329 331 @attachment.author_id = self.logged_in_user.id if self.logged_in_user
330 332 if @attachment.save
331 333 flash[:notice] = l(:notice_successful_create)
332 334 redirect_to :controller => 'projects', :action => 'list_files', :id => @project
333 335 end
334 336 end
335 337 end
336 338 @versions = @project.versions
337 339 end
338 340
339 341 def list_files
340 342 @versions = @project.versions
341 343 end
342 344
343 345 # Show changelog for @project
344 346 def changelog
345 347 @trackers = Tracker.find(:all, :conditions => ["is_in_chlog=?", true])
346 348 if request.get?
347 349 @selected_tracker_ids = @trackers.collect {|t| t.id.to_s }
348 350 else
349 351 @selected_tracker_ids = params[:tracker_ids].collect { |id| id.to_i.to_s } if params[:tracker_ids] and params[:tracker_ids].is_a? Array
350 352 end
351 353 @selected_tracker_ids ||= []
352 354 @fixed_issues = @project.issues.find(:all,
353 355 :include => [ :fixed_version, :status, :tracker ],
354 356 :conditions => [ "issue_statuses.is_closed=? and issues.tracker_id in (#{@selected_tracker_ids.join(',')}) and issues.fixed_version_id is not null", true],
355 357 :order => "versions.effective_date DESC, issues.id DESC"
356 358 ) unless @selected_tracker_ids.empty?
357 359 @fixed_issues ||= []
358 360 end
359 361
360 362 def activity
361 363 if params[:year] and params[:year].to_i > 1900
362 364 @year = params[:year].to_i
363 365 if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
364 366 @month = params[:month].to_i
365 367 end
366 368 end
367 369 @year ||= Date.today.year
368 370 @month ||= Date.today.month
369 371
370 372 @date_from = Date.civil(@year, @month, 1)
371 373 @date_to = (@date_from >> 1)-1
372 374
373 375 @events_by_day = {}
374 376
375 377 unless params[:show_issues] == "0"
376 378 @project.issues.find(:all, :include => [:author, :status], :conditions => ["issues.created_on>=? and issues.created_on<=?", @date_from, @date_to] ).each { |i|
377 379 @events_by_day[i.created_on.to_date] ||= []
378 380 @events_by_day[i.created_on.to_date] << i
379 381 }
380 382 @show_issues = 1
381 383 end
382 384
383 385 unless params[:show_news] == "0"
384 386 @project.news.find(:all, :conditions => ["news.created_on>=? and news.created_on<=?", @date_from, @date_to] ).each { |i|
385 387 @events_by_day[i.created_on.to_date] ||= []
386 388 @events_by_day[i.created_on.to_date] << i
387 389 }
388 390 @show_news = 1
389 391 end
390 392
391 393 unless params[:show_files] == "0"
392 394 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|
393 395 @events_by_day[i.created_on.to_date] ||= []
394 396 @events_by_day[i.created_on.to_date] << i
395 397 }
396 398 @show_files = 1
397 399 end
398 400
399 401 unless params[:show_documents] == "0"
400 402 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|
401 403 @events_by_day[i.created_on.to_date] ||= []
402 404 @events_by_day[i.created_on.to_date] << i
403 405 }
404 406 @show_documents = 1
405 407 end
406 408
407 409 render :layout => false if request.xhr?
408 410 end
409 411
410 412 def calendar
411 413 if params[:year] and params[:year].to_i > 1900
412 414 @year = params[:year].to_i
413 415 if params[:month] and params[:month].to_i > 0 and params[:month].to_i < 13
414 416 @month = params[:month].to_i
415 417 end
416 418 end
417 419 @year ||= Date.today.year
418 420 @month ||= Date.today.month
419 421
420 422 @date_from = Date.civil(@year, @month, 1)
421 423 @date_to = (@date_from >> 1)-1
422 424 # start on monday
423 425 @date_from = @date_from - (@date_from.cwday-1)
424 426 # finish on sunday
425 427 @date_to = @date_to + (7-@date_to.cwday)
426 428
427 429 @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])
428 430 render :layout => false if request.xhr?
429 431 end
430 432
431 433 def gantt
432 434 if params[:year] and params[:year].to_i >0
433 435 @year_from = params[:year].to_i
434 436 if params[:month] and params[:month].to_i >=1 and params[:month].to_i <= 12
435 437 @month_from = params[:month].to_i
436 438 else
437 439 @month_from = 1
438 440 end
439 441 else
440 442 @month_from ||= (Date.today << 1).month
441 443 @year_from ||= (Date.today << 1).year
442 444 end
443 445
444 446 @zoom = (params[:zoom].to_i > 0 and params[:zoom].to_i < 5) ? params[:zoom].to_i : 2
445 447 @months = (params[:months].to_i > 0 and params[:months].to_i < 25) ? params[:months].to_i : 6
446 448
447 449 @date_from = Date.civil(@year_from, @month_from, 1)
448 450 @date_to = (@date_from >> @months) - 1
449 451 @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])
450 452
451 453 if params[:output]=='pdf'
452 454 @options_for_rfpdf ||= {}
453 455 @options_for_rfpdf[:file_name] = "gantt.pdf"
454 456 render :template => "projects/gantt.rfpdf", :layout => false
455 457 else
456 458 render :template => "projects/gantt.rhtml"
457 459 end
458 460 end
459 461
460 462 private
461 463 # Find project of id params[:id]
462 464 # if not found, redirect to project list
463 465 # Used as a before_filter
464 466 def find_project
465 467 @project = Project.find(params[:id])
466 468 @html_title = @project.name
467 469 rescue
468 470 redirect_to :action => 'list'
469 471 end
470 472 end
@@ -1,76 +1,60
1 1 <h2><%=l(:label_issue_plural)%></h2>
2 2 <div class="topright">
3 3 <small>
4 4 <%= l(:label_export_to) %>&nbsp;
5 5 <%= link_to 'CSV', :action => 'export_issues_csv', :id => @project %>,
6 6 <%= link_to 'PDF', :action => 'export_issues_pdf', :id => @project %>
7 7 </small>
8 8 </div>
9 9
10 <div>
10 11 <%= start_form_tag :action => 'list_issues' %>
11 <table cellpadding=2>
12 <tr>
13 <td valign="bottom"><small><%=l(:field_status)%>:</small><br /><%= search_filter_tag 'status_id', :class => 'select-small' %></td>
14 <td valign="bottom"><small><%=l(:field_tracker)%>:</small><br /><%= search_filter_tag 'tracker_id', :class => 'select-small' %></td>
15 <td valign="bottom"><small><%=l(:field_priority)%>:</small><br /><%= search_filter_tag 'priority_id', :class => 'select-small' %></td>
16 <td valign="bottom"><small><%=l(:field_category)%>:</small><br /><%= search_filter_tag 'category_id', :class => 'select-small' %></td>
17 <td valign="bottom"><small><%=l(:field_fixed_version)%>:</small><br /><%= search_filter_tag 'fixed_version_id', :class => 'select-small' %></td>
18 <td valign="bottom"><small><%=l(:field_author)%>:</small><br /><%= search_filter_tag 'author_id', :class => 'select-small' %></td>
19 <td valign="bottom"><small><%=l(:field_assigned_to)%>:</small><br /><%= search_filter_tag 'assigned_to_id', :class => 'select-small' %></td>
20 <td valign="bottom"><small><%=l(:label_subproject_plural)%>:</small><br /><%= search_filter_tag 'subproject_id', :class => 'select-small' %></td>
21 <td valign="bottom">
22 <%= hidden_field_tag 'set_filter', 1 %>
23 <%= submit_tag l(:button_apply), :class => 'button-small' %>
24 </td>
25 <td valign="bottom">
26 <%= link_to l(:button_clear), :action => 'list_issues', :id => @project, :set_filter => 1 %>
27 </td>
28 </tr>
29 </table>
12 <%= render :partial => 'queries/filters', :locals => {:query => @query} %>
13 <%= submit_tag l(:button_apply), :class => "button-small" %>
30 14 <%= end_form_tag %>
31
15 </div>
32 16 &nbsp;
33 17 <table class="listTableContent">
34 18 <tr>
35 19 <td colspan="6" align="left"><small><%= check_all_links 'issues_form' %></small></td>
36 20 <td colspan="2" align="right">
37 21 <small><%= l(:label_per_page) %>:</small>
38 22 <%= start_form_tag %>
39 23 <%= select_tag 'per_page', options_for_select(@results_per_page_options, @results_per_page), :class => 'select-small'%>
40 24 <%= submit_tag l(:button_apply), :class => 'button-small'%>
41 25 <%= end_form_tag %>
42 26 </td>
43 27 </tr>
44 28 </table>
45 29 <%= start_form_tag({:controller => 'projects', :action => 'move_issues', :id => @project}, :id => 'issues_form' ) %>
46 30 <table class="listTableContent">
47 31
48 32 <tr class="ListHead">
49 33 <td></td>
50 34 <%= sort_header_tag('issues.id', :caption => '#') %>
51 35 <%= sort_header_tag('issue_statuses.name', :caption => l(:field_status)) %>
52 36 <%= sort_header_tag('issues.tracker_id', :caption => l(:field_tracker)) %>
53 37 <th><%=l(:field_subject)%></th>
54 38 <%= sort_header_tag('users.lastname', :caption => l(:field_author)) %>
55 39 <%= sort_header_tag('issues.created_on', :caption => l(:field_created_on)) %>
56 40 <%= sort_header_tag('issues.updated_on', :caption => l(:field_updated_on)) %>
57 41 </tr>
58 42 <% for issue in @issues %>
59 43 <tr class="<%= cycle("odd", "even") %>">
60 44 <td width="15"><%= check_box_tag "issue_ids[]", issue.id %></td>
61 45 <td align="center"><%= link_to issue.long_id, :controller => 'issues', :action => 'show', :id => issue %></td>
62 46 <td align="center" style="font-weight:bold;color:#<%= issue.status.html_color %>;"><%= issue.status.name %></font></td>
63 47 <td align="center"><%= issue.tracker.name %></td>
64 48 <td><%= link_to issue.subject, :controller => 'issues', :action => 'show', :id => issue %></td>
65 49 <td align="center"><%= issue.author.display_name %></td>
66 50 <td align="center"><%= format_time(issue.created_on) %></td>
67 51 <td align="center"><%= format_time(issue.updated_on) %></td>
68 52 </tr>
69 53 <% end %>
70 54 </table>
71 55 <p>
72 56 <%= pagination_links_full @issue_pages %>
73 57 [ <%= @issue_pages.current.first_item %> - <%= @issue_pages.current.last_item %> / <%= @issue_count %> ]
74 58 </p>
75 59 <%= submit_tag l(:button_move) %>
76 60 <%= end_form_tag %> No newline at end of file
@@ -1,489 +1,489
1 1 /* andreas08 - an open source xhtml/css website layout by Andreas Viklund - http://andreasviklund.com . Free to use in any way and for any purpose as long as the proper credits are given to the original designer. Version: 1.0, November 28, 2005 */
2 2 /* Edited by Jean-Philippe Lang *>
3 3 /**************** Body and tag styles ****************/
4 4
5 5
6 6 #header * {margin:0; padding:0;}
7 7 p, ul, ol, li {margin:0; padding:0;}
8 8
9 9
10 10 body{
11 11 font:76% Verdana,Tahoma,Arial,sans-serif;
12 12 line-height:1.4em;
13 13 text-align:center;
14 14 color:#303030;
15 15 background:#e8eaec;
16 16 margin:0;
17 17 }
18 18
19 19
20 20 a{
21 21 color:#467aa7;
22 22 font-weight:bold;
23 23 text-decoration:none;
24 24 background-color:inherit;
25 25 }
26 26
27 27 a:hover{color:#2a5a8a; text-decoration:none; background-color:inherit;}
28 28 a img{border:none;}
29 29
30 30 p{padding:0 0 1em 0;}
31 31 p form{margin-top:0; margin-bottom:20px;}
32 32
33 33 img.left,img.center,img.right{padding:4px; border:1px solid #a0a0a0;}
34 34 img.left{float:left; margin:0 12px 5px 0;}
35 35 img.center{display:block; margin:0 auto 5px auto;}
36 36 img.right{float:right; margin:0 0 5px 12px;}
37 37
38 38 /**************** Header and navigation styles ****************/
39 39
40 40 #container{
41 41 width:100%;
42 42 min-width: 800px;
43 43 margin:0;
44 44 padding:0;
45 45 text-align:left;
46 46 background:#ffffff;
47 47 color:#303030;
48 48 }
49 49
50 50 #header{
51 51 height:4.5em;
52 52 /*width:758px;*/
53 53 margin:0;
54 54 background:#467aa7;
55 55 color:#ffffff;
56 56 margin-bottom:1px;
57 57 }
58 58
59 59 #header h1{
60 60 padding:10px 0 0 20px;
61 61 font-size:2em;
62 62 background-color:inherit;
63 63 color:#fff; /*rgb(152, 26, 33);*/
64 64 letter-spacing:-1px;
65 65 font-weight:bold;
66 66 font-family: Trebuchet MS,Georgia,"Times New Roman",serif;
67 67 }
68 68
69 69 #header h2{
70 70 margin:3px 0 0 40px;
71 71 font-size:1.5em;
72 72 background-color:inherit;
73 73 color:#f0f2f4;
74 74 letter-spacing:-1px;
75 75 font-weight:normal;
76 76 font-family: Trebuchet MS,Georgia,"Times New Roman",serif;
77 77 }
78 78
79 79 #navigation{
80 80 height:2.2em;
81 81 line-height:2.2em;
82 82 /*width:758px;*/
83 83 margin:0;
84 84 background:#578bb8;
85 85 color:#ffffff;
86 86 }
87 87
88 88 #navigation li{
89 89 float:left;
90 90 list-style-type:none;
91 91 border-right:1px solid #ffffff;
92 92 white-space:nowrap;
93 93 }
94 94
95 95 #navigation li.right {
96 96 float:right;
97 97 list-style-type:none;
98 98 border-right:0;
99 99 border-left:1px solid #ffffff;
100 100 white-space:nowrap;
101 101 }
102 102
103 103 #navigation li a{
104 104 display:block;
105 105 padding:0px 10px 0px 22px;
106 106 font-size:0.8em;
107 107 font-weight:normal;
108 108 /*text-transform:uppercase;*/
109 109 text-decoration:none;
110 110 background-color:inherit;
111 111 color: #ffffff;
112 112 }
113 113
114 114 * html #navigation a {width:1%;}
115 115
116 116 #navigation .selected,#navigation a:hover{
117 117 color:#ffffff;
118 118 text-decoration:none;
119 119 background-color: #80b0da;
120 120 }
121 121
122 122 /**************** Icons links *******************/
123 123 .picHome { background: url(../images/home.png) no-repeat 4px 50%; }
124 124 .picUser { background: url(../images/user.png) no-repeat 4px 50%; }
125 125 .picUserPage { background: url(../images/user_page.png) no-repeat 4px 50%; }
126 126 .picAdmin { background: url(../images/admin.png) no-repeat 4px 50%; }
127 127 .picProject { background: url(../images/projects.png) no-repeat 4px 50%; }
128 128 .picLogout { background: url(../images/logout.png) no-repeat 4px 50%; }
129 129 .picHelp { background: url(../images/help.png) no-repeat 4px 50%; }
130 130
131 131 /**************** Content styles ****************/
132 132
133 133 html>body #content {
134 134 height: auto;
135 135 min-height: 500px;
136 136 }
137 137
138 138 #content{
139 139 /*float:right;*/
140 140 /*width:530px;*/
141 141 width: auto;
142 142 height:500px;
143 143 font-size:0.9em;
144 144 padding:20px 10px 10px 20px;
145 145 /*position: absolute;*/
146 146 margin-left: 120px;
147 147 border-left: 1px dashed #c0c0c0;
148 148
149 149 }
150 150
151 151 #content h2{
152 152 display:block;
153 153 margin:0 0 16px 0;
154 154 font-size:1.7em;
155 155 font-weight:normal;
156 156 letter-spacing:-1px;
157 157 color:#606060;
158 158 background-color:inherit;
159 159 font-family: Trebuchet MS,Georgia,"Times New Roman",serif;
160 160 }
161 161
162 162 #content h2 a{font-weight:normal;}
163 163 #content h3{margin:0 0 12px 0; font-size:1.4em;color:#707070;font-family: Trebuchet MS,Georgia,"Times New Roman",serif;}
164 164 #content a:hover,#subcontent a:hover{text-decoration:underline;}
165 165 #content ul,#content ol{margin:0 5px 16px 35px;}
166 166 #content dl{margin:0 5px 10px 25px;}
167 167 #content dt{font-weight:bold; margin-bottom:5px;}
168 168 #content dd{margin:0 0 10px 15px;}
169 169
170 170
171 171 /***********************************************/
172 172
173 173 /*
174 174 form{
175 175 padding:15px;
176 176 margin:0 0 20px 0;
177 177 border:1px solid #c0c0c0;
178 178 background-color:#CEE1ED;
179 179 width:600px;
180 180 }
181 181 */
182 182
183 183 form {
184 184 display: inline;
185 185 }
186 186
187 187 .noborder {
188 188 border:0px;
189 189 background-color:#fff;
190 190 width:100%;
191 191 }
192 192
193 193 textarea {
194 194 padding:0;
195 195 margin:0;
196 196 }
197 197
198 198 blockquote {
199 199 padding-left: 6px;
200 200 border-left: 2px solid #ccc;
201 201 }
202 202
203 203 input {
204 204 vertical-align: middle;
205 205 }
206 206
207 207 input.button-small
208 208 {
209 209 font-size: 0.8em;
210 210 }
211 211
212 212 select {
213 213 vertical-align: middle;
214 214 }
215 215
216 select.select-small
216 .select-small
217 217 {
218 218 border: 1px solid #7F9DB9;
219 219 padding: 1px;
220 220 font-size: 0.8em;
221 221 }
222 222
223 223 .active-filter
224 224 {
225 225 background-color: #F9FA9E;
226 226
227 227 }
228 228
229 229 label {
230 230 font-weight: bold;
231 231 font-size: 1em;
232 232 }
233 233
234 234 fieldset {
235 235 border:1px solid #7F9DB9;
236 236 padding: 6px;
237 237 }
238 238
239 239 legend {
240 240 color: #505050;
241 241
242 242 }
243 243
244 244 .required {
245 245 color: #bb0000;
246 246 }
247 247
248 248 table.listTableContent {
249 249 border:1px solid #578bb8;
250 250 width:99%;
251 251 border-collapse: collapse;
252 252 }
253 253
254 254 table.listTableContent td {
255 255 padding:2px;
256 256 }
257 257
258 258 tr.ListHead {
259 259 background-color:#467aa7;
260 260 color:#FFFFFF;
261 261 text-align:center;
262 262 }
263 263
264 264 tr.ListHead a {
265 265 color:#FFFFFF;
266 266 text-decoration:underline;
267 267 }
268 268
269 269 .odd {
270 270 background-color:#f0f1f2;
271 271 }
272 272 .even {
273 273 background-color: #fff;
274 274 }
275 275
276 276 table.reportTableContent {
277 277 border:1px solid #c0c0c0;
278 278 width:99%;
279 279 border-collapse: collapse;
280 280 }
281 281
282 282 table.reportTableContent td {
283 283 padding:2px;
284 284 }
285 285
286 286 table.calenderTable {
287 287 border:1px solid #578bb8;
288 288 width:99%;
289 289 border-collapse: collapse;
290 290 }
291 291
292 292 table.calenderTable td {
293 293 border:1px solid #578bb8;
294 294 }
295 295
296 296 hr { border:none; border-bottom: dotted 1px #c0c0c0; }
297 297
298 298
299 299 /**************** Sidebar styles ****************/
300 300
301 301 #subcontent{
302 302 position: absolute;
303 303 left: 0px;
304 304 width:110px;
305 305 padding:20px 20px 10px 5px;
306 306 }
307 307
308 308 #subcontent h2{
309 309 display:block;
310 310 margin:0 0 5px 0;
311 311 font-size:1.0em;
312 312 font-weight:bold;
313 313 text-align:left;
314 314 color:#606060;
315 315 background-color:inherit;
316 316 font-family: Trebuchet MS,Georgia,"Times New Roman",serif;
317 317 }
318 318
319 319 #subcontent p{margin:0 0 16px 0; font-size:0.9em;}
320 320
321 321 /**************** Menublock styles ****************/
322 322
323 323 .menublock{margin:0 0 20px 8px; font-size:0.8em;}
324 324 .menublock li{list-style:none; display:block; padding:1px; margin-bottom:0px;}
325 325 .menublock li a{font-weight:bold; text-decoration:none;}
326 326 .menublock li a:hover{text-decoration:none;}
327 327 .menublock li ul{margin:0; font-size:1em; font-weight:normal;}
328 328 .menublock li ul li{margin-bottom:0;}
329 329 .menublock li ul a{font-weight:normal;}
330 330
331 331 /**************** Searchbar styles ****************/
332 332
333 333 #searchbar{margin:0 0 20px 0;}
334 334 #searchbar form fieldset{margin-left:10px; border:0 solid;}
335 335
336 336 #searchbar #s{
337 337 height:1.2em;
338 338 width:110px;
339 339 margin:0 5px 0 0;
340 340 border:1px solid #a0a0a0;
341 341 }
342 342
343 343 #searchbar #searchbutton{
344 344 width:auto;
345 345 padding:0 1px;
346 346 border:1px solid #808080;
347 347 font-size:0.9em;
348 348 text-align:center;
349 349 }
350 350
351 351 /**************** Footer styles ****************/
352 352
353 353 #footer{
354 354 clear:both;
355 355 /*width:758px;*/
356 356 padding:5px 0;
357 357 margin:0;
358 358 font-size:0.9em;
359 359 color:#f0f0f0;
360 360 background:#467aa7;
361 361 }
362 362
363 363 #footer p{padding:0; margin:0; text-align:center;}
364 364 #footer a{color:#f0f0f0; background-color:inherit; font-weight:bold;}
365 365 #footer a:hover{color:#ffffff; background-color:inherit; text-decoration: underline;}
366 366
367 367 /**************** Misc classes and styles ****************/
368 368
369 369 .splitcontentleft{float:left; width:49%;}
370 370 .splitcontentright{float:right; width:49%;}
371 371 .clear{clear:both;}
372 372 .small{font-size:0.8em;line-height:1.4em;padding:0 0 0 0;}
373 373 .hide{display:none;}
374 374 .textcenter{text-align:center;}
375 375 .textright{text-align:right;}
376 376 .important{color:#f02025; background-color:inherit; font-weight:bold;}
377 377
378 378 .box{
379 379 margin:0 0 20px 0;
380 380 padding:10px;
381 381 border:1px solid #c0c0c0;
382 382 background-color:#fafbfc;
383 383 color:#505050;
384 384 line-height:1.5em;
385 385 }
386 386
387 387 a.close-icon {
388 388 display:block;
389 389 margin-top:3px;
390 390 overflow:hidden;
391 391 width:12px;
392 392 height:12px;
393 393 background-repeat: no-repeat;
394 394 cursor:hand;
395 395 cursor:pointer;
396 396 background-image:url('../images/close.png');
397 397 }
398 398
399 399 a.close-icon:hover {
400 400 background-image:url('../images/close_hl.png');
401 401 }
402 402
403 403 .rightbox{
404 404 background: #fafbfc;
405 405 border: 1px solid #c0c0c0;
406 406 float: right;
407 407 padding: 8px;
408 408 position: relative;
409 409 margin: 0 5px 5px;
410 410 }
411 411
412 412 .layout-active {
413 413 background: #ECF3E1;
414 414 }
415 415
416 416 .block-receiver {
417 417 border:1px dashed #c0c0c0;
418 418 margin-bottom: 20px;
419 419 padding: 15px 0 15px 0;
420 420 }
421 421
422 422 .mypage-box {
423 423 margin:0 0 20px 0;
424 424 color:#505050;
425 425 line-height:1.5em;
426 426 }
427 427
428 428 .handle {
429 429 cursor: move;
430 430 }
431 431
432 432 .topright{
433 433 position: absolute;
434 434 right: 25px;
435 435 top: 100px;
436 436 }
437 437
438 438 .login {
439 439 width: 50%;
440 440 text-align: left;
441 441 }
442 442
443 443 img.calendar-trigger {
444 444 cursor: pointer;
445 445 vertical-align: middle;
446 446 margin-left: 4px;
447 447 }
448 448
449 449 #history h4 {
450 450 font-size: 1em;
451 451 margin-bottom: 12px;
452 452 margin-top: 20px;
453 453 font-weight: normal;
454 454 border-bottom: dotted 1px #c0c0c0;
455 455 }
456 456
457 457 #history p {
458 458 margin-left: 34px;
459 459 }
460 460
461 461 /***** CSS FORM ******/
462 462 .tabular p{
463 463 margin: 0;
464 464 padding: 5px 0 8px 0;
465 465 padding-left: 180px; /*width of left column containing the label elements*/
466 466 height: 1%;
467 467 }
468 468
469 469 .tabular label{
470 470 font-weight: bold;
471 471 float: left;
472 472 margin-left: -180px; /*width of left column*/
473 473 width: 175px; /*width of labels. Should be smaller than left column to create some right
474 474 margin*/
475 475 }
476 476
477 477 .error {
478 478 color: #cc0000;
479 479 }
480 480
481 481
482 482 /*.threepxfix class below:
483 483 Targets IE6- ONLY. Adds 3 pixel indent for multi-line form contents.
484 484 to account for 3 pixel bug: http://www.positioniseverything.net/explorer/threepxtest.html
485 485 */
486 486
487 487 * html .threepxfix{
488 488 margin-left: 3px;
489 489 } No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now