##// END OF EJS Templates
Version details view changes:...
Jean-Philippe Lang -
r1193:9b59ea725658
parent child
Show More
@@ -1,199 +1,194
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 module ProjectsHelper
19 19 def link_to_version(version, options = {})
20 20 return '' unless version && version.is_a?(Version)
21 link_to version.name, {:controller => 'projects',
22 :action => 'roadmap',
23 :id => version.project_id,
24 :completed => (version.completed? ? 1 : nil),
25 :anchor => version.name
26 }, options
21 link_to h(version.name), { :controller => 'versions', :action => 'show', :id => version }, options
27 22 end
28 23
29 24 def format_activity_day(date)
30 25 date == Date.today ? l(:label_today).titleize : format_date(date)
31 26 end
32 27
33 28 def format_activity_description(text)
34 29 h(truncate(text, 250))
35 30 end
36 31
37 32 def project_settings_tabs
38 33 tabs = [{:name => 'info', :action => :edit_project, :partial => 'projects/edit', :label => :label_information_plural},
39 34 {:name => 'modules', :action => :select_project_modules, :partial => 'projects/settings/modules', :label => :label_module_plural},
40 35 {:name => 'members', :action => :manage_members, :partial => 'projects/settings/members', :label => :label_member_plural},
41 36 {:name => 'versions', :action => :manage_versions, :partial => 'projects/settings/versions', :label => :label_version_plural},
42 37 {:name => 'categories', :action => :manage_categories, :partial => 'projects/settings/issue_categories', :label => :label_issue_category_plural},
43 38 {:name => 'wiki', :action => :manage_wiki, :partial => 'projects/settings/wiki', :label => :label_wiki},
44 39 {:name => 'repository', :action => :manage_repository, :partial => 'projects/settings/repository', :label => :label_repository},
45 40 {:name => 'boards', :action => :manage_boards, :partial => 'projects/settings/boards', :label => :label_board_plural}
46 41 ]
47 42 tabs.select {|tab| User.current.allowed_to?(tab[:action], @project)}
48 43 end
49 44
50 45 # Generates a gantt image
51 46 # Only defined if RMagick is avalaible
52 47 def gantt_image(events, date_from, months, zoom)
53 48 date_to = (date_from >> months)-1
54 49 show_weeks = zoom > 1
55 50 show_days = zoom > 2
56 51
57 52 subject_width = 320
58 53 header_heigth = 18
59 54 # width of one day in pixels
60 55 zoom = zoom*2
61 56 g_width = (date_to - date_from + 1)*zoom
62 57 g_height = 20 * events.length + 20
63 58 headers_heigth = (show_weeks ? 2*header_heigth : header_heigth)
64 59 height = g_height + headers_heigth
65 60
66 61 imgl = Magick::ImageList.new
67 62 imgl.new_image(subject_width+g_width+1, height)
68 63 gc = Magick::Draw.new
69 64
70 65 # Subjects
71 66 top = headers_heigth + 20
72 67 gc.fill('black')
73 68 gc.stroke('transparent')
74 69 gc.stroke_width(1)
75 70 events.each do |i|
76 71 gc.text(4, top + 2, (i.is_a?(Issue) ? i.subject : i.name))
77 72 top = top + 20
78 73 end
79 74
80 75 # Months headers
81 76 month_f = date_from
82 77 left = subject_width
83 78 months.times do
84 79 width = ((month_f >> 1) - month_f) * zoom
85 80 gc.fill('white')
86 81 gc.stroke('grey')
87 82 gc.stroke_width(1)
88 83 gc.rectangle(left, 0, left + width, height)
89 84 gc.fill('black')
90 85 gc.stroke('transparent')
91 86 gc.stroke_width(1)
92 87 gc.text(left.round + 8, 14, "#{month_f.year}-#{month_f.month}")
93 88 left = left + width
94 89 month_f = month_f >> 1
95 90 end
96 91
97 92 # Weeks headers
98 93 if show_weeks
99 94 left = subject_width
100 95 height = header_heigth
101 96 if date_from.cwday == 1
102 97 # date_from is monday
103 98 week_f = date_from
104 99 else
105 100 # find next monday after date_from
106 101 week_f = date_from + (7 - date_from.cwday + 1)
107 102 width = (7 - date_from.cwday + 1) * zoom
108 103 gc.fill('white')
109 104 gc.stroke('grey')
110 105 gc.stroke_width(1)
111 106 gc.rectangle(left, header_heigth, left + width, 2*header_heigth + g_height-1)
112 107 left = left + width
113 108 end
114 109 while week_f <= date_to
115 110 width = (week_f + 6 <= date_to) ? 7 * zoom : (date_to - week_f + 1) * zoom
116 111 gc.fill('white')
117 112 gc.stroke('grey')
118 113 gc.stroke_width(1)
119 114 gc.rectangle(left.round, header_heigth, left.round + width, 2*header_heigth + g_height-1)
120 115 gc.fill('black')
121 116 gc.stroke('transparent')
122 117 gc.stroke_width(1)
123 118 gc.text(left.round + 2, header_heigth + 14, week_f.cweek.to_s)
124 119 left = left + width
125 120 week_f = week_f+7
126 121 end
127 122 end
128 123
129 124 # Days details (week-end in grey)
130 125 if show_days
131 126 left = subject_width
132 127 height = g_height + header_heigth - 1
133 128 wday = date_from.cwday
134 129 (date_to - date_from + 1).to_i.times do
135 130 width = zoom
136 131 gc.fill(wday == 6 || wday == 7 ? '#eee' : 'white')
137 132 gc.stroke('grey')
138 133 gc.stroke_width(1)
139 134 gc.rectangle(left, 2*header_heigth, left + width, 2*header_heigth + g_height-1)
140 135 left = left + width
141 136 wday = wday + 1
142 137 wday = 1 if wday > 7
143 138 end
144 139 end
145 140
146 141 # border
147 142 gc.fill('transparent')
148 143 gc.stroke('grey')
149 144 gc.stroke_width(1)
150 145 gc.rectangle(0, 0, subject_width+g_width, headers_heigth)
151 146 gc.stroke('black')
152 147 gc.rectangle(0, 0, subject_width+g_width, g_height+ headers_heigth-1)
153 148
154 149 # content
155 150 top = headers_heigth + 20
156 151 gc.stroke('transparent')
157 152 events.each do |i|
158 153 if i.is_a?(Issue)
159 154 i_start_date = (i.start_date >= date_from ? i.start_date : date_from )
160 155 i_end_date = (i.due_date <= date_to ? i.due_date : date_to )
161 156 i_done_date = i.start_date + ((i.due_date - i.start_date+1)*i.done_ratio/100).floor
162 157 i_done_date = (i_done_date <= date_from ? date_from : i_done_date )
163 158 i_done_date = (i_done_date >= date_to ? date_to : i_done_date )
164 159 i_late_date = [i_end_date, Date.today].min if i_start_date < Date.today
165 160
166 161 i_left = subject_width + ((i_start_date - date_from)*zoom).floor
167 162 i_width = ((i_end_date - i_start_date + 1)*zoom).floor # total width of the issue
168 163 d_width = ((i_done_date - i_start_date)*zoom).floor # done width
169 164 l_width = i_late_date ? ((i_late_date - i_start_date+1)*zoom).floor : 0 # delay width
170 165
171 166 gc.fill('grey')
172 167 gc.rectangle(i_left, top, i_left + i_width, top - 6)
173 168 gc.fill('red')
174 169 gc.rectangle(i_left, top, i_left + l_width, top - 6) if l_width > 0
175 170 gc.fill('blue')
176 171 gc.rectangle(i_left, top, i_left + d_width, top - 6) if d_width > 0
177 172 gc.fill('black')
178 173 gc.text(i_left + i_width + 5,top + 1, "#{i.status.name} #{i.done_ratio}%")
179 174 else
180 175 i_left = subject_width + ((i.start_date - date_from)*zoom).floor
181 176 gc.fill('green')
182 177 gc.rectangle(i_left, top, i_left + 6, top - 6)
183 178 gc.fill('black')
184 179 gc.text(i_left + 11, top + 1, i.name)
185 180 end
186 181 top = top + 20
187 182 end
188 183
189 184 # today red line
190 185 if Date.today >= date_from and Date.today <= date_to
191 186 gc.stroke('red')
192 187 x = (Date.today-date_from+1)*zoom + subject_width
193 188 gc.line(x, headers_heigth, x, headers_heigth + g_height-1)
194 189 end
195 190
196 191 gc.draw(imgl)
197 192 imgl
198 193 end if Object.const_defined?(:Magick)
199 194 end
@@ -1,96 +1,106
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 Version < ActiveRecord::Base
19 19 before_destroy :check_integrity
20 20 belongs_to :project
21 21 has_many :fixed_issues, :class_name => 'Issue', :foreign_key => 'fixed_version_id'
22 22 has_many :attachments, :as => :container, :dependent => :destroy
23 23
24 24 validates_presence_of :name
25 25 validates_uniqueness_of :name, :scope => [:project_id]
26 26 validates_length_of :name, :maximum => 30
27 27 validates_format_of :effective_date, :with => /^\d{4}-\d{2}-\d{2}$/, :message => :activerecord_error_not_a_date, :allow_nil => true
28 28
29 29 def start_date
30 30 effective_date
31 31 end
32 32
33 33 def due_date
34 34 effective_date
35 35 end
36 36
37 # Returns the total estimated time for this version
38 def estimated_hours
39 @estimated_hours ||= fixed_issues.sum(:estimated_hours).to_f
40 end
41
42 # Returns the total reported time for this version
43 def spent_hours
44 @spent_hours ||= TimeEntry.sum(:hours, :include => :issue, :conditions => ["#{Issue.table_name}.fixed_version_id = ?", id]).to_f
45 end
46
37 47 # Returns true if the version is completed: due date reached and no open issues
38 48 def completed?
39 49 effective_date && (effective_date <= Date.today) && (open_issues_count == 0)
40 50 end
41 51
42 52 def completed_pourcent
43 53 if fixed_issues.count == 0
44 54 0
45 55 elsif open_issues_count == 0
46 56 100
47 57 else
48 58 (closed_issues_count * 100 + Issue.sum('done_ratio', :include => 'status', :conditions => ["fixed_version_id = ? AND is_closed = ?", id, false]).to_f) / fixed_issues.count
49 59 end
50 60 end
51 61
52 62 def closed_pourcent
53 63 if fixed_issues.count == 0
54 64 0
55 65 else
56 66 closed_issues_count * 100.0 / fixed_issues.count
57 67 end
58 68 end
59 69
60 70 # Returns true if the version is overdue: due date reached and some open issues
61 71 def overdue?
62 72 effective_date && (effective_date < Date.today) && (open_issues_count > 0)
63 73 end
64 74
65 75 def open_issues_count
66 76 @open_issues_count ||= Issue.count(:all, :conditions => ["fixed_version_id = ? AND is_closed = ?", self.id, false], :include => :status)
67 77 end
68 78
69 79 def closed_issues_count
70 80 @closed_issues_count ||= Issue.count(:all, :conditions => ["fixed_version_id = ? AND is_closed = ?", self.id, true], :include => :status)
71 81 end
72 82
73 83 def wiki_page
74 84 if project.wiki && !wiki_page_title.blank?
75 85 @wiki_page ||= project.wiki.find_page(wiki_page_title)
76 86 end
77 87 @wiki_page
78 88 end
79 89
80 90 def to_s; name end
81 91
82 92 # Versions are sorted by effective_date
83 93 # Those with no effective_date are at the end, sorted by name
84 94 def <=>(version)
85 95 if self.effective_date
86 96 version.effective_date ? (self.effective_date <=> version.effective_date) : -1
87 97 else
88 98 version.effective_date ? 1 : (self.name <=> version.name)
89 99 end
90 100 end
91 101
92 102 private
93 103 def check_integrity
94 104 raise "Can't delete version" if self.fixed_issues.find(:first)
95 105 end
96 106 end
@@ -1,14 +1,49
1 1 <div class="contextual">
2 2 <%= link_to_if_authorized l(:button_edit), {:controller => 'versions', :action => 'edit', :id => @version}, :class => 'icon icon-edit' %>
3 3 </div>
4 4
5 5 <h2><%= h(@version.name) %></h2>
6 6
7 <div id="version-summary">
8 <% if @version.estimated_hours > 0 || User.current.allowed_to?(:view_time_entries, @project) %>
9 <fieldset><legend><%= l(:label_time_tracking) %></legend>
10 <table>
11 <tr>
12 <td width="130px" align="right"><%= l(:field_estimated_hours) %></td>
13 <td width="240px" class="total-hours"width="130px" align="right"><%= html_hours(lwr(:label_f_hour, @version.estimated_hours)) %></td>
14 </tr>
15 <% if User.current.allowed_to?(:view_time_entries, @project) %>
16 <tr>
17 <td width="130px" align="right"><%= l(:label_spent_time) %></td>
18 <td width="240px" class="total-hours"><%= html_hours(lwr(:label_f_hour, @version.spent_hours)) %></td>
19 </tr>
20 <% end %>
21 </table>
22 </fieldset>
23 <% end %>
24
7 25 <div id="status_by">
8 26 <%= render_issue_status_by(@version, params[:status_by]) if @version.fixed_issues.count > 0 %>
9 27 </div>
28 </div>
10 29
30 <div id="roadmap">
11 31 <%= render :partial => 'versions/overview', :locals => {:version => @version} %>
12 32 <%= render(:partial => "wiki/content", :locals => {:content => @version.wiki_page.content}) if @version.wiki_page %>
13 33
34 <% issues = @version.fixed_issues.find(:all,
35 :include => [:status, :tracker],
36 :order => "#{Tracker.table_name}.position, #{Issue.table_name}.id") %>
37 <% if issues.size > 0 %>
38 <fieldset class="related-issues"><legend><%= l(:label_related_issues) %></legend>
39 <ul>
40 <% issues.each do |issue| -%>
41 <li><%= link = link_to_issue(issue)
42 issue.status.is_closed? ? content_tag("del", link) : link %>: <%=h issue.subject %></li>
43 <% end -%>
44 </ul>
45 </fieldset>
46 <% end %>
47 </div>
48
14 49 <% html_title @version.name %>
@@ -1,570 +1,572
1 1 body { font-family: Verdana, sans-serif; font-size: 12px; color:#484848; margin: 0; padding: 0; min-width: 900px; }
2 2
3 3 h1, h2, h3, h4 { font-family: "Trebuchet MS", Verdana, sans-serif;}
4 4 h1 {margin:0; padding:0; font-size: 24px;}
5 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 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 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 9 /***** Layout *****/
10 10 #wrapper {background: white;}
11 11
12 12 #top-menu {background: #2C4056;color: #fff;height:1.5em; padding: 2px 6px 0px 6px;}
13 13 #top-menu ul {margin: 0; padding: 0;}
14 14 #top-menu li {
15 15 float:left;
16 16 list-style-type:none;
17 17 margin: 0px 0px 0px 0px;
18 18 padding: 0px 0px 0px 0px;
19 19 white-space:nowrap;
20 20 }
21 21 #top-menu a {color: #fff; padding-right: 4px;}
22 22 #top-menu #loggedas { float: right; margin-right: 0.5em; color: #fff; }
23 23
24 24 #account {float:right;}
25 25
26 26 #header {height:5.3em;margin:0;background-color:#507AAA;color:#f8f8f8; padding: 4px 8px 0px 6px; position:relative;}
27 27 #header a {color:#f8f8f8;}
28 28 #quick-search {float:right;}
29 29
30 30 #main-menu {position: absolute; bottom: 0px; left:6px; margin-right: -500px;}
31 31 #main-menu ul {margin: 0; padding: 0;}
32 32 #main-menu li {
33 33 float:left;
34 34 list-style-type:none;
35 35 margin: 0px 10px 0px 0px;
36 36 padding: 0px 0px 0px 0px;
37 37 white-space:nowrap;
38 38 }
39 39 #main-menu li a {
40 40 display: block;
41 41 color: #fff;
42 42 text-decoration: none;
43 43 margin: 0;
44 44 padding: 4px 4px 4px 4px;
45 45 background: #2C4056;
46 46 }
47 47 #main-menu li a:hover, #main-menu li a.selected {background:#759FCF;}
48 48
49 49 #main {background: url(../images/mainbg.png) repeat-x; background-color:#EEEEEE;}
50 50
51 51 #sidebar{ float: right; width: 17%; position: relative; z-index: 9; min-height: 600px; padding: 0; margin: 0;}
52 52 * html #sidebar{ width: 17%; }
53 53 #sidebar h3{ font-size: 14px; margin-top:14px; color: #666; }
54 54 #sidebar hr{ width: 100%; margin: 0 auto; height: 1px; background: #ccc; border: 0; }
55 55 * html #sidebar hr{ width: 95%; position: relative; left: -6px; color: #ccc; }
56 56
57 57 #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; 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 59 html>body #content {
60 60 height: auto;
61 61 min-height: 600px;
62 62 }
63 63
64 64 #main.nosidebar #sidebar{ display: none; }
65 65 #main.nosidebar #content{ width: auto; border-right: 0; }
66 66
67 67 #footer {clear: both; border-top: 1px solid #bbb; font-size: 0.9em; color: #aaa; padding: 5px; text-align:center; background:#fff;}
68 68
69 69 #login-form table {margin-top:5em; padding:1em; margin-left: auto; margin-right: auto; border: 2px solid #FDBF3B; background-color:#FFEBC1; }
70 70 #login-form table td {padding: 6px;}
71 71 #login-form label {font-weight: bold;}
72 72
73 73 .clear:after{ content: "."; display: block; height: 0; clear: both; visibility: hidden; }
74 74
75 75 /***** Links *****/
76 76 a, a:link, a:visited{ color: #2A5685; text-decoration: none; }
77 77 a:hover, a:active{ color: #c61a1a; text-decoration: underline;}
78 78 a img{ border: 0; }
79 79
80 80 /***** Tables *****/
81 81 table.list { border: 1px solid #e4e4e4; border-collapse: collapse; width: 100%; margin-bottom: 4px; }
82 82 table.list th { background-color:#EEEEEE; padding: 4px; white-space:nowrap; }
83 83 table.list td { overflow: hidden; vertical-align: top;}
84 84 table.list td.id { width: 2%; text-align: center;}
85 85 table.list td.checkbox { width: 15px; padding: 0px;}
86 86
87 87 tr.issue { text-align: center; white-space: nowrap; }
88 88 tr.issue td.subject, tr.issue td.category { white-space: normal; }
89 89 tr.issue td.subject { text-align: left; }
90 90 tr.issue td.done_ratio table.progress { margin-left:auto; margin-right: auto;}
91 91
92 92 tr.entry { border: 1px solid #f8f8f8; }
93 93 tr.entry td { white-space: nowrap; }
94 94 tr.entry td.filename { width: 30%; }
95 95 tr.entry td.size { text-align: right; font-size: 90%; }
96 96 tr.entry td.revision, tr.entry td.author { text-align: center; }
97 97 tr.entry td.age { text-align: right; }
98 98
99 99 tr.changeset td.author { text-align: center; width: 15%; }
100 100 tr.changeset td.committed_on { text-align: center; width: 15%; }
101 101
102 102 tr.message { height: 2.6em; }
103 103 tr.message td.last_message { font-size: 80%; }
104 104 tr.message.locked td.subject a { background-image: url(../images/locked.png); }
105 105 tr.message.sticky td.subject a { background-image: url(../images/sticky.png); font-weight: bold; }
106 106
107 107 tr.user td { width:13%; }
108 108 tr.user td.email { width:18%; }
109 109 tr.user td { white-space: nowrap; }
110 110 tr.user.locked, tr.user.registered { color: #aaa; }
111 111 tr.user.locked a, tr.user.registered a { color: #aaa; }
112 112
113 113 tr.time-entry { text-align: center; white-space: nowrap; }
114 114 tr.time-entry td.subject, tr.time-entry td.comments { text-align: left; }
115 115 tr.time-entry td.hours { text-align: right; font-weight: bold; padding-right: 0.5em; }
116 116 tr.time-entry .hours-dec { font-size: 0.9em; }
117 117
118 118 table.list tbody tr:hover { background-color:#ffffdd; }
119 119 table td {padding:2px;}
120 120 table p {margin:0;}
121 121 .odd {background-color:#f6f7f8;}
122 122 .even {background-color: #fff;}
123 123
124 124 .highlight { background-color: #FCFD8D;}
125 125 .highlight.token-1 { background-color: #faa;}
126 126 .highlight.token-2 { background-color: #afa;}
127 127 .highlight.token-3 { background-color: #aaf;}
128 128
129 129 .box{
130 130 padding:6px;
131 131 margin-bottom: 10px;
132 132 background-color:#f6f6f6;
133 133 color:#505050;
134 134 line-height:1.5em;
135 135 border: 1px solid #e4e4e4;
136 136 }
137 137
138 138 div.square {
139 139 border: 1px solid #999;
140 140 float: left;
141 141 margin: .3em .4em 0 .4em;
142 142 overflow: hidden;
143 143 width: .6em; height: .6em;
144 144 }
145 145
146 146 .contextual {float:right; white-space: nowrap; line-height:1.4em;margin-top:5px; padding-left: 10px; font-size:0.9em;}
147 147 .contextual input {font-size:0.9em;}
148 148
149 149 .splitcontentleft{float:left; width:49%;}
150 150 .splitcontentright{float:right; width:49%;}
151 151 form {display: inline;}
152 152 input, select {vertical-align: middle; margin-top: 1px; margin-bottom: 1px;}
153 153 fieldset {border: 1px solid #e4e4e4; margin:0;}
154 154 legend {color: #484848;}
155 155 hr { width: 100%; height: 1px; background: #ccc; border: 0;}
156 156 textarea.wiki-edit { width: 99%; }
157 157 li p {margin-top: 0;}
158 158 div.issue {background:#ffffdd; padding:6px; margin-bottom:6px;border: 1px solid #d7d7d7;}
159 159
160 160 div#issue-changesets {float:right; width:45%; margin-left: 1em; margin-bottom: 1em; background: #fff; padding-left: 1em; font-size: 90%;}
161 161 div#issue-changesets .changeset { padding: 4px;}
162 162 div#issue-changesets .changeset { border-bottom: 1px solid #ddd; }
163 163 div#issue-changesets p { margin-top: 0; margin-bottom: 1em;}
164 164
165 165 div#activity dl { margin-left: 2em; }
166 166 div#activity dd { margin-bottom: 1em; }
167 167 div#activity dt { margin-bottom: 1px; }
168 168 div#activity dt .time { color: #777; font-size: 80%; }
169 169 div#activity dd .description { font-style: italic; }
170 170
171 171 div#roadmap fieldset.related-issues { margin-bottom: 1em; }
172 172 div#roadmap fieldset.related-issues ul { margin-top: 0.3em; margin-bottom: 0.3em; }
173 173 div#roadmap .wiki h1:first-child { display: none; }
174 174 div#roadmap .wiki h1 { font-size: 120%; }
175 175 div#roadmap .wiki h2 { font-size: 110%; }
176 176
177 div#version-summary { float:right; width:380px; margin-left: 16px; margin-bottom: 16px; background-color: #fff; }
178 div#version-summary fieldset { margin-bottom: 1em; }
179 div#version-summary .total-hours { text-align: right; }
180
177 181 table#time-report td.hours { text-align: right; padding-right: 0.5em; }
178 182 table#time-report tbody tr { font-style: italic; color: #777; }
179 183 table#time-report tbody tr.last-level { font-style: normal; color: #555; }
180 184 table#time-report tbody tr.total { font-style: normal; font-weight: bold; color: #555; background-color:#EEEEEE; }
181 185 table#time-report .hours-dec { font-size: 0.9em; }
182 186
183 div.total-hours { text-align: left; font-size: 110%; font-weight: bold; }
184 div.total-hours span.hours-int { font-size: 120%; }
187 .total-hours { font-size: 110%; font-weight: bold; }
188 .total-hours span.hours-int { font-size: 120%; }
185 189
186 190 .autoscroll {overflow-x: auto; padding:1px; width:100%; margin-bottom: 1.2em;}
187 191 #user_firstname, #user_lastname, #user_mail, #my_account_form select { width: 90%; }
188 192
189 193 .pagination {font-size: 90%}
190 194 p.pagination {margin-top:8px;}
191 195
192 196 /***** Tabular forms ******/
193 197 .tabular p{
194 198 margin: 0;
195 199 padding: 5px 0 8px 0;
196 200 padding-left: 180px; /*width of left column containing the label elements*/
197 201 height: 1%;
198 202 clear:left;
199 203 }
200 204
201 205 .tabular label{
202 206 font-weight: bold;
203 207 float: left;
204 208 text-align: right;
205 209 margin-left: -180px; /*width of left column*/
206 210 width: 175px; /*width of labels. Should be smaller than left column to create some right
207 211 margin*/
208 212 }
209 213
210 214 .tabular label.floating{
211 215 font-weight: normal;
212 216 margin-left: 0px;
213 217 text-align: left;
214 218 width: 200px;
215 219 }
216 220
217 221 #preview fieldset {margin-top: 1em; background: url(../images/draft.png)}
218 222
219 223 .tabular.settings p{ padding-left: 300px; }
220 224 .tabular.settings label{ margin-left: -300px; width: 295px; }
221 225
222 226 .required {color: #bb0000;}
223 227 .summary {font-style: italic;}
224 228
225 229 #attachments_fields input[type=text] {margin-left: 8px; }
226 230
227 231 div.attachments p { margin:4px 0 2px 0; }
228 232 div.attachments img { vertical-align: middle; }
229 233 div.attachments span.author { font-size: 0.9em; color: #888; }
230 234
231 235 p.other-formats { text-align: right; font-size:0.9em; color: #666; }
232 236 .other-formats span + span:before { content: "| "; }
233 237
234 238 a.feed { background: url(../images/feed.png) no-repeat 1px 50%; padding: 2px 0px 3px 16px; }
235 239
236 240 /***** Flash & error messages ****/
237 241 #errorExplanation, div.flash, .nodata {
238 242 padding: 4px 4px 4px 30px;
239 243 margin-bottom: 12px;
240 244 font-size: 1.1em;
241 245 border: 2px solid;
242 246 }
243 247
244 248 div.flash {margin-top: 8px;}
245 249
246 250 div.flash.error, #errorExplanation {
247 251 background: url(../images/false.png) 8px 5px no-repeat;
248 252 background-color: #ffe3e3;
249 253 border-color: #dd0000;
250 254 color: #550000;
251 255 }
252 256
253 257 div.flash.notice {
254 258 background: url(../images/true.png) 8px 5px no-repeat;
255 259 background-color: #dfffdf;
256 260 border-color: #9fcf9f;
257 261 color: #005f00;
258 262 }
259 263
260 264 .nodata {
261 265 text-align: center;
262 266 background-color: #FFEBC1;
263 267 border-color: #FDBF3B;
264 268 color: #A6750C;
265 269 }
266 270
267 271 #errorExplanation ul { font-size: 0.9em;}
268 272
269 273 /***** Ajax indicator ******/
270 274 #ajax-indicator {
271 275 position: absolute; /* fixed not supported by IE */
272 276 background-color:#eee;
273 277 border: 1px solid #bbb;
274 278 top:35%;
275 279 left:40%;
276 280 width:20%;
277 281 font-weight:bold;
278 282 text-align:center;
279 283 padding:0.6em;
280 284 z-index:100;
281 285 filter:alpha(opacity=50);
282 286 opacity: 0.5;
283 287 }
284 288
285 289 html>body #ajax-indicator { position: fixed; }
286 290
287 291 #ajax-indicator span {
288 292 background-position: 0% 40%;
289 293 background-repeat: no-repeat;
290 294 background-image: url(../images/loading.gif);
291 295 padding-left: 26px;
292 296 vertical-align: bottom;
293 297 }
294 298
295 299 /***** Calendar *****/
296 300 table.cal {border-collapse: collapse; width: 100%; margin: 8px 0 6px 0;border: 1px solid #d7d7d7;}
297 301 table.cal thead th {width: 14%;}
298 302 table.cal tbody tr {height: 100px;}
299 303 table.cal th { background-color:#EEEEEE; padding: 4px; }
300 304 table.cal td {border: 1px solid #d7d7d7; vertical-align: top; font-size: 0.9em;}
301 305 table.cal td p.day-num {font-size: 1.1em; text-align:right;}
302 306 table.cal td.odd p.day-num {color: #bbb;}
303 307 table.cal td.today {background:#ffffdd;}
304 308 table.cal td.today p.day-num {font-weight: bold;}
305 309
306 310 /***** Tooltips ******/
307 311 .tooltip{position:relative;z-index:24;}
308 312 .tooltip:hover{z-index:25;color:#000;}
309 313 .tooltip span.tip{display: none; text-align:left;}
310 314
311 315 div.tooltip:hover span.tip{
312 316 display:block;
313 317 position:absolute;
314 318 top:12px; left:24px; width:270px;
315 319 border:1px solid #555;
316 320 background-color:#fff;
317 321 padding: 4px;
318 322 font-size: 0.8em;
319 323 color:#505050;
320 324 }
321 325
322 326 /***** Progress bar *****/
323 327 table.progress {
324 328 border: 1px solid #D7D7D7;
325 329 border-collapse: collapse;
326 330 border-spacing: 0pt;
327 331 empty-cells: show;
328 332 text-align: center;
329 333 float:left;
330 334 margin: 1px 6px 1px 0px;
331 335 }
332 336
333 337 table.progress td { height: 0.9em; }
334 338 table.progress td.closed { background: #BAE0BA none repeat scroll 0%; }
335 339 table.progress td.done { background: #DEF0DE none repeat scroll 0%; }
336 340 table.progress td.open { background: #FFF none repeat scroll 0%; }
337 341 p.pourcent {font-size: 80%;}
338 342 p.progress-info {clear: left; font-style: italic; font-size: 80%;}
339 343
340 div#status_by { float:right; width:380px; margin-left: 16px; margin-bottom: 16px; }
341
342 344 /***** Tabs *****/
343 345 #content .tabs {height: 2.6em; border-bottom: 1px solid #bbbbbb; margin-bottom:1.2em; position:relative;}
344 346 #content .tabs ul {margin:0; position:absolute; bottom:-2px; padding-left:1em;}
345 347 #content .tabs>ul { bottom:-1px; } /* others */
346 348 #content .tabs ul li {
347 349 float:left;
348 350 list-style-type:none;
349 351 white-space:nowrap;
350 352 margin-right:8px;
351 353 background:#fff;
352 354 }
353 355 #content .tabs ul li a{
354 356 display:block;
355 357 font-size: 0.9em;
356 358 text-decoration:none;
357 359 line-height:1.3em;
358 360 padding:4px 6px 4px 6px;
359 361 border: 1px solid #ccc;
360 362 border-bottom: 1px solid #bbbbbb;
361 363 background-color: #eeeeee;
362 364 color:#777;
363 365 font-weight:bold;
364 366 }
365 367
366 368 #content .tabs ul li a:hover {
367 369 background-color: #ffffdd;
368 370 text-decoration:none;
369 371 }
370 372
371 373 #content .tabs ul li a.selected {
372 374 background-color: #fff;
373 375 border: 1px solid #bbbbbb;
374 376 border-bottom: 1px solid #fff;
375 377 }
376 378
377 379 #content .tabs ul li a.selected:hover {
378 380 background-color: #fff;
379 381 }
380 382
381 383 /***** Diff *****/
382 384 .diff_out { background: #fcc; }
383 385 .diff_in { background: #cfc; }
384 386
385 387 /***** Wiki *****/
386 388 div.wiki table {
387 389 border: 1px solid #505050;
388 390 border-collapse: collapse;
389 391 }
390 392
391 393 div.wiki table, div.wiki td, div.wiki th {
392 394 border: 1px solid #bbb;
393 395 padding: 4px;
394 396 }
395 397
396 398 div.wiki .external {
397 399 background-position: 0% 60%;
398 400 background-repeat: no-repeat;
399 401 padding-left: 12px;
400 402 background-image: url(../images/external.png);
401 403 }
402 404
403 405 div.wiki a.new {
404 406 color: #b73535;
405 407 }
406 408
407 409 div.wiki pre {
408 410 margin: 1em 1em 1em 1.6em;
409 411 padding: 2px;
410 412 background-color: #fafafa;
411 413 border: 1px solid #dadada;
412 414 width:95%;
413 415 overflow-x: auto;
414 416 }
415 417
416 418 div.wiki div.toc {
417 419 background-color: #ffffdd;
418 420 border: 1px solid #e4e4e4;
419 421 padding: 4px;
420 422 line-height: 1.2em;
421 423 margin-bottom: 12px;
422 424 margin-right: 12px;
423 425 display: table
424 426 }
425 427 * html div.wiki div.toc { width: 50%; } /* IE6 doesn't autosize div */
426 428
427 429 div.wiki div.toc.right { float: right; margin-left: 12px; margin-right: 0; width: auto; }
428 430 div.wiki div.toc.left { float: left; margin-right: 12px; margin-left: 0; width: auto; }
429 431
430 432 div.wiki div.toc a {
431 433 display: block;
432 434 font-size: 0.9em;
433 435 font-weight: normal;
434 436 text-decoration: none;
435 437 color: #606060;
436 438 }
437 439 div.wiki div.toc a:hover { color: #c61a1a; text-decoration: underline;}
438 440
439 441 div.wiki div.toc a.heading2 { margin-left: 6px; }
440 442 div.wiki div.toc a.heading3 { margin-left: 12px; font-size: 0.8em; }
441 443
442 444 /***** My page layout *****/
443 445 .block-receiver {
444 446 border:1px dashed #c0c0c0;
445 447 margin-bottom: 20px;
446 448 padding: 15px 0 15px 0;
447 449 }
448 450
449 451 .mypage-box {
450 452 margin:0 0 20px 0;
451 453 color:#505050;
452 454 line-height:1.5em;
453 455 }
454 456
455 457 .handle {
456 458 cursor: move;
457 459 }
458 460
459 461 a.close-icon {
460 462 display:block;
461 463 margin-top:3px;
462 464 overflow:hidden;
463 465 width:12px;
464 466 height:12px;
465 467 background-repeat: no-repeat;
466 468 cursor:pointer;
467 469 background-image:url('../images/close.png');
468 470 }
469 471
470 472 a.close-icon:hover {
471 473 background-image:url('../images/close_hl.png');
472 474 }
473 475
474 476 /***** Gantt chart *****/
475 477 .gantt_hdr {
476 478 position:absolute;
477 479 top:0;
478 480 height:16px;
479 481 border-top: 1px solid #c0c0c0;
480 482 border-bottom: 1px solid #c0c0c0;
481 483 border-right: 1px solid #c0c0c0;
482 484 text-align: center;
483 485 overflow: hidden;
484 486 }
485 487
486 488 .task {
487 489 position: absolute;
488 490 height:8px;
489 491 font-size:0.8em;
490 492 color:#888;
491 493 padding:0;
492 494 margin:0;
493 495 line-height:0.8em;
494 496 }
495 497
496 498 .task_late { background:#f66 url(../images/task_late.png); border: 1px solid #f66; }
497 499 .task_done { background:#66f url(../images/task_done.png); border: 1px solid #66f; }
498 500 .task_todo { background:#aaa url(../images/task_todo.png); border: 1px solid #aaa; }
499 501 .milestone { background-image:url(../images/milestone.png); background-repeat: no-repeat; border: 0; }
500 502
501 503 /***** Icons *****/
502 504 .icon {
503 505 background-position: 0% 40%;
504 506 background-repeat: no-repeat;
505 507 padding-left: 20px;
506 508 padding-top: 2px;
507 509 padding-bottom: 3px;
508 510 }
509 511
510 512 .icon22 {
511 513 background-position: 0% 40%;
512 514 background-repeat: no-repeat;
513 515 padding-left: 26px;
514 516 line-height: 22px;
515 517 vertical-align: middle;
516 518 }
517 519
518 520 .icon-add { background-image: url(../images/add.png); }
519 521 .icon-edit { background-image: url(../images/edit.png); }
520 522 .icon-copy { background-image: url(../images/copy.png); }
521 523 .icon-del { background-image: url(../images/delete.png); }
522 524 .icon-move { background-image: url(../images/move.png); }
523 525 .icon-save { background-image: url(../images/save.png); }
524 526 .icon-cancel { background-image: url(../images/cancel.png); }
525 527 .icon-file { background-image: url(../images/file.png); }
526 528 .icon-folder { background-image: url(../images/folder.png); }
527 529 .open .icon-folder { background-image: url(../images/folder_open.png); }
528 530 .icon-package { background-image: url(../images/package.png); }
529 531 .icon-home { background-image: url(../images/home.png); }
530 532 .icon-user { background-image: url(../images/user.png); }
531 533 .icon-mypage { background-image: url(../images/user_page.png); }
532 534 .icon-admin { background-image: url(../images/admin.png); }
533 535 .icon-projects { background-image: url(../images/projects.png); }
534 536 .icon-logout { background-image: url(../images/logout.png); }
535 537 .icon-help { background-image: url(../images/help.png); }
536 538 .icon-attachment { background-image: url(../images/attachment.png); }
537 539 .icon-index { background-image: url(../images/index.png); }
538 540 .icon-history { background-image: url(../images/history.png); }
539 541 .icon-time { background-image: url(../images/time.png); }
540 542 .icon-stats { background-image: url(../images/stats.png); }
541 543 .icon-warning { background-image: url(../images/warning.png); }
542 544 .icon-fav { background-image: url(../images/fav.png); }
543 545 .icon-fav-off { background-image: url(../images/fav_off.png); }
544 546 .icon-reload { background-image: url(../images/reload.png); }
545 547 .icon-lock { background-image: url(../images/locked.png); }
546 548 .icon-unlock { background-image: url(../images/unlock.png); }
547 549 .icon-checked { background-image: url(../images/true.png); }
548 550 .icon-details { background-image: url(../images/zoom_in.png); }
549 551 .icon-report { background-image: url(../images/report.png); }
550 552
551 553 .icon22-projects { background-image: url(../images/22x22/projects.png); }
552 554 .icon22-users { background-image: url(../images/22x22/users.png); }
553 555 .icon22-tracker { background-image: url(../images/22x22/tracker.png); }
554 556 .icon22-role { background-image: url(../images/22x22/role.png); }
555 557 .icon22-workflow { background-image: url(../images/22x22/workflow.png); }
556 558 .icon22-options { background-image: url(../images/22x22/options.png); }
557 559 .icon22-notifications { background-image: url(../images/22x22/notifications.png); }
558 560 .icon22-authent { background-image: url(../images/22x22/authent.png); }
559 561 .icon22-info { background-image: url(../images/22x22/info.png); }
560 562 .icon22-comment { background-image: url(../images/22x22/comment.png); }
561 563 .icon22-package { background-image: url(../images/22x22/package.png); }
562 564 .icon22-settings { background-image: url(../images/22x22/settings.png); }
563 565 .icon22-plugin { background-image: url(../images/22x22/plugin.png); }
564 566
565 567 /***** Media print specific styles *****/
566 568 @media print {
567 569 #top-menu, #header, #main-menu, #sidebar, #footer, .contextual { display:none; }
568 570 #main { background: #fff; }
569 571 #content { width: 99%; margin: 0; padding: 0; border: 0; background: #fff; }
570 572 }
General Comments 0
You need to be logged in to leave comments. Login now