knjtasks 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +18 -0
- data/Gemfile.lock +66 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +19 -0
- data/Rakefile +49 -0
- data/VERSION +1 -0
- data/files/database_schema.rb +174 -0
- data/lib/knjtasks.rb +172 -0
- data/locales/da_DK/LC_MESSAGES/default.mo +0 -0
- data/locales/da_DK/LC_MESSAGES/default.po +1153 -0
- data/locales/da_DK/title.txt +1 -0
- data/locales/en_GB/title.txt +1 -0
- data/models/class_comment.rb +44 -0
- data/models/class_customer.rb +13 -0
- data/models/class_email_check.rb +7 -0
- data/models/class_project.rb +22 -0
- data/models/class_task.rb +163 -0
- data/models/class_task_assigned_user.rb +62 -0
- data/models/class_task_check.rb +26 -0
- data/models/class_timelog.rb +82 -0
- data/models/class_user.rb +125 -0
- data/models/class_user_project_link.rb +66 -0
- data/models/class_user_rank.rb +3 -0
- data/models/class_user_rank_link.rb +17 -0
- data/models/class_user_task_list_link.rb +17 -0
- data/pages/admin.rhtml +7 -0
- data/pages/comment_edit.rhtml +121 -0
- data/pages/comment_update_id_per_obj.rhtml +41 -0
- data/pages/customer_edit.rhtml +69 -0
- data/pages/customer_search.rhtml +80 -0
- data/pages/customer_show.rhtml +50 -0
- data/pages/frontpage.rhtml +198 -0
- data/pages/project_edit.rhtml +129 -0
- data/pages/project_search.rhtml +82 -0
- data/pages/project_show.rhtml +203 -0
- data/pages/task_check_edit.rhtml +98 -0
- data/pages/task_edit.rhtml +168 -0
- data/pages/task_search.rhtml +131 -0
- data/pages/task_show.rhtml +454 -0
- data/pages/timelog_edit.rhtml +134 -0
- data/pages/timelog_search.rhtml +318 -0
- data/pages/user_edit.rhtml +223 -0
- data/pages/user_login.rhtml +83 -0
- data/pages/user_profile.rhtml +89 -0
- data/pages/user_rank_search.rhtml +95 -0
- data/pages/user_search.rhtml +136 -0
- data/pages/user_show.rhtml +87 -0
- data/pages/workstatus.rhtml +320 -0
- data/scripts/fckeditor_validate_login.rb +23 -0
- data/spec/knjtasks_spec.rb +115 -0
- data/spec/spec_helper.rb +12 -0
- data/threads/thread_mail_task_comments.rb +114 -0
- data/www/api/task.rhtml +9 -0
- data/www/api/user.rhtml +20 -0
- data/www/clean.rhtml +14 -0
- data/www/css/default.css +186 -0
- data/www/gfx/body_bg.jpg +0 -0
- data/www/gfx/button_bg.png +0 -0
- data/www/gfx/main_box_design.png +0 -0
- data/www/gfx/main_box_left.png +0 -0
- data/www/gfx/main_box_right.png +0 -0
- data/www/gfx/main_box_top.png +0 -0
- data/www/gfx/main_box_top_left.png +0 -0
- data/www/gfx/main_box_top_right.png +0 -0
- data/www/index.rhtml +154 -0
- data/www/js/default.js +112 -0
- metadata +208 -0
@@ -0,0 +1,98 @@
|
|
1
|
+
<%
|
2
|
+
if _get["choice"] == "dosave"
|
3
|
+
save_hash = {
|
4
|
+
:name => _post["texname"],
|
5
|
+
:descr => _post["texdescr"]
|
6
|
+
}
|
7
|
+
end
|
8
|
+
|
9
|
+
if _get["check_id"].to_i > 0
|
10
|
+
check = _ob.get(:Task_check, _get["check_id"])
|
11
|
+
url = "&check_id=#{check.id}"
|
12
|
+
|
13
|
+
if _get["choice"] == "dosave"
|
14
|
+
check.update(save_hash)
|
15
|
+
exit
|
16
|
+
end
|
17
|
+
|
18
|
+
if _get["choice"] == "dodelete"
|
19
|
+
_ob.delete(check)
|
20
|
+
exit
|
21
|
+
end
|
22
|
+
|
23
|
+
if _get["choice"] == "setcheck"
|
24
|
+
check.update(:checked => _get["checkval"].to_i)
|
25
|
+
exit
|
26
|
+
end
|
27
|
+
else
|
28
|
+
task = _ob.get(:Task, _get["task_id"])
|
29
|
+
url = "&task_id=#{task.id}"
|
30
|
+
|
31
|
+
if _get["choice"] == "dosave"
|
32
|
+
save_hash[:task_id] = task.id
|
33
|
+
check = _ob.add(:Task_check, save_hash)
|
34
|
+
exit
|
35
|
+
end
|
36
|
+
end
|
37
|
+
%>
|
38
|
+
|
39
|
+
<form id="formtaskcheck" method="get" onsubmit="return do_task_check_save();">
|
40
|
+
|
41
|
+
<%=_site.boxt(_("Enter details"), "450px")%>
|
42
|
+
<table class="form">
|
43
|
+
<%
|
44
|
+
print Knj::Web.inputs([{
|
45
|
+
:title => _("Name"),
|
46
|
+
:name => :texname,
|
47
|
+
:value => [check, :name],
|
48
|
+
:descr => _("The name of the check as it should appear for the other users.")
|
49
|
+
},{
|
50
|
+
:title => _("Description"),
|
51
|
+
:name => :texdescr,
|
52
|
+
:value => [check, :descr],
|
53
|
+
:type => :textarea,
|
54
|
+
:height => 100,
|
55
|
+
:descr => _("A description that describes what should be done before marking this check.")
|
56
|
+
}])
|
57
|
+
%>
|
58
|
+
<tr>
|
59
|
+
<td colspan="2" class="buttons">
|
60
|
+
<%if check%>
|
61
|
+
<input type="button" value="<%=_"Delete"%>" onclick="if (confirm('<%=_("Do you want to delete this check?")%>')){}" />
|
62
|
+
<%end%>
|
63
|
+
<input type="submit" value="<%=_("Save")%>" />
|
64
|
+
</td>
|
65
|
+
</tr>
|
66
|
+
</table>
|
67
|
+
<%=_site.boxb%>
|
68
|
+
|
69
|
+
</form>
|
70
|
+
|
71
|
+
<script type="text/javascript">
|
72
|
+
modal_on_opened(function(){
|
73
|
+
$("#texname").focus();
|
74
|
+
});
|
75
|
+
|
76
|
+
function do_task_check_save(){
|
77
|
+
$.ajax({
|
78
|
+
type: "POST",
|
79
|
+
url: "clean.rhtml?show=task_check_edit&choice=dosave<%=url%>",
|
80
|
+
data: forms_inputs_read($("#formtaskcheck")),
|
81
|
+
cache: false,
|
82
|
+
async: false,
|
83
|
+
complete: function(data){
|
84
|
+
if (data.responseText.length > 0){
|
85
|
+
alert(data.responseText);
|
86
|
+
}
|
87
|
+
|
88
|
+
<%if !check%>
|
89
|
+
events.call("on_task_check_added");
|
90
|
+
<%end%>
|
91
|
+
|
92
|
+
events.call("do_task_check_update");
|
93
|
+
modal_close();
|
94
|
+
}
|
95
|
+
});
|
96
|
+
return false;
|
97
|
+
}
|
98
|
+
</script>
|
@@ -0,0 +1,168 @@
|
|
1
|
+
<%
|
2
|
+
if _get["choice"] == "dosave"
|
3
|
+
save_hash = {
|
4
|
+
:name => _post["texname"],
|
5
|
+
:descr => _post["texdescr"],
|
6
|
+
:project_id => _post["selproject"],
|
7
|
+
:type => _post["seltype"],
|
8
|
+
:status => _post["selstatus"],
|
9
|
+
:priority => _post["selpriority"]
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
if _get["task_id"].to_i > 0
|
14
|
+
task = _ob.get(:Task, _get["task_id"])
|
15
|
+
title = sprintf(_("Edit task: %s."), task.name.html)
|
16
|
+
project_id = task[:project_id]
|
17
|
+
|
18
|
+
if _get["choice"] == "dosave"
|
19
|
+
task.update(save_hash)
|
20
|
+
_hb.redirect("?show=task_show&task_id=#{task.id}")
|
21
|
+
end
|
22
|
+
|
23
|
+
if _get["choice"] == "dodelete"
|
24
|
+
_ob.delete(task)
|
25
|
+
_hb.redirect("?show=task_search")
|
26
|
+
end
|
27
|
+
else
|
28
|
+
title = _("Add new task")
|
29
|
+
project_id = _get["project_id"] if _get["project_id"].to_i > 0
|
30
|
+
|
31
|
+
if _get["choice"] == "dosave"
|
32
|
+
begin
|
33
|
+
task = _ob.add(:Task, save_hash)
|
34
|
+
_hb.redirect("?show=task_show&task_id=#{task.id}")
|
35
|
+
rescue => e
|
36
|
+
_hb.alert(e.message).back
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
project_opts = _ob.list_optshash(:Project)
|
42
|
+
if project_opts.empty?
|
43
|
+
_hb.alert(_("No projects has been added to this installation yet - please do that first.")).back
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
#Generate user-projects for the select-box.
|
48
|
+
projects_opts = {"" => _("None")}
|
49
|
+
|
50
|
+
if _site.has_rank?("admin")
|
51
|
+
_ob.list(:Project) do |project|
|
52
|
+
projects_opts[project.id] = project.name
|
53
|
+
end
|
54
|
+
else
|
55
|
+
_site.user.projects.each do |link|
|
56
|
+
projects_opts[link[:project_id]] = link.project.name
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
sorted = projects_opts.sort do |a, b|
|
61
|
+
if a[0] == ""
|
62
|
+
ret = -1
|
63
|
+
elsif b[0] == ""
|
64
|
+
ret = 1
|
65
|
+
else
|
66
|
+
ret = a[1].downcase <=> b[1].downcase
|
67
|
+
end
|
68
|
+
|
69
|
+
ret
|
70
|
+
end
|
71
|
+
|
72
|
+
projects_opts = {}
|
73
|
+
sorted.each do |sort|
|
74
|
+
projects_opts[sort[0]] = sort[1]
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
#Write page title.
|
79
|
+
print _site.header(title)
|
80
|
+
%>
|
81
|
+
|
82
|
+
<form method="post" action="?show=task_edit&choice=dosave<%if task; print "&task_id=#{task.id}"; end%>">
|
83
|
+
|
84
|
+
<%=_site.boxt(_("Enter details"), 700)%>
|
85
|
+
<table class="form">
|
86
|
+
<%
|
87
|
+
priority_opts = {}
|
88
|
+
1.upto(10) do |count|
|
89
|
+
priority_opts[count] = count
|
90
|
+
end
|
91
|
+
|
92
|
+
print _hb.inputs({
|
93
|
+
:title => _("Name"),
|
94
|
+
:name => :texname,
|
95
|
+
:value => [task, :name],
|
96
|
+
:descr => _("The name of the task as it should appear in this system.")
|
97
|
+
},{
|
98
|
+
:title => _("Project"),
|
99
|
+
:name => :selproject,
|
100
|
+
:value => project_id,
|
101
|
+
:opts => projects_opts,
|
102
|
+
:descr => _("The project that this task belongs under.")
|
103
|
+
},{
|
104
|
+
:title => _("Type"),
|
105
|
+
:name => :seltype,
|
106
|
+
:value => [task, :type],
|
107
|
+
:descr => _("The type of the task."),
|
108
|
+
:opts => _ob.static(:Task, :type_opts)
|
109
|
+
},{
|
110
|
+
:title => _("Status"),
|
111
|
+
:name => :selstatus,
|
112
|
+
:value => [task, :status],
|
113
|
+
:descr => _("The status of the task."),
|
114
|
+
:opts => _ob.static(:Task, :status_opts)
|
115
|
+
},{
|
116
|
+
:title => _("Priority"),
|
117
|
+
:name => :selpriority,
|
118
|
+
:value => [task, :priority],
|
119
|
+
:opts => priority_opts,
|
120
|
+
:descr => _("10 for most important and 1 for least important.")
|
121
|
+
},{
|
122
|
+
:title => _("Description"),
|
123
|
+
:name => :texdescr,
|
124
|
+
:value => [task, :descr],
|
125
|
+
:descr => _("The description as it should appear for the users."),
|
126
|
+
:type => :fckeditor,
|
127
|
+
:height => 500
|
128
|
+
})
|
129
|
+
%>
|
130
|
+
<tr>
|
131
|
+
<td colspan="2" class="buttons">
|
132
|
+
<input type="button" value="<%=_"Insert browser and os"%>" onclick="insert_browser_and_os()" />
|
133
|
+
<%if task%>
|
134
|
+
<input type="button" value="<%=_("Show")%>" onclick="location.href='?show=task_show&task_id=<%=task.id%>';" />
|
135
|
+
<input type="button" value="<%=_("Delete")%>" onclick="if (confirm('<%=_("Do you want to delete this task?")%>')){location.href='?show=task_edit&task_id=<%=task.id%>&choice=dodelete';}" />
|
136
|
+
<%end%>
|
137
|
+
<input type="submit" value="<%=_("Save")%>" />
|
138
|
+
</td>
|
139
|
+
</tr>
|
140
|
+
</table>
|
141
|
+
<%=_site.boxb%>
|
142
|
+
|
143
|
+
</form>
|
144
|
+
|
145
|
+
<%
|
146
|
+
browser = Knj::Web.browser
|
147
|
+
%>
|
148
|
+
|
149
|
+
<script type="text/javascript">
|
150
|
+
$("#texname").focus()
|
151
|
+
|
152
|
+
var browser_and_os_inserted = false
|
153
|
+
$("#seltype").change(function(){
|
154
|
+
if (this.value == "bug" && !browser_and_os_inserted){
|
155
|
+
insert_browser_and_os()
|
156
|
+
}
|
157
|
+
})
|
158
|
+
|
159
|
+
function insert_browser_and_os(){
|
160
|
+
browser_and_os_inserted = true
|
161
|
+
|
162
|
+
fck = FCKeditorAPI.GetInstance("texdescr")
|
163
|
+
fck.InsertHtml(" ")
|
164
|
+
fck.InsertHtml("<b><%=_'Browser'%>:</b> <%=Knj::Web.html(browser['title'])%><br />")
|
165
|
+
fck.InsertHtml("<b><%=_'Version'%>:</b> " + $.browser.version + "<br />")
|
166
|
+
fck.InsertHtml("<b><%=_'Operating system'%>:</b> <%=Knj::Web.html(Php4r.ucwords(browser['os']))%> <%=Knj::Web.html(browser['os_version'])%><br />")
|
167
|
+
}
|
168
|
+
</script>
|
@@ -0,0 +1,131 @@
|
|
1
|
+
<%
|
2
|
+
print _site.header(_("Search for tasks"))
|
3
|
+
%>
|
4
|
+
|
5
|
+
<form method="get">
|
6
|
+
<%=Knj::Web.hiddens([{:name => :show, :value => :task_search}, {:name => :choice, :value => :dosearch}])%>
|
7
|
+
|
8
|
+
<%=_site.boxt(_("Enter criteria"), 350)%>
|
9
|
+
<table class="form">
|
10
|
+
<%
|
11
|
+
if _site.has_rank?(:admin)
|
12
|
+
users = _ob.list(:User)
|
13
|
+
else
|
14
|
+
users = _site.user.users_list
|
15
|
+
end
|
16
|
+
|
17
|
+
users_opts = {"" => _("All")}
|
18
|
+
users.each do |user|
|
19
|
+
users_opts[user.id] = user.name
|
20
|
+
end
|
21
|
+
|
22
|
+
users = nil
|
23
|
+
|
24
|
+
print _hb.inputs({
|
25
|
+
:title => _("Name"),
|
26
|
+
:name => :texname,
|
27
|
+
:value => _get["texname"],
|
28
|
+
:descr => _("A part of the name of the task you are looking for.")
|
29
|
+
},{
|
30
|
+
:title => _("Description"),
|
31
|
+
:name => :texdescr,
|
32
|
+
:value => _get["texdescr"],
|
33
|
+
:descr => _("A part of the description of the task you are looking for.")
|
34
|
+
},{
|
35
|
+
:title => _("Status"),
|
36
|
+
:name => :selstatus,
|
37
|
+
:opts => {"" => _("All")}.merge(_ob.static(:Task, :status_opts)),
|
38
|
+
:descr => _("If you only want to find tasks with a specific status."),
|
39
|
+
:value => _get["selstatus"]
|
40
|
+
},{
|
41
|
+
:title => _("Type"),
|
42
|
+
:name => :seltype,
|
43
|
+
:opts => {"" => _("All")}.merge(_ob.static(:Task, :type_opts)),
|
44
|
+
:descr => _("If you only want to find tasks of a specific type."),
|
45
|
+
:value => _get["seltype"]
|
46
|
+
},{
|
47
|
+
:title => _("User"),
|
48
|
+
:name => :seluser,
|
49
|
+
:opts => users_opts,
|
50
|
+
:value => _get["seluser"],
|
51
|
+
:descr => _("If you only want to see tasks from a specific user.")
|
52
|
+
})
|
53
|
+
%>
|
54
|
+
<tr>
|
55
|
+
<td colspan="2" class="buttons">
|
56
|
+
<input type="button" value="<%=_"Add new"%>" onclick="location.href='?show=task_edit';" />
|
57
|
+
<input type="submit" value="<%=_"Search"%>" />
|
58
|
+
</td>
|
59
|
+
</tr>
|
60
|
+
</table>
|
61
|
+
<%=_site.boxb%>
|
62
|
+
|
63
|
+
</form>
|
64
|
+
|
65
|
+
<script type="text/javascript">
|
66
|
+
$("#texname").focus()
|
67
|
+
</script>
|
68
|
+
|
69
|
+
<%
|
70
|
+
if _get["choice"] == "dosearch"
|
71
|
+
args = {"orderby" => "name"}
|
72
|
+
args["name_search"] = _get["texname"] if _get["texname"].to_s.length > 0
|
73
|
+
args["descr_search"] = _get["texdescr"] if _get["texdescr"].to_s.length > 0
|
74
|
+
args["status"] = _get["selstatus"] if _get["selstatus"].to_s.length > 0
|
75
|
+
args["type"] = _get["seltype"] if _get["seltype"].to_s.length > 0
|
76
|
+
args["user_id"] = _get["seluser"] if _get["seluser"].to_i > 0
|
77
|
+
|
78
|
+
%>
|
79
|
+
<br />
|
80
|
+
|
81
|
+
<%=_site.boxt(_("Results"), 900)%>
|
82
|
+
<table class="list">
|
83
|
+
<thead>
|
84
|
+
<tr>
|
85
|
+
<th><%=_"Name"%></th>
|
86
|
+
<th><%=_"Status"%></th>
|
87
|
+
<th><%=_"Project"%></th>
|
88
|
+
<th><%=_"Author"%></th>
|
89
|
+
</tr>
|
90
|
+
</thead>
|
91
|
+
<tbody>
|
92
|
+
<%
|
93
|
+
count = 0
|
94
|
+
_ob.list(:Task, args) do |task|
|
95
|
+
next if !task.has_view_access?(_site.user)
|
96
|
+
count += 1
|
97
|
+
|
98
|
+
%>
|
99
|
+
<tr>
|
100
|
+
<td>
|
101
|
+
<%=task.html%>
|
102
|
+
</td>
|
103
|
+
<td>
|
104
|
+
<%=task.status_str.html%>
|
105
|
+
</td>
|
106
|
+
<td>
|
107
|
+
<%=task.project_html%>
|
108
|
+
</td>
|
109
|
+
<td>
|
110
|
+
<%=task.user_html%>
|
111
|
+
</td>
|
112
|
+
</tr>
|
113
|
+
<%
|
114
|
+
end
|
115
|
+
|
116
|
+
if count <= 0
|
117
|
+
%>
|
118
|
+
<tr>
|
119
|
+
<td colspan="1" class="error">
|
120
|
+
<%=_("No tasks were found.")%>
|
121
|
+
</td>
|
122
|
+
</tr>
|
123
|
+
<%
|
124
|
+
end
|
125
|
+
%>
|
126
|
+
</tbody>
|
127
|
+
</table>
|
128
|
+
<%=_site.boxb%>
|
129
|
+
<%
|
130
|
+
end
|
131
|
+
%>
|
@@ -0,0 +1,454 @@
|
|
1
|
+
<%
|
2
|
+
if _get["choice"] == "removeassigned"
|
3
|
+
link = _ob.get(:Task_assigned_user, _get["link_id"])
|
4
|
+
task = link.task
|
5
|
+
_hb.alert(_("You do not have access to that task and cannot view this page.")).back if !task.has_view_access?(_site.user)
|
6
|
+
_ob.delete(link)
|
7
|
+
exit
|
8
|
+
end
|
9
|
+
|
10
|
+
task = _ob.get(:Task, _get["task_id"])
|
11
|
+
_hb.alert(_("You do not have access to that task and cannot view this page.")).back if !task.has_view_access?(_site.user)
|
12
|
+
|
13
|
+
tlogs = task.timelogs("orderby" => [["date", "desc"]])
|
14
|
+
|
15
|
+
if _get["choice"] == "getcomments"
|
16
|
+
comments = task.comments("orderby" => ["date_saved", "id"])
|
17
|
+
|
18
|
+
comments.each do |comment|
|
19
|
+
%>
|
20
|
+
<div class="comment_<%=comment.id%>" style="padding-bottom: 25px;">
|
21
|
+
<table style="width: 100%;">
|
22
|
+
<tr>
|
23
|
+
<td style="white-space: nowrap; width: 25px;">
|
24
|
+
#<%=Knj::Locales.number_out(comment[:id_per_obj], 0)%>
|
25
|
+
</td>
|
26
|
+
<td style="font-weight: bold;">
|
27
|
+
<%=comment.user_html%>
|
28
|
+
</td>
|
29
|
+
<td style="width: 260px; text-align: right; font-weight: bold;">
|
30
|
+
<%if task.has_access?(_site.user)%>
|
31
|
+
(<a href="javascript: comment_edit('<%=comment.id%>');"><%=_"edit"%></a>, <a href="javascript: if (confirm('<%=_"Do you want to delete this comment?"%>')){comment_delete('<%=comment.id%>');}"><%=_"delete"%></a>)
|
32
|
+
|
33
|
+
<%end%>
|
34
|
+
<%=comment.date_saved_str%>
|
35
|
+
</td>
|
36
|
+
</tr>
|
37
|
+
<tr>
|
38
|
+
<td colspan="3" style="border-top: 1px solid #cfcfcf; border-bottom: 1px solid #cfcfcf;">
|
39
|
+
<%=comment[:comment]%>
|
40
|
+
</td>
|
41
|
+
</tr>
|
42
|
+
</table>
|
43
|
+
</div>
|
44
|
+
<%
|
45
|
+
end
|
46
|
+
|
47
|
+
if comments.empty?
|
48
|
+
%>
|
49
|
+
<div class="error">
|
50
|
+
<%=_"No comments were found for this task."%>
|
51
|
+
</div>
|
52
|
+
<%
|
53
|
+
end
|
54
|
+
|
55
|
+
exit
|
56
|
+
end
|
57
|
+
|
58
|
+
if _get["choice"] == "gettimelogs"
|
59
|
+
%>
|
60
|
+
<table class="list">
|
61
|
+
<thead>
|
62
|
+
<tr>
|
63
|
+
<th><%=_"ID"%></th>
|
64
|
+
<th><%=_"Hours"%></th>
|
65
|
+
<th><%=_"Date"%></th>
|
66
|
+
<th><%=_"User"%></th>
|
67
|
+
<th><%=_"Comment"%></th>
|
68
|
+
<%if _site.has_rank?("admin") and task.has_access?(_site.user)%>
|
69
|
+
<th><%=_"Delete"%></th>
|
70
|
+
<%end%>
|
71
|
+
</tr>
|
72
|
+
</thead>
|
73
|
+
<tbody>
|
74
|
+
<%
|
75
|
+
first = true
|
76
|
+
count_shown = 0
|
77
|
+
cur_date = Datet.new
|
78
|
+
|
79
|
+
tlogs.each do |tlog|
|
80
|
+
tlog_date = tlog.date
|
81
|
+
next if !_site.has_rank?("admin") and tlog_date.day == cur_date.day and tlog_date.month == cur_date.month and tlog_date.year == cur_date.year
|
82
|
+
|
83
|
+
dbt = Knj::Db::Dbtime.new(tlog[:time])
|
84
|
+
count_shown += 1
|
85
|
+
|
86
|
+
if !first
|
87
|
+
%>
|
88
|
+
<tr>
|
89
|
+
<td colspan="6"><hr size="1" color="#cfcfcf" /><td>
|
90
|
+
</tr>
|
91
|
+
<%
|
92
|
+
end
|
93
|
+
|
94
|
+
first = false if first
|
95
|
+
|
96
|
+
%>
|
97
|
+
<tr>
|
98
|
+
<td style="width: 50px;">
|
99
|
+
<%=tlog.html(:key => :id_localized)%>
|
100
|
+
</td>
|
101
|
+
<td style="width: 60px;">
|
102
|
+
<%=Knj::Locales.number_out(dbt.hours_total, 1)%>
|
103
|
+
</td>
|
104
|
+
<td class="nowrap" style="width: 90px;">
|
105
|
+
<%=tlog.date_str(:time => false)%>
|
106
|
+
</td>
|
107
|
+
<td style="width: 130px;">
|
108
|
+
<%=tlog.user_html%>
|
109
|
+
</td>
|
110
|
+
<td>
|
111
|
+
<%=tlog.comment_html%>
|
112
|
+
</td>
|
113
|
+
<%if _site.has_rank?("admin") and task.has_access?(_site.user)%>
|
114
|
+
<td style="width: 10%;">
|
115
|
+
(<a href="javascript: if (confirm('<%=_("Do you want to delete this timelog?")%>')){timelog_delete('<%=tlog.id%>');}"><%=_"delete"%></a>)
|
116
|
+
</td>
|
117
|
+
<%end%>
|
118
|
+
</tr>
|
119
|
+
<%
|
120
|
+
end
|
121
|
+
|
122
|
+
if count_shown <= 0
|
123
|
+
%>
|
124
|
+
<tr>
|
125
|
+
<td colspan="6" class="error">
|
126
|
+
<%=_("No timelogs were found.")%>
|
127
|
+
</td>
|
128
|
+
</tr>
|
129
|
+
<%
|
130
|
+
end
|
131
|
+
%>
|
132
|
+
</tbody>
|
133
|
+
</table>
|
134
|
+
<%
|
135
|
+
|
136
|
+
exit
|
137
|
+
end
|
138
|
+
|
139
|
+
if _get["choice"] == "getusers"
|
140
|
+
users = task.assigned_users
|
141
|
+
|
142
|
+
%>
|
143
|
+
<table class="list">
|
144
|
+
<thead>
|
145
|
+
<tr>
|
146
|
+
<th><%=_("User")%></th>
|
147
|
+
<th><%=_("Actions")%></th>
|
148
|
+
</tr>
|
149
|
+
</thead>
|
150
|
+
<tbody>
|
151
|
+
<%
|
152
|
+
users.each do |link|
|
153
|
+
%>
|
154
|
+
<tr>
|
155
|
+
<td>
|
156
|
+
<%=link.user.html%>
|
157
|
+
</td>
|
158
|
+
<td>
|
159
|
+
(<a href="javascript: if (confirm('<%=_("Do you want to remove this user from this task?")%>')){task_remove_assigned('<%=link.id%>');}"><%=_("remove")%></a>)
|
160
|
+
</td>
|
161
|
+
</tr>
|
162
|
+
<%
|
163
|
+
end
|
164
|
+
|
165
|
+
if users.empty?
|
166
|
+
%>
|
167
|
+
<tr>
|
168
|
+
<td colspan="2" class="error">
|
169
|
+
<%=_("No users has been assigned to this task.")%>
|
170
|
+
</td>
|
171
|
+
</tr>
|
172
|
+
<%
|
173
|
+
end
|
174
|
+
%>
|
175
|
+
</tbody>
|
176
|
+
</table>
|
177
|
+
<%
|
178
|
+
exit
|
179
|
+
end
|
180
|
+
|
181
|
+
if _get["choice"] == "assignuser"
|
182
|
+
begin
|
183
|
+
link = _ob.add(:Task_assigned_user, {
|
184
|
+
:task_id => task.id,
|
185
|
+
:user_id => _get["user_id"]
|
186
|
+
})
|
187
|
+
rescue RuntimeError => e
|
188
|
+
puts e.message
|
189
|
+
end
|
190
|
+
|
191
|
+
exit
|
192
|
+
end
|
193
|
+
|
194
|
+
if _get["choice"] == "getchecks"
|
195
|
+
checks = task.checks("orderby" => ["name", "id"])
|
196
|
+
|
197
|
+
checks.each do |check|
|
198
|
+
%>
|
199
|
+
<div>
|
200
|
+
<input type="checkbox" id="checheck_<%=check.id%>" name="checheck[<%=check.id%>]"<%if check[:checked].to_i == 1%> checked="checked"<%end%> onchange="task_check_set('<%=check.id%>', this.value);" />
|
201
|
+
<label for="checheck_<%=check.id%>"><%=check.name.html%></label>
|
202
|
+
|
203
|
+
(<a href="javascript: task_check_edit('<%=check.id%>');"><%=_("edit")%></a>, <a href="javascript: if (confirm('<%=_("Do you want to delete this check?")%>')){task_check_delete('<%=check.id%>');}"><%=_"delete"%></a>)
|
204
|
+
</div>
|
205
|
+
<%
|
206
|
+
|
207
|
+
if check[:descr].to_s.length > 0
|
208
|
+
%>
|
209
|
+
<div class="tdd">
|
210
|
+
<%=Php4r.nl2br(check[:descr].html)%>
|
211
|
+
</div>
|
212
|
+
<%
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
if checks.empty?
|
217
|
+
%>
|
218
|
+
<div class="error">
|
219
|
+
<%=_("No checks has been added for this task.")%>
|
220
|
+
</div>
|
221
|
+
<%
|
222
|
+
end
|
223
|
+
|
224
|
+
exit
|
225
|
+
end
|
226
|
+
|
227
|
+
if _get["choice"] == "addtolist"
|
228
|
+
_ob.add(:User_task_list_link, {
|
229
|
+
:task_id => task.id,
|
230
|
+
:user_id => _site.user.id
|
231
|
+
})
|
232
|
+
_hb.redirect("/?show=task_show&task_id=#{task.id}")
|
233
|
+
elsif _get["choice"] == "removefromlist"
|
234
|
+
_ob.list(:User_task_list_link, {
|
235
|
+
"task" => task,
|
236
|
+
"user" => _site.user
|
237
|
+
}) do |link|
|
238
|
+
_ob.delete(link)
|
239
|
+
end
|
240
|
+
|
241
|
+
_hb.redirect("/?show=task_show&task_id=#{task.id}")
|
242
|
+
end
|
243
|
+
|
244
|
+
print _site.header(sprintf(_("Show task: %s."), task.name.html))
|
245
|
+
%>
|
246
|
+
|
247
|
+
<div style="padding-bottom: 15px;">
|
248
|
+
<input type="button" value="<%=_"Edit task"%>" onclick="location.href='?show=task_edit&task_id=<%=task.id%>';" />
|
249
|
+
|
250
|
+
<%
|
251
|
+
task_link = _ob.get_by(:User_task_list_link, {
|
252
|
+
"user" => _site.user,
|
253
|
+
"task" => task
|
254
|
+
})
|
255
|
+
|
256
|
+
if task_link
|
257
|
+
%>
|
258
|
+
<input type="button" value="<%=_"Remove from list"%>" onclick="location.href='/?show=task_show&task_id=<%=task.id%>&choice=removefromlist';" />
|
259
|
+
<%
|
260
|
+
else
|
261
|
+
%>
|
262
|
+
<input type="button" value="<%=_"Add to list"%>" onclick="location.href='/?show=task_show&task_id=<%=task.id%>&choice=addtolist';" />
|
263
|
+
<%
|
264
|
+
end
|
265
|
+
%>
|
266
|
+
</div>
|
267
|
+
|
268
|
+
<div style="padding-bottom: 15px;">
|
269
|
+
<table style="width: 100%;" cellspacing="0" cellpadding="0">
|
270
|
+
<tr>
|
271
|
+
<td style="vertical-align: top; width: 60%;">
|
272
|
+
<%=_site.boxt(_("Task"))%>
|
273
|
+
<table class="form">
|
274
|
+
<%
|
275
|
+
print Knj::Web.inputs([{
|
276
|
+
:title => _("Status"),
|
277
|
+
:type => :info,
|
278
|
+
:value => _ob.static(:Task, :status_opts)[task[:status].to_sym],
|
279
|
+
:descr => _("The current status of the task.")
|
280
|
+
},{
|
281
|
+
:title => _("Type"),
|
282
|
+
:type => :info,
|
283
|
+
:value => _ob.static(:Task, :type_opts)[task[:type].to_sym],
|
284
|
+
:descr => _("The type of task this is.")
|
285
|
+
},{
|
286
|
+
:title => _("Date"),
|
287
|
+
:type => :info,
|
288
|
+
:value => task.date_added_str(:time => false),
|
289
|
+
:descr => _("The date this task was added.")
|
290
|
+
},{
|
291
|
+
:title => _("Project"),
|
292
|
+
:type => :info,
|
293
|
+
:value => task.project_html,
|
294
|
+
:descr => _("The project this task is created under.")
|
295
|
+
},{
|
296
|
+
:title => _("Author"),
|
297
|
+
:type => :info,
|
298
|
+
:value => task.user_html,
|
299
|
+
:descr => _("The user that created this task.")
|
300
|
+
},{
|
301
|
+
:title => _("Priority"),
|
302
|
+
:type => :info,
|
303
|
+
:value => _hb.num(task[:priority], 0),
|
304
|
+
:descr => _("The priority of the task. 10 as most important and 1 as least important.")
|
305
|
+
}])
|
306
|
+
%>
|
307
|
+
</table>
|
308
|
+
<%=_site.boxb%>
|
309
|
+
|
310
|
+
<br />
|
311
|
+
|
312
|
+
<%=_site.boxt(_("Description"))%>
|
313
|
+
<%
|
314
|
+
descr = task[:descr]
|
315
|
+
require "/usr/share/fckeditor/fckeditor.rb"
|
316
|
+
|
317
|
+
if FCKeditor.is_null?(descr)
|
318
|
+
%>
|
319
|
+
<div class="error">
|
320
|
+
<%=_("No description has been written for this task.")%>
|
321
|
+
</div>
|
322
|
+
<%
|
323
|
+
else
|
324
|
+
print descr
|
325
|
+
end
|
326
|
+
%>
|
327
|
+
<%=_site.boxb%>
|
328
|
+
</td>
|
329
|
+
<td style="vertical-align: top; padding-left: 15px;">
|
330
|
+
<%=_site.boxt(_("Assigned users"))%>
|
331
|
+
<div style="padding-bottom: 10px;">
|
332
|
+
<input type="button" value="<%=_("Assign a user")%>" onclick="modal({title: '<%=_"Assign user to task"%>', url: 'clean.rhtml?show=user_search&ajaxsearch=true&not_in_task_id=<%=task.id%>&jscallback=task_show_assign_user_choose'});" />
|
333
|
+
</div>
|
334
|
+
|
335
|
+
<div id="divusers">
|
336
|
+
<div class="error"><%=_"Loading - please wait..."%></div>
|
337
|
+
</div>
|
338
|
+
<%=_site.boxb%>
|
339
|
+
|
340
|
+
<br />
|
341
|
+
|
342
|
+
<%=_site.boxt(_("Checklist"))%>
|
343
|
+
<div style="padding-bottom: 15px;">
|
344
|
+
<input type="button" value="<%=_("Add new check")%>" onclick="modal({title: '<%=_"Add new check"%>', url: 'clean.rhtml?show=task_check_edit&task_id=<%=task.id%>'});" />
|
345
|
+
</div>
|
346
|
+
|
347
|
+
<div id="divchecks">
|
348
|
+
<div class="error"><%=_("Loading - please wait...")%></div>
|
349
|
+
</div>
|
350
|
+
<%=_site.boxb%>
|
351
|
+
</td>
|
352
|
+
</tr>
|
353
|
+
</table>
|
354
|
+
|
355
|
+
<div style="clear: both;"></div>
|
356
|
+
</div>
|
357
|
+
|
358
|
+
<div style="padding-bottom: 15px;">
|
359
|
+
<%=_site.boxt(_("Comments"))%>
|
360
|
+
<div style="padding-bottom: 15px;">
|
361
|
+
<input type="button" value="<%=_("Add new")%>" onclick="modal({title: '<%=_"Add new comment"%>', height: '540px', url: 'clean.rhtml?show=comment_edit&object_class=Task&object_id=<%=task.id%>'});" />
|
362
|
+
</div>
|
363
|
+
|
364
|
+
<div id="divcomments">
|
365
|
+
<div class="error"><%=_"Loading - please wait..."%></div>
|
366
|
+
</div>
|
367
|
+
|
368
|
+
<div>
|
369
|
+
<input type="button" value="<%=_("Add new")%>" onclick="modal({title: '<%=_"Add new comment"%>', height: '540px', url: 'clean.rhtml?show=comment_edit&object_class=Task&object_id=<%=task.id%>'});" />
|
370
|
+
</div>
|
371
|
+
<%=_site.boxb%>
|
372
|
+
</div>
|
373
|
+
|
374
|
+
<%=_site.boxt(_("Timelogs"))%>
|
375
|
+
<div style="padding-bottom: 15px;">
|
376
|
+
<input type="button" value="<%=_("Add new")%>" onclick="timelog_add('<%=task.id%>');" />
|
377
|
+
</div>
|
378
|
+
|
379
|
+
<div id="divtimelogs">
|
380
|
+
<div class="error"><%=_"Loading - please wait..."%></div>
|
381
|
+
</div>
|
382
|
+
<%=_site.boxb%>
|
383
|
+
|
384
|
+
<script type="text/javascript">
|
385
|
+
events.connect("do_comments_update", function(){
|
386
|
+
task_show_comments_update();
|
387
|
+
});
|
388
|
+
|
389
|
+
events.connect("do_timelogs_update", function(){
|
390
|
+
task_show_timelogs_update();
|
391
|
+
});
|
392
|
+
|
393
|
+
events.connect("do_task_assigned_users_update", function(){
|
394
|
+
task_show_users_update();
|
395
|
+
});
|
396
|
+
|
397
|
+
events.connect("do_task_check_update", function(){
|
398
|
+
task_show_checks_update();
|
399
|
+
});
|
400
|
+
|
401
|
+
function task_show_comments_update(){
|
402
|
+
$.ajax({type: "GET", url: "clean.rhtml?show=task_show&task_id=<%=task.id%>&choice=getcomments", async: true, cache: false, complete: function(data){
|
403
|
+
$("#divcomments").slideUp("fast", function(){
|
404
|
+
$("#divcomments").html(data.responseText);
|
405
|
+
$("#divcomments").slideDown("fast");
|
406
|
+
});
|
407
|
+
}});
|
408
|
+
}
|
409
|
+
|
410
|
+
function task_show_timelogs_update(){
|
411
|
+
$.ajax({type: "GET", url: "clean.rhtml?show=task_show&task_id=<%=task.id%>&choice=gettimelogs", async: true, cache: false, complete: function(data){
|
412
|
+
$("#divtimelogs").slideUp("fast", function(){
|
413
|
+
$("#divtimelogs").html(data.responseText);
|
414
|
+
$("#divtimelogs").slideDown("fast");
|
415
|
+
});
|
416
|
+
}});
|
417
|
+
}
|
418
|
+
|
419
|
+
function task_show_users_update(){
|
420
|
+
$.ajax({type: "GET", url: "clean.rhtml?show=task_show&task_id=<%=task.id%>&choice=getusers", async: true, cache: false, complete: function(data){
|
421
|
+
$("#divusers").slideUp("fast", function(){
|
422
|
+
$("#divusers").html(data.responseText);
|
423
|
+
$("#divusers").slideDown("fast");
|
424
|
+
});
|
425
|
+
}});
|
426
|
+
}
|
427
|
+
|
428
|
+
function task_show_assign_user_choose(user_id){
|
429
|
+
$.ajax({type: "GET", url: "clean.rhtml?show=task_show&task_id=<%=task.id%>&choice=assignuser&user_id=" + user_id, async: true, cache: false, complete: function(data){
|
430
|
+
if (data.responseText.length > 0){
|
431
|
+
alert(data.responseText);
|
432
|
+
}
|
433
|
+
|
434
|
+
task_show_users_update();
|
435
|
+
modal_close();
|
436
|
+
}});
|
437
|
+
}
|
438
|
+
|
439
|
+
function task_show_checks_update(){
|
440
|
+
$.ajax({type: "GET", url: "clean.rhtml?show=task_show&task_id=<%=task.id%>&choice=getchecks", async: true, cache: false, complete: function(data){
|
441
|
+
$("#divchecks").slideUp("fast", function(){
|
442
|
+
$("#divchecks").html(data.responseText);
|
443
|
+
$("#divchecks").slideDown("fast");
|
444
|
+
});
|
445
|
+
}});
|
446
|
+
}
|
447
|
+
|
448
|
+
$(document).ready(function(){
|
449
|
+
task_show_comments_update();
|
450
|
+
task_show_timelogs_update();
|
451
|
+
task_show_users_update();
|
452
|
+
task_show_checks_update();
|
453
|
+
});
|
454
|
+
</script>
|