backlog 0.22.1 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +28 -0
- data/README.txt +23 -2
- data/app/controllers/application.rb +15 -2
- data/app/controllers/periods_controller.rb +3 -0
- data/app/controllers/tasks_controller.rb +2 -2
- data/app/controllers/user_controller.rb +2 -2
- data/app/controllers/work_accounts_controller.rb +14 -0
- data/app/controllers/works_controller.rb +23 -3
- data/app/models/report_filter.rb +7 -3
- data/app/models/task.rb +11 -10
- data/app/models/work.rb +3 -2
- data/app/views/customers/_name_list.rhtml +5 -0
- data/app/views/periods/_show_active.rhtml +1 -0
- data/app/views/periods/_title.rhtml +8 -1
- data/app/views/periods/edit.rhtml +1 -1
- data/app/views/periods/order.rjs +0 -1
- data/app/views/tasks/_task.rhtml +6 -5
- data/app/views/user/login.rhtml +1 -1
- data/app/views/work_accounts/_title.rhtml +4 -0
- data/app/views/work_accounts/edit.rhtml +1 -3
- data/app/views/work_accounts/list.rhtml +9 -3
- data/app/views/work_accounts/show.rhtml +47 -30
- data/app/views/works/_form.rhtml +6 -0
- data/app/views/works/_row.rhtml +16 -9
- data/app/views/works/_row_field.rhtml +2 -2
- data/app/views/works/daily_work_sheet.rhtml +37 -7
- data/app/views/works/daily_work_sheet_old.rhtml +93 -0
- data/app/views/works/list.rhtml +11 -5
- data/app/views/works/update_row.rjs +5 -2
- data/config/environment.rb +19 -3
- data/lang/en.yaml +5 -0
- data/lang/no.yaml +5 -0
- data/lib/class_table_inheritance.rb +10 -3
- data/no_test.rb~ +6 -0
- data/test/client/login.rb +25 -0
- data/test/client/login.rb~ +33 -0
- data/test/client/login_test.rb +64 -0
- data/test/client/setup.rb +24 -0
- data/test/functional/works_controller_test.rb +3 -2
- data/test/unit/party_test.rb +10 -0
- data/test/unit/user_test.rb +15 -17
- metadata +12 -2
data/History.txt
CHANGED
@@ -1,3 +1,31 @@
|
|
1
|
+
== 0.23.0 2008-02-25
|
2
|
+
|
3
|
+
=== Features
|
4
|
+
|
5
|
+
* Improved input for daily_work_sheet
|
6
|
+
* Allowed override for development and test database with new config file
|
7
|
+
* Listed details for works without backlog in "Show Work Acoount" view.
|
8
|
+
* Added "List Works" view for Work Account.
|
9
|
+
* Added filtering of tasks grabbed by other users in the sprint view.
|
10
|
+
|
11
|
+
=== Fixes
|
12
|
+
|
13
|
+
* Improved work flow ("Back" links) several places.
|
14
|
+
* Fixed bug in layout when you had started tasks without a sprint.
|
15
|
+
* Some speedup of grabbing tasks.
|
16
|
+
* Fixed database corruption when trying to register users with duplicate login or email.
|
17
|
+
* Fixed display of welcome message after following link from "Forgot password" email.
|
18
|
+
* Fixed bug in daily work sheet when start time was not set for a work record.
|
19
|
+
* Starting work on a task grabs it.
|
20
|
+
* Changed to show "complete" check marks in sprint view for tasks that track time, but are not started.
|
21
|
+
* Display blank field for hours in daily work sheet if it has not been filled in yet.
|
22
|
+
* Always display row for new work record entry in daily work sheet.
|
23
|
+
Earlier, a row for new input was only shown if the previous row was ended.
|
24
|
+
* Removed message about missing database settings in main config file on startup since it is optional and deprecated.
|
25
|
+
* Fixed error in class table inheritance library. Validations for the subclass were not called.
|
26
|
+
* Added some Firewatir tests. EXPERIMENTAL!
|
27
|
+
* Added explenation on how to set database connection parameters.
|
28
|
+
|
1
29
|
== 0.22.1 2008-02-15
|
2
30
|
|
3
31
|
=== Features
|
data/README.txt
CHANGED
@@ -57,19 +57,40 @@ If you have concrete needs, and are willing to beta test the integration, please
|
|
57
57
|
|
58
58
|
=== Configuration
|
59
59
|
|
60
|
-
|
60
|
+
==== Setting port
|
61
|
+
|
62
|
+
You can set configuration parameters for backlog using the /etc/backlog.conf file on unix
|
63
|
+
and "c:\documents and settings\all\backlog.conf" on windows.
|
61
64
|
The format is YAML.
|
62
65
|
|
63
66
|
Example:
|
64
67
|
|
65
68
|
port: 3000
|
66
69
|
|
67
|
-
|
70
|
+
|
71
|
+
==== Setting database connection parameters
|
72
|
+
|
73
|
+
You can set database connnection parameters using the /etc/backlog/config/database.yml file on unix
|
74
|
+
and "c:\documents and settings\all\backlog\config\database.yml" on windows.
|
75
|
+
The format is YAML.
|
76
|
+
|
77
|
+
Example:
|
78
|
+
|
79
|
+
development:
|
80
|
+
adapter: postgresql
|
81
|
+
database: backlog_development
|
82
|
+
username: root
|
83
|
+
password: verySecret42
|
84
|
+
host: localhost
|
85
|
+
|
86
|
+
production:
|
68
87
|
adapter: postgresql
|
69
88
|
database: backlog_production
|
70
89
|
username: root
|
71
90
|
password: verySecret42
|
72
91
|
host: localhost
|
92
|
+
|
93
|
+
See the Rails documentation (http://rubyonrails.org) for more documentation on the databse connection seetings.
|
73
94
|
|
74
95
|
=== Charts
|
75
96
|
|
@@ -12,6 +12,7 @@ class ApplicationController < ActionController::Base
|
|
12
12
|
helper :user
|
13
13
|
before_filter :store_detour_from_params
|
14
14
|
before_filter :authenticate_user
|
15
|
+
before_filter :store_cookies_from_params
|
15
16
|
before_filter :populate_layout
|
16
17
|
|
17
18
|
def initialize
|
@@ -124,7 +125,20 @@ class ApplicationController < ActionController::Base
|
|
124
125
|
end
|
125
126
|
detour
|
126
127
|
end
|
127
|
-
|
128
|
+
|
129
|
+
|
130
|
+
|
131
|
+
def store_cookies_from_params
|
132
|
+
if params[:cookies]
|
133
|
+
params[:cookies].each_pair do |key, value|
|
134
|
+
logger.info "Storing cookie #{key.inspect}=#{value.inspect}"
|
135
|
+
#cookies[key] = {:value => value, :expires => 1.year.from_now}
|
136
|
+
session[key] = value
|
137
|
+
logger.info "Stored cookie #{key.inspect}=#{session[key].inspect}"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
128
142
|
|
129
143
|
def populate_shortcuts
|
130
144
|
@shortcuts = [
|
@@ -182,7 +196,6 @@ class ApplicationController < ActionController::Base
|
|
182
196
|
end
|
183
197
|
end
|
184
198
|
|
185
|
-
private
|
186
199
|
|
187
200
|
def user_id
|
188
201
|
session[:user_id]
|
@@ -36,6 +36,9 @@ class PeriodsController < ApplicationController
|
|
36
36
|
if @selected_task.nil?
|
37
37
|
@selected_task = @period.open_tasks.first
|
38
38
|
end
|
39
|
+
# TODO (uwe): Switch to use cookie since the same behavior should work on next session.
|
40
|
+
# TODO (uwe): Problem: Cannot read cookie in the same request it was written...
|
41
|
+
@show_only_grabbed_tasks = session['show_only_grabbed_tasks'] == 'true'
|
39
42
|
load_tasks(@period)
|
40
43
|
end
|
41
44
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class TasksController < ApplicationController
|
2
|
-
skip_before_filter :populate_layout, :except => [:edit, :list_started, :move_down, :move_to_bottom, :move_to_top, :move_up, :new, :specify]
|
2
|
+
skip_before_filter :populate_layout, :except => [:edit, :grab, :list_started, :move_down, :move_to_bottom, :move_to_top, :move_up, :new, :specify]
|
3
3
|
|
4
|
-
verify :method => :post, :except => [ :new, :show, :edit, :list_started, :move_to_next_period, :notes],
|
4
|
+
verify :method => :post, :except => [ :new, :show, :edit, :grab, :list_started, :move_to_next_period, :notes],
|
5
5
|
:redirect_to => { :controller => 'backlogs' }
|
6
6
|
|
7
7
|
def list_started
|
@@ -24,9 +24,9 @@ class UserController < ApplicationController
|
|
24
24
|
def signup
|
25
25
|
return if generate_blank_form
|
26
26
|
params['user'].delete('form')
|
27
|
-
@user = User.new(params['user'])
|
28
27
|
begin
|
29
28
|
User.transaction do
|
29
|
+
@user = User.new(params['user'])
|
30
30
|
@user.password_needs_confirmation = true
|
31
31
|
if @user.save
|
32
32
|
key = @user.generate_security_token
|
@@ -88,7 +88,7 @@ class UserController < ApplicationController
|
|
88
88
|
url = url_for(:action => 'change_password')
|
89
89
|
url += "?user[id]=#{user.id}&key=#{key}"
|
90
90
|
UserNotify.deliver_forgot_password(user, url)
|
91
|
-
flash[
|
91
|
+
flash[:notice] = "Instructions on resetting your password have been emailed to #{CGI.escapeHTML(params['user']['email'])}."
|
92
92
|
unless authenticated_user?
|
93
93
|
redirect_to :action => 'login'
|
94
94
|
return
|
@@ -19,6 +19,7 @@ class WorkAccountsController < ApplicationController
|
|
19
19
|
@task_totals = works.to_summarized_hash {|work| [work.task, work.hours]}
|
20
20
|
@task_totals_per_backlog = @task_totals.to_a.to_grouped_hash {|task, hours| [task && task.backlog, [task, hours]]}
|
21
21
|
@total_hours = works.inject(BigDecimal('0')) {|total, work| total += work.hours}
|
22
|
+
@works_without_backlog = works.select {|w| w.task_id.nil?}
|
22
23
|
end
|
23
24
|
|
24
25
|
def new
|
@@ -53,4 +54,17 @@ class WorkAccountsController < ApplicationController
|
|
53
54
|
WorkAccount.find(params[:id]).destroy
|
54
55
|
redirect_to :action => 'list'
|
55
56
|
end
|
57
|
+
|
58
|
+
def works
|
59
|
+
work_account = WorkAccount.find(params[:id])
|
60
|
+
@report_filter = ReportFilter.new(params[:report_filter])
|
61
|
+
@report_filter.title = "#{l :hours} for #{work_account.name} #{@report_filter.start_on && @report_filter.start_on.strftime('%Y-%m-%d - ')}#{@report_filter.end_on && @report_filter.end_on.strftime('%Y-%m-%d')}"
|
62
|
+
@works = Work.paginate :conditions => ["completed_at BETWEEN ? AND ? AND work_account_id = ?", @report_filter.start_on, @report_filter.end_on, work_account.id], :page => params[:page], :per_page => @report_filter.page_size
|
63
|
+
if params[:export] == 'excel'
|
64
|
+
render :template => '/works/list_excel', :layout => false
|
65
|
+
else
|
66
|
+
render :template => '/works/list'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
56
70
|
end
|
@@ -5,7 +5,7 @@ class WorksController < ApplicationController
|
|
5
5
|
in_place_edit_for :work, :completed_at_time
|
6
6
|
skip_before_filter :populate_layout, :except => [:create, :destroy, :edit, :index, :list, :new, :show, :update, :daily_work_sheet, :weekly_work_sheet_by_work_account]
|
7
7
|
auto_complete_for :work, :description
|
8
|
-
|
8
|
+
|
9
9
|
def index
|
10
10
|
list
|
11
11
|
render :action => 'list'
|
@@ -49,6 +49,14 @@ class WorksController < ApplicationController
|
|
49
49
|
account = WorkAccount.find_by_name(account_name)
|
50
50
|
params[:work][:work_account_id] = account.id
|
51
51
|
end
|
52
|
+
customer_name = params[:work].delete(:customer_name)
|
53
|
+
if customer_name && customer_name.size > 0
|
54
|
+
customer = Customer.find_by_name(customer_name)
|
55
|
+
if (customer.nil? )
|
56
|
+
customer = Customer.create!(:name => customer_name)
|
57
|
+
end
|
58
|
+
params[:work][:customer_id] = customer.id
|
59
|
+
end
|
52
60
|
end
|
53
61
|
convert_hours_param
|
54
62
|
convert_start_time_param
|
@@ -95,8 +103,11 @@ class WorksController < ApplicationController
|
|
95
103
|
def update_row
|
96
104
|
update_work
|
97
105
|
flash.discard
|
98
|
-
@
|
106
|
+
@next_field = params[:next_field] || 'work_account_name'
|
99
107
|
@work_accounts = WorkAccount.find(:all, :order => :name)
|
108
|
+
@customers = Customer.find(:all, :order => :name)
|
109
|
+
works = Work.find_work_for_day((@work.started_at || @work.completed_at).to_date)
|
110
|
+
@day_total = works.inject(BigDecimal('0')){|total,work|total+=work.hours}
|
100
111
|
end
|
101
112
|
|
102
113
|
def update_time
|
@@ -107,7 +118,6 @@ class WorksController < ApplicationController
|
|
107
118
|
|
108
119
|
def update_work
|
109
120
|
@work = Work.find(params[:id])
|
110
|
-
convert_start_time_param
|
111
121
|
convert_hours_param
|
112
122
|
if @work.update_attributes(params[:work])
|
113
123
|
flash[:notice] = 'Work was successfully updated.'
|
@@ -137,6 +147,7 @@ class WorksController < ApplicationController
|
|
137
147
|
@date = (params[:id] && Date.parse(params[:id])) || Date.today
|
138
148
|
@periods = []
|
139
149
|
@works = Work.find_work_for_day @date
|
150
|
+
@customers = Customer.find(:all, :order => :name)
|
140
151
|
@started_works = Task.find_started
|
141
152
|
@work = Work.new(:started_at => Time.now, :completed_at => Time.now)
|
142
153
|
@work_accounts = WorkAccount.find(:all, :order => :name)
|
@@ -182,6 +193,15 @@ class WorksController < ApplicationController
|
|
182
193
|
render :partial => '/work_accounts/name_list'
|
183
194
|
end
|
184
195
|
|
196
|
+
def auto_complete_for_work_customer_name
|
197
|
+
@customers = Customer.find(:all,
|
198
|
+
:conditions => [ 'LOWER(name) LIKE ?',
|
199
|
+
'%' + params[:work][:customer_name].downcase + '%' ],
|
200
|
+
:order => 'name ASC',
|
201
|
+
:limit => 16)
|
202
|
+
render :partial => '/customers/name_list'
|
203
|
+
end
|
204
|
+
|
185
205
|
def auto_complete_for_work_backlog_name
|
186
206
|
@backlogs = Backlog.find(:all,
|
187
207
|
:conditions => [ 'LOWER(name) LIKE ?',
|
data/app/models/report_filter.rb
CHANGED
@@ -5,17 +5,21 @@ class ReportFilter
|
|
5
5
|
attr_reader :page_size
|
6
6
|
|
7
7
|
def initialize(attributes)
|
8
|
+
@start_on = Date.civil(2007, 01, 01)
|
9
|
+
@end_on = Date.today
|
10
|
+
@page_size = 1000
|
11
|
+
|
8
12
|
if attributes
|
9
13
|
attributes = attributes.clone
|
10
14
|
|
11
15
|
start_on_param = attributes.delete(:start_on)
|
12
|
-
@start_on = start_on_param && start_on_param.size > 0
|
16
|
+
@start_on = Date.parse(start_on_param) if start_on_param && start_on_param.size > 0
|
13
17
|
|
14
18
|
end_on_param = attributes.delete(:end_on)
|
15
|
-
@end_on = end_on_param && end_on_param.size > 0
|
19
|
+
@end_on = Date.parse(end_on_param) if end_on_param && end_on_param.size > 0
|
16
20
|
|
17
21
|
page_size_param = attributes.delete(:page_size)
|
18
|
-
@page_size = page_size_param.to_i
|
22
|
+
@page_size = page_size_param.to_i if page_size_param.to_i > 0
|
19
23
|
|
20
24
|
raise "Unknown parameters: #{attributes.inspect}" unless attributes.empty?
|
21
25
|
end
|
data/app/models/task.rb
CHANGED
@@ -57,7 +57,7 @@ class Task < ActiveRecord::Base
|
|
57
57
|
end
|
58
58
|
conditions = "completed_at IS NULL AND (user_id IS NULL#{user_clause})"
|
59
59
|
Work.find(:all, :conditions => conditions).map {|work| work.task}.compact.sort_by do |t|
|
60
|
-
[t.root_task.backlog.name, t.root_task.period.end_on, t.position || 0]
|
60
|
+
[t.root_task.backlog.name, t.root_task.period ? t.root_task.period.end_on : 0, t.position || 0]
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
@@ -344,21 +344,22 @@ class Task < ActiveRecord::Base
|
|
344
344
|
def start_work
|
345
345
|
return if work_started?
|
346
346
|
open
|
347
|
+
grab if current_user
|
347
348
|
new_work = works.new
|
348
349
|
|
349
350
|
# TODO (uwe): Only needed for rails 1.2.x branch. Remove when moving to 1.3 or 2.0.
|
350
351
|
new_work.task = self
|
351
352
|
|
352
353
|
new_work.started_at = Time.previous_quarter
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
354
|
+
if current_user
|
355
|
+
last_work = current_user.works.select {|w| w.completed_at}.last
|
356
|
+
else
|
357
|
+
last_work = Work.find(:first, :conditions => 'completed_at IS NOT NULL', :order => 'completed_at DESC')
|
358
|
+
end
|
359
|
+
if last_work && last_work.completed_at > new_work.started_at
|
360
|
+
new_work.started_at = last_work.completed_at
|
361
|
+
end
|
362
|
+
|
362
363
|
new_work.user = current_user
|
363
364
|
new_work.work_account_id = work_account.id
|
364
365
|
new_work.save!
|
data/app/models/work.rb
CHANGED
@@ -110,8 +110,9 @@ class Work < ActiveRecord::Base
|
|
110
110
|
end
|
111
111
|
|
112
112
|
def started_at_time=(new_value)
|
113
|
-
|
114
|
-
|
113
|
+
new_value = '0:00' if new_value == ''
|
114
|
+
raise "invalid time format: #{new_value}" unless new_value =~ /(\d{0,2}):(\d{2})/
|
115
|
+
new_hour, new_minutes = $1.to_i, $2.to_i
|
115
116
|
t = started_at || Time.now
|
116
117
|
self.started_at = Time.local(t.year, t.month, t.day, new_hour, new_minutes)
|
117
118
|
end
|
@@ -36,6 +36,7 @@ function handleEvent(field, event, id) {
|
|
36
36
|
<%=render :partial => '/tasks/fields_header', :locals => { :backlog => nil, :active => true, :track_todo => @tasks.find {|t|t.period && t.period.active?}, :track_times => @tasks.find {|t|t.period && t.period.active?}, :track_done => @tasks.find {|t|t.period && t.period.active? }, :work_done => @tasks.find {|t| t.total_done > 0} } %>
|
37
37
|
<ul id="active_tasks_<%=@period.id%>" class="task_list">
|
38
38
|
<% for task in @tasks -%>
|
39
|
+
<% next if @show_only_grabbed_tasks && !(task.users.empty? || task.users.include?(current_user))%>
|
39
40
|
<%=render :partial => '/tasks/task', :locals => { :task => task, :i => i, :active => true, :highlight_task => task == @selected_task, :update => :spotlight, :show_backlog => true, :hidden => false } %>
|
40
41
|
<% i += 1 %>
|
41
42
|
<% end -%>
|
@@ -7,5 +7,12 @@
|
|
7
7
|
|
8
8
|
<%=if @period.higher_item then link_to(image_tag(url_for("arrow_left.png"), :alt => "#{l :previous} #{l :period}", :title => "#{l :previous} #{l :period}", :class => 'image-submit'), :controller => 'periods', :action => :show, :id => @period.higher_item) end%>
|
9
9
|
<%=unless @period.passed? then detour_to(image_tag(url_for("add.png"), :alt => l(:add_task), :title => l(:add_task), :class => 'image-submit'), :controller => 'tasks', :action => 'new', :task => {:period_id => (@period ? @period.id : (@backlog && @backlog.periods.first ? @backlog.periods.first.id : nil))} ) end %>
|
10
|
-
<h4><%=h @period.name %> (<%=@period.start_on%> - <%=@period.end_on%>)
|
10
|
+
<h4><%=h @period.name %> (<%=@period.start_on%> - <%=@period.end_on%>)
|
11
|
+
<% filter_style = {:style => 'float: none; vertical-align: bottom'} %>
|
12
|
+
<% if @show_only_grabbed_tasks %>
|
13
|
+
<%=image_link_to('grab.png', l(:release_task), {'cookies[show_only_grabbed_tasks]' => 'false'}, filter_style, false)%>
|
14
|
+
<% else %>
|
15
|
+
<%=image_link_to('grab_gray.png', l(:grab_task), {'cookies[show_only_grabbed_tasks]' => 'true'}, filter_style, false)%>
|
16
|
+
<% end %>
|
17
|
+
</h4>
|
11
18
|
</div>
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<% form_tag :action => 'update', :id => @period do %>
|
5
5
|
<%= render :partial => 'form' %>
|
6
6
|
<%= submit_tag l(:save) %>
|
7
|
-
<%=
|
7
|
+
<%=back_or_link_to l(:back), :action => 'show', :id => @period %>
|
8
8
|
<% end %>
|
9
9
|
|
10
10
|
</div>
|
data/app/views/periods/order.rjs
CHANGED
@@ -1 +0,0 @@
|
|
1
|
-
record page, 'alert("hi");'
|
data/app/views/tasks/_task.rhtml
CHANGED
@@ -75,9 +75,10 @@
|
|
75
75
|
<% else -%>
|
76
76
|
<%=@task.todo %>
|
77
77
|
<% end -%>
|
78
|
-
|
79
|
-
|
80
|
-
|
78
|
+
<% else %>
|
79
|
+
<% if !@task.work_started? && (@task.period.nil? || @task.period.active?) %>
|
80
|
+
<%=image_link_to_remote('checkmark.png', l(:complete), {:action => :finish_task, :id => @task}, nil, true)%>
|
81
|
+
<% end -%>
|
81
82
|
<% end -%>
|
82
83
|
<% end -%>
|
83
84
|
</div>
|
@@ -87,9 +88,9 @@
|
|
87
88
|
<% unless @task.work_started? -%>
|
88
89
|
<% if @task.backlog.enable_users? %>
|
89
90
|
<% if @task.users.include?(current_user) %>
|
90
|
-
<%=image_link_to_remote('grab.png', l(:
|
91
|
+
<%=image_link_to_remote('grab.png', l(:release_task), with_detour({:controller => 'tasks', :action => :release, :id => @task}), nil, true)%>
|
91
92
|
<% else %>
|
92
|
-
<%=image_link_to_remote('grab_gray.png', l(:
|
93
|
+
<%=image_link_to_remote('grab_gray.png', "#{l:grab_task} #{" (#{l :not_grabbed})" if @task.users.empty?}", with_detour({:controller => 'tasks', :action => :grab, :id => @task}), nil, true)%>
|
93
94
|
<% end %>
|
94
95
|
<% end %>
|
95
96
|
<%=image_link_to_remote('arrow_right.png', l(:move_to_next_period), {:action => :move_task_to_next_period, :id => @task}, nil, true) if @task.backlog.enable_periods? || @task.period_id%>
|
data/app/views/user/login.rhtml
CHANGED
@@ -1,9 +1,7 @@
|
|
1
1
|
<% @page_title = "#{l(:editing)} #{l(:work_account)}" %>
|
2
2
|
|
3
3
|
<div id="spotlight">
|
4
|
-
|
5
|
-
<h4><%=@work_account.name%></h4>
|
6
|
-
</div>
|
4
|
+
<%=render :partial => 'title'%>
|
7
5
|
|
8
6
|
<% form_tag :action => 'update', :id => @work_account do %>
|
9
7
|
<%=render :partial => 'form' %>
|
@@ -1,4 +1,10 @@
|
|
1
|
-
|
1
|
+
<% @page_title = "#{l :work_accounts}"%>
|
2
|
+
|
3
|
+
<div id="spotlight">
|
4
|
+
<div class="btitle">
|
5
|
+
<%=image_detour_to 'add.png', l(:new_work_account), :action => 'new' %>
|
6
|
+
<h4><%=@page_title%></h4>
|
7
|
+
</div>
|
2
8
|
|
3
9
|
<table>
|
4
10
|
<tr>
|
@@ -21,6 +27,6 @@
|
|
21
27
|
|
22
28
|
<%=will_paginate @work_accounts %>
|
23
29
|
|
24
|
-
|
30
|
+
<%=back_or_link_to l(:back), :controller => 'welcome', :action => 'index' %>
|
25
31
|
|
26
|
-
|
32
|
+
</div>
|
@@ -1,33 +1,50 @@
|
|
1
1
|
<% @page_title = "#{l(:work_account)} #{l(:work_account)}" %>
|
2
|
-
|
3
2
|
<div id="spotlight">
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
3
|
+
<%=render :partial => 'title'%>
|
4
|
+
<table>
|
5
|
+
<% for backlog in @backlog_totals.keys %>
|
6
|
+
<tr>
|
7
|
+
<th>
|
8
|
+
<%=backlog ? backlog.name : l(:no_backlog) %>
|
9
|
+
</th>
|
10
|
+
<th>
|
11
|
+
<%=@backlog_totals[backlog] %>
|
12
|
+
</th>
|
13
|
+
</tr>
|
14
|
+
<% if backlog %>
|
15
|
+
<% for task, hours in @task_totals_per_backlog[backlog] %>
|
16
|
+
<tr>
|
17
|
+
<td>
|
18
|
+
<% if task %>
|
19
|
+
<%=link_to task.description, :controller => 'tasks', :action => :edit, :id => task.id %>
|
20
|
+
<% end %>
|
21
|
+
</td>
|
22
|
+
<td align="right" valign="top">
|
23
|
+
<%='%.2f' % hours %>
|
24
|
+
</td>
|
25
|
+
</tr>
|
26
|
+
<% end %>
|
27
|
+
<% else %>
|
28
|
+
<% for work in @works_without_backlog %>
|
29
|
+
<tr>
|
30
|
+
<td>
|
31
|
+
<%=work.description %>
|
32
|
+
</td>
|
33
|
+
<td align="right" valign="top">
|
34
|
+
<%='%.2f' % work.hours %>
|
35
|
+
</td>
|
36
|
+
</tr>
|
37
|
+
<% end %>
|
38
|
+
<% end %>
|
39
|
+
<% end %>
|
40
|
+
<tr>
|
41
|
+
<th>
|
42
|
+
Total hours
|
43
|
+
</th>
|
44
|
+
<th>
|
45
|
+
<%=@total_hours %>
|
46
|
+
</th>
|
47
|
+
</tr>
|
48
|
+
</table>
|
49
|
+
<%=detour_to l(:edit), :action => 'edit', :id => @work_account %>|<%=back_or_link_to l(:back), :action => 'list' %>
|
33
50
|
</div>
|