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,223 @@
|
|
1
|
+
<%
|
2
|
+
if !_site.has_rank?("admin")
|
3
|
+
_hb.alert(_("You are not an administrator and cannot view this page.")).back
|
4
|
+
end
|
5
|
+
|
6
|
+
if _get["choice"] == "dosave"
|
7
|
+
save_hash = {
|
8
|
+
:name => _post["texname"],
|
9
|
+
:username => _post["texusername"],
|
10
|
+
:email => _post["texemail"],
|
11
|
+
:active => Knj::Web.checkval(_post["cheactive"], 1, 0)
|
12
|
+
}
|
13
|
+
|
14
|
+
if _post["texpasswd_md5"].to_s.length > 0 and _post["texpasswd_md5"] != Php4r.md5("")
|
15
|
+
save_hash[:passwd] = _post["texpasswd_md5"]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
if _get["user_id"].to_i > 0
|
20
|
+
user = _ob.get(:User, _get["user_id"])
|
21
|
+
title = sprintf(_("Edit user: %s."), user.name.html)
|
22
|
+
|
23
|
+
if _get["choice"] == "dosave"
|
24
|
+
user.update(save_hash)
|
25
|
+
_hb.redirect("?show=user_edit&user_id=#{user.id}")
|
26
|
+
end
|
27
|
+
|
28
|
+
if _get["choice"] == "dodelete"
|
29
|
+
begin
|
30
|
+
_ob.delete(user)
|
31
|
+
_hb.redirect("?show=user_search")
|
32
|
+
rescue => e
|
33
|
+
_hb.alert(e.message).back
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
if _get["choice"] == "dologinas"
|
38
|
+
_session[:user_id] = user.id
|
39
|
+
_hb.redirect("?show=user_login")
|
40
|
+
end
|
41
|
+
else
|
42
|
+
title = _("Add new user")
|
43
|
+
|
44
|
+
if _get["choice"] == "dosave"
|
45
|
+
user = _ob.add(:User, save_hash)
|
46
|
+
_hb.redirect("?show=user_edit&user_id=#{user.id}")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
if _get["choice"] == "getranks"
|
51
|
+
ranks = user.ranks
|
52
|
+
|
53
|
+
%>
|
54
|
+
<table class="list">
|
55
|
+
<thead>
|
56
|
+
<tr>
|
57
|
+
<th><%=_"Rank"%></th>
|
58
|
+
<th><%=_"Actions"%></th>
|
59
|
+
</tr>
|
60
|
+
</thead>
|
61
|
+
<tbody>
|
62
|
+
<%
|
63
|
+
ranks.each do |link|
|
64
|
+
%>
|
65
|
+
<tr>
|
66
|
+
<td><%=link.rank.name.html%></td>
|
67
|
+
<td>
|
68
|
+
(<a href="javascript: if (confirm('<%=_"Do you want to remove this rank?"%>')){rank_remove('<%=link.id%>');}"><%=_"remove"%></a>)
|
69
|
+
</td>
|
70
|
+
</tr>
|
71
|
+
<%
|
72
|
+
end
|
73
|
+
|
74
|
+
if ranks.empty?
|
75
|
+
%>
|
76
|
+
<tr>
|
77
|
+
<td colspan="1" class="error">
|
78
|
+
<%=_"No ranks has been added to this user."%>
|
79
|
+
</td>
|
80
|
+
</tr>
|
81
|
+
<%
|
82
|
+
end
|
83
|
+
%>
|
84
|
+
</tbody>
|
85
|
+
</table>
|
86
|
+
<%
|
87
|
+
|
88
|
+
exit
|
89
|
+
end
|
90
|
+
|
91
|
+
if _get["choice"] == "doremoverank"
|
92
|
+
link = _ob.get(:User_rank_link, _get["link_id"])
|
93
|
+
_ob.delete(link)
|
94
|
+
exit
|
95
|
+
end
|
96
|
+
|
97
|
+
if _get["choice"] == "doaddrank"
|
98
|
+
begin
|
99
|
+
link = _ob.add(:User_rank_link, {
|
100
|
+
:user_id => user.id,
|
101
|
+
:rank_id => _get["rank_id"]
|
102
|
+
})
|
103
|
+
rescue => e
|
104
|
+
print e.message
|
105
|
+
end
|
106
|
+
|
107
|
+
exit
|
108
|
+
end
|
109
|
+
|
110
|
+
print _site.header(title)
|
111
|
+
%>
|
112
|
+
|
113
|
+
<form autocomplete="off" method="post" action="?show=user_edit&choice=dosave<%if user; print "&user_id=#{user.id}"; end%>" onsubmit="return do_save_user();">
|
114
|
+
<%=Knj::Web.hiddens([{:name => :texpasswd_md5, :value => ""}])%>
|
115
|
+
|
116
|
+
<%=_site.boxt(_("Enter details"), 350)%>
|
117
|
+
<table class="form">
|
118
|
+
<%
|
119
|
+
print _hb.inputs({
|
120
|
+
:title => _("Username"),
|
121
|
+
:name => :texusername,
|
122
|
+
:value => [user, :username],
|
123
|
+
:descr => _("The username that this user should use to log in.")
|
124
|
+
},{
|
125
|
+
:title => _("Password"),
|
126
|
+
:name => :texpasswd,
|
127
|
+
:value => "",
|
128
|
+
:type => :password,
|
129
|
+
:descr => _("Only write a password here if you whish to change it.")
|
130
|
+
},{
|
131
|
+
:title => _("Name"),
|
132
|
+
:name => :texname,
|
133
|
+
:value => [user, :name],
|
134
|
+
:descr => _("The real name of the user.")
|
135
|
+
},{
|
136
|
+
:title => _("Email"),
|
137
|
+
:name => :texemail,
|
138
|
+
:value => [user, :email],
|
139
|
+
:descr => _("The email of the user which will be used for notifications and other stuff as well.")
|
140
|
+
},{
|
141
|
+
:title => _("Active"),
|
142
|
+
:name => :cheactive,
|
143
|
+
:value => [user, :active],
|
144
|
+
:descr => _("If the user is active or not. In-active users cant log in.")
|
145
|
+
})
|
146
|
+
%>
|
147
|
+
<tr>
|
148
|
+
<td colspan="2" class="buttons">
|
149
|
+
<%if user%>
|
150
|
+
<input type="button" value="<%=_"Log in as"%>" onclick="location.href='?show=user_edit&user_id=<%=user.id%>&choice=dologinas';" />
|
151
|
+
<input type="button" value="<%=_"Show"%>" onclick="location.href='?show=user_show&user_id=<%=user.id%>';" />
|
152
|
+
<input type="button" value="<%=_"Delete"%>" onclick="if (confirm('<%=_("Do you want to delete this user?")%>')){location.href='?show=user_edit&user_id=<%=user.id%>&choice=dodelete';}" />
|
153
|
+
<%end%>
|
154
|
+
<input type="submit" value="<%=_"Save"%>" />
|
155
|
+
</td>
|
156
|
+
</tr>
|
157
|
+
</table>
|
158
|
+
<%=_site.boxb%>
|
159
|
+
|
160
|
+
</form>
|
161
|
+
|
162
|
+
<%if user%>
|
163
|
+
<br />
|
164
|
+
|
165
|
+
<%=_site.boxt(_("Permissions"), 350)%>
|
166
|
+
<div style="padding-bottom: 15px;">
|
167
|
+
<input type="button" value="<%=_"Add rank"%>" onclick="modal({title: '<%=_"Add rank"%>', url: '/clean.rhtml?show=user_rank_search&jsfunc=rank_add'});" />
|
168
|
+
</div>
|
169
|
+
|
170
|
+
<div id="divpermissions">
|
171
|
+
<div class="error">
|
172
|
+
<%=_"Loading - please wait..."%>
|
173
|
+
</div>
|
174
|
+
</div>
|
175
|
+
<%=_site.boxb%>
|
176
|
+
<%end%>
|
177
|
+
|
178
|
+
<script type="text/javascript">
|
179
|
+
$("#texusername").focus();
|
180
|
+
|
181
|
+
function do_save_user(){
|
182
|
+
$("input[name=texpasswd_md5]").val($.md5($("#texpasswd").val()));
|
183
|
+
$("#texpasswd").val("");
|
184
|
+
return true;
|
185
|
+
}
|
186
|
+
|
187
|
+
<%if user%>
|
188
|
+
function ranks_reload(){
|
189
|
+
$.ajax({type: "GET", url: "/clean.rhtml?show=user_edit&user_id=<%=user.id%>&choice=getranks", async: true, cache: false, complete: function(data){
|
190
|
+
$("#divpermissions").slideUp("fast", function(){
|
191
|
+
$("#divpermissions").html(data.responseText);
|
192
|
+
$("#divpermissions").slideDown("fast");
|
193
|
+
});
|
194
|
+
}});
|
195
|
+
}
|
196
|
+
|
197
|
+
function rank_remove(link_id){
|
198
|
+
$.ajax({type: "GET", url: "/clean.rhtml?show=user_edit&choice=doremoverank&user_id=<%=user.id%>&link_id=" + link_id, async: true, cache: false, complete: function(data){
|
199
|
+
if (data.responseText.length > 0){
|
200
|
+
alert(data.responseText);
|
201
|
+
}
|
202
|
+
|
203
|
+
ranks_reload();
|
204
|
+
}});
|
205
|
+
}
|
206
|
+
|
207
|
+
function rank_add(rank_id){
|
208
|
+
modal_close();
|
209
|
+
|
210
|
+
$.ajax({type: "GET", url: "/clean.rhtml?show=user_edit&choice=doaddrank&user_id=<%=user.id%>&rank_id=" + rank_id, async: true, cache: false, complete: function(data){
|
211
|
+
if (data.responseText.length > 0){
|
212
|
+
alert(data.responseText);
|
213
|
+
}
|
214
|
+
|
215
|
+
ranks_reload();
|
216
|
+
}});
|
217
|
+
}
|
218
|
+
|
219
|
+
$(document).ready(function(){
|
220
|
+
ranks_reload();
|
221
|
+
});
|
222
|
+
<%end%>
|
223
|
+
</script>
|
@@ -0,0 +1,83 @@
|
|
1
|
+
<%
|
2
|
+
if _get["choice"] == "dologin"
|
3
|
+
user = _ob.get_by(:User, {
|
4
|
+
"username" => _post["texuser"],
|
5
|
+
"passwd" => _post["texpass_md5"]
|
6
|
+
})
|
7
|
+
|
8
|
+
if !user
|
9
|
+
_hb.alert(_("A user with that username and/or password was found.")).back
|
10
|
+
elsif !user.active?
|
11
|
+
_hb.alert(_("That user is not active any more and cant be used.")).back
|
12
|
+
else
|
13
|
+
_session[:user_id] = user.id
|
14
|
+
|
15
|
+
if _post["cheremember"] == "on"
|
16
|
+
_hb.session_remember
|
17
|
+
else
|
18
|
+
_hb.session_dont_remember
|
19
|
+
end
|
20
|
+
|
21
|
+
if _get["backurl"].to_s.strip.length > 0
|
22
|
+
_hb.redirect(_get["backurl"])
|
23
|
+
else
|
24
|
+
_hb.redirect("?show=user_login")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
if _get["choice"] == "dologout"
|
30
|
+
_session.delete(:user_id)
|
31
|
+
_hb.redirect("?show=user_login")
|
32
|
+
end
|
33
|
+
|
34
|
+
print _site.header(_("Log in"))
|
35
|
+
|
36
|
+
if _site.user
|
37
|
+
print sprintf(_("You are logged in as %s."), _site.user.html)
|
38
|
+
else
|
39
|
+
%>
|
40
|
+
<form method="post" action="?show=user_login&choice=dologin&backurl=<%=Php4r.urlencode(_get["backurl"])%>" onsubmit="return do_login();">
|
41
|
+
<%=Knj::Web.hiddens([{:name => :texpass_md5, :value => ""}])%>
|
42
|
+
|
43
|
+
<%=_site.boxt(_("Enter details"), "350px")%>
|
44
|
+
<table class="form">
|
45
|
+
<%
|
46
|
+
print _hb.inputs({
|
47
|
+
:title => _("Username"),
|
48
|
+
:name => :texuser,
|
49
|
+
:value => "",
|
50
|
+
:descr => _("The username you want to log in as.")
|
51
|
+
},{
|
52
|
+
:title => _("Password"),
|
53
|
+
:name => :texpass,
|
54
|
+
:value => "",
|
55
|
+
:type => :password,
|
56
|
+
:descr => _("The password associated with the entered username.")
|
57
|
+
},{
|
58
|
+
:title => _("Remember me on this computer"),
|
59
|
+
:name => :cheremember,
|
60
|
+
:descr => _("If you do not want to log in again on this computer then check this box.")
|
61
|
+
})
|
62
|
+
%>
|
63
|
+
<tr>
|
64
|
+
<td colspan="2" class="buttons">
|
65
|
+
<input type="submit" value="<%=_("Log in")%>" />
|
66
|
+
</td>
|
67
|
+
</tr>
|
68
|
+
</table>
|
69
|
+
<%=_site.boxb%>
|
70
|
+
</form>
|
71
|
+
|
72
|
+
<script type="text/javascript">
|
73
|
+
$("#texuser").focus();
|
74
|
+
|
75
|
+
function do_login(){
|
76
|
+
$("input[name=texpass_md5]").val($.md5($("#texpass").val()));
|
77
|
+
$("#texpass").val("");
|
78
|
+
return true;
|
79
|
+
}
|
80
|
+
</script>
|
81
|
+
<%
|
82
|
+
end
|
83
|
+
%>
|
@@ -0,0 +1,89 @@
|
|
1
|
+
<%
|
2
|
+
if _get["choice"] == "dosave"
|
3
|
+
_site.user.update(
|
4
|
+
:passwd => _post["passwd_md5"]
|
5
|
+
)
|
6
|
+
_hb.redirect("/?show=user_profile")
|
7
|
+
end
|
8
|
+
|
9
|
+
print _site.header(_("Your profile"))
|
10
|
+
%>
|
11
|
+
|
12
|
+
<form method="post" action="/?show=user_profile&choice=dosave" onsubmit="return on_profile_save()">
|
13
|
+
<%=Knj::Web.hiddens([["passwd_md5", nil]])%>
|
14
|
+
|
15
|
+
<%=_site.boxt(_("Enter details"), 350)%>
|
16
|
+
<table class="form">
|
17
|
+
<%
|
18
|
+
print _hb.inputs({
|
19
|
+
:title => _("Password"),
|
20
|
+
:name => "texpasswd",
|
21
|
+
:type => :password,
|
22
|
+
:descr => _("You can enter a new password to change it.")
|
23
|
+
})
|
24
|
+
%>
|
25
|
+
<tr>
|
26
|
+
<td colspan="2" class="buttons">
|
27
|
+
<input type="submit" value="<%=_"Save"%>" />
|
28
|
+
</td>
|
29
|
+
</tr>
|
30
|
+
</table>
|
31
|
+
<%=_site.boxb%>
|
32
|
+
|
33
|
+
</form>
|
34
|
+
|
35
|
+
<script>
|
36
|
+
$(document).ready(function(){
|
37
|
+
$("#texpasswd").val("")
|
38
|
+
$("#texpasswd").focus()
|
39
|
+
})
|
40
|
+
|
41
|
+
function on_profile_save(){
|
42
|
+
$("input[name=passwd_md5]").val($.md5($("#texpasswd").val()))
|
43
|
+
$("#texpasswd").val("")
|
44
|
+
return true
|
45
|
+
}
|
46
|
+
</script>
|
47
|
+
|
48
|
+
<br />
|
49
|
+
|
50
|
+
<%=_site.boxt(_("Task-list"), 350)%>
|
51
|
+
<table class="list">
|
52
|
+
<thead>
|
53
|
+
<tr>
|
54
|
+
<th><%=_"Task"%></th>
|
55
|
+
</tr>
|
56
|
+
</thead>
|
57
|
+
<tbody>
|
58
|
+
<%
|
59
|
+
count = 0
|
60
|
+
|
61
|
+
_ob.list(:Task, {
|
62
|
+
[:User_task_list_link, "user"] => _site.user,
|
63
|
+
"orderby" => "name"
|
64
|
+
}) do |task|
|
65
|
+
next if !task.has_access?
|
66
|
+
count += 1
|
67
|
+
|
68
|
+
%>
|
69
|
+
<tr>
|
70
|
+
<td>
|
71
|
+
<%=task.html%>
|
72
|
+
</td>
|
73
|
+
</tr>
|
74
|
+
<%
|
75
|
+
end
|
76
|
+
|
77
|
+
if count <= 0
|
78
|
+
%>
|
79
|
+
<tr>
|
80
|
+
<td colspan="1" class="error">
|
81
|
+
<%=_"No tasks has been added to your list."%>
|
82
|
+
</td>
|
83
|
+
</tr>
|
84
|
+
<%
|
85
|
+
end
|
86
|
+
%>
|
87
|
+
</tbody>
|
88
|
+
</table>
|
89
|
+
<%=_site.boxb%>
|
@@ -0,0 +1,95 @@
|
|
1
|
+
<%
|
2
|
+
if _get["choice"] == "dosearch"
|
3
|
+
args = {"orderby" => "name"}
|
4
|
+
args["name_search"] = _get["texname"] if _get["texname"].to_s.length > 0
|
5
|
+
|
6
|
+
ranks = _ob.list(:User_rank, args)
|
7
|
+
|
8
|
+
%>
|
9
|
+
<%=_site.boxt(_("Results"), 350)%>
|
10
|
+
<table class="list">
|
11
|
+
<thead>
|
12
|
+
<tr>
|
13
|
+
<th><%=_"Rank"%></th>
|
14
|
+
</tr>
|
15
|
+
</thead>
|
16
|
+
<tbody>
|
17
|
+
<%
|
18
|
+
ranks.each do |rank|
|
19
|
+
%>
|
20
|
+
<tr>
|
21
|
+
<td>
|
22
|
+
<a href="javascript: <%=_get["jsfunc"]%>('<%=rank.id%>');"><%=rank.name.html%></a>
|
23
|
+
</td>
|
24
|
+
</tr>
|
25
|
+
<%
|
26
|
+
end
|
27
|
+
|
28
|
+
if ranks.empty?
|
29
|
+
%>
|
30
|
+
<tr>
|
31
|
+
<td colspan="1" class="error">
|
32
|
+
<%=_"No ranks were found."%>
|
33
|
+
</td>
|
34
|
+
</tr>
|
35
|
+
<%
|
36
|
+
end
|
37
|
+
%>
|
38
|
+
</tbody>
|
39
|
+
</table>
|
40
|
+
<%=_site.boxb%>
|
41
|
+
<%
|
42
|
+
|
43
|
+
exit
|
44
|
+
end
|
45
|
+
%>
|
46
|
+
|
47
|
+
<form id="formuserranksearch" method="post" onsubmit="return do_user_rank_search_submit();">
|
48
|
+
|
49
|
+
<%=_site.boxt(_("Enter criteria"), 350)%>
|
50
|
+
<table class="form">
|
51
|
+
<%
|
52
|
+
print Knj::Web.inputs([{
|
53
|
+
:title => _("Name"),
|
54
|
+
:name => :texname,
|
55
|
+
:value => _get["texname"],
|
56
|
+
:descr => _("Enter a part of the name of the permission you are searching for.")
|
57
|
+
}])
|
58
|
+
%>
|
59
|
+
<tr>
|
60
|
+
<td colspan="2" class="buttons">
|
61
|
+
<input type="submit" value="<%=_"Search"%>" />
|
62
|
+
</td>
|
63
|
+
</tr>
|
64
|
+
</table>
|
65
|
+
<%=_site.boxb%>
|
66
|
+
|
67
|
+
</form>
|
68
|
+
|
69
|
+
<br />
|
70
|
+
|
71
|
+
<div id="divuserranksearchresults">
|
72
|
+
<div class="error">
|
73
|
+
<%=_"Please enter criteria and search..."%>
|
74
|
+
</div>
|
75
|
+
</div>
|
76
|
+
|
77
|
+
<script type="text/javascript">
|
78
|
+
function do_user_rank_search_submit(){
|
79
|
+
$.ajax({
|
80
|
+
type: "POST",
|
81
|
+
data: forms_inputs_read($("#formuserranksearch")),
|
82
|
+
url: "/clean.rhtml?show=user_rank_search&choice=dosearch&jsfunc=<%=_get["jsfunc"]%>",
|
83
|
+
async: true,
|
84
|
+
cache: false,
|
85
|
+
complete: function(data){
|
86
|
+
$("#divuserranksearchresults").slideUp("fast", function(){
|
87
|
+
$("#divuserranksearchresults").html(data.responseText);
|
88
|
+
$("#divuserranksearchresults").slideDown("fast");
|
89
|
+
});
|
90
|
+
}
|
91
|
+
});
|
92
|
+
|
93
|
+
return false;
|
94
|
+
}
|
95
|
+
</script>
|