knjtasks 0.0.3

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 (69) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +18 -0
  4. data/Gemfile.lock +66 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.rdoc +19 -0
  7. data/Rakefile +49 -0
  8. data/VERSION +1 -0
  9. data/files/database_schema.rb +174 -0
  10. data/lib/knjtasks.rb +172 -0
  11. data/locales/da_DK/LC_MESSAGES/default.mo +0 -0
  12. data/locales/da_DK/LC_MESSAGES/default.po +1153 -0
  13. data/locales/da_DK/title.txt +1 -0
  14. data/locales/en_GB/title.txt +1 -0
  15. data/models/class_comment.rb +44 -0
  16. data/models/class_customer.rb +13 -0
  17. data/models/class_email_check.rb +7 -0
  18. data/models/class_project.rb +22 -0
  19. data/models/class_task.rb +163 -0
  20. data/models/class_task_assigned_user.rb +62 -0
  21. data/models/class_task_check.rb +26 -0
  22. data/models/class_timelog.rb +82 -0
  23. data/models/class_user.rb +125 -0
  24. data/models/class_user_project_link.rb +66 -0
  25. data/models/class_user_rank.rb +3 -0
  26. data/models/class_user_rank_link.rb +17 -0
  27. data/models/class_user_task_list_link.rb +17 -0
  28. data/pages/admin.rhtml +7 -0
  29. data/pages/comment_edit.rhtml +121 -0
  30. data/pages/comment_update_id_per_obj.rhtml +41 -0
  31. data/pages/customer_edit.rhtml +69 -0
  32. data/pages/customer_search.rhtml +80 -0
  33. data/pages/customer_show.rhtml +50 -0
  34. data/pages/frontpage.rhtml +198 -0
  35. data/pages/project_edit.rhtml +129 -0
  36. data/pages/project_search.rhtml +82 -0
  37. data/pages/project_show.rhtml +203 -0
  38. data/pages/task_check_edit.rhtml +98 -0
  39. data/pages/task_edit.rhtml +168 -0
  40. data/pages/task_search.rhtml +131 -0
  41. data/pages/task_show.rhtml +454 -0
  42. data/pages/timelog_edit.rhtml +134 -0
  43. data/pages/timelog_search.rhtml +318 -0
  44. data/pages/user_edit.rhtml +223 -0
  45. data/pages/user_login.rhtml +83 -0
  46. data/pages/user_profile.rhtml +89 -0
  47. data/pages/user_rank_search.rhtml +95 -0
  48. data/pages/user_search.rhtml +136 -0
  49. data/pages/user_show.rhtml +87 -0
  50. data/pages/workstatus.rhtml +320 -0
  51. data/scripts/fckeditor_validate_login.rb +23 -0
  52. data/spec/knjtasks_spec.rb +115 -0
  53. data/spec/spec_helper.rb +12 -0
  54. data/threads/thread_mail_task_comments.rb +114 -0
  55. data/www/api/task.rhtml +9 -0
  56. data/www/api/user.rhtml +20 -0
  57. data/www/clean.rhtml +14 -0
  58. data/www/css/default.css +186 -0
  59. data/www/gfx/body_bg.jpg +0 -0
  60. data/www/gfx/button_bg.png +0 -0
  61. data/www/gfx/main_box_design.png +0 -0
  62. data/www/gfx/main_box_left.png +0 -0
  63. data/www/gfx/main_box_right.png +0 -0
  64. data/www/gfx/main_box_top.png +0 -0
  65. data/www/gfx/main_box_top_left.png +0 -0
  66. data/www/gfx/main_box_top_right.png +0 -0
  67. data/www/index.rhtml +154 -0
  68. data/www/js/default.js +112 -0
  69. metadata +208 -0
@@ -0,0 +1,134 @@
1
+ <%
2
+ task_id = _get["task_id"] if _get["task_id"].to_i > 0
3
+
4
+ if _get["choice"] == "dosave"
5
+ save_hash = {
6
+ :time => _post["textime"],
7
+ :time_transport => _post["textimetransport"],
8
+ :transport_length => _post["textransportlength"],
9
+ :date => Datet.in(_post["texdate"]),
10
+ :comment => _post["texcomment"],
11
+ :task_id => _post["seltask"],
12
+ :invoiced => Knj::Web.checkval(_post["cheinvoiced"], 1, 0)
13
+ }
14
+ end
15
+
16
+ if _get["timelog_id"].to_i > 0
17
+ timelog = _ob.get(:Timelog, _get["timelog_id"])
18
+ task_id = timelog.task.id
19
+ date_val = Datet.in(timelog[:date]).out(:time => false)
20
+ time_val = timelog[:time]
21
+ time_transport_val = timelog[:time_transport]
22
+ url = "&timelog_id=#{timelog.id}"
23
+
24
+ if _get["choice"] == "dosave"
25
+ timelog.update(save_hash)
26
+ exit
27
+ end
28
+
29
+ if _get["choice"] == "dodelete"
30
+ _ob.delete(timelog)
31
+ exit
32
+ end
33
+ else
34
+ date_val = Datet.new.out(:time => false)
35
+ time_val = "00:00:00"
36
+ time_transport_val = "00:00:00"
37
+
38
+ if _get["choice"] == "dosave"
39
+ begin
40
+ timelog = _ob.add(:Timelog, save_hash)
41
+ rescue RuntimeError => e
42
+ puts e.message
43
+ end
44
+
45
+ exit
46
+ end
47
+ end
48
+ %>
49
+
50
+ <form method="get" onsubmit="return do_save_timelog();">
51
+
52
+ <%=_site.boxt(_("Enter details"))%>
53
+ <table class="form" id="formtimelogedit">
54
+ <%
55
+ opts = _ob.list_optshash(:Task, {:debug => false})
56
+ raise "Empty opts?" if opts.empty?
57
+
58
+ print _hb.inputs({
59
+ :title => _("Task"),
60
+ :name => :seltask,
61
+ :value => task_id,
62
+ :opts => opts,
63
+ :descr => _("On which task should this timelog be saved?")
64
+ },{
65
+ :title => _("Time"),
66
+ :name => :textime,
67
+ :value => time_val,
68
+ :descr => _("How much time should be logged?")
69
+ },{
70
+ :title => _("Time transportation"),
71
+ :name => :textimetransport,
72
+ :value => time_transport_val,
73
+ :descr => _("How much time was used on transportation?")
74
+ },{
75
+ :title => _("Transportation length"),
76
+ :name => :textransportlength,
77
+ :value => [timelog, :transport_length],
78
+ :descr => _("How many km was used on transportation?")
79
+ },{
80
+ :title => _("Date"),
81
+ :name => :texdate,
82
+ :value => date_val,
83
+ :descr => _("On which date was the time used?")
84
+ },{
85
+ :title => _("Invoiced"),
86
+ :name => :cheinvoiced,
87
+ :value => [timelog, :invoiced],
88
+ :descr => _("If this timelog has been invoiced or not.")
89
+ },{
90
+ :title => _("Comment"),
91
+ :name => :texcomment,
92
+ :value => [timelog, :comment],
93
+ :type => :textarea,
94
+ :descr => _("What whas done using the time."),
95
+ :height => 200
96
+ })
97
+ %>
98
+ <tr>
99
+ <td colspan="2" class="buttons">
100
+ <input type="submit" value="<%=_("Save")%>" />
101
+ </td>
102
+ </tr>
103
+ </table>
104
+ <%=_site.boxb%>
105
+
106
+ </form>
107
+
108
+ <script type="text/javascript">
109
+ modal_on_opened(function(){
110
+ $("#textime").focus();
111
+ });
112
+
113
+ function do_save_timelog(){
114
+ urlstr = "clean.rhtml?show=timelog_edit&choice=dosave<%=url%>";
115
+ formdata = forms_inputs_read($("#formtimelogedit"));
116
+
117
+ $.ajax({
118
+ type: "POST",
119
+ url: urlstr,
120
+ data: formdata,
121
+ complete: function(data){
122
+ if (data.responseText.length > 0){
123
+ alert(data.responseText);
124
+ }else{
125
+ modal_close();
126
+ events.call("on_timelog_added");
127
+ events.call("do_timelogs_update");
128
+ }
129
+ }
130
+ });
131
+
132
+ return false;
133
+ }
134
+ </script>
@@ -0,0 +1,318 @@
1
+ <%
2
+ _hb.alert(_("You do not have permission to view this page.")).back if !_site.has_rank?("admin")
3
+
4
+ if _get["choice"] == "dosearch"
5
+ begin
6
+ date_from = Datet.in(_get["texdatefrom"])
7
+ rescue
8
+ _hb.alert(_("Invalid date-from.")).back
9
+ end
10
+
11
+ begin
12
+ date_to = Datet.in(_get["texdateto"])
13
+ rescue
14
+ _hb.alert(_("Invalid date-to.")).back
15
+ end
16
+ else
17
+ date_from = Datet.new
18
+ date_from.day = 1
19
+
20
+ date_to = Datet.new
21
+ date_to.day = date_to.days_in_month
22
+ end
23
+
24
+ if _get["choice"] == "domarktimelogsasinvoiced"
25
+ _post["tlog_ids"].split(";").each do |tlog_id|
26
+ tlog = _ob.get(:Timelog, tlog_id)
27
+ tlog[:invoiced] = 1 if !tlog.invoiced?
28
+ end
29
+
30
+ exit
31
+ end
32
+
33
+ print _site.header(_("Timelogs"))
34
+ %>
35
+
36
+ <form method="get" onsubmit="return do_submit_criterias();">
37
+ <%=Knj::Web.hiddens([{:name => :show, :value => :timelog_search}, {:name => :choice, :value => :dosearch}, {:name => :users, :value => ""}, {:name => :projects, :value => ""}])%>
38
+
39
+ <%=_site.boxt(_("Enter criteria"), "400px")%>
40
+ <table class="form">
41
+ <%
42
+ print _hb.inputs({
43
+ :title => _("Date from"),
44
+ :name => :texdatefrom,
45
+ :value => date_from.out(:time => false),
46
+ :descr => _("If you only want timelogs from a specific date and up.")
47
+ },{
48
+ :title => _("Date to"),
49
+ :name => :texdateto,
50
+ :value => date_to.out(:time => false),
51
+ :descr => _("If you only want timelogs up to a specific date.")
52
+ },{
53
+ :title => _("Comment"),
54
+ :name => :texcomment,
55
+ :value => _get["texcomment"],
56
+ :descr => _("A part of the comment in the timelog you are looking for.")
57
+ },{
58
+ :title => _("Users"),
59
+ :name => :seluser,
60
+ :opts => _ob.list_optshash(:User, :list_args => {"orderby" => "name"}),
61
+ :multiple => true,
62
+ :size => 5,
63
+ :values => _get["users"].to_s.split(";").map{|ele| ele.to_i},
64
+ :descr => _("If you want to find timelogs from specific users.")
65
+ },{
66
+ :title => _("Projects"),
67
+ :name => :selproject,
68
+ :opts => _ob.list_optshash(:Project, :list_args => {"orderby" => "name"}),
69
+ :multiple => true,
70
+ :size => 5,
71
+ :values => _get["projects"].to_s.split(";").map{|ele| ele.to_i},
72
+ :descr => _("If you want to find timelogs from specific projects.")
73
+ },{
74
+ :title => _("Invoiced"),
75
+ :name => :selinvoiced,
76
+ :value => _get["selinvoiced"],
77
+ :descr => _("If you only want to view invoiced, uninvoiced or all timelogs."),
78
+ :opts => {
79
+ "" => _("All"),
80
+ "1" => _("Only invoiced"),
81
+ "0" => _("Only un-invoiced")
82
+ }
83
+ })
84
+ %>
85
+ <tr>
86
+ <td colspan="2" class="buttons">
87
+ <input type="submit" value="<%=_("Search")%>" />
88
+ </td>
89
+ </tr>
90
+ </table>
91
+ <%=_site.boxb%>
92
+
93
+ </form>
94
+
95
+ <script type="text/javascript">
96
+ $("#texdatefrom").focus();
97
+
98
+ function do_submit_criterias(){
99
+ $("input[name=users]").val(select_values({sel: $("#seluser"), selected: true, expl: ";"}));
100
+ $("input[name=projects]").val(select_values({sel: $("#selproject"), selected: true, expl: ";"}));
101
+ $("#seluser").val(false);
102
+ return true;
103
+ }
104
+
105
+ function do_mark_invoiced(){
106
+ tlog_ids = []
107
+ $("input[type=hidden]", $("#table_customer_message")).each(function(){
108
+ id = $(this).attr("name").substring(9);
109
+ tlog_ids.push(id);
110
+ });
111
+
112
+ $.ajax({
113
+ type: "POST",
114
+ url: "/clean.rhtml?show=timelog_search&choice=domarktimelogsasinvoiced",
115
+ data: {tlog_ids: tlog_ids.join(";")},
116
+ async: true,
117
+ cache: false,
118
+ complete: function(data){
119
+ if (data.responseText.length > 0){
120
+ alert(data.responseText);
121
+ }else{
122
+ alert("<%=_'All timelogs was marked as invoiced.'%>");
123
+ }
124
+ }
125
+ });
126
+ }
127
+ </script>
128
+
129
+ <%
130
+ if _get["choice"] == "dosearch"
131
+ args = {"orderby" => "date"}
132
+
133
+ if _get["texdatefrom"].to_s.length > 0
134
+ args["date_from"] = date_from
135
+ end
136
+
137
+ if _get["texdateto"].to_s.length > 0
138
+ args["date_to"] = date_to
139
+ end
140
+
141
+ if _get["texcomment"].to_s.length > 0
142
+ args["comment_search"] = _get["texcomment"]
143
+ end
144
+
145
+ if _get["users"].to_s.length > 0
146
+ args["user_id"] = _get["users"].to_s.split(";")
147
+ end
148
+
149
+ if _get["projects"].to_s.length > 0
150
+ args["project_id"] = _get["projects"].to_s.split(";")
151
+ end
152
+
153
+ if _get["selinvoiced"].to_s == "1" or _get["selinvoiced"].to_s == "0"
154
+ args["invoiced"] = _get["selinvoiced"].to_s
155
+ end
156
+
157
+ args_count = args.merge(:count => true)
158
+
159
+ tlogs = _ob.list(:Timelog, args)
160
+ tlogs_count = _ob.list(:Timelog, args_count)
161
+
162
+ %>
163
+ <br />
164
+
165
+ <%=_site.boxt(_("Sum"), "350px")%>
166
+ <table class="form">
167
+ <%
168
+ print _hb.inputs({
169
+ :title => _("Total hours"),
170
+ :type => :info,
171
+ :value => Knj::Locales.number_out(tlogs_count[:sum_time].to_f / 3600, 1) + " / " + Knj::Locales.number_out(tlogs_count[:sum_time_transport].to_f / 3600, 1),
172
+ :descr => _("The total amount of hours of all the found time-logs (first hours used then time used on transport).")
173
+ },{
174
+ :title => _("Total transport"),
175
+ :type => :info,
176
+ :value => Knj::Locales.number_out(tlogs_count[:sum_transport_length], 1),
177
+ :descr => _("Total km's of transport used in all the timelogs found.")
178
+ })
179
+ %>
180
+ </table>
181
+ <%=_site.boxb%>
182
+
183
+ <br />
184
+
185
+ <%=_site.boxt(_("Results"))%>
186
+ <table class="form">
187
+ <thead>
188
+ <tr>
189
+ <th><%=_"Timelog"%></th>
190
+ <th><%=_"User"%></th>
191
+ <th><%=_"Date"%></th>
192
+ <th><%=_"Task"%></th>
193
+ <th><%=_"Invoiced"%></th>
194
+ <th><%=_"Time"%> / <%=_"Transport"%></th>
195
+ <th><%=_"Transport length"%></th>
196
+ </tr>
197
+ </thead>
198
+ <tbody>
199
+ <%
200
+ tlogs_sorted = {}
201
+ tlogs.each do |tlog|
202
+ dbt = Knj::Db::Dbtime.new(tlog[:time])
203
+ dbt_transport = Knj::Db::Dbtime.new(tlog[:time_transport])
204
+ tlogs_sorted[tlog[:task_id]] = [] if !tlogs_sorted.has_key?(tlog[:task_id])
205
+ tlogs_sorted[tlog[:task_id]] << tlog
206
+
207
+ %>
208
+ <tr>
209
+ <td>
210
+ <%=tlog.html%>
211
+ </td>
212
+ <td>
213
+ <%=tlog.user_html%>
214
+ </td>
215
+ <td>
216
+ <%=tlog.date_str(:time => false)%>
217
+ </td>
218
+ <td>
219
+ <%=tlog.task_html%>
220
+ </td>
221
+ <td>
222
+ <%=Knj::Strings.yn_str(tlog.invoiced?, _("Yes"), _("No"))%>
223
+ </td>
224
+ <td>
225
+ <%=Knj::Locales.number_out(dbt.hours_total, 1)%> / <%=Knj::Locales.number_out(dbt_transport.hours_total, 1)%>
226
+ </td>
227
+ <td>
228
+ <%=Knj::Locales.number_out(tlog[:transport_length], 0)%>
229
+ </td>
230
+ </tr>
231
+ <%
232
+ end
233
+
234
+ if tlogs.empty?
235
+ %>
236
+ <tr>
237
+ <td colspan="1" class="error">
238
+ <%=_("No timelogs were found.")%>
239
+ </td>
240
+ </tr>
241
+ <%
242
+ end
243
+ %>
244
+ </tbody>
245
+ </table>
246
+ <%=_site.boxb%>
247
+
248
+ <br />
249
+
250
+ <%=_site.boxt(_("Customer message"))%>
251
+ <table class="list" id="table_customer_message">
252
+ <thead>
253
+ <tr>
254
+ <th><%=_"Date"%>/<%=_"Hours"%></th>
255
+ <th><%=_"User"%></th>
256
+ <th><%=_"Description"%></th>
257
+ </tr>
258
+ </thead>
259
+ <tbody>
260
+ <%
261
+ tlogs_sorted.each do |task_id, tlogs_arr|
262
+ task = _ob.get(:Task, task_id)
263
+
264
+ %>
265
+ <tr>
266
+ <td colspan="3" class="tdt" style="padding-top: 10px;">
267
+ <%=task.name.html%>
268
+ </td>
269
+ </tr>
270
+ <%
271
+
272
+ first = true
273
+ tlogs_arr.each do |tlog|
274
+ if !first
275
+ %>
276
+ <tr>
277
+ <td colspan="3"><hr size="1" color="#cfcfcf" /></td>
278
+ </tr>
279
+ <%
280
+ end
281
+
282
+ first = false if first
283
+
284
+ %>
285
+ <tr>
286
+ <td style="text-align: center;">
287
+ <input type="hidden" name="timelogs_<%=tlog.id%>" value="1" />
288
+
289
+ <%=tlog.date_str(:time => false)%><br />
290
+ <%=Knj::Locales.number_out(tlog.time_dbt.hours_total, 2)%> / <%=Knj::Locales.number_out(tlog.time_transport_dbt.hours_total, 2)%>
291
+ </td>
292
+ <td class="nowrap">
293
+ <%=tlog.user.name.html%>
294
+ </td>
295
+ <td>
296
+ <%=tlog.comment_html%>
297
+ </td>
298
+ </tr>
299
+ <%
300
+ end
301
+ end
302
+
303
+ if !tlogs_sorted.empty?
304
+ %>
305
+ <tr>
306
+ <td colspan="3" style="padding-top: 15px; text-align: right;">
307
+ <input type="button" value="<%=_"Mark timelogs as invoiced"%>" onclick="if (confirm('<%=_"Are you sure you want to mark all the found timelogs as invoiced?"%>')){do_mark_invoiced();}" />
308
+ </td>
309
+ </tr>
310
+ <%
311
+ end
312
+ %>
313
+ </tbody>
314
+ </table>
315
+ <%=_site.boxb%>
316
+ <%
317
+ end
318
+ %>