Project

General

Profile

Patch #756 » redmine-trunk.diff

sunday walker, 2008-03-01 03:45

View differences:

app/helpers/projects_helper.rb (working copy)
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 17

  
18 18
module ProjectsHelper
19
  include IssuesHelper
19 20
  def link_to_version(version, options = {})
20 21
    return '' unless version && version.is_a?(Version)
21 22
    link_to version.name, {:controller => 'projects',
......
152 153
    gc.stroke('transparent')
153 154
    events.each do |i|      
154 155
      if i.is_a?(Issue)       
155
        i_start_date = (i.start_date >= date_from ? i.start_date : date_from )
156
        i_end_date = (i.due_date <= date_to ? i.due_date : date_to )        
157
        i_done_date = i.start_date + ((i.due_date - i.start_date+1)*i.done_ratio/100).floor
156
        i_start_date = (i.total('start_date') >= date_from ? i.total('start_date') : date_from )
157
        i_end_date = (i.total('due_date') <= date_to ? i.total('due_date') : date_to )        
158
        i_done_date = i.total('start_date') + i.total('actual_days')
158 159
        i_done_date = (i_done_date <= date_from ? date_from : i_done_date )
159 160
        i_done_date = (i_done_date >= date_to ? date_to : i_done_date )        
160 161
        i_late_date = [i_end_date, Date.today].min if i_start_date < Date.today
......
171 172
        gc.fill('blue')
172 173
        gc.rectangle(i_left, top, i_left + d_width, top - 6) if d_width > 0
173 174
        gc.fill('black')
174
        gc.text(i_left + i_width + 5,top + 1, "#{i.status.name} #{i.done_ratio}%")
175
        gc.text(i_left + i_width + 5,top + 1, "#{i.total('status').name} #{i.total('done_ratio')}%")
175 176
      else
176 177
        i_left = subject_width + ((i.start_date - date_from)*zoom).floor
177 178
        gc.fill('green')
app/helpers/issues_helper.rb (working copy)
27 27
    @cached_label_priority ||= l(:field_priority)
28 28
    
29 29
    link_to_issue(issue) + ": #{h(issue.subject)}<br /><br />" +
30
      "<strong>#{@cached_label_start_date}</strong>: #{format_date(issue.start_date)}<br />" +
31
      "<strong>#{@cached_label_due_date}</strong>: #{format_date(issue.due_date)}<br />" +
30
      "<strong>#{@cached_label_start_date}</strong>: #{format_date(issue.total('start_date'))}<br />" +
31
      "<strong>#{@cached_label_due_date}</strong>: #{format_date(issue.total('due_date'))}<br />" +
32 32
      "<strong>#{@cached_label_assigned_to}</strong>: #{issue.assigned_to}<br />" +
33
      "<strong>#{@cached_label_priority}</strong>: #{issue.priority.name}"
33
      "<strong>#{@cached_label_priority}</strong>: #{issue.total('priority').name}"
34 34
  end
35 35

  
36 36
  def show_detail(detail, no_html=false)
......
104 104
      end
105 105
    end
106 106
  end
107
    
108
  def  linklist_add_child(elements, no_my, no_child)
109
    if elements[no_my]["child"] == -1 #edge
110
      elements[no_my]["child"] = no_child
111
      
112
      elements[no_child]["parent"] = no_my
113
      my_previous = elements[no_my]["previous"]
114
      my_next = elements[no_my]["next"]
115
      child_previous = elements[no_child]["previous"]
116
      child_next = elements[no_child]["next"]
117
      elements[no_my]["previous"] = child_previous
118
      elements[no_my]["next"] = child_next
119
      elements[child_previous]["next"] = no_my if child_previous != -1
120
      elements[child_next]["previous"] = no_my if child_next != -1
121
      elements[my_previous]["next"] = my_next if my_previous != -1
122
      elements[my_next]["previous"] = my_previous if my_next != -1
123
      elements[no_child]["previous"] = -1
124
      elements[no_child]["next"] = -1
125
    else
126
      no_element = elements[no_my]["child"]
127
      while elements[no_element]["next"] != -1 #until last
128
        no_element = elements[no_element]["next"]
129
      end
130
      elements[no_element]["next"] = no_child
131
      
132
      elements[no_child]["parent"] = no_my
133
      child_previous = elements[no_child]["previous"]
134
      child_next = elements[no_child]["next"]
135
      elements[child_previous]["next"] = child_next if child_previous != -1
136
      elements[child_next]["previous"] = child_previous if child_next != -1
137
      elements[no_child]["previous"] = no_element
138
      elements[no_child]["next"] = -1
139
    end
140
      
141
    elements
142
  end
143
   
144
  def make_outline(elements, outline_level, no_my)
145
    no_next = no_my
146
    while no_next != -1
147
      elements[0]["no"] += 1
148
      elements[no_next]["no"] = elements[0]["no"]
149
      elements[no_next]["issue"].outline_level(outline_level)
150
      if elements[no_next]["child"] != -1
151
        elements = make_outline(elements, outline_level+1, elements[no_next]["child"])
152
      end
153
      no_next = elements[no_next]["next"]
154
    end
155
    elements
156
  end
107 157
  
158
  def issues_to_outlines(issues)
159
    no_used = 0
160
    outlines = []
161
    outlines << {"no"=>0,"previous"=>-1,"next"=>-1,"parent"=>-1,"child"=>-1}
162
    # add edges
163
    issues.each do |issue|
164
      unless issue.childs && issue.childs.size > 0
165
        outlines[no_used]["next"] = no_used + 1
166
        outlines << {"no"=>0,"previous"=>no_used,"next"=>-1,"parent"=>-1,"child"=>-1,"issue"=>issue}
167
        no_used += 1
168
      end
169
    end
170
    # add non edges
171
    issues.each do |issue|
172
      if issue.childs && issue.childs.size > 0
173
        outlines[no_used]["next"] = no_used + 1
174
        outlines << {"no"=>0,"previous"=>no_used,"next"=>-1,"parent"=>-1,"child"=>-1,"issue"=>issue}
175
        no_used += 1
176
      end
177
    end
178
    # link family
179
    1.upto(outlines.size-1) do |i|
180
      (i+1).upto(outlines.size-1) do |j|
181
        if outlines[i]["issue"].parents && (outlines[i]["issue"].parents.size > 0) && (outlines[i]["issue"].parents[0].id == outlines[j]["issue"].id)
182
          outlines = linklist_add_child(outlines, j, i)
183
        elsif  outlines[j]["issue"].parents && (outlines[j]["issue"].parents.size > 0) && (outlines[j]["issue"].parents[0].id == outlines[i]["issue"].id)
184
          outlines = linklist_add_child(outlines, i, j)
185
        end
186
      end
187
    end
188
    # make outline
189
    outlines2 = make_outline(outlines, 1, outlines[0]["next"])
190
    # sort
191
    outlines2.shift
192
    issues = []
193
    1.upto(outlines2.size) do |no|
194
      outlines2.each do |outline|
195
        if outline["no"] == no
196
          issues << outline["issue"]
197
          break
198
        end
199
      end
200
    end
201
    0.upto(issues.size-1) do |no|
202
      if (no >= issues.size-1) || (issues[no].outline_level >= issues[no+1].outline_level)
203
        issues[no].edge(1)
204
      end
205
    end
206
    issues
207
  end
208
  
209
  
108 210
  def issues_to_csv(issues, project = nil)
109 211
    ic = Iconv.new(l(:general_csv_encoding), 'UTF-8')    
110 212
    export = StringIO.new
......
115 217
                  l(:field_project),
116 218
                  l(:field_tracker),
117 219
                  l(:field_priority),
220
                  l(:field_outline),
118 221
                  l(:field_subject),
119 222
                  l(:field_assigned_to),
120 223
                  l(:field_category),
......
132 235
      custom_fields = project.nil? ? IssueCustomField.for_all : project.all_custom_fields
133 236
      custom_fields.each {|f| headers << f.name}
134 237
      csv << headers.collect {|c| begin; ic.iconv(c.to_s); rescue; c.to_s; end }
238
      issues = issues_to_outlines(issues)
135 239
      # csv lines
136 240
      issues.each do |issue|
137 241
        fields = [issue.id,
138
                  issue.status.name, 
242
                  issue.total('status').name, 
139 243
                  issue.project.name,
140 244
                  issue.tracker.name, 
141
                  issue.priority.name,
245
                  issue.total('priority').name,
246
                  issue.outline_level,
142 247
                  issue.subject,
143 248
                  issue.assigned_to,
144 249
                  issue.category,
145 250
                  issue.fixed_version,
146 251
                  issue.author.name,
147
                  format_date(issue.start_date),
148
                  format_date(issue.due_date),
149
                  issue.done_ratio,
252
                  format_date(issue.total('start_date')),
253
                  format_date(issue.total('due_date')),
254
                  issue.total('done_ratio'),
150 255
                  issue.estimated_hours,
151 256
                  format_time(issue.created_on),  
152 257
                  format_time(issue.updated_on)
app/helpers/queries_helper.rb (working copy)
32 32
      cv = issue.custom_values.detect {|v| v.custom_field_id == column.custom_field.id}
33 33
      show_value(cv)
34 34
    else
35
      value = issue.send(column.name)
35
#      value = issue.send(column.name)
36
      value = issue.total(column.name)
36 37
      if value.is_a?(Date)
37 38
        format_date(value)
38 39
      elsif value.is_a?(Time)
app/models/issue.rb (working copy)
223 223
  def duplicates
224 224
    relations.select {|r| r.relation_type == IssueRelation::TYPE_DUPLICATES}.collect {|r| r.other_issue(self)}
225 225
  end
226

  
227
  def duration1
228
    (start_date && due_date) ? (due_date - start_date + 1) : 0
229
  end
226 230
  
227 231
  def duration
228 232
    (start_date && due_date) ? due_date - start_date : 0
......
231 235
  def soonest_start
232 236
    @soonest_start ||= relations_to.collect{|relation| relation.successor_soonest_start}.compact.min
233 237
  end
234
  
238
 
235 239
  def self.visible_by(usr)
236 240
    with_scope(:find => { :conditions => Project.visible_by(usr) }) do
237 241
      yield
238 242
    end
239 243
  end
244
  
245
  def total(filed)
246
    filed = filed.to_s
247
    if filed == 'done_ratio' || filed == 'planned_days' || filed == 'actual_days'
248
      @total_planned_days ||= self.duration1
249
      @total_actual_days ||= done_ratio ?  (@total_planned_days * done_ratio / 100).floor : 0
250
      @total_done_ratio ||= done_ratio
251
    else
252
      eval("@total_#{filed} ||= #{filed}")
253
    end
254
    if filed == 'estimated_hours' || filed == 'spent_hours'
255
      type = 'sum'
256
    elsif filed == 'start_date'
257
      type = 'min'
258
    elsif filed == 'due_date'
259
      type = 'max'
260
    elsif filed == 'priority' || filed == 'fixed_version'
261
      type = 'max_id'
262
    elsif filed == 'status'
263
      type = 'min_id'
264
    elsif filed == 'done_ratio' || filed == 'planned_days' || filed == 'actual_days'
265
      type = 'done_ratio'
266
    else
267
      return(eval("@total_#{filed}"))
268
    end
269
    if !eval("@total_#{filed}") || (eval("@total_#{filed}") == 0) || (type == 'max_id') || (type == 'min_id')
270
      relations_to.each do |relation|
271
        if relation.relation_type == IssueRelation::TYPE_PARENTS
272
          othertotal = relation.other_issue(self).total(filed)
273
          if ! eval("@total_#{filed}")
274
            eval("@total_#{filed} = othertotal")
275
          elsif type == 'done_ratio' || type == 'planned_days' || type == 'actual_days'
276
            planned_days = relation.other_issue(self).total('duration1')
277
            actual_days = relation.other_issue(self).total('done_ratio') ?  (planned_days * relation.other_issue(self).total('done_ratio') / 100).floor : 0
278
            @total_planned_days += planned_days
279
            @total_actual_days += actual_days
280
            @total_done_ratio = @total_planned_days != 0 ? (@total_actual_days * 100 / @total_planned_days).floor : 0
281
          elsif type == 'max_id'
282
            if othertotal && eval("@total_#{filed}.id") < othertotal.id
283
              eval("@total_#{filed} = othertotal")
284
            end
285
          elsif type == 'min_id'
286
            if othertotal && eval("@total_#{filed}.id") > othertotal.id
287
              eval("@total_#{filed} = othertotal")
288
            end
289
          elsif type == 'sum'
290
            if othertotal
291
              eval("@total_#{filed} += othertotal")
292
            end
293
          elsif type == 'max'
294
            if othertotal && eval("@total_#{filed}") < othertotal
295
              eval("@total_#{filed} = othertotal")
296
            end
297
          elsif type == 'min'
298
            if othertotal && eval("@total_#{filed}") > othertotal
299
              eval("@total_#{filed} = othertotal")
300
            end
301
          end
302
        end
303
      end
304
    end
305
    eval("@total_#{filed}")
306
  end
307
  
308
  def childs
309
    childs = []
310
    relations_to.each do |relation|
311
      if relation.relation_type == IssueRelation::TYPE_PARENTS
312
        childs << relation.other_issue(self)
313
      end
314
    end
315
    childs
316
  end
317
  
318
  def parents
319
    parents = []
320
    relations_from.each do |relation|
321
      if relation.relation_type == IssueRelation::TYPE_PARENTS
322
        parents << relation.other_issue(self)
323
      end
324
    end
325
    parents
326
  end
327
  
328
  def outline_level(outline_level=0)
329
    
330
    @outline_level = outline_level if outline_level != 0
331
    @outline_level ? @outline_level : 1
332
  end
333
  
334
  def edge(edge=false)
335
    @edge = edge if edge
336
    @edge ? @edge : false
337
  end
240 338
end
app/models/issue_relation.rb (working copy)
23 23
  TYPE_DUPLICATES   = "duplicates"
24 24
  TYPE_BLOCKS       = "blocks"
25 25
  TYPE_PRECEDES     = "precedes"
26
  TYPE_PARENTS     = "parents"
26 27
  
27 28
  TYPES = { TYPE_RELATES =>     { :name => :label_relates_to, :sym_name => :label_relates_to, :order => 1 },
28 29
            TYPE_DUPLICATES =>  { :name => :label_duplicates, :sym_name => :label_duplicates, :order => 2 },
29 30
            TYPE_BLOCKS =>      { :name => :label_blocks, :sym_name => :label_blocked_by, :order => 3 },
30 31
            TYPE_PRECEDES =>    { :name => :label_precedes, :sym_name => :label_follows, :order => 4 },
32
            TYPE_PARENTS =>    { :name => :label_parents, :sym_name => :label_children, :order => 5 },
31 33
          }.freeze
32 34
  
33 35
  validates_presence_of :issue_from, :issue_to, :relation_type
app/controllers/projects_controller.rb (working copy)
368 368
    end
369 369
    @events += @project.versions.find(:all, :conditions => ["effective_date BETWEEN ? AND ?", @date_from, @date_to])
370 370
    @events.sort! {|x,y| x.start_date <=> y.start_date }
371

  
372
    parent_ids = []
373
    my_ids = []
374
    @events.each do |i|
375
      my_ids << i.id
376
      while i.parents && (i.parents.size > 0)
377
        @selected_tracker_ids.each do |tracker_id|
378
          parent_ids |= [i.parents[0].id] if tracker_id.to_i == i.parents[0].tracker_id
379
        end
380
        i = i.parents[0]
381
      end
382
    end
383
    parent_ids.sort
384
    my_ids.sort
385
    parent_ids = parent_ids - my_ids
386
    @events += Issue.find(:all, :include => [:tracker, :status, :assigned_to, :priority, :project], :conditions => ["#{Issue.table_name}.id in (#{parent_ids.join(',')}) and #{Issue.table_name}.tracker_id in (#{@selected_tracker_ids.join(',')})"])  unless @selected_tracker_ids.empty? || parent_ids.empty?
387
    @events = issues_to_outlines(@events)
371 388
    
372 389
    if params[:format]=='pdf'
373 390
      @options_for_rfpdf ||= {}
app/views/projects/gantt.rhtml (working copy)
70 70
@events.each do |i| %>
71 71
    <div style="position: absolute;line-height:1.2em;height:16px;top:<%= top %>px;left:4px;overflow:hidden;"><small>    
72 72
    <% if i.is_a? Issue %>
73
        <% indent = "" %>
74
        <% (2).upto(i.outline_level) do |j| %>
75
            <% indent += image_tag('white.png') %>
76
 	      <% end %>  	
77
        <% indent += (i.edge ? image_tag('white.png'):image_tag('expanded.png')) %>
78
        <%= indent %>
73 79
      	<%= h("#{i.project.name} -") unless @project && @project == i.project %>
74 80
      	<%= link_to_issue i %>:	<%=h i.subject %>
75 81
  	<% else %>
......
126 132
		width = (week_f + 6 <= @date_to) ? 7 * zoom -1 : (@date_to - week_f + 1) * zoom-1
127 133
		%>
128 134
		<div style="left:<%= left %>px;top:19px;width:<%= width %>px;height:<%= height %>px;" class="gantt_hdr">
129
		<small><%= week_f.cweek if width >= 16 %></small>
130
		</div>
135
  	<small><% week_f.cweek if width >= 16 %><%= week_f.day if width >= 16 %></small>
136
 		</div>
131 137
		<% 
132 138
		left = left + width+1
133 139
		week_f = week_f+7
......
162 168
top = headers_height + 10
163 169
@events.each do |i| 
164 170
  if i.is_a? Issue 
165
	i_start_date = (i.start_date >= @date_from ? i.start_date : @date_from )
166
	i_end_date = (i.due_date <= @date_to ? i.due_date : @date_to )
171
	i_start_date = (i.total('start_date') >= @date_from ? i.total('start_date') : @date_from )
172
	i_end_date = (i.total('due_date') <= @date_to ? i.total('due_date') : @date_to )
167 173
	
168
	i_done_date = i.start_date + ((i.due_date - i.start_date+1)*i.done_ratio/100).floor
174
	i_done_date = i.total('start_date') + i.total('actual_days')
169 175
	i_done_date = (i_done_date <= @date_from ? @date_from : i_done_date )
170 176
	i_done_date = (i_done_date >= @date_to ? @date_to : i_done_date )
171 177
	
......
184 190
	    <div style="top:<%= top %>px;left:<%= i_left %>px;width:<%= d_width %>px;" class="task task_done">&nbsp;</div>
185 191
	<% end %>
186 192
	<div style="top:<%= top %>px;left:<%= i_left + i_width + 5 %>px;background:#fff;" class="task">
187
	<%= i.status.name %>
188
	<%= (i.done_ratio).to_i %>%
193
	<%= i.total('status').name %>
194
	<%= (i.total('done_ratio')).to_i %>%
189 195
	</div>
190 196
	<% # === tooltip === %>
191 197
	<div class="tooltip" style="position: absolute;top:<%= top %>px;left:<%= i_left %>px;width:<%= i_width %>px;height:12px;">
......
193 199
    <%= render_issue_tooltip i %>
194 200
	</span></div>
195 201
<% else 
196
    i_left = ((i.start_date - @date_from)*zoom).floor
202
    i_left = ((i.total('start_date') - @date_from)*zoom).floor
197 203
    %>
198 204
    <div style="top:<%= top %>px;left:<%= i_left %>px;width:15px;" class="task milestone">&nbsp;</div>
199 205
	<div style="top:<%= top %>px;left:<%= i_left + 12 %>px;background:#fff;" class="task">
app/views/projects/gantt.rfpdf (working copy)
4 4
pdf.AliasNbPages
5 5
pdf.footer_date = format_date(Date.today)
6 6
pdf.AddPage("L")
7
pdf.SetFontStyle('B',12)
8
pdf.SetX(15)
9
pdf.Cell(70, 20, @project.name)
10
pdf.Ln
11
pdf.SetFontStyle('B',9)
12 7

  
13 8
subject_width = 70
14 9
header_heigth = 5
......
31 26
g_height = 120
32 27
t_height = g_height + headers_heigth
33 28

  
29
top = 20
30
@events.each do |i|
31

  
32
if (top == 20)
33
pdf.SetFontStyle('B',12)
34
pdf.SetX(15)
35
pdf.Cell(70, 20, @project.name)
36
pdf.Ln
37
pdf.SetFontStyle('B',9)
38

  
34 39
y_start = pdf.GetY
35 40

  
36

  
37 41
#
38 42
# Months headers
39 43
#
......
71 75
		width = (week_f + 6 <= @date_to) ? 7 * zoom : (@date_to - week_f + 1) * zoom
72 76
		pdf.SetY(y_start + header_heigth)
73 77
		pdf.SetX(left)
74
		pdf.Cell(width, height, (width >= 5 ? week_f.cweek.to_s : ""), "LTR", 0, "C")
78
#		pdf.Cell(width, height, (width >= 5 ? week_f.cweek.to_s : ""), "LTR", 0, "C")
79
		pdf.Cell(width, height, (width >= 5 ? week_f.day.to_s : ""), "LTR", 0, "C")
75 80
		left = left + width
76 81
		week_f = week_f+7
77 82
	end
......
100 105
pdf.SetX(15)
101 106
pdf.Cell(subject_width+g_width-15, headers_heigth, "", 1)
102 107

  
108
top = headers_heigth + y_start
109
end
103 110

  
104 111
#
105 112
# Tasks
106 113
#
107
top = headers_heigth + y_start
108 114
pdf.SetFontStyle('B',7)
109
@events.each do |i|
110 115
	pdf.SetY(top)
111 116
	pdf.SetX(15)
112 117
	
113 118
	if i.is_a? Issue
114
		pdf.Cell(subject_width-15, 5, "#{i.tracker.name} #{i.id}: #{i.subject}".sub(/^(.{30}[^\s]*\s).*$/, '\1 (...)'), "LR")
119
    pdf.Image('public/images/expanded.png', pdf.GetX+3*(i.outline_level-1)+0.5, pdf.GetY+1, 3, 3) unless i.edge
120
    pdf.Cell(3*i.outline_level+1,5,'',0)
121
		pdf.Cell(subject_width-15-(3*i.outline_level+1), 5, "#{i.tracker.name} #{i.id}: #{i.subject}".sub(/^(.{30}[^\s]*\s).*$/, '\1 (...)'), 0)
122
    pdf.SetX(15)
123
		pdf.Cell(subject_width-15, 5, '', "LR")
115 124
	else
116 125
		pdf.Cell(subject_width-15, 5, "#{l(:label_version)}: #{i.name}", "LR")
117 126
	end
......
123 132
	pdf.SetY(top+1.5)
124 133
	
125 134
	if i.is_a? Issue
126
		i_start_date = (i.start_date >= @date_from ? i.start_date : @date_from )
127
		i_end_date = (i.due_date <= @date_to ? i.due_date : @date_to )
135
		i_start_date = (i.total('start_date') >= @date_from ? i.total('start_date') : @date_from )
136
		i_end_date = (i.total('due_date') <= @date_to ? i.total('due_date') : @date_to )
128 137
		
129
		i_done_date = i.start_date + ((i.due_date - i.start_date+1)*i.done_ratio/100).floor
138
		i_done_date = i.total('start_date') + i.total('actual_days')
130 139
		i_done_date = (i_done_date <= @date_from ? @date_from : i_done_date )
131 140
		i_done_date = (i_done_date >= @date_to ? @date_to : i_done_date )
132 141
		
......
157 166
		
158 167
		pdf.SetY(top+1.5)
159 168
		pdf.SetX(subject_width + i_left + i_width)
160
		pdf.Cell(30, 2, "#{i.status.name} #{i.done_ratio}%")
169
		pdf.Cell(30, 2, "#{i.total('status').name} #{i.total('done_ratio')}%")
161 170
	else
162
		i_left = ((i.start_date - @date_from)*zoom) 
171
		i_left = ((i.total('start_date') - @date_from)*zoom) 
163 172
		
164 173
		pdf.SetX(subject_width + i_left)
165 174
		pdf.SetFillColor(50,200,50)
......
175 184
	pdf.SetDrawColor(200, 200, 200)
176 185
	pdf.Line(15, top, subject_width+g_width, top)
177 186
	if pdf.GetY() > 180
187
  	pdf.SetDrawColor(0, 0, 0)
188
		pdf.Line(15, top, subject_width+g_width, top)
178 189
		pdf.AddPage("L")
179 190
		top = 20
180
		pdf.Line(15, top, subject_width+g_width, top)
181 191
	end
182 192
	pdf.SetDrawColor(0, 0, 0)
183 193
end
app/views/issues/_relations.rhtml (working copy)
12 12
<tr>
13 13
<td><%= l(relation.label_for(@issue)) %> <%= "(#{lwr(:actionview_datehelper_time_in_words_day, relation.delay)})" if relation.delay && relation.delay != 0 %> <%= link_to_issue relation.other_issue(@issue) %></td>
14 14
<td><%=h relation.other_issue(@issue).subject %></td>
15
<td><%= relation.other_issue(@issue).status.name %></td>
16
<td><%= format_date(relation.other_issue(@issue).start_date) %></td>
17
<td><%= format_date(relation.other_issue(@issue).due_date) %></td>
15
<td><%= relation.other_issue(@issue).total('status').name %></td>
16
<td><%= format_date(relation.other_issue(@issue).total('start_date')) %></td>
17
<td><%= format_date(relation.other_issue(@issue).total('due_date')) %></td>
18 18
<td><%= link_to_remote(image_tag('delete.png'), { :url => {:controller => 'issue_relations', :action => 'destroy', :issue_id => @issue, :id => relation},                                              
19 19
                                                  :method => :post
20 20
                                                }, :title => l(:label_relation_delete)) if authorize_for('issue_relations', 'destroy') %></td>
app/views/issues/show.rhtml (working copy)
18 18

  
19 19
<table width="100%">
20 20
<tr>
21
    <td style="width:15%"><b><%=l(:field_status)%> :</b></td><td style="width:35%"><%= @issue.status.name %></td>
22
    <td style="width:15%"><b><%=l(:field_start_date)%> :</b></td><td style="width:35%"><%= format_date(@issue.start_date) %></td>
21
    <td style="width:15%"><b><%=l(:field_status)%> :</b></td><td style="width:35%"><%= @issue.total('status').name %></td>
22
    <td style="width:15%"><b><%=l(:field_start_date)%> :</b></td><td style="width:35%"><%= format_date(@issue.total('start_date')) %></td>
23 23
</tr>
24 24
<tr>
25
    <td><b><%=l(:field_priority)%> :</b></td><td><%= @issue.priority.name %></td>
26
    <td><b><%=l(:field_due_date)%> :</b></td><td><%= format_date(@issue.due_date) %></td>
25
    <td><b><%=l(:field_priority)%> :</b></td><td><%= @issue.total('priority').name %></td>
26
    <td><b><%=l(:field_due_date)%> :</b></td><td><%= format_date(@issue.total('due_date')) %></td>
27 27
</tr>
28 28
<tr>
29 29
    <td><b><%=l(:field_assigned_to)%> :</b></td><td><%= @issue.assigned_to ? link_to_user(@issue.assigned_to) : "-" %></td>
30
    <td><b><%=l(:field_done_ratio)%> :</b></td><td><%= progress_bar @issue.done_ratio, :width => '80px', :legend => "#{@issue.done_ratio}%" %></td>
30
    <td><b><%=l(:field_done_ratio)%> :</b></td><td><%= progress_bar @issue.total('done_ratio'), :width => '80px', :legend => "#{@issue.total('done_ratio')}%" %></td>
31 31
</tr>
32 32
<tr>
33 33
    <td><b><%=l(:field_category)%> :</b></td><td><%=h @issue.category ? @issue.category.name : "-" %></td>
34 34
    <% if User.current.allowed_to?(:view_time_entries, @project) %>
35 35
    <td><b><%=l(:label_spent_time)%> :</b></td>
36
    <td><%= @issue.spent_hours > 0 ? (link_to lwr(:label_f_hour, @issue.spent_hours), {:controller => 'timelog', :action => 'details', :issue_id => @issue}, :class => 'icon icon-time') : "-" %></td>
36
    <td><%= @issue.total('spent_hours') > 0 ? (link_to lwr(:label_f_hour, @issue.total('spent_hours')), {:controller => 'timelog', :action => 'details', :issue_id => @issue}, :class => 'icon icon-time') : "-" %></td>
37 37
    <% end %>
38 38
</tr>
39 39
<tr>
40 40
    <td><b><%=l(:field_fixed_version)%> :</b></td><td><%= @issue.fixed_version ? link_to_version(@issue.fixed_version) : "-" %></td>
41
    <% if @issue.estimated_hours %>
42
    <td><b><%=l(:field_estimated_hours)%> :</b></td><td><%= lwr(:label_f_hour, @issue.estimated_hours) %></td>
41
    <% if @issue.total('estimated_hours') %>
42
    <td><b><%=l(:field_estimated_hours)%> :</b></td><td><%= lwr(:label_f_hour, @issue.total('estimated_hours')) %></td>
43 43
    <% end %>
44 44
</tr>
45 45
<tr>
app/views/issues/index.rfpdf (working copy)
5 5
	pdf.footer_date = format_date(Date.today)
6 6
	pdf.AddPage("L")
7 7
	row_height = 7
8
	
9
	#
8

  
9
  @issues = issues_to_outlines(@issues)
10

  
11
  @issues.each do |issue|		
12

  
13
	if pdf.GetY() < 20
14
  #
10 15
	# title
11 16
	#
12 17
	pdf.SetFontStyle('B',11)   	
......
18 23
	#	
19 24
	pdf.SetFontStyle('B',10)
20 25
	pdf.SetFillColor(230, 230, 230)
21
   	pdf.Cell(15, row_height, "#", 0, 0, 'L', 1)
26
   	pdf.Cell(15, row_height, "#", 0, 0, 'R', 1)
22 27
   	pdf.Cell(30, row_height, l(:field_tracker), 0, 0, 'L', 1)
23 28
   	pdf.Cell(30, row_height, l(:field_status), 0, 0, 'L', 1)
24 29
   	pdf.Cell(30, row_height, l(:field_priority), 0, 0, 'L', 1)
......
29 34
   	pdf.Ln
30 35
   	pdf.Line(10, pdf.GetY, 287, pdf.GetY)
31 36
   	pdf.SetY(pdf.GetY() + 1)
37
  end
32 38
	
33 39
	#
34 40
	# rows
35 41
	#
36 42
	pdf.SetFontStyle('',9)
37 43
	pdf.SetFillColor(255, 255, 255)
38
	@issues.each do |issue|		
39
	   	pdf.Cell(15, row_height, issue.id.to_s, 0, 0, 'L', 1)
44
	   	pdf.Cell(15, row_height, issue.id.to_s, 0, 0, 'R', 1)
40 45
	   	pdf.Cell(30, row_height, issue.tracker.name, 0, 0, 'L', 1)
41
	   	pdf.Cell(30, row_height, issue.status.name, 0, 0, 'L', 1)
42
	   	pdf.Cell(30, row_height, issue.priority.name, 0, 0, 'L', 1)
46
	   	pdf.Cell(30, row_height, issue.total('status').name, 0, 0, 'L', 1)
47
	   	pdf.Cell(30, row_height, issue.total('priority').name, 0, 0, 'L', 1)
43 48
	   	pdf.Cell(40, row_height, issue.assigned_to ? issue.assigned_to.name : '', 0, 0, 'L', 1)
44 49
	   	pdf.Cell(25, row_height, format_date(issue.updated_on), 0, 0, 'L', 1)
50
      pdf.Image('public/images/expanded.png', pdf.GetX+3*(issue.outline_level-1)+0.5, pdf.GetY+2, 3, 3) unless issue.edge
51
      pdf.Cell(3*issue.outline_level+1,row_height,'',0)
45 52
	   	pdf.MultiCell(0, row_height, (@project == issue.project ? issue.subject : "#{issue.project.name} - #{issue.subject}"))
46 53
   		pdf.Line(10, pdf.GetY, 287, pdf.GetY)
47 54
   		pdf.SetY(pdf.GetY() + 1)
55
      
56
	if pdf.GetY() > 180
57
		pdf.AddPage("L")
48 58
	end
59
	end
49 60
%>
50 61
<%= pdf.Output %>
app/views/issues/_pdf.rfpdf (working copy)
7 7
    pdf.SetFontStyle('B',9)
8 8
    pdf.Cell(35,5, l(:field_status) + ":","LT")
9 9
    pdf.SetFontStyle('',9)
10
    pdf.Cell(60,5, issue.status.name,"RT")
10
    pdf.Cell(60,5, issue.total('status').name,"RT")
11 11
    pdf.SetFontStyle('B',9)
12 12
    pdf.Cell(35,5, l(:field_priority) + ":","LT")
13 13
    pdf.SetFontStyle('',9)
14
    pdf.Cell(60,5, issue.priority.name,"RT")        
14
    pdf.Cell(60,5, issue.total('priority').name,"RT")        
15 15
    pdf.Ln
16 16
    
17 17
    pdf.SetFontStyle('B',9)
......
41 41
    pdf.SetFontStyle('B',9)
42 42
    pdf.Cell(35,5, l(:field_due_date) + ":","LB")
43 43
    pdf.SetFontStyle('',9)
44
    pdf.Cell(60,5, format_date(issue.due_date),"RB")
44
    pdf.Cell(60,5, format_date(issue.total('due_date')),"RB")
45 45
    pdf.Ln
46 46
    
47 47
	for custom_value in issue.custom_values
lang/uk.yml (working copy)
122 122
field_due_date: Дата виконання
123 123
field_assigned_to: Призначена до
124 124
field_priority: Пріоритет
125
field_outline: Outline
125 126
field_fixed_version: Фіксована версія
126 127
field_user: Користувач
127 128
field_role: Роль
......
411 412
label_blocked_by: заблоковане 
412 413
label_precedes: передує
413 414
label_follows: наступний за
415
label_parents: parents
416
label_children: children
414 417
label_end_to_start: з кінця до початку
415 418
label_end_to_end: з кінця до кінця
416 419
label_start_to_start: з початку до початку
lang/lt.yml (working copy)
125 125
field_due_date: Užbaigimo data 
126 126
field_assigned_to: Paskirtas 
127 127
field_priority: Prioritetas 
128
field_outline: Outline
128 129
field_fixed_version: Pastovi versija
129 130
field_user: Vartotojas 
130 131
field_role: Vaidmuo 
......
414 415
label_blocked_by: blokuotas 
415 416
label_precedes: įvyksta pirma 
416 417
label_follows: seka 
418
label_parents: parents
419
label_children: children
417 420
label_end_to_start: užbaigti, kad pradėti
418 421
label_end_to_end: užbaigti, kad pabaigti 
419 422
label_start_to_start: pradėkite pradėti 
lang/ro.yml (working copy)
117 117
field_due_date: Data finalizarii 
118 118
field_assigned_to: Atribuit pentru
119 119
field_priority: Prioritate
120
field_outline: Outline
120 121
field_fixed_version: Versiune rezolvata 
121 122
field_user: Utilizator
122 123
field_role: Rol
......
393 394
label_blocked_by: blocat de
394 395
label_precedes: precedes
395 396
label_follows: follows
397
label_parents: parents
398
label_children: children
396 399
label_end_to_start: de la sfarsit la capat
397 400
label_end_to_end: de la sfarsit la sfarsit
398 401
label_start_to_start: de la capat la capat
lang/zh.yml (working copy)
120 120
field_due_date: 到期日
121 121
field_assigned_to: 指派
122 122
field_priority: 优先级
123
field_outline: Outline
123 124
field_fixed_version: 修订版本
124 125
field_user: 用户
125 126
field_role: 角色
......
397 398
label_blocked_by: blocked by
398 399
label_precedes: precedes
399 400
label_follows: follows
401
label_parents: parents
402
label_children: children
400 403
label_end_to_start: end to start
401 404
label_end_to_end: end to end
402 405
label_start_to_start: start to start
lang/pt.yml (working copy)
117 117
field_due_date: Data final
118 118
field_assigned_to: Atribuído para
119 119
field_priority: Prioridade
120
field_outline: Outline
120 121
field_fixed_version: Versão corrigida
121 122
field_user: Usuário
122 123
field_role: Regra
......
395 396
label_blocked_by: bloqueado por
396 397
label_precedes: procede
397 398
label_follows: segue
399
label_parents: parents
400
label_children: children
398 401
label_end_to_start: fim ao início
399 402
label_end_to_end: fim ao fim
400 403
label_start_to_start: ínícia ao inícia
lang/sr.yml (working copy)
121 121
field_due_date: Do datuma
122 122
field_assigned_to: Dodeljeno
123 123
field_priority: Prioritet
124
field_outline: Outline
124 125
field_fixed_version: Ispravljena verzija
125 126
field_user: Korisnik
126 127
field_role: Uloga
......
405 406
label_blocked_by: blokiran od strane
406 407
label_precedes: prethodi
407 408
label_follows: sledi
409
label_parents: parents
410
label_children: children
408 411
label_end_to_start: od kraja do početka
409 412
label_end_to_end: od kraja do kraja
410 413
label_start_to_start: od početka do pocetka
lang/pt-br.yml (working copy)
117 117
field_due_date: Data devida
118 118
field_assigned_to: Atribuido para
119 119
field_priority: Prioridade
120
field_outline: Outline
120 121
field_fixed_version: Versao corrigida
121 122
field_user: Usuario
122 123
field_role: Regra
......
395 396
label_blocked_by: blocked by
396 397
label_precedes: precedes
397 398
label_follows: follows
399
label_parents: parents
400
label_children: children
398 401
label_end_to_start: end to start
399 402
label_end_to_end: end to end
400 403
label_start_to_start: start to start
lang/ru.yml (working copy)
127 127
field_due_date: Дата выполнения
128 128
field_assigned_to: Назначена
129 129
field_priority: Приоритет
130
field_outline: Outline
130 131
field_fixed_version: Фиксированная версия
131 132
field_user: Пользователь
132 133
field_role: Роль
......
418 419
label_blocked_by: заблокировано 
419 420
label_precedes: предшествует
420 421
label_follows: следующий
422
label_parents: parents
423
label_children: children
421 424
label_end_to_start: с конца к началу
422 425
label_end_to_end: с конца к концу
423 426
label_start_to_start: с начала к началу
lang/sv.yml (working copy)
117 117
field_due_date: Färdigdatum
118 118
field_assigned_to: Tilldelad
119 119
field_priority: Prioritet
120
field_outline: Outline
120 121
field_fixed_version: Fixed version
121 122
field_user: Användare
122 123
field_role: Roll
......
395 396
label_blocked_by: blocked by
396 397
label_precedes: precedes
397 398
label_follows: follows
399
label_parents: parents
400
label_children: children
398 401
label_end_to_start: end to start
399 402
label_end_to_end: end to end
400 403
label_start_to_start: start to start
lang/bg.yml (working copy)
117 117
field_due_date: Крайна дата
118 118
field_assigned_to: Възложена на
119 119
field_priority: Приоритет
120
field_outline: Outline
120 121
field_fixed_version: Версия
121 122
field_user: Потребител
122 123
field_role: Роля
......
395 396
label_blocked_by: блокирана от
396 397
label_precedes: предшества
397 398
label_follows: изпълнява се след
399
label_parents: parents
400
label_children: children
398 401
label_end_to_start: end to start
399 402
label_end_to_end: end to end
400 403
label_start_to_start: start to start
lang/de.yml (working copy)
126 126
field_due_date: Abgabedatum
127 127
field_assigned_to: Zugewiesen an
128 128
field_priority: Priorität
129
field_outline: Outline
129 130
field_fixed_version: Erledigt in Version
130 131
field_user: Benutzer
131 132
field_role: Rolle
......
420 421
label_blocked_by: Blockiert durch
421 422
label_precedes: Vorgänger von
422 423
label_follows: folgt
424
label_parents: parents
425
label_children: children
423 426
label_end_to_start: Ende - Anfang
424 427
label_end_to_end: Ende - Ende
425 428
label_start_to_start: Anfang - Anfang
lang/ja.yml (working copy)
118 118
field_due_date: 期限日
119 119
field_assigned_to: 担当者
120 120
field_priority: 優先度
121
field_outline: アウトライン
121 122
field_fixed_version: 修正されたバージョン
122 123
field_user: ユーザ
123 124
field_role: 役割
......
396 397
label_blocked_by: ブロックされている
397 398
label_precedes: 先行する
398 399
label_follows: 後続する
400
label_parents: 親
401
label_children: 子
399 402
label_end_to_start: end to start
400 403
label_end_to_end: end to end
401 404
label_start_to_start: start to start
lang/he.yml (working copy)
119 119
field_due_date: תאריך סיום
120 120
field_assigned_to: מוצב ל
121 121
field_priority: עדיפות
122
field_outline: Outline
122 123
field_fixed_version: גירסא מקובעת
123 124
field_user: מתשמש
124 125
field_role: תפקיד
......
400 401
label_blocked_by: חסום ע"י
401 402
label_precedes: מקדים את
402 403
label_follows: עוקב אחרי
404
label_parents: parents
405
label_children: children
403 406
label_end_to_start: מהתחלה לסוף
404 407
label_end_to_end: מהסוף לסוף
405 408
label_start_to_start: מהתחלה להתחלה
lang/fi.yml (working copy)
126 126
field_due_date: Määräaika
127 127
field_assigned_to: Nimetty
128 128
field_priority: Prioriteetti
129
field_outline: Outline
129 130
field_fixed_version: Määrätty versio
130 131
field_user: Käyttäjä
131 132
field_role: Rooli
......
418 419
label_blocked_by: estetty
419 420
label_precedes: edeltää
420 421
label_follows: seuraa
422
label_parents: parents
423
label_children: children
421 424
label_end_to_start: loppu alkuun
422 425
label_end_to_end: loppu loppuun
423 426
label_start_to_start: alku alkuun
lang/en.yml (working copy)
127 127
field_due_date: Due date
128 128
field_assigned_to: Assigned to
129 129
field_priority: Priority
130
field_outline: Outline
130 131
field_fixed_version: Fixed version
131 132
field_user: User
132 133
field_role: Role
......
443 444
label_blocked_by: blocked by
444 445
label_precedes: precedes
445 446
label_follows: follows
447
label_parents: parents
448
label_children: children
446 449
label_end_to_start: end to start
447 450
label_end_to_end: end to end
448 451
label_start_to_start: start to start
lang/cs.yml (working copy)
117 117
field_due_date: Po lhůtě
118 118
field_assigned_to: Přiřazeno
119 119
field_priority: Priorita
120
field_outline: Outline
120 121
field_fixed_version: Pevná verze
121 122
field_user: Uživatel
122 123
field_role: Role
......
393 394
label_blocked_by: zamčeno
394 395
label_precedes: předchází
395 396
label_follows: následuje
397
label_parents: parents
398
label_children: children
396 399
label_end_to_start: od konce do začátku
397 400
label_end_to_end: od konce do konce
398 401
label_start_to_start: od začátku do začátku
lang/fr.yml (working copy)
127 127
field_due_date: Date d'échéance
128 128
field_assigned_to: Assigné à
129 129
field_priority: Priorité
130
field_outline: Outline
130 131
field_fixed_version: Version corrigée
131 132
field_user: Utilisateur
132 133
field_role: Rôle
......
443 444
label_blocked_by: bloqué par
444 445
label_precedes: précède
445 446
label_follows: suit
447
label_parents: parents
448
label_children: children
446 449
label_end_to_start: fin à début
447 450
label_end_to_end: fin à fin
448 451
label_start_to_start: début à début
lang/es.yml (working copy)
114 114
field_due_date: Fecha fin
115 115
field_assigned_to: Asignado a
116 116
field_priority: Prioridad
117
field_outline: Outline
117 118
field_fixed_version: Versión
118 119
field_user: Usuario
119 120
field_role: Perfil
......
386 387
label_blocked_by: bloqueado por
387 388
label_precedes: anterior a
388 389
label_follows: posterior a 
390
label_parents: parents
391
label_children: children
389 392
label_end_to_start: fin a principio
390 393
label_end_to_end: fin a fin
391 394
label_start_to_start: principio a principio
lang/nl.yml (working copy)
117 117
field_due_date: Verwachte datum gereed
118 118
field_assigned_to: Toegewezen aan
119 119
field_priority: Prioriteit
120
field_outline: Outline
120 121
field_fixed_version: Opgeloste versie
121 122
field_user: Gebruiker
122 123
field_role: Rol
......
395 396
label_blocked_by: geblokkeerd door
396 397
label_precedes: gaat vooraf aan
397 398
label_follows: volgt op
399
label_parents: parents
400
label_children: children
398 401
label_end_to_start: eind tot start
399 402
label_end_to_end: eind tot eind
400 403
label_start_to_start: start tot start
lang/ko.yml (working copy)
119 119
field_due_date: 완료 기한
120 120
field_assigned_to: 담당자
121 121
field_priority: 우선순위
122
field_outline: Outline
122 123
field_fixed_version: 마일스톤
123 124
field_user: 유저
124 125
field_role: 역할
......
402 403
label_blocked_by: 막고 있는 티켓
403 404
label_precedes: 다음 티켓보다 앞서서 처리해야 함.
404 405
label_follows: 선처리티켓
406
label_parents: parents
407
label_children: children
405 408
label_end_to_start: end to start
406 409
label_end_to_end: end to end
407 410
label_start_to_start: start to start
lang/zh-tw.yml (working copy)
126 126
field_due_date: 完成日期
127 127
field_assigned_to: 分派給
128 128
field_priority: 優先權
129
field_outline: Outline
129 130
field_fixed_version: 版本
130 131
field_user: 用戶
131 132
field_role: 角色
......
425 426
label_blocked_by: 被阻擋
426 427
label_precedes: 優先於
427 428
label_follows: 跟隨於
429
label_parents: parents
430
label_children: children
428 431
label_end_to_start: end to start
429 432
label_end_to_end: end to end
430 433
label_start_to_start: start to start
lang/pl.yml (working copy)
114 114
field_due_date: Data oddania
115 115
field_assigned_to: Przydzielony do
116 116
field_priority: Priorytet
117
field_outline: Outline
117 118
field_fixed_version: Wersja
118 119
field_user: Użytkownik
119 120
field_role: Rola
......
386 387
label_blocked_by: zablokowane przez
387 388
label_precedes: poprzedza
388 389
label_follows: podąża
390
label_parents: parents
391
label_children: children
389 392
label_end_to_start: koniec do początku
390 393
label_end_to_end: koniec do końca
391 394
label_start_to_start: początek do początku
lang/it.yml (working copy)
117 117
field_due_date: Data ultima
118 118
field_assigned_to: Assegnato a
119 119
field_priority: Priorita'
120
field_outline: Outline
120 121
field_fixed_version: Versione di fix
121 122
field_user: Utente
122 123
field_role: Ruolo
......
395 396
label_blocked_by: blocked by
396 397
label_precedes: precedes
397 398
label_follows: follows
399
label_parents: parents
400
label_children: children
398 401
label_end_to_start: end to start
399 402
label_end_to_end: end to end
400 403
label_start_to_start: start to start
(1-1/3)