implement private messages
This commit is contained in:
parent
e47a054e75
commit
fc1c474fb3
|
@ -569,8 +569,6 @@ table.data th {
|
||||||
background-color: #eaeaea;
|
background-color: #eaeaea;
|
||||||
border-bottom: 1px solid #cacaca;
|
border-bottom: 1px solid #cacaca;
|
||||||
border-top: 1px solid #cacaca;
|
border-top: 1px solid #cacaca;
|
||||||
padding: 2px;
|
|
||||||
padding-left: 3px;
|
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
table.data th img {
|
table.data th img {
|
||||||
|
@ -583,10 +581,13 @@ table.data th.r, table.data td.r {
|
||||||
padding-right: 3px;
|
padding-right: 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table.data th,
|
||||||
table.data td {
|
table.data td {
|
||||||
padding-left: 3px;
|
padding: 0.25em 0.5em;
|
||||||
padding-top: 4px;
|
}
|
||||||
padding-bottom: 3px;
|
|
||||||
|
table.data tr.bold td {
|
||||||
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
table.thread td {
|
table.thread td {
|
||||||
|
@ -600,11 +601,13 @@ table.thread td img {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
table.data tr.row0 td {
|
table.data tr.row0 td,
|
||||||
|
table.data.zebra tr:nth-child(even) td {
|
||||||
background-color: #f8f8f8;
|
background-color: #f8f8f8;
|
||||||
border-bottom: 1px solid #eaeaea;
|
border-bottom: 1px solid #eaeaea;
|
||||||
}
|
}
|
||||||
table.data tr.row1 td {
|
table.data tr.row1 td,
|
||||||
|
table.data.zebra tr:nth-child(odd) td {
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
border-bottom: 1px solid #eaeaea;
|
border-bottom: 1px solid #eaeaea;
|
||||||
}
|
}
|
||||||
|
@ -642,6 +645,16 @@ table.data tr.void td, table.data tr.void td a {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 11pt;
|
font-size: 11pt;
|
||||||
}
|
}
|
||||||
|
.box .sublegend {
|
||||||
|
font-size: 10pt;
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: italic;
|
||||||
|
color: gray;
|
||||||
|
}
|
||||||
|
.box .legend.right {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
.box .boxtitle {
|
.box .boxtitle {
|
||||||
background-color: #f0f0f0;
|
background-color: #f0f0f0;
|
||||||
border-bottom: 1px solid #cacaca;
|
border-bottom: 1px solid #cacaca;
|
||||||
|
|
|
@ -1,2 +1,73 @@
|
||||||
class MessagesController < ApplicationController
|
class MessagesController < ApplicationController
|
||||||
|
before_filter :require_logged_in_user
|
||||||
|
before_filter :find_message, :only => [ :show, :destroy, :keep_as_new ]
|
||||||
|
|
||||||
|
def index
|
||||||
|
@new_message = Message.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
@new_message = Message.new(params[:message])
|
||||||
|
@new_message.author_user_id = @user.id
|
||||||
|
|
||||||
|
if @new_message.save
|
||||||
|
flash.now[:success] = "Your message has been sent to " <<
|
||||||
|
@new_message.recipient.username
|
||||||
|
|
||||||
|
@new_message = Message.new
|
||||||
|
end
|
||||||
|
|
||||||
|
render :action => "index"
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
@new_message = Message.new
|
||||||
|
@new_message.recipient_username = (@message.author_user_id == @user.id ?
|
||||||
|
@message.recipient.username : @message.author.username)
|
||||||
|
|
||||||
|
if @message.recipient_user_id == @user.id
|
||||||
|
@message.has_been_read = true
|
||||||
|
@message.save
|
||||||
|
end
|
||||||
|
|
||||||
|
if @message.subject.match(/^re:/i)
|
||||||
|
@new_message.subject = @message.subject
|
||||||
|
else
|
||||||
|
@new_message.subject = "Re: #{@message.subject}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
if @message.author_user_id == @user.id
|
||||||
|
@message.deleted_by_author = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if @message.recipient_user_id == @user.id
|
||||||
|
@message.deleted_by_recipient = true
|
||||||
|
end
|
||||||
|
|
||||||
|
@message.save
|
||||||
|
|
||||||
|
flash[:success] = "Deleted message"
|
||||||
|
return redirect_to "/messages"
|
||||||
|
end
|
||||||
|
|
||||||
|
def keep_as_new
|
||||||
|
@message.has_been_read = false
|
||||||
|
@message.save
|
||||||
|
|
||||||
|
return redirect_to "/messages"
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
def find_message
|
||||||
|
if @message = Message.find_by_short_id(params[:message_id ] || params[:id])
|
||||||
|
if !(@message.author_user_id == @user.id ||
|
||||||
|
@message.recipient_user_id == @user.id)
|
||||||
|
flash[:error] = "Could not find message"
|
||||||
|
redirect_to "/messages"
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
12
app/mailers/email_message.rb
Normal file
12
app/mailers/email_message.rb
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
class EmailMessage < ActionMailer::Base
|
||||||
|
default :from => "nobody@lobste.rs"
|
||||||
|
|
||||||
|
def notify(message, user)
|
||||||
|
@message = message
|
||||||
|
@user = user
|
||||||
|
|
||||||
|
mail(:to => user.email, :from => "Lobsters <nobody@lobste.rs>",
|
||||||
|
:subject => "[Lobsters] Private Message from " <<
|
||||||
|
"#{message.author.username}: #{message.subject}")
|
||||||
|
end
|
||||||
|
end
|
|
@ -12,7 +12,7 @@ class Comment < ActiveRecord::Base
|
||||||
:indent_level, :highlighted
|
:indent_level, :highlighted
|
||||||
|
|
||||||
before_create :assign_short_id_and_upvote
|
before_create :assign_short_id_and_upvote
|
||||||
after_create :assign_votes, :mark_submitter, :email_reply
|
after_create :assign_votes, :mark_submitter, :deliver_reply_notifications
|
||||||
after_destroy :unassign_votes
|
after_destroy :unassign_votes
|
||||||
|
|
||||||
MAX_EDIT_MINS = 45
|
MAX_EDIT_MINS = 45
|
||||||
|
@ -32,12 +32,14 @@ class Comment < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def assign_short_id_and_upvote
|
def assign_short_id_and_upvote
|
||||||
(1...10).each do |tries|
|
10.times do |try|
|
||||||
if tries == 10
|
if try == 10
|
||||||
raise "too many hash collisions"
|
raise "too many hash collisions"
|
||||||
end
|
end
|
||||||
|
|
||||||
if !Comment.find_by_short_id(self.short_id = Utils.random_str(6))
|
self.short_id = Utils.random_str(6)
|
||||||
|
|
||||||
|
if !Comment.find_by_short_id(self.short_id)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -56,14 +58,14 @@ class Comment < ActiveRecord::Base
|
||||||
Keystore.increment_value_for("user:#{self.user_id}:comments_posted")
|
Keystore.increment_value_for("user:#{self.user_id}:comments_posted")
|
||||||
end
|
end
|
||||||
|
|
||||||
def email_reply
|
def deliver_reply_notifications
|
||||||
begin
|
begin
|
||||||
if self.parent_comment_id && u = self.parent_comment.try(:user)
|
if self.parent_comment_id && u = self.parent_comment.try(:user)
|
||||||
if u.email_replies?
|
if u.email_replies?
|
||||||
EmailReply.reply(self, u).deliver
|
EmailReply.reply(self, u).deliver
|
||||||
end
|
end
|
||||||
|
|
||||||
if u.pushover_replies?
|
if u.pushover_replies? && u.pushover_user_key.present?
|
||||||
Pushover.push(u.pushover_user_key, u.pushover_device, {
|
Pushover.push(u.pushover_user_key, u.pushover_device, {
|
||||||
:title => "Lobsters reply from #{self.user.username} on " <<
|
:title => "Lobsters reply from #{self.user.username} on " <<
|
||||||
"#{self.story.title}",
|
"#{self.story.title}",
|
||||||
|
|
93
app/models/message.rb
Normal file
93
app/models/message.rb
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
class Message < ActiveRecord::Base
|
||||||
|
belongs_to :recipient,
|
||||||
|
:class_name => "User",
|
||||||
|
:foreign_key => "recipient_user_id"
|
||||||
|
belongs_to :author,
|
||||||
|
:class_name => "User",
|
||||||
|
:foreign_key => "author_user_id"
|
||||||
|
|
||||||
|
validates_presence_of :recipient
|
||||||
|
validates_presence_of :author
|
||||||
|
|
||||||
|
attr_accessor :recipient_username
|
||||||
|
|
||||||
|
attr_accessible :recipient_username, :subject, :body
|
||||||
|
|
||||||
|
validates_length_of :subject, :in => 1..150
|
||||||
|
validates_length_of :body, :maximum => (64 * 1024)
|
||||||
|
|
||||||
|
before_create :assign_short_id
|
||||||
|
after_create :deliver_reply_notifications
|
||||||
|
after_save :check_for_both_deleted
|
||||||
|
after_save :update_unread_counts
|
||||||
|
|
||||||
|
def assign_short_id
|
||||||
|
10.times do |try|
|
||||||
|
if try == 10
|
||||||
|
raise "too many hash collisions"
|
||||||
|
end
|
||||||
|
|
||||||
|
self.short_id = Utils.random_str(6)
|
||||||
|
|
||||||
|
if !Message.find_by_short_id(self.short_id)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_for_both_deleted
|
||||||
|
if self.deleted_by_author && self.deleted_by_recipient
|
||||||
|
self.destroy
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_unread_counts
|
||||||
|
self.recipient.update_unread_message_count!
|
||||||
|
end
|
||||||
|
|
||||||
|
def deliver_reply_notifications
|
||||||
|
begin
|
||||||
|
if self.recipient.email_messages?
|
||||||
|
EmailMessage.notify(self, self.recipient).deliver
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.recipient.pushover_messages? &&
|
||||||
|
self.recipient.pushover_user_key.present?
|
||||||
|
Pushover.push(self.recipient.pushover_user_key,
|
||||||
|
self.recipient.pushover_device, {
|
||||||
|
:title => "Lobsters message from #{self.author.username}: " <<
|
||||||
|
"#{self.subject}",
|
||||||
|
:message => self.plaintext_body,
|
||||||
|
:url => self.url,
|
||||||
|
:url_title => "Reply to #{self.author.username}",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def recipient_username=(username)
|
||||||
|
self.recipient_user_id = nil
|
||||||
|
|
||||||
|
if u = User.find_by_username(username)
|
||||||
|
self.recipient_user_id = u.id
|
||||||
|
@recipient_username = username
|
||||||
|
else
|
||||||
|
errors.add(:recipient_username, "is not a valid user")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def linkified_body
|
||||||
|
RDiscount.new(self.body.to_s, :smart, :autolink, :safelink,
|
||||||
|
:filter_html).to_html
|
||||||
|
end
|
||||||
|
|
||||||
|
def plaintext_body
|
||||||
|
# TODO: linkify then strip tags and convert entities back
|
||||||
|
self.body.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def url
|
||||||
|
Rails.application.routes.url_helpers.root_url + "messages/#{self.short_id}"
|
||||||
|
end
|
||||||
|
end
|
|
@ -18,10 +18,9 @@ class Story < ActiveRecord::Base
|
||||||
attr_accessor :vote, :story_type, :already_posted_story, :fetched_content
|
attr_accessor :vote, :story_type, :already_posted_story, :fetched_content
|
||||||
attr_accessor :new_tags, :tags_to_add, :tags_to_delete
|
attr_accessor :new_tags, :tags_to_add, :tags_to_delete
|
||||||
|
|
||||||
after_save :deal_with_tags
|
|
||||||
|
|
||||||
before_create :assign_short_id
|
before_create :assign_short_id
|
||||||
after_create :mark_submitter
|
after_create :mark_submitter
|
||||||
|
after_save :deal_with_tags
|
||||||
|
|
||||||
validate do
|
validate do
|
||||||
if self.url.present?
|
if self.url.present?
|
||||||
|
@ -47,12 +46,13 @@ class Story < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def assign_short_id
|
def assign_short_id
|
||||||
(1...10).each do |tries|
|
10.times do |try|
|
||||||
if tries == 10
|
if try == 10
|
||||||
raise "too many hash collisions"
|
raise "too many hash collisions"
|
||||||
end
|
end
|
||||||
|
|
||||||
self.short_id = Utils.random_str(6)
|
self.short_id = Utils.random_str(6)
|
||||||
|
|
||||||
if !Story.find_by_short_id(self.short_id)
|
if !Story.find_by_short_id(self.short_id)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
class User < ActiveRecord::Base
|
class User < ActiveRecord::Base
|
||||||
has_many :stories,
|
has_many :stories,
|
||||||
:include => :user
|
:include => :user
|
||||||
|
has_many :comments
|
||||||
|
has_many :authored_messages,
|
||||||
|
:class_name => "Message",
|
||||||
|
:foreign_key => "author_user_id"
|
||||||
|
has_many :received_messages,
|
||||||
|
:class_name => "Message",
|
||||||
|
:foreign_key => "recipient_user_id"
|
||||||
has_secure_password
|
has_secure_password
|
||||||
|
|
||||||
validates_format_of :username, :with => /\A[A-Za-z0-9][A-Za-z0-9_-]*\Z/
|
validates_format_of :username, :with => /\A[A-Za-z0-9][A-Za-z0-9_-]*\Z/
|
||||||
|
@ -13,7 +20,7 @@ class User < ActiveRecord::Base
|
||||||
|
|
||||||
attr_accessible :username, :email, :password, :password_confirmation,
|
attr_accessible :username, :email, :password, :password_confirmation,
|
||||||
:about, :email_replies, :pushover_replies, :pushover_user_key,
|
:about, :email_replies, :pushover_replies, :pushover_user_key,
|
||||||
:pushover_device
|
:pushover_device, :email_messages, :pushover_messages
|
||||||
|
|
||||||
before_save :check_session_token
|
before_save :check_session_token
|
||||||
|
|
||||||
|
@ -24,8 +31,13 @@ class User < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
|
|
||||||
def unread_message_count
|
def unread_message_count
|
||||||
0
|
Keystore.value_for("user:#{self.id}:unread_messages").to_i
|
||||||
#Message.where(:recipient_user_id => self.id, :has_been_read => 0).count
|
end
|
||||||
|
|
||||||
|
def update_unread_message_count!
|
||||||
|
Keystore.put("user:#{self.id}:unread_messages",
|
||||||
|
Message.where(:recipient_user_id => self.id,
|
||||||
|
:has_been_read => false).count)
|
||||||
end
|
end
|
||||||
|
|
||||||
def karma
|
def karma
|
||||||
|
|
3
app/views/email_message/notify.text.erb
Normal file
3
app/views/email_message/notify.text.erb
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<%= word_wrap(@comment.plaintext_body, :line_width => 72).gsub(/\n/, "\n ") %>
|
||||||
|
|
||||||
|
Reply at <%= @message.url %>
|
|
@ -2,6 +2,4 @@
|
||||||
|
|
||||||
<%= word_wrap(@comment.plaintext_comment, :line_width => 72).gsub(/\n/, "\n ") %>
|
<%= word_wrap(@comment.plaintext_comment, :line_width => 72).gsub(/\n/, "\n ") %>
|
||||||
|
|
||||||
You can view this reply at:
|
Continue this discussion at <%= @comment.url %>
|
||||||
|
|
||||||
<%= @comment.url %>
|
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<div id="headerright" class="<%= @user ? "loggedin" : "" %>">
|
<div id="headerright" class="<%= @user ? "loggedin" : "" %>">
|
||||||
<% if @user %>
|
<% if @user %>
|
||||||
<a href="/settings"><%= @user.username %> (<%= @user.karma %>)</a>
|
|
||||||
|
|
||||||
<% if false %>
|
|
||||||
<% if (count = @user.unread_message_count) > 0 %>
|
<% if (count = @user.unread_message_count) > 0 %>
|
||||||
<a href="/messages"><%= count %> New Message<%= count == 1 ? "" : "s"
|
<a href="/messages"><%= count %> New Message<%= count == 1 ? "" : "s"
|
||||||
%></a>
|
%></a>
|
||||||
<% else %>
|
<% else %>
|
||||||
<a href="/messages">Messages</a>
|
<a href="/messages">Messages</a>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
|
||||||
|
<a href="/settings"><%= @user.username %> (<%= @user.karma %>)</a>
|
||||||
|
|
||||||
<%= link_to "Logout", { :controller => "login", :action => "logout" },
|
<%= link_to "Logout", { :controller => "login", :action => "logout" },
|
||||||
{ :confirm => "Are you sure you want to logout?",
|
{ :confirm => "Are you sure you want to logout?",
|
||||||
"method" => "post" } %>
|
"method" => "post" } %>
|
||||||
|
|
58
app/views/messages/index.html.erb
Normal file
58
app/views/messages/index.html.erb
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
<div class="box wide">
|
||||||
|
<div class="legend">
|
||||||
|
Private Messages
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<% if @user.received_messages.any? %>
|
||||||
|
<table class="data zebra" width="100%" cellspacing=0>
|
||||||
|
<tr>
|
||||||
|
<th width="15%">From</th>
|
||||||
|
<th width="20%">Sent</th>
|
||||||
|
<th width="60%">Subject</th>
|
||||||
|
</tr>
|
||||||
|
<% @user.received_messages.each do |message| %>
|
||||||
|
<tr class="<%= message.has_been_read? ? "" : "bold" %>">
|
||||||
|
<td><a href="/u/<%= message.author.username %>"><%=
|
||||||
|
message.author.username %></a></td>
|
||||||
|
<td><%= time_ago_in_words(message.created_at) %> ago</td>
|
||||||
|
<td><a href="/messages/<%= message.short_id %>"><%= message.subject
|
||||||
|
%></a></td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</table>
|
||||||
|
<% else %>
|
||||||
|
<p>
|
||||||
|
You do not have any private messages.
|
||||||
|
</p>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<div class="legend">
|
||||||
|
Compose Message
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= form_for @new_message, :method => :post do |f| %>
|
||||||
|
<%= error_messages_for @new_message %>
|
||||||
|
|
||||||
|
<div class="boxline">
|
||||||
|
<%= f.label :recipient_username, "To:", :class => "required" %>
|
||||||
|
<%= f.text_field :recipient_username, :size => 20 %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="boxline">
|
||||||
|
<%= f.label :subject, "Subject:", :class => "required" %>
|
||||||
|
<%= f.text_field :subject, :style => "width: 500px;" %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="boxline">
|
||||||
|
<%= f.label :body, "Message:", :class => "required" %>
|
||||||
|
<%= f.text_area :body, :style => "width: 500px;", :rows => 5 %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="boxline">
|
||||||
|
<p></p>
|
||||||
|
<%= submit_tag "Send Message" %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
66
app/views/messages/show.html.erb
Normal file
66
app/views/messages/show.html.erb
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
<div class="box wide">
|
||||||
|
<div class="legend" style="float: right;">
|
||||||
|
<a href="/messages">Back to Messages</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="legend">
|
||||||
|
<%= @message.subject %>
|
||||||
|
|
||||||
|
<div class="sublegend">
|
||||||
|
Sent from <a href="/u/<%= @message.author.username %>"><%=
|
||||||
|
@message.author.username %></a>
|
||||||
|
to
|
||||||
|
<a href="/u/<%= @message.recipient.username %>"><%=
|
||||||
|
@message.recipient.username %></a>
|
||||||
|
<%= time_ago_in_words(@message.created_at) %> ago
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="boxline">
|
||||||
|
<%= raw @message.linkified_body %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<div class="boxline">
|
||||||
|
<div style="float: left;">
|
||||||
|
<%= form_tag message_url(@message.short_id), :method => :delete do %>
|
||||||
|
<%= submit_tag "Delete Message" %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="float: left; padding-left: 1em;">
|
||||||
|
<%= form_tag message_url(@message.short_id) + "/keep_as_new",
|
||||||
|
:method => :post do %>
|
||||||
|
<%= submit_tag "Keep As New" %>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<div class="legend">
|
||||||
|
Compose Reply To <%= @new_message.recipient_username %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= form_for @new_message, :method => :post do |f| %>
|
||||||
|
<%= f.hidden_field :recipient_username %>
|
||||||
|
|
||||||
|
<%= error_messages_for @new_message %>
|
||||||
|
|
||||||
|
<div class="boxline">
|
||||||
|
<%= f.text_field :subject, :style => "width: 500px;" %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="boxline">
|
||||||
|
<%= f.text_area :body, :style => "width: 500px;", :rows => 5 %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="boxline">
|
||||||
|
<p></p>
|
||||||
|
<%= submit_tag "Send Message" %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
|
</div>
|
|
@ -1,4 +1,116 @@
|
||||||
<div class="box wide">
|
<div class="box wide">
|
||||||
|
<div class="legend right">
|
||||||
|
<a href="/u/<%= @user.username %>">View Profile</a>
|
||||||
|
</div>
|
||||||
|
<div class="legend">
|
||||||
|
Account Settings
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= form_for @edit_user, :url => settings_url, :method => :post do |f| %>
|
||||||
|
<%= error_messages_for f.object %>
|
||||||
|
|
||||||
|
<div class="boxline">
|
||||||
|
<%= f.label :username, "Username:", :class => "required" %>
|
||||||
|
<%= f.text_field :username, :size => 15 %>
|
||||||
|
<span class="hint">
|
||||||
|
<tt>[A-Za-z0-9][A-Za-z0-9_-]*</tt>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="boxline">
|
||||||
|
<%= f.label :password, "New Password:", :class => "required" %>
|
||||||
|
<%= f.password_field :password, :size => 40 %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="boxline">
|
||||||
|
<%= f.label :password_confirmation, "Confirm Password:",
|
||||||
|
:class => "required" %>
|
||||||
|
<%= f.password_field :password_confirmation, :size => 40 %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="boxline">
|
||||||
|
<%= f.label :email, "E-mail Address:", :class => "required" %>
|
||||||
|
<%= f.text_field :email, :size => 40 %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="boxline">
|
||||||
|
<%= f.label :pushover_user_key,
|
||||||
|
raw("<a href=\"https://pushover.net/\">Pushover</a> User Key:"),
|
||||||
|
:class => "required" %>
|
||||||
|
<%= f.text_field :pushover_user_key, :size => 40 %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="boxline">
|
||||||
|
<%= f.label :pushover_device, "Pushover Device:",
|
||||||
|
:class => "required" %>
|
||||||
|
<%= f.text_field :pushover_device, :placeholder => "optional",
|
||||||
|
:size => 15 %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="boxline">
|
||||||
|
<%= f.label :about, "About:", :class => "required" %>
|
||||||
|
<%= f.text_area :about, :size => "100x5" %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="box">
|
||||||
|
<div class="boxline markdown_help_toggler" style="margin-left: 9em;">
|
||||||
|
<div class="markdown_help_label">
|
||||||
|
<span class="fakea">Limited Markdown formatting available</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="clear: both;"></div>
|
||||||
|
|
||||||
|
<%= render :partial => "global/markdownhelp" %>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="legend">
|
||||||
|
Comment Reply Notification Settings
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="boxline">
|
||||||
|
<%= f.label :email_replies, "Receive E-mail:", :class => "required" %>
|
||||||
|
<%= f.check_box :email_replies %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="boxline">
|
||||||
|
<%= f.label :pushover_replies,
|
||||||
|
raw("Receive <a href=\"https://pushover.net/\">Pushover</a> Alert:"),
|
||||||
|
:class => "required" %>
|
||||||
|
<%= f.check_box :pushover_replies %>
|
||||||
|
<span class="hint">
|
||||||
|
Requires user key entered above
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
<div class="legend">
|
||||||
|
Private Message Notification Settings
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="boxline">
|
||||||
|
<%= f.label :email_messages, "Receive E-mail:", :class => "required" %>
|
||||||
|
<%= f.check_box :email_messages %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="boxline">
|
||||||
|
<%= f.label :pushover_messages,
|
||||||
|
raw("Receive <a href=\"https://pushover.net/\">Pushover</a> Alert:"),
|
||||||
|
:class => "required" %>
|
||||||
|
<%= f.check_box :pushover_replies %>
|
||||||
|
<span class="hint">
|
||||||
|
Requires user key entered above
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<%= f.submit "Save All Settings" %>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<br>
|
||||||
|
<br>
|
||||||
|
|
||||||
<div class="legend">
|
<div class="legend">
|
||||||
Invite a New User
|
Invite a New User
|
||||||
</div>
|
</div>
|
||||||
|
@ -19,86 +131,4 @@
|
||||||
<%= submit_tag "Send Invitation" %>
|
<%= submit_tag "Send Invitation" %>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
<div class="legend">
|
|
||||||
Account Settings (<a href="/u/<%= @user.username %>">View Profile</a>)
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<%= form_for @edit_user, :url => settings_url, :method => :post do |f| %>
|
|
||||||
<%= error_messages_for f.object %>
|
|
||||||
|
|
||||||
<div class="boxline">
|
|
||||||
<%= f.label :username, "Username:", :class => "required" %>
|
|
||||||
<%= f.text_field :username %>
|
|
||||||
<span class="hint">
|
|
||||||
<tt>[A-Za-z0-9][A-Za-z0-9_-]*</tt>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="boxline">
|
|
||||||
<%= f.label :email, "E-mail Address:", :class => "required" %>
|
|
||||||
<%= f.text_field :email %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="boxline">
|
|
||||||
<%= f.label :password, "New Password:", :class => "required" %>
|
|
||||||
<%= f.password_field :password %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="boxline">
|
|
||||||
<%= f.label :password_confirmation, "Confirm Password:",
|
|
||||||
:class => "required" %>
|
|
||||||
<%= f.password_field :password_confirmation %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="boxline">
|
|
||||||
<%= f.label :about, "About:", :class => "required" %>
|
|
||||||
<%= f.text_area :about, :size => "100x5" %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="box">
|
|
||||||
<div class="boxline markdown_help_toggler" style="margin-left: 9em;">
|
|
||||||
<div class="markdown_help_label">
|
|
||||||
<span class="fakea">Limited Markdown formatting available</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="clear: both;"></div>
|
|
||||||
|
|
||||||
<%= render :partial => "global/markdownhelp" %>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="legend">
|
|
||||||
Reply Notification Settings
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="boxline">
|
|
||||||
<%= f.label :email_replies, "E-mail:", :class => "required" %>
|
|
||||||
<%= f.check_box :email_replies %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="boxline">
|
|
||||||
<%= f.label :pushover_replies, raw("<a href=\"https://pushover.net/\">" +
|
|
||||||
"Pushover</a>:"), :class => "required" %>
|
|
||||||
<%= f.check_box :pushover_replies %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="boxline">
|
|
||||||
<%= f.label :pushover_user_key, "Pushover User Key:",
|
|
||||||
:class => "required" %>
|
|
||||||
<%= f.text_field :pushover_user_key, :size => 40 %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="boxline">
|
|
||||||
<%= f.label :pushover_device, "Pushover Device:",
|
|
||||||
:class => "required" %>
|
|
||||||
<%= f.text_field :pushover_device, :placeholder => "optional",
|
|
||||||
:size => 15 %>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<br>
|
|
||||||
<%= f.submit "Save All Settings" %>
|
|
||||||
<% end %>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -27,7 +27,7 @@ module Lobsters
|
||||||
|
|
||||||
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
||||||
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
||||||
# config.time_zone = 'Central Time (US & Canada)'
|
config.time_zone = 'Central Time (US & Canada)'
|
||||||
|
|
||||||
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
||||||
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
||||||
|
|
|
@ -38,6 +38,10 @@ Lobsters::Application.routes.draw do
|
||||||
post "/comments/:story_id" => "comments#create"
|
post "/comments/:story_id" => "comments#create"
|
||||||
post "/comments/preview/:story_id" => "comments#preview"
|
post "/comments/preview/:story_id" => "comments#preview"
|
||||||
|
|
||||||
|
resources :messages do
|
||||||
|
post "keep_as_new"
|
||||||
|
end
|
||||||
|
|
||||||
get "/s/:id/:title/comments/:comment_short_id" => "stories#show_comment"
|
get "/s/:id/:title/comments/:comment_short_id" => "stories#show_comment"
|
||||||
get "/s/:id/(:title)" => "stories#show"
|
get "/s/:id/(:title)" => "stories#show"
|
||||||
get "/u/:id" => "users#show"
|
get "/u/:id" => "users#show"
|
||||||
|
|
11
db/migrate/20120704004020_fix_up_messages.rb
Normal file
11
db/migrate/20120704004020_fix_up_messages.rb
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
class FixUpMessages < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
rename_column :messages, :random_hash, :short_id
|
||||||
|
|
||||||
|
add_column :messages, :deleted_by_author, :boolean, :default => false
|
||||||
|
add_column :messages, :deleted_by_recipient, :boolean, :default => false
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
end
|
||||||
|
end
|
13
db/migrate/20120704013019_pm_notification_options.rb
Normal file
13
db/migrate/20120704013019_pm_notification_options.rb
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
class PmNotificationOptions < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
change_table :messages do |t|
|
||||||
|
t.change :has_been_read, :boolean, :default => false
|
||||||
|
end
|
||||||
|
|
||||||
|
add_column :users, :email_messages, :boolean, :default => true
|
||||||
|
add_column :users, :pushover_messages, :boolean, :default => true
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
end
|
||||||
|
end
|
14
db/schema.rb
14
db/schema.rb
|
@ -11,7 +11,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended to check this file into your version control system.
|
# It's strongly recommended to check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(:version => 20120703184957) do
|
ActiveRecord::Schema.define(:version => 20120704013019) do
|
||||||
|
|
||||||
create_table "comments", :force => true do |t|
|
create_table "comments", :force => true do |t|
|
||||||
t.datetime "created_at", :null => false
|
t.datetime "created_at", :null => false
|
||||||
|
@ -52,13 +52,15 @@ ActiveRecord::Schema.define(:version => 20120703184957) do
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
t.integer "author_user_id"
|
t.integer "author_user_id"
|
||||||
t.integer "recipient_user_id"
|
t.integer "recipient_user_id"
|
||||||
t.integer "has_been_read", :limit => 1, :default => 0
|
t.boolean "has_been_read", :default => false
|
||||||
t.string "subject", :limit => 100
|
t.string "subject", :limit => 100
|
||||||
t.text "body"
|
t.text "body"
|
||||||
t.string "random_hash", :limit => 30
|
t.string "short_id", :limit => 30
|
||||||
|
t.boolean "deleted_by_author", :default => false
|
||||||
|
t.boolean "deleted_by_recipient", :default => false
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "messages", ["random_hash"], :name => "random_hash", :unique => true
|
add_index "messages", ["short_id"], :name => "random_hash", :unique => true
|
||||||
|
|
||||||
create_table "stories", :force => true do |t|
|
create_table "stories", :force => true do |t|
|
||||||
t.datetime "created_at"
|
t.datetime "created_at"
|
||||||
|
@ -106,6 +108,8 @@ ActiveRecord::Schema.define(:version => 20120703184957) do
|
||||||
t.boolean "pushover_replies", :default => false
|
t.boolean "pushover_replies", :default => false
|
||||||
t.string "pushover_user_key"
|
t.string "pushover_user_key"
|
||||||
t.string "pushover_device"
|
t.string "pushover_device"
|
||||||
|
t.boolean "email_messages", :default => true
|
||||||
|
t.boolean "pushover_messages", :default => true
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "users", ["session_token"], :name => "session_hash", :unique => true
|
add_index "users", ["session_token"], :name => "session_hash", :unique => true
|
||||||
|
|
Loading…
Reference in a new issue