Patch #1470 ยป MyPage_Projects_Block.patch
app/controllers/my_controller.rb (working copy) | ||
---|---|---|
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 |
class MyController < ApplicationController |
18 | 18 |
helper :issues |
19 | ||
19 | ||
20 | 20 |
layout 'base' |
21 | 21 |
before_filter :require_login |
... | ... | |
27 | 27 |
'news' => :label_news_latest, |
28 | 28 |
'calendar' => :label_calendar, |
29 | 29 |
'documents' => :label_document_plural, |
30 |
'timelog' => :label_spent_time |
|
30 |
'timelog' => :label_spent_time, |
|
31 |
'projects' => :label_project_plural |
|
31 | 32 |
}.freeze |
32 |
DEFAULT_LAYOUT = { 'left' => ['issuesassignedtome'], |
|
33 |
'right' => ['issuesreportedbyme'] |
|
33 |
DEFAULT_LAYOUT = { 'left' => ['issuesassignedtome'], |
|
34 |
'right' => ['issuesreportedbyme'] |
|
34 | 35 |
}.freeze |
35 | 36 |
verify :xhr => true, |
... | ... | |
72 | 73 |
# Only users that belong to more than 1 project can select projects for which they are notified |
73 | 74 |
# Note that @user.membership.size would fail since AR ignores :include association option when doing a count |
74 | 75 |
@notification_options.insert 1, [l(:label_user_mail_option_selected), 'selected'] if @user.memberships.length > 1 |
75 |
@notification_option = @user.mail_notification? ? 'all' : (@user.notified_projects_ids.empty? ? 'none' : 'selected') |
|
76 |
@notification_option = @user.mail_notification? ? 'all' : (@user.notified_projects_ids.empty? ? 'none' : 'selected') |
|
76 | 77 |
end |
77 | 78 |
# Manage user's password |
... | ... | |
91 | 92 |
end |
92 | 93 |
end |
93 | 94 |
end |
94 | ||
95 | ||
95 | 96 |
# Create a new feeds key |
96 | 97 |
def reset_rss_key |
97 | 98 |
if request.post? && User.current.rss_token |
... | ... | |
110 | 111 |
@block_options = [] |
111 | 112 |
BLOCKS.each {|k, v| @block_options << [l(v), k]} |
112 | 113 |
end |
113 | ||
114 | ||
114 | 115 |
# Add a block to user's page |
115 | 116 |
# The block is added on top of the page |
116 | 117 |
# params[:block] : id of the block to add |
... | ... | |
124 | 125 |
session[:page_layout]['top'].unshift block |
125 | 126 |
render :partial => "block", :locals => {:user => @user, :block_name => block} |
126 | 127 |
end |
127 | ||
128 | ||
128 | 129 |
# Remove a block to user's page |
129 | 130 |
# params[:block] : id of the block to remove |
130 | 131 |
def remove_block |
... | ... | |
145 | 146 |
%w(top left right).each {|f| |
146 | 147 |
session[:page_layout][f] = (session[:page_layout][f] || []) - group_items |
147 | 148 |
} |
148 |
session[:page_layout][group] = group_items |
|
149 |
session[:page_layout][group] = group_items |
|
149 | 150 |
end |
150 | 151 |
render :nothing => true |
151 | 152 |
end |
152 | ||
153 |
# Save user's page layout |
|
153 | ||
154 |
# Save user's page layout |
|
154 | 155 |
def page_layout_save |
155 | 156 |
@user = User.current |
156 | 157 |
@user.pref[:my_page_layout] = session[:page_layout] if session[:page_layout] |
app/models/project.rb (working copy) | ||
---|---|---|
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. |
... | ... | |
19 | 19 |
# Project statuses |
20 | 20 |
STATUS_ACTIVE = 1 |
21 | 21 |
STATUS_ARCHIVED = 9 |
22 | ||
22 | ||
23 | 23 |
has_many :members, :include => :user, :conditions => "#{User.table_name}.status=#{User::STATUS_ACTIVE}" |
24 | 24 |
has_many :users, :through => :members |
25 | 25 |
has_many :custom_values, :dependent => :delete_all, :as => :customized |
... | ... | |
38 | 38 |
has_many :changesets, :through => :repository |
39 | 39 |
has_one :wiki, :dependent => :destroy |
40 | 40 |
# Custom field for the project issues |
41 |
has_and_belongs_to_many :custom_fields, |
|
41 |
has_and_belongs_to_many :custom_fields, |
|
42 | 42 |
:class_name => 'IssueCustomField', |
43 | 43 |
:order => "#{CustomField.table_name}.position", |
44 | 44 |
:join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}", |
45 | 45 |
:association_foreign_key => 'custom_field_id' |
46 | ||
46 | ||
47 | 47 |
acts_as_tree :order => "name", :counter_cache => true |
48 | 48 |
acts_as_searchable :columns => ['name', 'description'], :project_key => 'id', :permission => nil |
... | ... | |
51 | 51 |
:url => Proc.new {|o| {:controller => 'projects', :action => 'show', :id => o.id}} |
52 | 52 |
attr_protected :status, :enabled_module_names |
53 | ||
53 | ||
54 | 54 |
validates_presence_of :name, :identifier |
55 | 55 |
validates_uniqueness_of :name, :identifier |
56 | 56 |
validates_associated :custom_values, :on => :update |
... | ... | |
60 | 60 |
validates_length_of :homepage, :maximum => 255 |
61 | 61 |
validates_length_of :identifier, :in => 3..20 |
62 | 62 |
validates_format_of :identifier, :with => /^[a-z0-9\-]*$/ |
63 | ||
63 | ||
64 | 64 |
before_destroy :delete_all_members |
65 | ||
65 | ||
66 | 66 |
def identifier=(identifier) |
67 | 67 |
super unless identifier_frozen? |
68 | 68 |
end |
69 | ||
69 | ||
70 | 70 |
def identifier_frozen? |
71 | 71 |
errors[:identifier].nil? && !(new_record? || identifier.blank?) |
72 | 72 |
end |
73 | ||
73 | ||
74 | 74 |
def issues_with_subprojects(include_subprojects=false) |
75 | 75 |
conditions = nil |
76 | 76 |
if include_subprojects |
... | ... | |
79 | 79 |
end |
80 | 80 |
conditions ||= ["#{Project.table_name}.id = ?", id] |
81 | 81 |
# Quick and dirty fix for Rails 2 compatibility |
82 |
Issue.send(:with_scope, :find => { :conditions => conditions }) do |
|
82 |
Issue.send(:with_scope, :find => { :conditions => conditions }) do |
|
83 | 83 |
Version.send(:with_scope, :find => { :conditions => conditions }) do |
84 | 84 |
yield |
85 | 85 |
end |
86 |
end |
|
86 |
end |
|
87 | 87 |
end |
88 | 88 |
# returns latest created projects |
89 | 89 |
# non public projects will be returned only if user is a member of those |
90 | 90 |
def self.latest(user=nil, count=5) |
91 |
find(:all, :limit => count, :conditions => visible_by(user), :order => "created_on DESC") |
|
92 |
end |
|
91 |
find(:all, :limit => count, :conditions => visible_by(user), :order => "created_on DESC") |
|
92 |
end |
|
93 | 93 |
def self.visible_by(user=nil) |
94 | 94 |
user ||= User.current |
... | ... | |
102 | 102 |
return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE} AND #{Project.table_name}.is_public = #{connection.quoted_true}" |
103 | 103 |
end |
104 | 104 |
end |
105 | ||
105 | ||
106 |
def self.members(user=nil) |
|
107 |
user ||= User.current |
|
108 |
if user && user.memberships.any? |
|
109 |
return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE} AND #{Project.table_name}.id IN (#{user.memberships.collect{|m| m.project_id}.join(',')})" |
|
110 |
end |
|
111 |
end |
|
112 | ||
113 | ||
106 | 114 |
def self.allowed_to_condition(user, permission, options={}) |
107 | 115 |
statements = [] |
108 | 116 |
base_statement = "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}" |
... | ... | |
119 | 127 |
statements << "#{Project.table_name}.id IN (#{allowed_project_ids.join(',')})" if allowed_project_ids.any? |
120 | 128 |
elsif Role.anonymous.allowed_to?(permission) |
121 | 129 |
# anonymous user allowed on public project |
122 |
statements << "#{Project.table_name}.is_public = #{connection.quoted_true}" |
|
130 |
statements << "#{Project.table_name}.is_public = #{connection.quoted_true}" |
|
123 | 131 |
else |
124 | 132 |
# anonymous user is not authorized |
125 | 133 |
statements << "1=0" |
126 | 134 |
end |
127 | 135 |
statements.empty? ? base_statement : "((#{base_statement}) AND (#{statements.join(' OR ')}))" |
128 | 136 |
end |
129 | ||
137 | ||
130 | 138 |
def project_condition(with_subprojects) |
131 | 139 |
cond = "#{Project.table_name}.id = #{id}" |
132 | 140 |
cond = "(#{cond} OR #{Project.table_name}.parent_id = #{id})" if with_subprojects |
133 | 141 |
cond |
134 | 142 |
end |
135 | ||
143 | ||
136 | 144 |
def self.find(*args) |
137 | 145 |
if args.first && args.first.is_a?(String) && !args.first.match(/^\d*$/) |
138 | 146 |
project = find_by_identifier(*args) |
... | ... | |
142 | 150 |
super |
143 | 151 |
end |
144 | 152 |
end |
145 | ||
153 | ||
146 | 154 |
def to_param |
147 | 155 |
# id is used for projects with a numeric identifier (compatibility) |
148 | 156 |
@to_param ||= (identifier.to_s =~ %r{^\d*$} ? id : identifier) |
149 | 157 |
end |
150 | ||
158 | ||
151 | 159 |
def active? |
152 | 160 |
self.status == STATUS_ACTIVE |
153 | 161 |
end |
154 | ||
162 | ||
155 | 163 |
def archive |
156 | 164 |
# Archive subprojects if any |
157 | 165 |
children.each do |subproject| |
... | ... | |
159 | 167 |
end |
160 | 168 |
update_attribute :status, STATUS_ARCHIVED |
161 | 169 |
end |
162 | ||
170 | ||
163 | 171 |
def unarchive |
164 | 172 |
return false if parent && !parent.active? |
165 | 173 |
update_attribute :status, STATUS_ACTIVE |
166 | 174 |
end |
167 | ||
175 | ||
168 | 176 |
def active_children |
169 | 177 |
children.select {|child| child.active?} |
170 | 178 |
end |
171 | ||
179 | ||
172 | 180 |
# Returns an array of the trackers used by the project and its sub projects |
173 | 181 |
def rolled_up_trackers |
174 | 182 |
@rolled_up_trackers ||= |
... | ... | |
177 | 185 |
:conditions => ["#{Project.table_name}.id = ? OR #{Project.table_name}.parent_id = ?", id, id], |
178 | 186 |
:order => "#{Tracker.table_name}.position") |
179 | 187 |
end |
180 | ||
188 | ||
181 | 189 |
# Deletes all project's members |
182 | 190 |
def delete_all_members |
183 | 191 |
Member.delete_all(['project_id = ?', id]) |
184 | 192 |
end |
185 | ||
193 | ||
186 | 194 |
# Users issues can be assigned to |
187 | 195 |
def assignable_users |
188 | 196 |
members.select {|m| m.role.assignable?}.collect {|m| m.user}.sort |
189 | 197 |
end |
190 | ||
198 | ||
191 | 199 |
# Returns the mail adresses of users that should be always notified on project events |
192 | 200 |
def recipients |
193 | 201 |
members.select {|m| m.mail_notification? || m.user.mail_notification?}.collect {|m| m.user.mail} |
194 | 202 |
end |
195 | ||
203 | ||
196 | 204 |
# Returns an array of all custom fields enabled for project issues |
197 | 205 |
# (explictly associated custom fields and custom fields enabled for all projects) |
198 | 206 |
def custom_fields_for_issues(tracker) |
199 | 207 |
all_custom_fields.select {|c| tracker.custom_fields.include? c } |
200 | 208 |
end |
201 | ||
209 | ||
202 | 210 |
def all_custom_fields |
203 | 211 |
@all_custom_fields ||= (IssueCustomField.for_all + custom_fields).uniq |
204 | 212 |
end |
205 | ||
213 | ||
206 | 214 |
def project |
207 | 215 |
self |
208 | 216 |
end |
209 | ||
217 | ||
210 | 218 |
def <=>(project) |
211 | 219 |
name.downcase <=> project.name.downcase |
212 | 220 |
end |
213 | ||
221 | ||
214 | 222 |
def to_s |
215 | 223 |
name |
216 | 224 |
end |
217 | ||
225 | ||
218 | 226 |
# Returns a short description of the projects (first lines) |
219 | 227 |
def short_description(length = 255) |
220 | 228 |
description.gsub(/^(.{#{length}}[^\n]*).*$/m, '\1').strip if description |
221 | 229 |
end |
222 | ||
230 | ||
223 | 231 |
def allows_to?(action) |
224 | 232 |
if action.is_a? Hash |
225 | 233 |
allowed_actions.include? "#{action[:controller]}/#{action[:action]}" |
... | ... | |
227 | 235 |
allowed_permissions.include? action |
228 | 236 |
end |
229 | 237 |
end |
230 | ||
238 | ||
231 | 239 |
def module_enabled?(module_name) |
232 | 240 |
module_name = module_name.to_s |
233 | 241 |
enabled_modules.detect {|m| m.name == module_name} |
234 | 242 |
end |
235 | ||
243 | ||
236 | 244 |
def enabled_module_names=(module_names) |
237 | 245 |
enabled_modules.clear |
238 | 246 |
module_names = [] unless module_names && module_names.is_a?(Array) |
... | ... | |
247 | 255 |
errors.add_to_base("A project with subprojects can't be a subproject") if parent and children.size > 0 |
248 | 256 |
errors.add(:identifier, :activerecord_error_invalid) if !identifier.blank? && identifier.match(/^\d*$/) |
249 | 257 |
end |
250 | ||
258 | ||
251 | 259 |
private |
252 | 260 |
def allowed_permissions |
253 | 261 |
@allowed_permissions ||= begin |
app/views/my/blocks/_projects.rhtml (revision 0) | ||
---|---|---|
1 |
<h3><%=l(:label_project_plural)%></h3> |
|
2 | ||
3 |
<% myprojects = Project.find(:all, |
|
4 |
:conditions => ["#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"]) %> |
|
5 |
<% form_tag({}) do %> |
|
6 |
<table class="list projects"> |
|
7 |
<thead><tr> |
|
8 |
<th align="left"><%=l(:field_project)%></th> |
|
9 |
<th align="center"><%=l(:label_assigned_issues)%></th> |
|
10 |
<th align="center"><%=l(:label_reported_issues)%></th> |
|
11 |
<th align="center"><%=l(:label_all_time)%></th> |
|
12 |
</tr></thead> |
|
13 |
<tbody> |
|
14 |
<% for project in myprojects %> |
|
15 |
<% if User.current.member_of?(project) %> |
|
16 |
<tr class="<%= cycle('odd', 'even') %>" > |
|
17 |
<td> |
|
18 |
<%= link_to h(project.name), :controller => 'projects', :action => 'show', :id => project %> |
|
19 |
</td><td align="center"> |
|
20 |
<% num_assigned = 0 %> |
|
21 |
<% num_reported = 0 %> |
|
22 |
<% spent_time = 0 %> |
|
23 |
<% for issue in project.issues %> |
|
24 |
<% if issue.assigned_to == User.current && !issue.status.is_closed %> |
|
25 |
<% num_assigned = num_assigned + 1 %> |
|
26 |
<% end %> |
|
27 |
<% if issue.author == User.current && !issue.status.is_closed %> |
|
28 |
<% num_reported = num_reported + 1 %> |
|
29 |
<% end %> |
|
30 |
<% for timeentry in issue.time_entries %> |
|
31 |
<% if timeentry.user_id == User.current.id %> |
|
32 |
<% spent_time = spent_time + timeentry.hours %> |
|
33 |
<% end %> |
|
34 |
<% end %> |
|
35 |
<% end %> |
|
36 |
<% if num_assigned > 0 %> |
|
37 |
<%= link_to num_assigned, :controller => 'projects/' << project.identifier, :action => 'issues', :set_filter => 1, :assigned_to_id => 'me' %> |
|
38 |
<% end %> |
|
39 |
</td><td align="center"> |
|
40 |
<% if num_reported > 0 %> |
|
41 |
<%= link_to num_reported, :controller => 'projects/' << project.identifier, :action => 'issues', :set_filter => 1, :author_id => 'me' %> |
|
42 |
<% end %> |
|
43 |
</td><td align="center"> |
|
44 |
<% if spent_time > 0 %> |
|
45 |
<%= link_to spent_time, :controller => 'projects/' << project.identifier << '/timelog', :action => 'details' %> |
|
46 |
<% end %> |
|
47 |
</td></tr> |
|
48 |
<% end %> |
|
49 |
<% end %> |
|
50 |
</tbody> |
|
51 |
</table> |
|
52 |
<% end %> |
|
53 | ||
54 |
<% if myprojects.length > 0 %> |
|
55 |
<p class="small"><%= link_to l(:label_project_all), :controller => 'projects', :action => 'index' %></p> |
|
56 |
<% end %> |
lang/en.yml (working copy) | ||
---|---|---|
278 | 278 |
label_login: Sign in |
279 | 279 |
label_logout: Sign out |
280 | 280 |
label_help: Help |
281 |
label_reported_issues: Reported issues |
|
281 |
label_reported_issues: Reported |
|
282 |
label_assigned_issues: Assigned |
|
282 | 283 |
label_assigned_to_me_issues: Issues assigned to me |
283 | 284 |
label_last_login: Last connection |
284 | 285 |
label_last_updates: Last updated |
... | ... | |
373 | 374 |
label_in_more_than: in more than |
374 | 375 |
label_in: in |
375 | 376 |
label_today: today |
376 |
label_all_time: all time
|
|
377 |
label_all_time: Time
|
|
377 | 378 |
label_yesterday: yesterday |
378 | 379 |
label_this_week: this week |
379 | 380 |
label_last_week: last week |
... | ... | |
409 | 410 |
label_sort_lower: Move down |
410 | 411 |
label_sort_lowest: Move to bottom |
411 | 412 |
label_roadmap: Roadmap |
412 |
label_roadmap_due_in: Due in |
|
413 |
label_roadmap_due_in: Due in |
|
413 | 414 |
label_roadmap_overdue: %s late |
414 | 415 |
label_roadmap_no_issues: No issues for this version |
415 | 416 |
label_search: Search |
public/stylesheets/application.css (working copy) | ||
---|---|---|
57 | 57 |
#content { width: 80%; background-color: #fff; margin: 0px; border-right: 1px solid #ddd; padding: 6px 10px 10px 10px; z-index: 10; height:600px; min-height: 600px;} |
58 | 58 |
* html #content{ width: 80%; padding-left: 0; margin-top: 0px; padding: 6px 10px 10px 10px;} |
59 |
html>body #content { height: auto; min-height: 600px; overflow: auto; } |
|
59 |
html>body #content { height: auto; min-height: 600px; overflow: auto; } |
|
60 | 60 |
#main.nosidebar #sidebar{ display: none; } |
61 | 61 |
#main.nosidebar #content{ width: auto; border-right: 0; } |
... | ... | |
78 | 78 |
a.issue.closed, .issue.closed a { text-decoration: line-through; } |
79 | 79 |
/***** Tables *****/ |
80 |
table.list { border: 1px solid #e4e4e4; border-collapse: collapse; width: 100%; margin-bottom: 4px; }
|
|
80 |
table.list { border: 1px solid #e4e4e4; border-collapse: collapse; width: 100%; margin-bottom: 4px;} |
|
81 | 81 |
table.list th { background-color:#EEEEEE; padding: 4px; white-space:nowrap; } |
82 | 82 |
table.list td { vertical-align: top; } |
83 | 83 |
table.list td.id { width: 2%; text-align: center;} |
84 | 84 |
table.list td.checkbox { width: 15px; padding: 0px;} |
85 |
table.list.issues { margin-top: 10px; } |
|
86 |
table.projects { margin-top: 10px; } |
|
85 |
table.list.issues { margin-top: 10px; } |
|
86 | 87 |
tr.issue { text-align: center; white-space: nowrap; } |
87 | 88 |
tr.issue td.subject, tr.issue td.category { white-space: normal; } |
88 | 89 |
tr.issue td.subject { text-align: left; } |
... | ... | |
159 | 160 |
li p {margin-top: 0;} |
160 | 161 |
div.issue {background:#ffffdd; padding:6px; margin-bottom:6px;border: 1px solid #d7d7d7;} |
161 | 162 |
p.breadcrumb { font-size: 0.9em; margin: 4px 0 4px 0;} |
162 |
p.subtitle { font-size: 0.9em; margin: -6px 0 12px 0; font-style: italic; } |
|
163 |
p.subtitle { font-size: 0.9em; margin: -6px 0 12px 0; font-style: italic; } |
|
163 | 164 |
fieldset#filters { padding: 0.7em; } |
164 | 165 |
fieldset#filters p { margin: 1.2em 0 0.8em 2px; } |
... | ... | |
236 | 237 |
float: left; |
237 | 238 |
text-align: right; |
238 | 239 |
margin-left: -180px; /*width of left column*/ |
239 |
width: 175px; /*width of labels. Should be smaller than left column to create some right |
|
240 |
width: 175px; /*width of labels. Should be smaller than left column to create some right |
|
240 | 241 |
margin*/ |
241 | 242 |
} |
... | ... | |
272 | 273 |
#errorExplanation, div.flash, .nodata, .warning { |
273 | 274 |
padding: 4px 4px 4px 30px; |
274 | 275 |
margin-bottom: 12px; |
275 |
font-size: 1.1em; |
|
276 |
border: 2px solid; |
|
276 |
font-size: 1.1em;
|
|
277 |
border: 2px solid;
|
|
277 | 278 |
} |
278 | 279 |
div.flash {margin-top: 8px;} |
279 | 280 |
div.flash.error, #errorExplanation { |
280 | 281 |
background: url(../images/false.png) 8px 5px no-repeat; |
281 |
background-color: #ffe3e3; |
|
282 |
border-color: #dd0000; |
|
283 |
color: #550000; |
|
282 |
background-color: #ffe3e3;
|
|
283 |
border-color: #dd0000;
|
|
284 |
color: #550000;
|
|
284 | 285 |
} |
285 | 286 |
div.flash.notice { |
286 | 287 |
background: url(../images/true.png) 8px 5px no-repeat; |
287 |
background-color: #dfffdf; |
|
288 |
border-color: #9fcf9f; |
|
289 |
color: #005f00; |
|
288 |
background-color: #dfffdf;
|
|
289 |
border-color: #9fcf9f;
|
|
290 |
color: #005f00;
|
|
290 | 291 |
} |
291 | 292 |
.nodata, .warning { |
292 | 293 |
text-align: center; |
293 |
background-color: #FFEBC1; |
|
294 |
border-color: #FDBF3B; |
|
295 |
color: #A6750C; |
|
294 |
background-color: #FFEBC1;
|
|
295 |
border-color: #FDBF3B;
|
|
296 |
color: #A6750C;
|
|
296 | 297 |
} |
297 | 298 |
#errorExplanation ul { font-size: 0.9em;} |
... | ... | |
528 | 529 |
} |
529 | 530 |
.task_late { background:#f66 url(../images/task_late.png); border: 1px solid #f66; } |
530 |
.task_done { background:#66f url(../images/task_done.png); border: 1px solid #66f; } |
|
531 |
.task_done { background:#66f url(../images/task_done.png); border: 1px solid #66f; } |
|
531 | 532 |
.task_todo { background:#aaa url(../images/task_todo.png); border: 1px solid #aaa; } |
532 | 533 |
.milestone { background-image:url(../images/milestone.png); background-repeat: no-repeat; border: 0; } |