timesheet_plugin 0.5.0 → 0.6.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.
Files changed (44) hide show
  1. data/README.rdoc +1 -0
  2. data/Rakefile +2 -2
  3. data/VERSION +1 -1
  4. data/app/controllers/timesheet_controller.rb +16 -3
  5. data/app/helpers/timesheet_helper.rb +13 -8
  6. data/app/models/timesheet.rb +120 -12
  7. data/app/views/timesheet/_form.rhtml +5 -31
  8. data/app/views/timesheet/_issue_time_entries.rhtml +9 -2
  9. data/app/views/timesheet/index.rhtml +2 -5
  10. data/app/views/timesheet/report.rhtml +2 -5
  11. data/assets/images/csv.png +0 -0
  12. data/assets/javascripts/timesheet.js +17 -0
  13. data/assets/stylesheets/timesheet.css +6 -0
  14. data/config/locales/hu.yml +1 -1
  15. data/config/locales/hy.yml +9 -0
  16. data/config/locales/ja.yml +10 -0
  17. data/config/locales/pt-br.yml +10 -0
  18. data/config/locales/ru.yml +1 -0
  19. data/config/locales/sr.yml +10 -0
  20. data/config/locales/sv.yml +10 -0
  21. data/config/locales/uk.yml +10 -0
  22. data/config/routes.rb +4 -0
  23. data/init.rb +47 -1
  24. data/lang/hu.yml +1 -1
  25. data/lang/hy.yml +8 -0
  26. data/lang/ja.yml +9 -0
  27. data/lang/pt-br.yml +9 -0
  28. data/lang/ru.yml +1 -0
  29. data/lang/sr.yml +9 -0
  30. data/lang/sv.yml +9 -0
  31. data/lang/uk.yml +9 -0
  32. data/lib/timesheet_compatibility.rb +12 -1
  33. data/rails/init.rb +1 -29
  34. data/test/functional/timesheet_controller_test.rb +256 -0
  35. data/test/integration/timesheet_menu_test.rb +53 -0
  36. data/test/test_helper.rb +24 -0
  37. data/test/unit/sanity_test.rb +20 -0
  38. data/test/unit/timesheet_test.rb +653 -0
  39. metadata +28 -7
  40. data/lib/tasks/plugin_stat.rake +0 -38
  41. data/spec/controllers/timesheet_controller_spec.rb +0 -263
  42. data/spec/models/timesheet_spec.rb +0 -537
  43. data/spec/sanity_spec.rb +0 -7
  44. data/spec/spec_helper.rb +0 -40
@@ -0,0 +1,10 @@
1
+ pt-BR:
2
+ timesheet_title: Relatório de Apontamentos
3
+ timesheet_date_from_label: De
4
+ timesheet_date_to_label: Até
5
+ timesheet_project_label: Projeto
6
+ timesheet_activities_label: Atividades
7
+ timesheet_users_label: Usuários
8
+ timesheet_showing_users: 'Exibindo usuários: '
9
+ timesheet_permalink: 'Link permanente'
10
+ timesheet_group_by: 'Agrupar por'
@@ -5,5 +5,6 @@ ru:
5
5
  timesheet_project_label: Проект
6
6
  timesheet_activities_label: Активность
7
7
  timesheet_users_label: Пользователи
8
+ timesheet_showing_users: 'сводка для пользователя: '
8
9
  timesheet_permalink: '(Постоянная ссылка на эту таблицу)'
9
10
  timesheet_group_by: Группировать по
@@ -0,0 +1,10 @@
1
+ "sr":
2
+ timesheet_title: Satnica
3
+ timesheet_date_from_label: Od
4
+ timesheet_date_to_label: Do
5
+ timesheet_project_label: Projekat
6
+ timesheet_activities_label: Aktivnost
7
+ timesheet_users_label: Korisnici
8
+ timesheet_showing_users: 'pokazujem vreme za: '
9
+ timesheet_permalink: '(Stalni link za ovu satnicu)'
10
+ timesheet_group_by: Grupiši po
@@ -0,0 +1,10 @@
1
+ "sv":
2
+ timesheet_title: Tidkort
3
+ timesheet_date_from_label: Fr�n
4
+ timesheet_date_to_label: Till
5
+ timesheet_project_label: Projekt
6
+ timesheet_activities_label: Aktivitet
7
+ timesheet_users_label: Anv�ndare
8
+ timesheet_showing_users: 'visar tid f�r: '
9
+ timesheet_permalink: '(Permal�nk till detta tidkort)'
10
+ timesheet_group_by: Gruppera efter
@@ -0,0 +1,10 @@
1
+ uk:
2
+ timesheet_title: Таблиця витрат часу
3
+ timesheet_date_from_label: Починаючи з
4
+ timesheet_date_to_label: до
5
+ timesheet_project_label: Проект
6
+ timesheet_activities_label: Активність
7
+ timesheet_users_label: Користувачі
8
+ timesheet_showing_users: 'час витрачений користувачем: '
9
+ timesheet_permalink: '(Постійний лінк на цю таблицю)'
10
+ timesheet_group_by: Групувати за
data/config/routes.rb ADDED
@@ -0,0 +1,4 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ map.connect 'timesheet/report.:format', :controller => 'timesheet', :action => 'report'
3
+ map.connect 'timesheet/reset', :controller => 'timesheet', :action => 'reset', :conditions => { :method => :delete }
4
+ end
data/init.rb CHANGED
@@ -1,2 +1,48 @@
1
- require File.dirname(__FILE__) + "/rails/init"
1
+ require 'redmine'
2
2
 
3
+ # Taken from lib/redmine.rb
4
+ if RUBY_VERSION < '1.9'
5
+ require 'faster_csv'
6
+ else
7
+ require 'csv'
8
+ FCSV = CSV
9
+ end
10
+
11
+ require 'dispatcher'
12
+ Dispatcher.to_prepare :timesheet_plugin do
13
+ # Needed for the compatibility check
14
+ begin
15
+ require_dependency 'time_entry_activity'
16
+ rescue LoadError
17
+ # TimeEntryActivity is not available
18
+ end
19
+ end
20
+
21
+
22
+ unless Redmine::Plugin.registered_plugins.keys.include?(:timesheet_plugin)
23
+ Redmine::Plugin.register :timesheet_plugin do
24
+ name 'Timesheet Plugin'
25
+ author 'Eric Davis of Little Stream Software'
26
+ description 'This is a Timesheet plugin for Redmine to show timelogs for all projects'
27
+ url 'https://projects.littlestreamsoftware.com/projects/redmine-timesheet'
28
+ author_url 'http://www.littlestreamsoftware.com'
29
+
30
+ version '0.6.0'
31
+ requires_redmine :version_or_higher => '0.8.7'
32
+
33
+ settings :default => {'list_size' => '5', 'precision' => '2'}, :partial => 'settings/timesheet_settings'
34
+
35
+ permission :see_project_timesheets, { }, :require => :member
36
+
37
+ menu(:top_menu,
38
+ :timesheet,
39
+ {:controller => 'timesheet', :action => 'index'},
40
+ :caption => :timesheet_title,
41
+ :if => Proc.new {
42
+ User.current.allowed_to?(:see_project_timesheets, nil, :global => true) ||
43
+ User.current.allowed_to?(:view_time_entries, nil, :global => true) ||
44
+ User.current.admin?
45
+ })
46
+
47
+ end
48
+ end
data/lang/hu.yml CHANGED
@@ -1,4 +1,4 @@
1
- timesheet_title: Időlap
1
+ timesheet_title: Időlap
2
2
  timesheet_date_from_label: Kezdő dátum
3
3
  timesheet_date_to_label: Vég dátum
4
4
  timesheet_project_label: Projekt
data/lang/hy.yml ADDED
@@ -0,0 +1,8 @@
1
+ timesheet_title: Ծախսված ժամանակի աղյուսակ
2
+ timesheet_date_from_label: Սկսած
3
+ timesheet_date_to_label: մինչև
4
+ timesheet_project_label: Նախագիծ
5
+ timesheet_activities_label: Ակտիվությունը
6
+ timesheet_users_label: Օգտագործողներ
7
+ timesheet_permalink: '(Մշտական հղում դեպի այս աղյուսակը)'
8
+ timesheet_group_by: Դասավորել ըստ
data/lang/ja.yml ADDED
@@ -0,0 +1,9 @@
1
+ timesheet_title: 記録時間表
2
+ timesheet_date_from_label: 期間
3
+ timesheet_date_to_label: から
4
+ timesheet_project_label: プロジェクト
5
+ timesheet_activities_label: 活動
6
+ timesheet_users_label: ユーザ
7
+ timesheet_showing_users: 'ユーザ: '
8
+ timesheet_permalink: '(この記録時間表へ直接リンク)'
9
+ timesheet_group_by: グループ化
data/lang/pt-br.yml ADDED
@@ -0,0 +1,9 @@
1
+ timesheet_title: Relatório de Apontamentos
2
+ timesheet_date_from_label: De
3
+ timesheet_date_to_label: Até
4
+ timesheet_project_label: Projeto
5
+ timesheet_activities_label: Atividades
6
+ timesheet_users_label: Usuários
7
+ timesheet_showing_users: 'Exibindo usuários: '
8
+ timesheet_permalink: 'Link permanente'
9
+ timesheet_group_by: 'Agrupar por'
data/lang/ru.yml CHANGED
@@ -4,5 +4,6 @@ timesheet_date_to_label: по
4
4
  timesheet_project_label: Проект
5
5
  timesheet_activities_label: Активность
6
6
  timesheet_users_label: Пользователи
7
+ timesheet_showing_users: 'сводка для пользователя: '
7
8
  timesheet_permalink: '(Постоянная ссылка на эту таблицу)'
8
9
  timesheet_group_by: Группировать по
data/lang/sr.yml ADDED
@@ -0,0 +1,9 @@
1
+ timesheet_title: Satnica
2
+ timesheet_date_from_label: Od
3
+ timesheet_date_to_label: Do
4
+ timesheet_project_label: Projekat
5
+ timesheet_activities_label: Aktivnost
6
+ timesheet_users_label: Korisnici
7
+ timesheet_showing_users: 'pokazujem vreme za: '
8
+ timesheet_permalink: '(Stalni link za ovu satnicu)'
9
+ timesheet_group_by: Grupiši po
data/lang/sv.yml ADDED
@@ -0,0 +1,9 @@
1
+ timesheet_title: "Tidkort"
2
+ timesheet_date_from_label: "Från"
3
+ timesheet_date_to_label: "Till"
4
+ timesheet_project_label: "Projekt"
5
+ timesheet_activities_label: "Aktivitet"
6
+ timesheet_users_label: "Användare"
7
+ timesheet_showing_users: 'visar tid för: '
8
+ timesheet_permalink: '(Permalänk till detta tidkort)'
9
+ timesheet_group_by: "Gruppera efter"
data/lang/uk.yml ADDED
@@ -0,0 +1,9 @@
1
+ timesheet_title: Таблиця витрат часу
2
+ timesheet_date_from_label: Починаючи з
3
+ timesheet_date_to_label: до
4
+ timesheet_project_label: Проект
5
+ timesheet_activities_label: Активність
6
+ timesheet_users_label: Користувачі
7
+ timesheet_showing_users: 'час витрачений користувачем: '
8
+ timesheet_permalink: '(Постійний лінк на цю таблицю)'
9
+ timesheet_group_by: Групувати за
@@ -4,11 +4,22 @@ module TimesheetCompatibility
4
4
  # Wrapper around Redmine's API since Enumerations changed in r2472
5
5
  # This can be removed once 0.9.0 is stable
6
6
  def self.activities
7
- if ::Enumeration.respond_to?(:activities)
7
+ if Object.const_defined?('TimeEntryActivity')
8
+ return ::TimeEntryActivity.all
9
+ elsif ::Enumeration.respond_to?(:activities)
8
10
  return ::Enumeration.activities
9
11
  else
10
12
  return ::Enumeration::get_values('ACTI')
11
13
  end
12
14
  end
15
+
16
+ # Wrapper for Project Specific Enumerations in Redmine 0.9+
17
+ def self.project_specific_sql
18
+ if ::Enumeration.column_names.include?('parent_id') && ::Enumeration.column_names.include?('project_id')
19
+ "OR (#{::Enumeration.table_name}.parent_id IN (:activities) AND #{::Enumeration.table_name}.project_id IN (:projects))"
20
+ else
21
+ ''
22
+ end
23
+ end
13
24
  end
14
25
  end
data/rails/init.rb CHANGED
@@ -1,29 +1 @@
1
- require 'redmine'
2
-
3
- unless Redmine::Plugin.registered_plugins.keys.include?(:timesheet_plugin)
4
- Redmine::Plugin.register :timesheet_plugin do
5
- name 'Timesheet Plugin'
6
- author 'Eric Davis of Little Stream Software'
7
- description 'This is a Timesheet plugin for Redmine to show timelogs for all projects'
8
- url 'https://projects.littlestreamsoftware.com/projects/redmine-timesheet'
9
- author_url 'http://www.littlestreamsoftware.com'
10
-
11
- version '0.5.0'
12
- requires_redmine :version_or_higher => '0.8.0'
13
-
14
- settings :default => {'list_size' => '5', 'precision' => '2'}, :partial => 'settings/timesheet_settings'
15
-
16
- permission :see_project_timesheets, { }, :require => :member
17
-
18
- menu(:top_menu,
19
- :timesheet,
20
- {:controller => 'timesheet', :action => 'index'},
21
- :caption => :timesheet_title,
22
- :if => Proc.new {
23
- User.current.allowed_to?(:see_project_timesheets, nil, :global => true) ||
24
- User.current.allowed_to?(:view_time_entries, nil, :global => true) ||
25
- User.current.admin?
26
- })
27
-
28
- end
29
- end
1
+ require File.dirname(__FILE__) + "/../init"
@@ -0,0 +1,256 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+ class ActiveSupport::TestCase
3
+ def self.use_timesheet_controller_shared(&block)
4
+ should 'should set @timesheet.allowed_projects to the list of current projects the user is a member of' do
5
+ Member.destroy_all # clear any setup memberships
6
+
7
+ project1 = Project.generate!
8
+ project2 = Project.generate!
9
+ projects = [project1, project2]
10
+
11
+ projects.each do |project|
12
+ Member.generate!(:principal => @current_user, :project => project, :roles => [@normal_role])
13
+ end
14
+
15
+ instance_eval &block
16
+
17
+ assert_equal projects, assigns['timesheet'].allowed_projects
18
+ end
19
+
20
+ should 'include public projects in @timesheet.allowed_projects' do
21
+ project1 = Project.generate!(:is_public => true)
22
+ project2 = Project.generate!(:is_public => true)
23
+ projects = [project1, project2]
24
+
25
+ instance_eval &block
26
+
27
+ assert_contains assigns['timesheet'].allowed_projects, project1
28
+ assert_contains assigns['timesheet'].allowed_projects, project2
29
+ end
30
+
31
+ should 'should set @timesheet.allowed_projects to all the projects if the user is an admin' do
32
+ Member.destroy_all # clear any setup memberships
33
+
34
+ @current_user.admin = true
35
+ project1, _ = *generate_project_membership(@current_user)
36
+ project2, _ = *generate_project_membership(@current_user)
37
+ projects = [project1, project2]
38
+
39
+ instance_eval &block
40
+
41
+ assert_equal projects, assigns['timesheet'].allowed_projects
42
+ end
43
+
44
+ should 'should get the list size from the settings' do
45
+ settings = { 'list_size' => 10, 'precision' => '2' }
46
+ Setting.plugin_timesheet_plugin = settings
47
+
48
+ instance_eval &block
49
+ assert_equal 10, assigns['list_size']
50
+ end
51
+
52
+ should 'should get the precision from the settings' do
53
+ settings = { 'list_size' => 10, 'precision' => '2' }
54
+ Setting.plugin_timesheet_plugin = settings
55
+
56
+ instance_eval &block
57
+ assert_equal 2, assigns['precision']
58
+ end
59
+
60
+ should 'should create a new @timesheet' do
61
+ instance_eval &block
62
+ assert assigns['timesheet']
63
+ end
64
+ end
65
+ end
66
+
67
+
68
+ class TimesheetControllerTest < ActionController::TestCase
69
+ def generate_and_login_user(options = {})
70
+ @current_user = User.generate_with_protected!(:admin => false)
71
+ @request.session[:user_id] = @current_user.id
72
+ end
73
+
74
+ def generate_project_membership(user)
75
+ @project = Project.generate!(:is_public => false)
76
+ @member = Member.generate!(:principal => user, :project => @project, :roles => [@normal_role])
77
+ [@project, @member]
78
+ end
79
+
80
+ def setup
81
+ @normal_role = Role.generate!(:name => 'Normal User', :permissions => [:view_time_entries])
82
+ end
83
+
84
+ context "#index with GET request" do
85
+ setup do
86
+ generate_and_login_user
87
+ generate_project_membership(@current_user)
88
+ get 'index'
89
+ end
90
+
91
+ use_timesheet_controller_shared do
92
+ get 'index'
93
+ end
94
+
95
+ should_render_template :index
96
+
97
+ should 'have no timelog entries' do
98
+ assert assigns['timesheet'].time_entries.empty?
99
+ end
100
+ end
101
+
102
+ context "#index with GET request and a session" do
103
+
104
+ should 'should read the session data' do
105
+ generate_and_login_user
106
+ @current_user.admin = true
107
+ @current_user.save!
108
+
109
+ projects = []
110
+ 4.times do |i|
111
+ projects << Project.generate!
112
+ end
113
+
114
+ session[TimesheetController::SessionKey] = HashWithIndifferentAccess.new(
115
+ :projects => projects.collect(&:id).collect(&:to_s),
116
+ :date_to => '2009-01-01',
117
+ :date_from => '2009-01-01'
118
+ )
119
+
120
+ get :index
121
+ assert_equal '2009-01-01', assigns['timesheet'].date_from
122
+ assert_equal '2009-01-01', assigns['timesheet'].date_to
123
+ assert_equal projects, assigns['timesheet'].projects
124
+ end
125
+ end
126
+
127
+ context "#index with GET request from an Anonymous user" do
128
+ setup do
129
+ get 'index'
130
+ end
131
+
132
+ should_render_template :no_projects
133
+
134
+ end
135
+
136
+ context "#report with GET request from an Anonymous user" do
137
+ setup do
138
+ get :report
139
+ end
140
+
141
+ should_respond_with :redirect
142
+ should_redirect_to('index') {{:action => 'index'}}
143
+ end
144
+
145
+ context "#report with POST request from an Anonymous user" do
146
+ setup do
147
+ post :report
148
+ end
149
+
150
+ should_respond_with :redirect
151
+ should_redirect_to('index') {{:action => 'index'}}
152
+
153
+ end
154
+
155
+ context "#report with POST request" do
156
+ setup do
157
+ generate_and_login_user
158
+ end
159
+
160
+ use_timesheet_controller_shared do
161
+ post :report, :timesheet => {}
162
+ end
163
+
164
+ should 'should only allow the allowed projects into @timesheet.projects' do
165
+ project1 = Project.generate!(:is_public => false)
166
+ project2 = Project.generate!(:is_public => false)
167
+ projects = [project1, project2]
168
+
169
+ Member.generate!(:principal => @current_user, :project => project1, :roles => [@normal_role])
170
+
171
+ post :report, :timesheet => { :projects => [project1.id.to_s, project2.id.to_s] }
172
+
173
+ assert_equal [project1], assigns['timesheet'].projects
174
+ end
175
+
176
+ should 'include public projects' do
177
+ project1 = Project.generate!(:is_public => true)
178
+ project2 = Project.generate!(:is_public => true)
179
+ projects = [project1, project2]
180
+
181
+ post :report, :timesheet => { :projects => [project1.id.to_s, project2.id.to_s] }
182
+
183
+ assert_contains assigns['timesheet'].allowed_projects, project1
184
+ assert_contains assigns['timesheet'].allowed_projects, project2
185
+ end
186
+
187
+ should 'should save the session data' do
188
+ generate_project_membership(@current_user)
189
+ post :report, :timesheet => { :projects => ['1'] }
190
+
191
+ assert @request.session[TimesheetController::SessionKey]
192
+ assert @request.session[TimesheetController::SessionKey].keys.include?('projects')
193
+ assert_equal ['1'], @request.session[TimesheetController::SessionKey]['projects']
194
+ end
195
+
196
+ context ":csv format" do
197
+ setup do
198
+ generate_project_membership(@current_user)
199
+ post :report, :timesheet => {:projects => ['1']}, :format => 'csv'
200
+ end
201
+
202
+ should_respond_with_content_type 'text/csv'
203
+ should_respond_with :success
204
+ end
205
+ end
206
+
207
+ context "#report with request with no data" do
208
+ setup do
209
+ generate_and_login_user
210
+ end
211
+
212
+ context 'should redirect to the index' do
213
+ context "from a GET request" do
214
+ setup do
215
+ get 'report', { }
216
+ end
217
+
218
+ should_respond_with :redirect
219
+ should_redirect_to('index') {{:action => 'index' }}
220
+ end
221
+
222
+ context "from a POST request" do
223
+ setup do
224
+ post 'report', { }
225
+ end
226
+
227
+ should_respond_with :redirect
228
+ should_redirect_to('index') {{:action => 'index' }}
229
+ end
230
+ end
231
+ end
232
+
233
+ context "DELETE to :reset" do
234
+ setup do
235
+ generate_and_login_user
236
+ @current_user.admin = true
237
+ @current_user.save!
238
+
239
+ @project = Project.generate!
240
+ session[TimesheetController::SessionKey] = HashWithIndifferentAccess.new(
241
+ :projects => [@project.id.to_s],
242
+ :date_to => '2009-01-01',
243
+ :date_from => '2009-01-01'
244
+ )
245
+
246
+ delete :reset
247
+ end
248
+
249
+ should_respond_with :redirect
250
+ should_redirect_to('index') {{:action => 'index'}}
251
+ should 'clear the session' do
252
+ assert session[TimesheetController::SessionKey].blank?
253
+ end
254
+
255
+ end
256
+ end