has_messages_generators 0.0.1
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.
- data/MIT-LICENSE +20 -0
- data/README.mdown +43 -0
- data/lib/generators/base.rb +179 -0
- data/lib/generators/has_messages/install/USAGE +10 -0
- data/lib/generators/has_messages/install/install_generator.rb +126 -0
- data/lib/generators/has_messages/install/templates/README +26 -0
- data/lib/generators/has_messages/install/templates/assets/javascripts/jquery.tokeninput.js +718 -0
- data/lib/generators/has_messages/install/templates/assets/javascripts/messages.js +19 -0
- data/lib/generators/has_messages/install/templates/assets/stylesheets/messages.css +107 -0
- data/lib/generators/has_messages/install/templates/assets/stylesheets/token-input-facebook.css +122 -0
- data/lib/generators/has_messages/install/templates/controllers/messages_controller.rb +111 -0
- data/lib/generators/has_messages/install/templates/helpers/messages_helper.rb +2 -0
- data/lib/generators/has_messages/install/templates/lib/has_messages.rb +67 -0
- data/lib/generators/has_messages/install/templates/models/create_messages.rb +24 -0
- data/lib/generators/has_messages/install/templates/models/message.rb +67 -0
- data/lib/generators/has_messages/install/templates/views/_head.html.erb +20 -0
- data/lib/generators/has_messages/install/templates/views/_messages.html.erb +56 -0
- data/lib/generators/has_messages/install/templates/views/_tabs_panel.html.erb +11 -0
- data/lib/generators/has_messages/install/templates/views/index.html.erb +10 -0
- data/lib/generators/has_messages/install/templates/views/index.js.erb +1 -0
- data/lib/generators/has_messages/install/templates/views/new.html.erb +26 -0
- data/lib/generators/has_messages/install/templates/views/show.html.erb +35 -0
- metadata +78 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
$(function() {
|
2
|
+
// Check all the checkboxes when the head one is selected
|
3
|
+
$(".checkall").live("click", function() {
|
4
|
+
$("input[type='checkbox']").attr('checked', $(this).is(':checked'));
|
5
|
+
});
|
6
|
+
|
7
|
+
// handle pagination through ajax
|
8
|
+
$("#tabs-messages .pagination a").live("click", function(e) {
|
9
|
+
$.getScript(this.href);
|
10
|
+
history.pushState(null, document.title, this.href);
|
11
|
+
e.preventDefault();
|
12
|
+
});
|
13
|
+
|
14
|
+
//bind window for postate
|
15
|
+
$(window).bind("popstate", function() {
|
16
|
+
$.getScript(location.href);
|
17
|
+
});
|
18
|
+
|
19
|
+
});
|
@@ -0,0 +1,107 @@
|
|
1
|
+
/* pretty-table */
|
2
|
+
table.pretty {
|
3
|
+
border-collapse: collapse;
|
4
|
+
}
|
5
|
+
|
6
|
+
.pretty td, .pretty th {
|
7
|
+
padding: 4px 10px;
|
8
|
+
border: solid 1px #AAA;
|
9
|
+
}
|
10
|
+
|
11
|
+
.pretty th .current {
|
12
|
+
padding-right: 12px;
|
13
|
+
background-repeat: no-repeat;
|
14
|
+
background-position: right center;
|
15
|
+
}
|
16
|
+
|
17
|
+
.pretty tr.alt { background-color: #EBEBEB; }
|
18
|
+
|
19
|
+
.pretty tr.unread { font-weight: bold; }
|
20
|
+
|
21
|
+
ul.tabs {
|
22
|
+
margin: 0;
|
23
|
+
padding: 0;
|
24
|
+
float: left;
|
25
|
+
list-style: none;
|
26
|
+
height: 32px; /*--Set height of tabs--*/
|
27
|
+
border-bottom: 1px solid #999;
|
28
|
+
border-left: 1px solid #999;
|
29
|
+
width: 100%;
|
30
|
+
}
|
31
|
+
ul.tabs li {
|
32
|
+
float: left;
|
33
|
+
margin: 0;
|
34
|
+
padding: 0;
|
35
|
+
height: 31px; /*--Subtract 1px from the height of the unordered list--*/
|
36
|
+
line-height: 31px; /*--Vertically aligns the text within the tab--*/
|
37
|
+
border: 1px solid #999;
|
38
|
+
border-left: none;
|
39
|
+
margin-bottom: -1px; /*--Pull the list item down 1px--*/
|
40
|
+
overflow: hidden;
|
41
|
+
position: relative;
|
42
|
+
background: #e0e0e0;
|
43
|
+
}
|
44
|
+
ul.tabs li a {
|
45
|
+
text-decoration: none;
|
46
|
+
color: #000;
|
47
|
+
display: block;
|
48
|
+
padding: 0 20px;
|
49
|
+
border: 1px solid #fff; /*--Gives the bevel look with a 1px white border inside the list item--*/
|
50
|
+
outline: none;
|
51
|
+
}
|
52
|
+
ul.tabs li a:hover {
|
53
|
+
background: #ccc;
|
54
|
+
}
|
55
|
+
html ul.tabs li.active, html ul.tabs li.active a:hover { /*--Makes sure that the active tab does not listen to the hover properties--*/
|
56
|
+
background: #fff;
|
57
|
+
border-bottom: 1px solid #fff; /*--Makes the active tab look like it's connected with its content--*/
|
58
|
+
}
|
59
|
+
|
60
|
+
.message {
|
61
|
+
margin: 8px 0;
|
62
|
+
padding: 8px 15px;
|
63
|
+
border: solid 1px #999;
|
64
|
+
width: 300px;
|
65
|
+
border-radius: 12px;
|
66
|
+
background-image: -webkit-gradient(
|
67
|
+
linear,
|
68
|
+
left bottom,
|
69
|
+
left top,
|
70
|
+
color-stop(0, #CCC),
|
71
|
+
color-stop(1, #F5F5F5)
|
72
|
+
);
|
73
|
+
background-image: -moz-linear-gradient(
|
74
|
+
center bottom,
|
75
|
+
#CCC 0%,
|
76
|
+
#F5F5F5 100%
|
77
|
+
);
|
78
|
+
}
|
79
|
+
|
80
|
+
.message .content a {
|
81
|
+
color: #000;
|
82
|
+
text-decoration: none;
|
83
|
+
}
|
84
|
+
|
85
|
+
.message .created_at {
|
86
|
+
color: #555;
|
87
|
+
font-size: 12px;
|
88
|
+
float: right;
|
89
|
+
}
|
90
|
+
|
91
|
+
.message .actions {
|
92
|
+
font-size: 12px;
|
93
|
+
margin-top: 5px;
|
94
|
+
}
|
95
|
+
|
96
|
+
.message .actions a {
|
97
|
+
text-decoration: none;
|
98
|
+
}
|
99
|
+
|
100
|
+
.nested_messages {
|
101
|
+
margin-left: 30px;
|
102
|
+
}
|
103
|
+
|
104
|
+
/*.nested_messages .nested_messages .nested_messages .nested_messages {
|
105
|
+
margin-left: 0;
|
106
|
+
}
|
107
|
+
*/
|
data/lib/generators/has_messages/install/templates/assets/stylesheets/token-input-facebook.css
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
/* Example tokeninput style #2: Facebook style */
|
2
|
+
ul.token-input-list-facebook {
|
3
|
+
overflow: hidden;
|
4
|
+
height: auto !important;
|
5
|
+
height: 1%;
|
6
|
+
width: 400px;
|
7
|
+
border: 1px solid #8496ba;
|
8
|
+
cursor: text;
|
9
|
+
font-size: 12px;
|
10
|
+
font-family: Verdana;
|
11
|
+
min-height: 1px;
|
12
|
+
z-index: 999;
|
13
|
+
margin: 0;
|
14
|
+
padding: 0;
|
15
|
+
background-color: #fff;
|
16
|
+
list-style-type: none;
|
17
|
+
clear: left;
|
18
|
+
}
|
19
|
+
|
20
|
+
ul.token-input-list-facebook li input {
|
21
|
+
border: 0;
|
22
|
+
width: 100px;
|
23
|
+
padding: 3px 8px;
|
24
|
+
background-color: white;
|
25
|
+
margin: 2px 0;
|
26
|
+
-webkit-appearance: caret;
|
27
|
+
}
|
28
|
+
|
29
|
+
li.token-input-token-facebook {
|
30
|
+
overflow: hidden;
|
31
|
+
height: auto !important;
|
32
|
+
height: 15px;
|
33
|
+
margin: 3px;
|
34
|
+
padding: 1px 3px;
|
35
|
+
background-color: #eff2f7;
|
36
|
+
color: #000;
|
37
|
+
cursor: default;
|
38
|
+
border: 1px solid #ccd5e4;
|
39
|
+
font-size: 11px;
|
40
|
+
border-radius: 5px;
|
41
|
+
-moz-border-radius: 5px;
|
42
|
+
-webkit-border-radius: 5px;
|
43
|
+
float: left;
|
44
|
+
white-space: nowrap;
|
45
|
+
}
|
46
|
+
|
47
|
+
li.token-input-token-facebook p {
|
48
|
+
display: inline;
|
49
|
+
padding: 0;
|
50
|
+
margin: 0;
|
51
|
+
}
|
52
|
+
|
53
|
+
li.token-input-token-facebook span {
|
54
|
+
color: #a6b3cf;
|
55
|
+
margin-left: 5px;
|
56
|
+
font-weight: bold;
|
57
|
+
cursor: pointer;
|
58
|
+
}
|
59
|
+
|
60
|
+
li.token-input-selected-token-facebook {
|
61
|
+
background-color: #5670a6;
|
62
|
+
border: 1px solid #3b5998;
|
63
|
+
color: #fff;
|
64
|
+
}
|
65
|
+
|
66
|
+
li.token-input-input-token-facebook {
|
67
|
+
float: left;
|
68
|
+
margin: 0;
|
69
|
+
padding: 0;
|
70
|
+
list-style-type: none;
|
71
|
+
}
|
72
|
+
|
73
|
+
div.token-input-dropdown-facebook {
|
74
|
+
position: absolute;
|
75
|
+
width: 400px;
|
76
|
+
background-color: #fff;
|
77
|
+
overflow: hidden;
|
78
|
+
border-left: 1px solid #ccc;
|
79
|
+
border-right: 1px solid #ccc;
|
80
|
+
border-bottom: 1px solid #ccc;
|
81
|
+
cursor: default;
|
82
|
+
font-size: 11px;
|
83
|
+
font-family: Verdana;
|
84
|
+
z-index: 1;
|
85
|
+
}
|
86
|
+
|
87
|
+
div.token-input-dropdown-facebook p {
|
88
|
+
margin: 0;
|
89
|
+
padding: 5px;
|
90
|
+
font-weight: bold;
|
91
|
+
color: #777;
|
92
|
+
}
|
93
|
+
|
94
|
+
div.token-input-dropdown-facebook ul {
|
95
|
+
margin: 0;
|
96
|
+
padding: 0;
|
97
|
+
}
|
98
|
+
|
99
|
+
div.token-input-dropdown-facebook ul li {
|
100
|
+
background-color: #fff;
|
101
|
+
padding: 3px;
|
102
|
+
margin: 0;
|
103
|
+
list-style-type: none;
|
104
|
+
}
|
105
|
+
|
106
|
+
div.token-input-dropdown-facebook ul li.token-input-dropdown-item-facebook {
|
107
|
+
background-color: #fff;
|
108
|
+
}
|
109
|
+
|
110
|
+
div.token-input-dropdown-facebook ul li.token-input-dropdown-item2-facebook {
|
111
|
+
background-color: #fff;
|
112
|
+
}
|
113
|
+
|
114
|
+
div.token-input-dropdown-facebook ul li em {
|
115
|
+
font-weight: bold;
|
116
|
+
font-style: normal;
|
117
|
+
}
|
118
|
+
|
119
|
+
div.token-input-dropdown-facebook ul li.token-input-selected-dropdown-item-facebook {
|
120
|
+
background-color: #3b5998;
|
121
|
+
color: #fff;
|
122
|
+
}
|
@@ -0,0 +1,111 @@
|
|
1
|
+
class MessagesController < ApplicationController
|
2
|
+
<%- if gemfile_included?("devise") -%>
|
3
|
+
before_filter :authenticate_user!
|
4
|
+
<%- end -%>
|
5
|
+
def index
|
6
|
+
@messagebox = params[:messagebox].blank? ? "inbox" : params[:messagebox]
|
7
|
+
@messages = current_user.send(@messagebox).group(:subject_id).page(params[:page]).per(10)
|
8
|
+
|
9
|
+
case @messagebox
|
10
|
+
when "trash"
|
11
|
+
@options = ["Read","Unread","Delete","Undelete"]
|
12
|
+
else
|
13
|
+
@options = ["Read","Unread","Delete"]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def show
|
18
|
+
unless params[:messagebox].blank?
|
19
|
+
message = current_user.send(params[:messagebox]).find(params[:id])
|
20
|
+
|
21
|
+
@messages = message.root.subtree
|
22
|
+
@parent_id = @messages.last.id
|
23
|
+
|
24
|
+
if @messages.last.copies
|
25
|
+
@user_tokens = @messages.last.recipient_id
|
26
|
+
@parent_id = @messages.last.ancestor_ids.last unless @parent_id.nil?
|
27
|
+
else
|
28
|
+
@user_tokens = @messages.last.sender_id
|
29
|
+
end
|
30
|
+
|
31
|
+
read_unread_messages(true, *@messages)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def new
|
36
|
+
end
|
37
|
+
|
38
|
+
def create
|
39
|
+
unless params[:user_tokens].blank? or params[:subject].blank? or params[:content].blank?
|
40
|
+
recipients = User.find(params[:user_tokens].split(",").collect { |id| id.to_i })
|
41
|
+
if current_user.send_message?(:recipients => recipients, :subject_id => params[:subject_id], :subject => params[:subject], :content => params[:content], :parent_id => params[:parent_id])
|
42
|
+
redirect_to box_messages_url(:inbox), :notice => 'Successfully send message.'
|
43
|
+
else
|
44
|
+
flash.now[:alert] = "Unable to send message."
|
45
|
+
render "new"
|
46
|
+
end
|
47
|
+
else
|
48
|
+
flash.now[:alert] = "Invalid input for sending message."
|
49
|
+
render "new"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def update
|
54
|
+
unless params[:messages].nil?
|
55
|
+
message = current_user.send(params[:messagebox]).find(params[:messages])
|
56
|
+
message.each do |message|
|
57
|
+
messages = message.root.subtree
|
58
|
+
if params[:option].downcase == "read"
|
59
|
+
read_unread_messages(true,*messages)
|
60
|
+
elsif params[:option].downcase == "unread"
|
61
|
+
read_unread_messages(false,*messages)
|
62
|
+
elsif params[:option].downcase == "delete"
|
63
|
+
delete_messages(true,*messages)
|
64
|
+
elsif params[:option].downcase == "undelete"
|
65
|
+
delete_messages(false,*messages)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
redirect_to box_messages_url(params[:messagebox])
|
70
|
+
end
|
71
|
+
|
72
|
+
def empty
|
73
|
+
unless params[:messagebox].nil?
|
74
|
+
current_user.empty_messages(params[:messagebox].to_sym => true)
|
75
|
+
redirect_to box_messages_url(params[:messagebox]), :notice => "Successfully delete all messages."
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def token
|
80
|
+
query = "%" + params[:q] + "%"
|
81
|
+
recipients = User.select("id,email").where("email like ?", query)
|
82
|
+
respond_to do |format|
|
83
|
+
format.json { render :json => recipients.map { |u| { "id" => u.id, "name" => u.email} } }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def read_unread_messages(isRead, *messages)
|
90
|
+
messages.each do |msg|
|
91
|
+
unless msg.copies
|
92
|
+
if isRead
|
93
|
+
msg.mark_as_read unless msg.read?
|
94
|
+
else
|
95
|
+
msg.mark_as_unread if msg.read?
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def delete_messages(isDelete, *messages)
|
102
|
+
messages.each do |msg|
|
103
|
+
if isDelete
|
104
|
+
msg.delete
|
105
|
+
else
|
106
|
+
msg.undelete
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module HasMessages
|
2
|
+
|
3
|
+
def send_message?(options)
|
4
|
+
send_message(options)
|
5
|
+
true
|
6
|
+
rescue Exception => e
|
7
|
+
false
|
8
|
+
end
|
9
|
+
|
10
|
+
def send_message(options)
|
11
|
+
unless options[:recipients].nil?
|
12
|
+
transaction do
|
13
|
+
recipients = options[:recipients]
|
14
|
+
options.delete(:recipients)
|
15
|
+
|
16
|
+
options[:subject_id] = Message.sequence_subject_id if options[:subject_id].nil?
|
17
|
+
|
18
|
+
recipients.each do |rec|
|
19
|
+
# => create message copies
|
20
|
+
options[:user_id] = self.id
|
21
|
+
options[:sender_id] = self.id
|
22
|
+
options[:recipient_id] = rec.id
|
23
|
+
options[:copies] = true
|
24
|
+
Message.create(options)
|
25
|
+
# => create message
|
26
|
+
options[:user_id] = rec.id
|
27
|
+
options[:sender_id] = self.id
|
28
|
+
options[:recipient_id] = rec.id
|
29
|
+
options[:copies] = false
|
30
|
+
options[:parent_id] = Message.next_parent_id(options[:parent_id]) unless options[:parent_id].nil?
|
31
|
+
Message.create(options)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
else
|
35
|
+
raise "Required recipients"
|
36
|
+
end
|
37
|
+
rescue Exception => e
|
38
|
+
raise e
|
39
|
+
end
|
40
|
+
|
41
|
+
def inbox(options = {})
|
42
|
+
options[:deleted] = false
|
43
|
+
options[:copies] = false
|
44
|
+
self.messages.where(options)
|
45
|
+
end
|
46
|
+
|
47
|
+
def outbox(options = {})
|
48
|
+
options[:deleted] = false
|
49
|
+
options[:copies] = true
|
50
|
+
self.messages.where(options)
|
51
|
+
end
|
52
|
+
|
53
|
+
def trash(options = {})
|
54
|
+
options[:deleted] = true
|
55
|
+
self.messages.where(options)
|
56
|
+
end
|
57
|
+
|
58
|
+
def empty_messages(options = {})
|
59
|
+
if options.empty? or options[:inbox] or options[:outbox]
|
60
|
+
self.inbox.update_all(:deleted => true)
|
61
|
+
self.outbox.update_all(:deleted => true)
|
62
|
+
elsif options[:trash]
|
63
|
+
self.trash.delete_all
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class CreateMessages < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :messages do |t|
|
4
|
+
t.integer :user_id
|
5
|
+
t.integer :sender_id
|
6
|
+
t.integer :recipient_id
|
7
|
+
t.integer :subject_id
|
8
|
+
t.string :subject
|
9
|
+
t.text :content
|
10
|
+
t.boolean :opened, :default => false
|
11
|
+
t.boolean :deleted, :default => false
|
12
|
+
t.boolean :copies, :default => false
|
13
|
+
t.string :ancestry
|
14
|
+
t.timestamps
|
15
|
+
end
|
16
|
+
|
17
|
+
add_index :messages, [:user_id, :subject_id, :ancestry], :name => "messages_idx"
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.down
|
21
|
+
drop_index :messages, "messages_idx"
|
22
|
+
drop_table :messages
|
23
|
+
end
|
24
|
+
end
|