Description:
[web] added message feature git-svn-id: http://theory.cpe.ku.ac.th/grader/web/trunk@194 6386c4cd-e34a-4fa8-8920-d93eb39b512e
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r102:8fbc279e8875 - - 16 files changed: 279 inserted, 1 deleted

@@ -0,0 +1,73
1 + class MessagesController < ApplicationController
2 +
3 + before_filter :authenticate
4 +
5 + verify :method => :post, :only => ['create'],
6 + :redirect_to => { :action => 'list' }
7 +
8 + before_filter :only => ['console','show'] do |controller|
9 + controller.authorization_by_roles(['admin'])
10 + end
11 +
12 + def list
13 + @user = User.find(session[:user_id])
14 + @messages = Message.find_all_sent_by_user(@user)
15 + end
16 +
17 + def console
18 + @user = User.find(session[:user_id])
19 + @messages = Message.find_all_system_unreplied_messages
20 + end
21 +
22 + def show
23 + @message = Message.find(params[:id])
24 + end
25 +
26 + def create
27 + user = User.find(session[:user_id])
28 + @message = Message.new(params[:message])
29 + @message.sender = user
30 + if !@message.save
31 + render :action => 'list' and return
32 + else
33 + flash[:notice] = 'New message posted'
34 + redirect_to :action => 'list'
35 + end
36 + end
37 +
38 + def reply
39 + user = User.find(session[:user_id])
40 + @message = Message.new(params[:r_message])
41 + @message.sender = user
42 + if !@message.save
43 + render :action => 'show' and return
44 + else
45 + flash[:notice] = 'Message replied'
46 + rep_msg = @message.replying_message
47 + rep_msg.replied = true
48 + rep_msg.save
49 + redirect_to :action => 'console'
50 + end
51 + end
52 +
53 + protected
54 + def build_replying_message_hierarchy(user)
55 + @all_messages = {}
56 +
57 +
58 + # manually build replies hierarchy (to improve efficiency)
59 + [@messages, @replied_messages].each do |collection|
60 + collection.each do |m|
61 + @all_messages[m.id] = {:msg => m, :replies => []}
62 + end
63 + end
64 +
65 + @all_messages.each do |m|
66 + rep_id = m.replying_message_id
67 + if @all_messages[rep_id]!=nil
68 + @all_messages[rep_id][:replies] << m
69 + end
70 + end
71 + end
72 +
73 + end
@@ -0,0 +1,2
1 + module MessagesHelper
2 + end
@@ -0,0 +1,60
1 + class Message < ActiveRecord::Base
2 +
3 + belongs_to :sender, :class_name => "User"
4 + belongs_to :receiver, :class_name => "User"
5 +
6 + belongs_to :replying_message, :class_name => "Message"
7 +
8 + # commented manually do it
9 + #
10 + #has_many :replied_messages, {
11 + # :class_name => "Message",
12 + # :foreign_key => "replying_message_id"
13 + #}
14 + #
15 +
16 + attr_accessor :replied_messages
17 +
18 + def self.find_all_sent_by_user(user)
19 + messages = user.messages
20 + replied_messages = user.replied_messages
21 + Message.build_replying_message_hierarchy messages, replied_messages
22 + return messages
23 + end
24 +
25 + def self.find_all_system_unreplied_messages
26 + self.find(:all,
27 + :conditions => 'ISNULL(receiver_id) ' +
28 + 'AND (ISNULL(replied) OR replied=0)',
29 + :order => 'created_at')
30 + end
31 +
32 + def self.build_replying_message_hierarchy(*args)
33 + # manually build replies hierarchy (to improve efficiency)
34 + all_messages = {}
35 +
36 + args.each do |collection|
37 + collection.each do |m|
38 + all_messages[m.id] = m
39 + m.replied_messages = []
40 + end
41 + end
42 +
43 + all_messages.each_value do |m|
44 + rep_id = m.replying_message_id
45 + if all_messages[rep_id]!=nil
46 + all_messages[rep_id].add_replied_message(m)
47 + end
48 + end
49 + end
50 +
51 + def add_replied_message(m)
52 + if @replied_messages==nil
53 + @replied_messages = [m]
54 + else
55 + @replied_messages << m
56 + end
57 + @replied_messages
58 + end
59 +
60 + end
@@ -0,0 +1,7
1 + .message
2 + .stat
3 + = "#{message.sender.full_name} at #{message.created_at}"
4 + %div{:class => (!defined?(reply) or (reply==false)) ? "body" : "reply-body"}
5 + = simple_format(message.body)
6 + - if message.replied_messages.length!=0
7 + = render :partial => 'message', :collection => message.replied_messages, :locals => {:reply => true}
@@ -0,0 +1,6
1 + %tr
2 + %td=h short_message.sender.full_name
3 + %td= "#{short_message.created_at}"
4 + %td=h truncate(short_message.body)
5 + %td
6 + = link_to "[reply]", :action => 'show', :id => short_message.id
@@ -0,0 +1,13
1 + = user_title_bar(@user)
2 +
3 + %h1 Console: active messages
4 +
5 + = link_to '[all messages]', :action => 'list_all'
6 +
7 + %table
8 + %tr
9 + %th From
10 + %th When
11 + %th Message
12 + %th
13 + = render :partial => "short_message", :collection => @messages
@@ -0,0 +1,14
1 + = user_title_bar(@user)
2 +
3 + %h3 Your Messages
4 +
5 + - form_for 'message', nil, :url => { :action => 'create'} do |f|
6 + %p
7 + %b New message
8 + = submit_tag "Post"
9 + %br/
10 + = f.text_area :body, :rows => 5, :cols => 100
11 +
12 + %hr/
13 +
14 + = render :partial => 'message', :collection => @messages, :locals => {:reply => false}
@@ -0,0 +1,13
1 + %h3 Message
2 +
3 + .message
4 + .stat
5 + = "#{@message.sender.full_name} at #{@message.created_at}"
6 + .body= simple_format(@message.body)
7 +
8 + %h3 Your reply:
9 + - form_for 'r_message', nil, :url => { :action => 'reply'} do |f|
10 + = f.text_area :body, :rows => 5, :cols => 100
11 + = f.hidden_field :receiver_id, {:value => @message.sender_id }
12 + = f.hidden_field :replying_message_id, {:value => @message.id }
13 + = submit_tag "Post"
@@ -0,0 +1,17
1 + class CreateMessages < ActiveRecord::Migration
2 + def self.up
3 + create_table :messages do |t|
4 + t.column "sender_id", :integer
5 + t.column "receiver_id", :integer
6 + t.column "replying_message_id", :integer
7 + t.column "body", :text
8 + t.column "replied", :boolean # this is for efficiency
9 +
10 + t.timestamps
11 + end
12 + end
13 +
14 + def self.down
15 + drop_table :messages
16 + end
17 + end
@@ -0,0 +1,7
1 + # Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
2 +
3 + # one:
4 + # column: value
5 + #
6 + # two:
7 + # column: value
@@ -0,0 +1,8
1 + require File.dirname(__FILE__) + '/../test_helper'
2 +
3 + class MessagesControllerTest < ActionController::TestCase
4 + # Replace this with your real tests.
5 + def test_truth
6 + assert true
7 + end
8 + end
@@ -0,0 +1,8
1 + require File.dirname(__FILE__) + '/../test_helper'
2 +
3 + class MessageTest < ActiveSupport::TestCase
4 + # Replace this with your real tests.
5 + def test_truth
6 + assert true
7 + end
8 + end
@@ -6,22 +6,24
6 user = User.find(session[:user_id])
6 user = User.find(session[:user_id])
7
7
8 if (user!=nil) and (user.admin?)
8 if (user!=nil) and (user.admin?)
9 # admin menu
9 # admin menu
10 menu_items << "<b>Administrative task:</b> "
10 menu_items << "<b>Administrative task:</b> "
11 append_to menu_items, '[Announcements]', 'announcements', 'index'
11 append_to menu_items, '[Announcements]', 'announcements', 'index'
12 + append_to menu_items, '[Msg console]', 'messages', 'console'
12 append_to menu_items, '[Problem admin]', 'problems', 'index'
13 append_to menu_items, '[Problem admin]', 'problems', 'index'
13 append_to menu_items, '[User admin]', 'user_admin', 'index'
14 append_to menu_items, '[User admin]', 'user_admin', 'index'
14 append_to menu_items, '[User stat]', 'user_admin', 'user_stat'
15 append_to menu_items, '[User stat]', 'user_admin', 'user_stat'
15 #append_to menu_items, '[Graders]', 'graders', 'list'
16 #append_to menu_items, '[Graders]', 'graders', 'list'
16 append_to menu_items, '[Site config]', 'configurations', 'index'
17 append_to menu_items, '[Site config]', 'configurations', 'index'
17 menu_items << "<br/>"
18 menu_items << "<br/>"
18 end
19 end
19
20
20 # main page
21 # main page
21 append_to menu_items, '[Main]', 'main', 'list'
22 append_to menu_items, '[Main]', 'main', 'list'
23 + append_to menu_items, '[Messages]', 'messages', 'list'
22 append_to menu_items, '[Tasks]', 'tasks', 'list'
24 append_to menu_items, '[Tasks]', 'tasks', 'list'
23 append_to menu_items, '[Submissions]', 'main', 'submission'
25 append_to menu_items, '[Submissions]', 'main', 'submission'
24 append_to menu_items, '[Test]', 'test', 'index'
26 append_to menu_items, '[Test]', 'test', 'index'
25 append_to menu_items, '[Settings]', 'users', 'index'
27 append_to menu_items, '[Settings]', 'users', 'index'
26 append_to menu_items, '[Log out]', 'main', 'login'
28 append_to menu_items, '[Log out]', 'main', 'login'
27
29
@@ -3,12 +3,22
3 class User < ActiveRecord::Base
3 class User < ActiveRecord::Base
4
4
5 has_and_belongs_to_many :roles
5 has_and_belongs_to_many :roles
6
6
7 has_many :test_requests, :order => "submitted_at DESC"
7 has_many :test_requests, :order => "submitted_at DESC"
8
8
9 + has_many :messages,
10 + :class_name => "Message",
11 + :foreign_key => "sender_id",
12 + :order => 'created_at DESC'
13 +
14 + has_many :replied_messages,
15 + :class_name => "Message",
16 + :foreign_key => "receiver_id",
17 + :order => 'created_at DESC'
18 +
9 belongs_to :site
19 belongs_to :site
10
20
11 validates_presence_of :login
21 validates_presence_of :login
12 validates_presence_of :full_name
22 validates_presence_of :full_name
13 validates_length_of :full_name, :minimum => 1
23 validates_length_of :full_name, :minimum => 1
14
24
@@ -6,13 +6,13
6 # to create the application database on another system, you should be using db:schema:load, not running
6 # to create the application database on another system, you should be using db:schema:load, not running
7 # all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
7 # all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations
8 # you'll amass, the slower it'll run and the greater likelihood for issues).
8 # you'll amass, the slower it'll run and the greater likelihood for issues).
9 #
9 #
10 # It's strongly recommended to check this file into your version control system.
10 # It's strongly recommended to check this file into your version control system.
11
11
12 - ActiveRecord::Schema.define(:version => 31) do
12 + ActiveRecord::Schema.define(:version => 32) do
13
13
14 create_table "announcements", :force => true do |t|
14 create_table "announcements", :force => true do |t|
15 t.string "author"
15 t.string "author"
16 t.text "body"
16 t.text "body"
17 t.boolean "published"
17 t.boolean "published"
18 t.datetime "created_at"
18 t.datetime "created_at"
@@ -49,12 +49,22
49 create_table "languages", :force => true do |t|
49 create_table "languages", :force => true do |t|
50 t.string "name", :limit => 10
50 t.string "name", :limit => 10
51 t.string "pretty_name"
51 t.string "pretty_name"
52 t.string "ext", :limit => 10
52 t.string "ext", :limit => 10
53 end
53 end
54
54
55 + create_table "messages", :force => true do |t|
56 + t.integer "sender_id"
57 + t.integer "receiver_id"
58 + t.integer "replying_message_id"
59 + t.text "body"
60 + t.boolean "replied"
61 + t.datetime "created_at"
62 + t.datetime "updated_at"
63 + end
64 +
55 create_table "problems", :force => true do |t|
65 create_table "problems", :force => true do |t|
56 t.string "name", :limit => 30
66 t.string "name", :limit => 30
57 t.string "full_name"
67 t.string "full_name"
58 t.integer "full_score"
68 t.integer "full_score"
59 t.date "date_added"
69 t.date "date_added"
60 t.boolean "available"
70 t.boolean "available"
@@ -188,6 +188,34
188
188
189 div.pub-info, div.pub-info p {
189 div.pub-info, div.pub-info p {
190 text-align: right;
190 text-align: right;
191 font-style: italic;
191 font-style: italic;
192 font-size: 9px;
192 font-size: 9px;
193 }
193 }
194 +
195 + /******************
196 + [Messages
197 + ******************/
198 +
199 + div.message {
200 + padding-top: 5px;
201 + padding-left: 10px;
202 + }
203 +
204 + div.message div.body {
205 + border: 1px solid green;
206 + background: #eeffee;
207 + padding-left: 5px;
208 + }
209 +
210 + div.message div.reply-body {
211 + border: 1px solid black;
212 + background: #ffeeee;
213 + padding-left: 5px;
214 + }
215 +
216 + div.message div.stat {
217 + font-size: 10px;
218 + color: white;
219 + background: green;
220 + font-weight: bold;
221 + }
You need to be logged in to leave comments. Login now