Merge pull request #56 from mccabe615/master

Adding messaging system
This commit is contained in:
Ken Johnson
2013-10-13 20:08:28 -07:00
18 changed files with 485 additions and 5 deletions
+2
View File
@@ -20,6 +20,8 @@ group :development do
gem 'rack-livereload' gem 'rack-livereload'
gem 'rb-fsevent' gem 'rb-fsevent'
gem 'travis-lint' gem 'travis-lint'
gem 'better_errors'
gem 'binding_of_caller'
end end
gem 'gauntlt' gem 'gauntlt'
+8
View File
@@ -35,6 +35,11 @@ GEM
cucumber (>= 1.1.1) cucumber (>= 1.1.1)
rspec-expectations (>= 2.7.0) rspec-expectations (>= 2.7.0)
bcrypt-ruby (3.0.1) bcrypt-ruby (3.0.1)
better_errors (1.0.1)
coderay (>= 1.0.0)
erubis (>= 2.6.6)
binding_of_caller (0.7.2)
debug_inspector (>= 0.0.1)
brakeman (1.9.5) brakeman (1.9.5)
erubis (~> 2.6) erubis (~> 2.6)
fastercsv (~> 1.5) fastercsv (~> 1.5)
@@ -72,6 +77,7 @@ GEM
gherkin (~> 2.12.0) gherkin (~> 2.12.0)
multi_json (~> 1.3) multi_json (~> 1.3)
database_cleaner (1.0.1) database_cleaner (1.0.1)
debug_inspector (0.0.2)
diff-lcs (1.2.4) diff-lcs (1.2.4)
em-websocket (0.5.0) em-websocket (0.5.0)
eventmachine (>= 0.12.9) eventmachine (>= 0.12.9)
@@ -247,6 +253,8 @@ PLATFORMS
DEPENDENCIES DEPENDENCIES
aruba aruba
bcrypt-ruby bcrypt-ruby
better_errors
binding_of_caller
brakeman brakeman
bundler-audit bundler-audit
capybara capybara
+40
View File
@@ -0,0 +1,40 @@
class MessagesController < ApplicationController
def index
@messages = current_user.messages
end
def show
@message = Message.where(:id => params[:id]).first
end
def destroy
message = Message.where(:id => params[:id]).first
if message.destroy
flash[:success] = "Your message has been deleted."
redirect_to user_messages_path(:user_id => current_user.user_id)
else
flash[:error] = "Could not delete message."
end
end
def new
@message = Message.new
end
def create
if Message.create(params[:message])
respond_to do |format|
format.html { redirect_to user_messages_path(:user_id => current_user.user_id) }
format.json { render :json => {:msg => "success"} }
end
else
respond_to do |format|
format.html { redirect_to user_messages_path }
format.json { render :json => {:msg => "failure"} }
end
end
end
end
+2
View File
@@ -0,0 +1,2 @@
module MessagesHelper
end
+10
View File
@@ -0,0 +1,10 @@
class Message < ActiveRecord::Base
belongs_to :user
attr_accessible :creator_id, :message, :read, :receiver_id
validates_presence_of :creator_id, :receiver_id, :message
def creator_name
creator = User.where(:id => self.creator_id).first
creator.full_name
end
end
+3 -3
View File
@@ -17,7 +17,7 @@ class User < ActiveRecord::Base
has_one :paid_time_off, :foreign_key => :user_id, :primary_key => :user_id, :dependent => :destroy has_one :paid_time_off, :foreign_key => :user_id, :primary_key => :user_id, :dependent => :destroy
has_one :work_info, :foreign_key => :user_id, :primary_key => :user_id, :dependent => :destroy has_one :work_info, :foreign_key => :user_id, :primary_key => :user_id, :dependent => :destroy
has_many :performance, :foreign_key => :user_id, :primary_key => :user_id, :dependent => :destroy has_many :performance, :foreign_key => :user_id, :primary_key => :user_id, :dependent => :destroy
has_many :messages, :foreign_key => :receiver_id, :primary_key => :user_id, :dependent => :destroy
def build_benefits_data def build_benefits_data
@@ -26,13 +26,13 @@ class User < ActiveRecord::Base
build_work_info(POPULATE_WORK_INFO.shuffle.first) build_work_info(POPULATE_WORK_INFO.shuffle.first)
performance.build(POPULATE_PERFORMANCE.shuffle.first) performance.build(POPULATE_PERFORMANCE.shuffle.first)
end end
private
def full_name def full_name
"#{self.first_name} #{self.last_name}" "#{self.first_name} #{self.last_name}"
end end
private
def self.authenticate(email, password) def self.authenticate(email, password)
auth = nil auth = nil
user = find_by_email(email) user = find_by_email(email)
@@ -58,6 +58,14 @@
Performance Performance
<% end %> <% end %>
</li> </li>
<li id="messages">
<%= link_to user_messages_path(:user_id => current_user.user_id) do %>
<div class="icon">
<span class="fs1" aria-hidden="true" data-icon="&#xe040;"></span>
</div>
Messages
<% end %>
</li>
</ul> </ul>
</div> </div>
+44
View File
@@ -0,0 +1,44 @@
<div class="dashboard-wrapper">
<div class="main-container">
<div class="row-fluid">
<div class="span12">
<div class="widget">
<div class="widget-header">
<div class="title">
<span class="fs1" aria-hidden="true" data-icon="&#xe022;"></span> Messages for <%= current_user.full_name %>
<span class="fs1" aria-hidden="true" data-icon="&#xe006;"><%= link_to "Send Message", new_user_message_path %></span>
</div>
</div>
<div class="widget-body">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th style="width:7%">From:</th>
<th style="width:6%">Date</th>
<th style="width:16%">Message</th>
<th style="width:6%">Actions</th>
</tr>
</thead>
<tbody>
<tr>
<% if @messages.empty? %>
<td><%= "No messages!" %></td><td></td><td></td><td></td>
<% end %>
<% @messages.each do |message| %>
<td><%= message.creator_name %></td>
<td><%= message.created_at.to_date %></td>
<td><%= message.message %></td>
<td><%= link_to "Details", user_message_path(:id => message.id), {:class => "btn btn-info pull-left"}%>
<%= link_to "Delete", user_message_path(:id => message.id), {:method => 'delete', :class => "btn btn-danger pull-left"}%></td>
</tr>
</tbody>
<% end %>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
+88
View File
@@ -0,0 +1,88 @@
<div class="dashboard-wrapper">
<div class="main-container">
<div class="row-fluid">
<div class="span12">
<div id="success" style="display: none;" class="alert alert-block alert-success fade in">
<h4 class="alert-heading">
Success!
</h4>
<p>
Message successfully sent.
</p>
</div>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<div id="failure" style="display: none;" class="alert alert-block alert-error fade in">
<h4 class="alert-heading">
Error!
</h4>
<p>
Failed to send message.
</p>
</div>
</div>
</div>
<div class="row-fluid">
<div class="span6">
<div class="widget">
<div class="widget-header">
<div class="title">
<span class="fs1" aria-hidden="true" data-icon="&#xe006;"></span> New Message</span>
</div>
</div>
<div class="widget-body">
<%= form_for @message, :url => user_messages_path, :method => :post, :html => {:id => "send_message"} do |f|%>
<%= f.hidden_field :creator_id, :value => current_user.id %>
<%= f.hidden_field :read, :value => '0' %>
<div class="control-group">
<%= f.label "To:", nil, {:class => "control-label"}%>
<%= f.select(:receiver_id, options_from_collection_for_select(User.all, :id, :full_name)) %>
</div>
<div class="control-group">
<%= f.label :message, nil, {:class => "control-label"}%>
<%= f.text_area :message, {:class => "span12"} %>
</div>
<div class="form-actions no-margin">
<%= f.submit "Submit", {:id => 'submit_button', :class => "btn btn-info pull-right"} %>
</div>
<div class="clearfix"></div>
<% end %>
</div>
</div>
</div>
</div>
<%= javascript_include_tag ('validation.js')%>
<script type="text/javascript">
$("#submit_button").click(function(event) {
var valuesToSubmit = $("#send_message").serialize();
event.preventDefault();
$.ajax({
url: <%= "/users/#{current_user.user_id}/messages.json".inspect.html_safe %>,
data: valuesToSubmit,
type: "POST",
success: function(response) {
if (response.msg == "failure") {
$('#failure').show(500).delay(1500).fadeOut();
} else {
$('#success').show(500).delay(1500).fadeOut();
}
},
error: function(event) {
$('#failure').show(500).delay(1500).fadeOut();
}
});
});
</script>
+171
View File
@@ -0,0 +1,171 @@
<div class="dashboard-wrapper">
<div class="main-container">
<div class="row-fluid">
<div class="span12">
<div class="widget">
<div class="widget-header">
<div class="title">
<span class="fs1" aria-hidden="true" data-icon="&#xe088;"></span> Messages for <%= current_user.full_name %>
</div>
</div>
<div class="widget-body">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th style="width:7%">From:</th>
<th style="width:6%">Date</th>
<th style="width:30%">Message</th>
<th style="width:6%">Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td><%= @message.creator_name %></td>
<td><%= @message.created_at.to_date %></td>
<td><%= @message.message %></td>
<td><%= link_to "Delete", user_message_path, {:id => "@message.id", :method => 'delete', :class => "btn btn-danger pull-left"}%></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<!--/.fluid-container-->
</div>
<footer>
<p>
&copy; BlackForest 2013
</p>
</footer>
<script src="js/jquery.min.js">
</script>
<script src="js/bootstrap.js">
</script>
<script type="text/javascript" src="js/date-picker/date.js">
</script>
<script type="text/javascript" src="js/date-picker/daterangepicker.js">
</script>
<script type="text/javascript">
//ScrollUp
$(function () {
$.scrollUp({
scrollName: 'scrollUp', // Element ID
topDistance: '300', // Distance from top before showing element (px)
topSpeed: 300, // Speed back to top (ms)
animation: 'fade', // Fade, slide, none
animationInSpeed: 400, // Animation in speed (ms)
animationOutSpeed: 400, // Animation out speed (ms)
scrollText: 'Scroll to top', // Text for element
activeOverlay: false, // Set CSS color to display scrollUp active point, e.g '#00FFFF'
});
});
//Tooltip
$('a').tooltip('hide');
//Main menu navigation
$('.submenu > a').click(function(e){
e.preventDefault();
var submenu = $(this).siblings('ul');
var li = $(this).parents('li');
var submenus = $('#mainnav li.submenu ul');
var submenus_parents = $('#mainnav li.submenu');
if(li.hasClass('open'))
{
if(($(window).width() > 768) || ($(window).width() < 479)) {
submenu.slideUp();
} else {
submenu.fadeOut(250);
}
li.removeClass('open');
} else
{
if(($(window).width() > 768) || ($(window).width() < 479)) {
submenus.slideUp();
submenu.slideDown();
} else {
submenus.fadeOut(250);
submenu.fadeIn(250);
}
submenus_parents.removeClass('open');
li.addClass('open');
}
});
var ul = $('#mainnav > ul');
$('#mainnav > a').click(function(e)
{
e.preventDefault();
var mainnav = $('#mainnav');
if(mainnav.hasClass('open'))
{
mainnav.removeClass('open');
ul.slideUp(250);
} else
{
mainnav.addClass('open');
ul.slideDown(250);
}
});
//Range Date Picker
$('.report_range').daterangepicker({
ranges: {
'Today': ['today', 'today'],
'Yesterday': ['yesterday', 'yesterday'],
'Last 7 Days': [Date.today().add({
days: -6
}), 'today'],
'Last 30 Days': [Date.today().add({
days: -29
}), 'today'],
'This Month': [Date.today().moveToFirstDayOfMonth(), Date.today().moveToLastDayOfMonth()],
'Last Month': [Date.today().moveToFirstDayOfMonth().add({
months: -1
}), Date.today().moveToFirstDayOfMonth().add({
days: -1
})]
},
opens: 'left',
format: 'MM/dd/yyyy',
separator: ' to ',
startDate: Date.today().add({
days: -29
}),
endDate: Date.today(),
minDate: '01/01/2012',
maxDate: '12/31/2013',
locale: {
applyLabel: 'Submit',
fromLabel: 'From',
toLabel: 'To',
customRangeLabel: 'Custom Range',
daysOfWeek: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
monthNames: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
firstDay: 1
},
showWeekNumbers: true,
buttonClasses: ['btn-danger']
},
function (start, end) {
$('.report_range span').html(start.toString('MMMM d, yyyy') + ' - ' + end.toString('MMMM d, yyyy'));
});
//Set the initial state of the picker label
$('.report_range span').html(Date.today().add({
days: -29
}).toString('MMMM d, yyyy') + ' - ' + Date.today().toString('MMMM d, yyyy'));
</script>
</body>
</html>
+3
View File
@@ -28,6 +28,9 @@ resources :users do
end end
resources :messages do
end
end end
get "download" => "benefit_forms#download" get "download" => "benefit_forms#download"
@@ -0,0 +1,12 @@
class CreateMessages < ActiveRecord::Migration
def change
create_table :messages do |t|
t.integer :creator_id
t.integer :receiver_id
t.text :message
t.boolean :read
t.timestamps
end
end
end
+10 -1
View File
@@ -11,13 +11,22 @@
# #
# 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 => 20130708202859) do ActiveRecord::Schema.define(:version => 20131011180207) do
create_table "benefits", :force => true do |t| create_table "benefits", :force => true do |t|
t.datetime "created_at", :null => false t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false t.datetime "updated_at", :null => false
end end
create_table "messages", :force => true do |t|
t.integer "creator_id"
t.integer "receiver_id"
t.text "message"
t.boolean "read"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "paid_time_offs", :force => true do |t| create_table "paid_time_offs", :force => true do |t|
t.integer "user_id" t.integer "user_id"
t.integer "sick_days_taken" t.integer "sick_days_taken"
+34 -1
View File
@@ -234,7 +234,34 @@ paid_time_off = [
:date_submitted => Date.new(2013, 01, 01), :date_submitted => Date.new(2013, 01, 01),
:score => 2 :score => 2
} }
] ]
messages = [
{
:receiver_id => 2,
:creator_id => 5,
:message => 'Your benefits have been updated.',
:read => false
},
{
:receiver_id => 3,
:creator_id => 4,
:message => 'Please update your profile.',
:read => false
},
{
:receiver_id => 4,
:creator_id => 3,
:message => 'Welcome to Railsgoat.',
:read => false
},
{
:receiver_id => 5,
:creator_id => 2,
:message => 'Hello friend.',
:read => false
}
]
users.each do |user_info| users.each do |user_info|
@@ -273,3 +300,9 @@ performance.each do |perf|
p.user_id = perf[:user_id] p.user_id = perf[:user_id]
p.save p.save
end end
messages.each do |message|
m = Message.new(message.reject {|k| k == :creator_id})
m.creator_id = message[:creator_id]
m.save
end
@@ -0,0 +1,5 @@
require 'spec_helper'
describe MessagesController do
end
+15
View File
@@ -0,0 +1,15 @@
require 'spec_helper'
# Specs in this file have access to a helper object that includes
# the MessagesHelper. For example:
#
# describe MessagesHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# expect(helper.concat_strings("this","that")).to eq("this that")
# end
# end
# end
describe MessagesHelper do
pending "add some examples to (or delete) #{__FILE__}"
end
+25
View File
@@ -0,0 +1,25 @@
require 'spec_helper.rb'
describe User do
before(:all) do
UserFixture.reset_all_users
DatabaseCleaner.strategy = :transaction
end
after(:all) do
DatabaseCleaner.strategy = :truncation
end
it "can be instantiated" do
Benefits.new.should be_an_instance_of(Benefits)
end
it "name can be updated" do
new_name = "Bobby"
user = User.all.first
user.first_name = new_name
user.save!
User.all.first.first_name.should == new_name
end
end
+5
View File
@@ -0,0 +1,5 @@
require 'spec_helper'
describe Message do
pending "add some examples to (or delete) #{__FILE__}"
end