knjtasks 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ gem "knjrbfw"
7
+ gem "datet"
8
+ gem "hayabusa"
9
+
10
+ # Add dependencies to develop your gem here.
11
+ # Include everything needed to run rake, tests, features, etc.
12
+ group :development do
13
+ gem "http2"
14
+ gem "sqlite3"
15
+ gem "rspec", "~> 2.3.0"
16
+ gem "bundler", ">= 1.0.0"
17
+ gem "jeweler", "~> 1.6.3"
18
+ end
@@ -0,0 +1,66 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ datet (0.0.20)
5
+ diff-lcs (1.1.3)
6
+ erubis (2.7.0)
7
+ fcgi (0.8.8)
8
+ git (1.2.5)
9
+ hayabusa (0.0.18)
10
+ datet
11
+ erubis
12
+ fcgi
13
+ http2
14
+ knjrbfw
15
+ mail
16
+ tpool
17
+ http2 (0.0.13)
18
+ i18n (0.6.1)
19
+ jeweler (1.6.4)
20
+ bundler (~> 1.0)
21
+ git (>= 1.2.5)
22
+ rake
23
+ knjrbfw (0.0.100)
24
+ datet
25
+ http2
26
+ php4r
27
+ tsafe
28
+ wref
29
+ mail (2.4.4)
30
+ i18n (>= 0.4.0)
31
+ mime-types (~> 1.16)
32
+ treetop (~> 1.4.8)
33
+ mime-types (1.19)
34
+ php4r (0.0.3)
35
+ datet
36
+ http2
37
+ polyglot (0.3.3)
38
+ rake (0.9.2.2)
39
+ rspec (2.3.0)
40
+ rspec-core (~> 2.3.0)
41
+ rspec-expectations (~> 2.3.0)
42
+ rspec-mocks (~> 2.3.0)
43
+ rspec-core (2.3.1)
44
+ rspec-expectations (2.3.0)
45
+ diff-lcs (~> 1.1.2)
46
+ rspec-mocks (2.3.0)
47
+ sqlite3 (1.3.6)
48
+ tpool (0.0.4)
49
+ treetop (1.4.11)
50
+ polyglot
51
+ polyglot (>= 0.3.1)
52
+ tsafe (0.0.11)
53
+ wref (0.0.5)
54
+
55
+ PLATFORMS
56
+ ruby
57
+
58
+ DEPENDENCIES
59
+ bundler (>= 1.0.0)
60
+ datet
61
+ hayabusa
62
+ http2
63
+ jeweler (~> 1.6.3)
64
+ knjrbfw
65
+ rspec (~> 2.3.0)
66
+ sqlite3
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Kasper Johansen
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,19 @@
1
+ = knjtasks
2
+
3
+ Description goes here.
4
+
5
+ == Contributing to knjtasks
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
9
+ * Fork the project
10
+ * Start a feature/bugfix branch
11
+ * Commit and push until you are happy with your contribution
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2011 Kasper Johansen. See LICENSE.txt for
18
+ further details.
19
+
@@ -0,0 +1,49 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "knjtasks"
18
+ gem.homepage = "http://github.com/kaspernj/knjtasks"
19
+ gem.license = "MIT"
20
+ gem.summary = %Q{A task system for managing various projects, timelogs and much more.}
21
+ gem.description = %Q{A longer description will come...}
22
+ gem.email = "k@spernj.org"
23
+ gem.authors = ["Kasper Johansen"]
24
+ # dependencies defined in Gemfile
25
+ end
26
+ Jeweler::RubygemsDotOrgTasks.new
27
+
28
+ require 'rspec/core'
29
+ require 'rspec/core/rake_task'
30
+ RSpec::Core::RakeTask.new(:spec) do |spec|
31
+ spec.pattern = FileList['spec/**/*_spec.rb']
32
+ end
33
+
34
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
35
+ spec.pattern = 'spec/**/*_spec.rb'
36
+ spec.rcov = true
37
+ end
38
+
39
+ task :default => :spec
40
+
41
+ require 'rake/rdoctask'
42
+ Rake::RDocTask.new do |rdoc|
43
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
44
+
45
+ rdoc.rdoc_dir = 'rdoc'
46
+ rdoc.title = "knjtasks #{version}"
47
+ rdoc.rdoc_files.include('README*')
48
+ rdoc.rdoc_files.include('lib/**/*.rb')
49
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.3
@@ -0,0 +1,174 @@
1
+ $schema = {
2
+ "tables" => {
3
+ "Customer" => {
4
+ "columns" => [
5
+ {"name" => "id", "type" => "int", "autoincr" => true, "primarykey" => true},
6
+ {"name" => "name", "type" => "varchar"},
7
+ {"name" => "date_added", "type" => "datetime"}
8
+ ]
9
+ },
10
+ "Comment" => {
11
+ "columns" => [
12
+ {"name" => "id", "type" => "int", "autoincr" => true, "primarykey" => true},
13
+ {"name" => "id_per_obj", "type" => "int"},
14
+ {"name" => "object_class", "type" => "varchar"},
15
+ {"name" => "object_id", "type" => "int"},
16
+ {"name" => "user_id", "type" => "int"},
17
+ {"name" => "date_saved", "type" => "datetime"},
18
+ {"name" => "comment", "type" => "text"}
19
+ ],
20
+ "indexes" => [
21
+ {"name" => "object_lookup", "columns" => ["object_class", "object_id"]},
22
+ {"name" => "user_id", "columns" => ["user_id"]}
23
+ ]
24
+ },
25
+ "Email_check" => {
26
+ "columns" => [
27
+ {"name" => "id", "type" => "int", "autoincr" => true, "primarykey" => true},
28
+ {"name" => "email_id_str", "type" => "varchar"}
29
+ ],
30
+ "indexes" => [
31
+ {"name" => "email_id_str", "columns" => ["email_id_str"]}
32
+ ]
33
+ },
34
+ "Project" => {
35
+ "columns" => [
36
+ {"name" => "id", "type" => "int", "autoincr" => true, "primarykey" => true},
37
+ {"name" => "customer_id", "type" => "int"},
38
+ {"name" => "name", "type" => "varchar"},
39
+ {"name" => "descr", "type" => "text"},
40
+ {"name" => "added_date", "type" => "datetime"},
41
+ {"name" => "added_user_id", "type" => "int"},
42
+ {"name" => "date_deadline", "type" => "date"}
43
+ ],
44
+ "indexes" => [
45
+ {"name" => "customer_id", "columns" => ["customer_id"]},
46
+ {"name" => "added_user_id", "columns" => ["added_user_id"]}
47
+ ]
48
+ },
49
+ "Task" => {
50
+ "columns" => [
51
+ {"name" => "id", "type" => "int", "autoincr" => true, "primarykey" => true},
52
+ {"name" => "project_id", "type" => "int"},
53
+ {"name" => "user_id", "type" => "int"},
54
+ {"name" => "date_added", "type" => "datetime"},
55
+ {"name" => "name", "type" => "varchar"},
56
+ {"name" => "descr", "type" => "text"},
57
+ {"name" => "type", "type" => "enum", "maxlength" => "'feature','bug','question','other'"},
58
+ {"name" => "status", "type" => "enum", "maxlength" => "'open','confirmed','waiting','closed'"},
59
+ {"name" => "priority", "type" => "int", "default" => 1}
60
+ ],
61
+ "indexes" => [
62
+ {"name" => "project_id", "columns" => ["project_id"]},
63
+ {"name" => "user_id", "columns" => ["user_id"]}
64
+ ]
65
+ },
66
+ "Task_check" => {
67
+ "columns" => [
68
+ {"name" => "id", "type" => "int", "autoincr" => true, "primarykey" => true},
69
+ {"name" => "task_id", "type" => "int"},
70
+ {"name" => "added_user_id", "type" => "int"},
71
+ {"name" => "date_added", "type" => "datetime"},
72
+ {"name" => "name", "type" => "varchar"},
73
+ {"name" => "descr", "type" => "text"},
74
+ {"name" => "checked", "type" => "enum", "maxlength" => "'0','1'", "default" => 0},
75
+ ],
76
+ "indexes" => [
77
+ {"name" => "task_id", "columns" => ["task_id"]}
78
+ ]
79
+ },
80
+ "Task_assigned_user" => {
81
+ "columns" => [
82
+ {"name" => "id", "type" => "int", "autoincr" => true, "primarykey" => true},
83
+ {"name" => "task_id", "type" => "int"},
84
+ {"name" => "user_id", "type" => "int"}
85
+ ],
86
+ "indexes" => [
87
+ {"name" => "task_id", "columns" => ["task_id"]},
88
+ {"name" => "user_id", "columns" => ["user_id"]}
89
+ ]
90
+ },
91
+ "Timelog" => {
92
+ "columns" => [
93
+ {"name" => "id", "type" => "int", "autoincr" => true, "primarykey" => true},
94
+ {"name" => "task_id", "type" => "int"},
95
+ {"name" => "user_id", "type" => "int"},
96
+ {"name" => "date", "type" => "date"},
97
+ {"name" => "time", "type" => "time"},
98
+ {"name" => "time_transport", "type" => "time"},
99
+ {"name" => "transport_length", "type" => "int"},
100
+ {"name" => "comment", "type" => "text"},
101
+ {"name" => "invoiced", "type" => "enum", "maxlength" => "'0','1'", "default" => "0"},
102
+ {"name" => "invoiced_date", "type" => "datetime"},
103
+ {"name" => "invoiced_user_id", "type" => "int"}
104
+ ],
105
+ "indexes" => [
106
+ {"name" => "task_id", "columns" => ["task_id"]},
107
+ {"name" => "user_id", "columns" => ["user_id"]}
108
+ ]
109
+ },
110
+ "User" => {
111
+ "columns" => [
112
+ {"name" => "id", "type" => "int", "autoincr" => true, "primarykey" => true},
113
+ {"name" => "name", "type" => "varchar"},
114
+ {"name" => "username", "type" => "varchar"},
115
+ {"name" => "passwd", "type" => "varchar"},
116
+ {"name" => "email", "type" => "varchar"},
117
+ {"name" => "locale", "type" => "varchar", "maxlength" => 5, "default" => "en_GB", "comment" => "The current locale of the user which should be used for the stuff sent to him."},
118
+ {"name" => "active", "type" => "enum", "maxlength" => "'0','1'", "default" => 1, "comment" => "If the user is active or not. This can prevent the user from logging in."}
119
+ ],
120
+ "on_create_after" => proc{|data|
121
+ data["db"].insert(:User, {"username" => "admin", "passwd" => Digest::MD5.hexdigest("admin")})
122
+ }
123
+ },
124
+ "User_project_link" => {
125
+ "columns" => [
126
+ {"name" => "id", "type" => "int", "autoincr" => true, "primarykey" => true},
127
+ {"name" => "user_id", "type" => "int"},
128
+ {"name" => "project_id", "type" => "int"}
129
+ ],
130
+ "indexes" => [
131
+ {"name" => "user_id", "columns" => ["user_id"]},
132
+ {"name" => "project_id", "columns" => ["project_id"]}
133
+ ]
134
+ },
135
+ "User_rank" => {
136
+ "columns" => [
137
+ {"name" => "id", "type" => "int", "autoincr" => true, "primarykey" => true},
138
+ {"name" => "id_str", "type" => "varchar"},
139
+ {"name" => "name", "type" => "varchar"}
140
+ ],
141
+ "indexes" => [
142
+ {"name" => "id_str", "columns" => ["name"]}
143
+ ],
144
+ "rows" => [
145
+ {
146
+ "find_by" => {"id" => 1},
147
+ "data" => {"id" => 1, "id_str" => "admin", "name" => "Administrator"}
148
+ }
149
+ ]
150
+ },
151
+ "User_rank_link" => {
152
+ "columns" => [
153
+ {"name" => "id", "type" => "int", "autoincr" => true, "primarykey" => true},
154
+ {"name" => "user_id", "type" => "int"},
155
+ {"name" => "rank_id", "type" => "int"}
156
+ ],
157
+ "indexes" => [
158
+ {"name" => "user_id", "columns" => ["user_id"]},
159
+ {"name" => "rank_id", "columns" => ["rank_id"]}
160
+ ],
161
+ "on_create_after" => proc{|data|
162
+ data["db"].insert(:User_rank_link, {:user_id => 1, :rank_id => 1})
163
+ }
164
+ },
165
+ "User_task_list_link" => {
166
+ "columns" => [
167
+ {"name" => "id", "type" => "int", "autoincr" => true, "primarykey" => true},
168
+ {"name" => "user_id", "type" => "int"},
169
+ {"name" => "task_id", "type" => "int"}
170
+ ],
171
+ "indexes" => ["user_id", "task_id"]
172
+ }
173
+ }
174
+ }
@@ -0,0 +1,172 @@
1
+ class Knjtasks
2
+ attr_reader :hayabusa, :ob, :db, :args
3
+
4
+ def initialize(args = {})
5
+ @args = args
6
+
7
+ if @args[:hayabusa]
8
+ @db = @args[:hayabusa].db
9
+ elsif @args[:db]
10
+ @db = @args[:db]
11
+ else
12
+ raise "Could not figure out database."
13
+ end
14
+
15
+ require "rubygems"
16
+ require "#{@args[:hayabusa_path]}hayabusa"
17
+ require "#{@args[:knjrbfw_path]}knjrbfw"
18
+
19
+ require "#{@args[:knjrbfw_path]}knj/autoload"
20
+
21
+
22
+ check_args = [:knjjs_url, :email_admin, :email_robot]
23
+ check_args.each do |key|
24
+ raise "No '#{key}' given in arguments." if !@args.has_key?(key)
25
+ end
26
+
27
+ require "#{File.dirname(__FILE__)}/../files/database_schema.rb"
28
+ Knj::Db::Revision.new.init_db("schema" => $schema, "db" => @db)
29
+
30
+ @ob = Knj::Objects.new(
31
+ :datarow => true,
32
+ :db => @db,
33
+ :class_path => "#{File.dirname(__FILE__)}/../models",
34
+ :module => Knjtasks,
35
+ :require_all => true
36
+ )
37
+
38
+ @ob.events.connect(:no_html, &self.method(:no_html))
39
+ @ob.events.connect(:no_date, &self.method(:no_date))
40
+
41
+ if @args[:hayabusa]
42
+ @hayabusa = @args[:hayabusa]
43
+ else
44
+ @hayabusa = Hayabusa.new(
45
+ :debug => @args[:debug],
46
+ :autorestart => false,
47
+ :autoload => false,
48
+ :verbose => false,
49
+ :title => @args[:title],
50
+ :port => @args[:port],
51
+ :host => @args[:host],
52
+ :default_page => "index.rhtml",
53
+ :doc_root => "#{File.dirname(__FILE__)}/../www",
54
+ :hostname => false,
55
+ :error_report_emails => [@args[:email_admin]],
56
+ :error_report_from => @args[:email_robot],
57
+ :locales_root => "#{File.dirname(__FILE__)}/../locales",
58
+ :locales_gettext_funcs => true,
59
+ :locale_default => "en_GB",
60
+ :knjrbfw_path => @args[:knjrbfw_path],
61
+ :db => @db,
62
+ :smtp_args => @args[:smtp_args],
63
+ :httpsession_db_args => @args[:db_args]
64
+ )
65
+ end
66
+
67
+ @hayabusa.define_magic_var(:_site, self)
68
+ @hayabusa.define_magic_var(:_ob, @ob)
69
+ @hayabusa.thread_init
70
+
71
+ if @args.has_key?(:mail_args)
72
+ require "#{File.dirname(__FILE__)}/../threads/thread_mail_task_comments.rb"
73
+ @thread_mail_task_comments = Knjtasks::Thread_mail_task_comments.new(
74
+ :knjtasks => self,
75
+ :ob => @ob,
76
+ :appsrv => @hayabusa,
77
+ :args => @args
78
+ )
79
+
80
+ if @args[:debug]
81
+ time = 5
82
+ else
83
+ time = 60
84
+ end
85
+
86
+ @hayabusa.timeout(:time => time, &self.method(:mail_task_comments_run))
87
+ end
88
+
89
+ @class_translations = {
90
+ :User => _("user"),
91
+ :Project => _("project"),
92
+ :Task => _("task")
93
+ }
94
+ end
95
+
96
+ def no_html(event, classname)
97
+ class_trans = @class_translations[classname]
98
+ class_trans = classname.to_s.downcase if !class_trans
99
+ return "[#{sprintf(_("no %s"), class_trans)}]"
100
+ end
101
+
102
+ def no_date(event, date)
103
+ return "[#{_("no date")}]"
104
+ end
105
+
106
+ def mail_task_comments_run
107
+ @thread_mail_task_comments.run
108
+ end
109
+
110
+ def join
111
+ @hayabusa.join
112
+ end
113
+
114
+ def start
115
+ @hayabusa.start
116
+ end
117
+
118
+ def load_request
119
+ @hayabusa.header("Content-Type", "text/html; charset=utf-8")
120
+
121
+ #This will make the new Ruby-tasks-system compatible with mails sent from the old PHP-tasks-system.
122
+ _get["show"] = "task_show" if _get["show"] == "tasks_show"
123
+ _get["show"] = "user_login" if _get["show"] == "users_login"
124
+
125
+ if _get.has_key?("l")
126
+ _session[:locale] = _get["l"]
127
+ _site.user[:locale] = _get["l"] if _site.user
128
+ _hb.redirect(_meta["REQUEST_URI"].gsub(/&l=([A-z_]+)/, ""))
129
+ end
130
+ end
131
+
132
+ def header(title)
133
+ return "<h1>#{title}</h1>"
134
+ end
135
+
136
+ def boxt(title, width = "100%")
137
+ width = "#{width}px" if width.is_a?(Fixnum) or width.is_a?(Integer)
138
+
139
+ html = ""
140
+ html += "<table class=\"box\" style=\"width: #{width};\" cellspacing=\"0\" cellpadding=\"0\">"
141
+ html += "<tr><td class=\"box_header_spacer\">&nbsp;</td><td class=\"box_header\">#{title}</td></tr>"
142
+ html += "<tr><td colspan=\"2\" class=\"box_content\">"
143
+ return html
144
+ end
145
+
146
+ def boxb
147
+ return "</td></tr></table>"
148
+ end
149
+
150
+ def user
151
+ begin
152
+ if _session[:user_id].to_i > 0
153
+ user = @ob.get(:User, _session[:user_id])
154
+ if !user.active?
155
+ _session.delete(:user_id)
156
+ return false
157
+ end
158
+
159
+ return user
160
+ end
161
+ rescue
162
+ return false
163
+ end
164
+
165
+ return false
166
+ end
167
+
168
+ def has_rank?(rank_str)
169
+ return false if !self.user
170
+ return self.user.has_rank?(rank_str)
171
+ end
172
+ end