From d7755f00eda9506c2952d5e005840671a3640eb1 Mon Sep 17 00:00:00 2001 From: Jason Denney Date: Sun, 19 May 2013 15:43:44 -0400 Subject: [PATCH 1/3] Initial stab at check-in feature --- app/assets/javascripts/login.js | 43 +++++++++++++++++++ app/controllers/api/v1/base_controller.rb | 23 ++++++++++ app/controllers/api/v1/logs_controller.rb | 20 +++++++++ app/models/user.rb | 33 ++++++++++++++ app/views/devise/sessions/new.html.erb | 9 +++- config/initializers/devise.rb | 6 +++ config/routes.rb | 9 ++++ .../acts_as_loggable/user_actions.yml | 5 +++ 8 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 app/assets/javascripts/login.js create mode 100644 app/controllers/api/v1/base_controller.rb create mode 100644 app/controllers/api/v1/logs_controller.rb diff --git a/app/assets/javascripts/login.js b/app/assets/javascripts/login.js new file mode 100644 index 0000000..70a2f44 --- /dev/null +++ b/app/assets/javascripts/login.js @@ -0,0 +1,43 @@ +$("#checkin_menu").show(); +$("#checkin").click( function(e){ + var username = $("#user_email").val(); + var password = $("#user_password").val(); + $.ajax({ + type: 'POST', + url: '/api/v1/checkin', + dataType: 'json', + contentType: 'application/json', + processData: false, + data: JSON.stringify({"username": username, "password": password }), + complete: function() { }, + success: function(data) { + alert("Checked IN!"); + $("#user_email").val(''); + $("#user_password").val(''); + }, + error: function(data,textStatus) { + alert( "Error: " + JSON.parse(data.responseText)["error"]); + } + }) +}); +$("#checkout").click( function(e){ + var username = $("#user_email").val(); + var password = $("#user_password").val(); + $.ajax({ + type: 'POST', + url: '/api/v1/checkout', + dataType: 'json', + contentType: 'application/json', + processData: false, + data: JSON.stringify({"username": username, "password": password }), + complete: function() { }, + success: function(data) { + alert("Checked OUT!"); + $("#user_email").val(''); + $("#user_password").val(''); + }, + error: function(data,textStatus) { + alert( "Error: " + JSON.parse(data.responseText)["error"]); + } + }) +}); diff --git a/app/controllers/api/v1/base_controller.rb b/app/controllers/api/v1/base_controller.rb new file mode 100644 index 0000000..da644d0 --- /dev/null +++ b/app/controllers/api/v1/base_controller.rb @@ -0,0 +1,23 @@ +class Api::V1::BaseController < ActionController::Base + respond_to :json + + before_filter :authenticate_user + + private + def authenticate_user + if params[:token] + @current_user = User.find_by_authentication_token(params[:token]) + else + user = User.find_for_database_authentication( :email => params[:username] ) + @current_user = user if user && user.valid_password?( params[:password] ) + end + unless @current_user + render :json => {:error => "Username/Password/Token invalid" }, :status => 403 + end + end + + def current_user + @current_user + end +end + diff --git a/app/controllers/api/v1/logs_controller.rb b/app/controllers/api/v1/logs_controller.rb new file mode 100644 index 0000000..498b6d2 --- /dev/null +++ b/app/controllers/api/v1/logs_controller.rb @@ -0,0 +1,20 @@ +class Api::V1::LogsController < Api::V1::BaseController + + def checkin + if @current_user.checked_in? + render :json => { "error" => "You are already checked in."}, :status => 404 and return + else + @current_user.checkin + render :nothing => true, :status => 204 and return + end + end + + def checkout + if !@current_user.checked_in? + render :json => { "error" => "You were not even checked in."}, :status => 404 and return + else + @current_user.checkout + render :nothing => true, :status => 204 and return + end + end +end diff --git a/app/models/user.rb b/app/models/user.rb index 9b67e65..ce53d43 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -36,6 +36,8 @@ class User < ActiveRecord::Base user_role.to_s == role.to_s end +### TODO methods below probably belong somewhere else + def total_hours ActsAsLoggable::Log.where( :loggable_type => self.class.to_s, :loggable_id => self.id).sum { |l| (l.end_date - l.start_date)/3600 }.round(2) end @@ -49,4 +51,35 @@ class User < ActiveRecord::Base .sum { |l| (l.end_date - l.start_date)/3600 } .round(2) end + + def checked_in? + log_action = ::ActsAsLoggable::UserAction.find_by_action("CHECKIN") + checked = logs.where( log_action_id: log_action.id). + where("start_date >= ?", Time.zone.now.beginning_of_day). + where("start_date = end_date") + !checked.empty? + end + + def checkin + log_action = ::ActsAsLoggable::UserAction.find_by_action("CHECKIN") + time = Time.now + logs.create( logger_id: self.id, + logger_type: self.class.to_s, + start_date: time, + end_date: time, + log_action_id: log_action.id, + log_action_type: log_action.class.to_s) + save + puts logs.inspect + end + + def checkout + log_action = ::ActsAsLoggable::UserAction.find_by_action("CHECKIN") + checked = logs.where( log_action_id: log_action.id). + where("start_date >= ?", Time.zone.now.beginning_of_day). + where("start_date = end_date").first + checked.end_date = Time.now + checked.save + puts logs.inspect + end end diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb index 6acf013..d275e3f 100644 --- a/app/views/devise/sessions/new.html.erb +++ b/app/views/devise/sessions/new.html.erb @@ -1,6 +1,6 @@ <%= stylesheet_link_tag "bootstrap_and_overrides", :media => "all" %> -

Sign in

+

Velocipede

<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
<%= f.label :email %>
@@ -14,8 +14,15 @@ <% end -%>
<%= f.submit "Sign in" %>
+ + <% end %> + + <%= render "links" %> <% if Rails.env.development? %> diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index e0d6120..69a4619 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -221,3 +221,9 @@ Devise.setup do |config| # manager.default_strategies(:scope => :user).unshift :some_external_strategy # end end + +#Check in the user if they sign in. (Devise uses Warden) +Warden::Manager.after_authentication do |user,auth,opts| + user.checkin unless user.checked_in? +end + diff --git a/config/routes.rb b/config/routes.rb index 31c9f6e..59ff145 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -4,4 +4,13 @@ Velocipede::Application.routes.draw do netzke root :to => 'site#index' + ########################### + # API Routes + scope 'api', :module => :api do + scope 'v1', :module => :v1 do + post 'checkin' => "logs#checkin", :as => "api_checkin" + post 'checkout' => "logs#checkout", :as => "api_checkout" + end + end + end diff --git a/db/seed/fixtures/acts_as_loggable/user_actions.yml b/db/seed/fixtures/acts_as_loggable/user_actions.yml index f3c3a18..f5e86f3 100644 --- a/db/seed/fixtures/acts_as_loggable/user_actions.yml +++ b/db/seed/fixtures/acts_as_loggable/user_actions.yml @@ -13,3 +13,8 @@ staff: action: STAFF created_at: <%= Time.now %> updated_at: <%= Time.now %> +checkin: + id: 4 + action: CHECKIN + created_at: <%= Time.now %> + updated_at: <%= Time.now %> From a00c1ed925adc953c2cec8cc6d4971082685f8d2 Mon Sep 17 00:00:00 2001 From: Jason Denney Date: Sun, 19 May 2013 16:41:43 -0400 Subject: [PATCH 2/3] Finished Checkin/out feature for now -Checkin/out api methods can be used while signed in -Added checkout button in Netzke App, which also signs out in addition to checking out. --- app/components/app_tab_panel.rb | 8 ++++++-- .../app_tab_panel/javascripts/sign_out.js | 12 ++++++++++++ app/controllers/api/v1/base_controller.rb | 19 +++++++++---------- app/controllers/api/v1/logs_controller.rb | 2 ++ 4 files changed, 29 insertions(+), 12 deletions(-) diff --git a/app/components/app_tab_panel.rb b/app/components/app_tab_panel.rb index faf4bc8..4268fda 100644 --- a/app/components/app_tab_panel.rb +++ b/app/components/app_tab_panel.rb @@ -6,6 +6,11 @@ class AppTabPanel < Netzke::Basepack::TabPanel c.text = "Sign out #{controller.current_user.email}" if controller.current_user end + action :check_out do |c| + c.icon = :door_out + c.text = "CHECK OUT" if controller.current_user + end + def configure(c) #all users @@ -49,7 +54,7 @@ class AppTabPanel < Netzke::Basepack::TabPanel end c.prevent_header = true - c.tbar = [:sign_out] + c.tbar = [:sign_out, :check_out] c.items = @@app_tab_panel_items super end @@ -58,6 +63,5 @@ class AppTabPanel < Netzke::Basepack::TabPanel #gets js from app_tab_panel/javascripts/sign_out.js c.mixin :sign_out end - end diff --git a/app/components/app_tab_panel/javascripts/sign_out.js b/app/components/app_tab_panel/javascripts/sign_out.js index d7c9bc3..8672024 100644 --- a/app/components/app_tab_panel/javascripts/sign_out.js +++ b/app/components/app_tab_panel/javascripts/sign_out.js @@ -5,5 +5,17 @@ url: '/users/sign_out', method: 'DELETE' }); + }, + onCheckOut: function(){ + Ext.Ajax.request({ + url: '/api/v1/checkout', + method: 'POST', + success: function(response, opts) { + Ext.Ajax.request({ + url: '/users/sign_out', + method: 'DELETE' + }); + } + }); } } diff --git a/app/controllers/api/v1/base_controller.rb b/app/controllers/api/v1/base_controller.rb index da644d0..a3ed9c1 100644 --- a/app/controllers/api/v1/base_controller.rb +++ b/app/controllers/api/v1/base_controller.rb @@ -5,19 +5,18 @@ class Api::V1::BaseController < ActionController::Base private def authenticate_user - if params[:token] - @current_user = User.find_by_authentication_token(params[:token]) - else + if params[:username] user = User.find_for_database_authentication( :email => params[:username] ) @current_user = user if user && user.valid_password?( params[:password] ) - end - unless @current_user - render :json => {:error => "Username/Password/Token invalid" }, :status => 403 - end - end - def current_user - @current_user + if @current_user.nil? + msg = "Username/Password/Token invalid" + render :json => {:error => msg }, :status => 403 and return + end + else + authenticate_user! + @current_user = current_user + end end end diff --git a/app/controllers/api/v1/logs_controller.rb b/app/controllers/api/v1/logs_controller.rb index 498b6d2..b226b24 100644 --- a/app/controllers/api/v1/logs_controller.rb +++ b/app/controllers/api/v1/logs_controller.rb @@ -1,6 +1,7 @@ class Api::V1::LogsController < Api::V1::BaseController def checkin + #must use @current_user since user may not have signed in if @current_user.checked_in? render :json => { "error" => "You are already checked in."}, :status => 404 and return else @@ -10,6 +11,7 @@ class Api::V1::LogsController < Api::V1::BaseController end def checkout + #must use @current_user since user may not have signed in if !@current_user.checked_in? render :json => { "error" => "You were not even checked in."}, :status => 404 and return else From 145a731ed2bffc82b49c66c81d094e13e3f332a8 Mon Sep 17 00:00:00 2001 From: Jason Denney Date: Sun, 19 May 2013 16:44:28 -0400 Subject: [PATCH 3/3] Remove puts --- app/models/user.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/models/user.rb b/app/models/user.rb index ce53d43..1db9cb5 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -70,7 +70,6 @@ class User < ActiveRecord::Base log_action_id: log_action.id, log_action_type: log_action.class.to_s) save - puts logs.inspect end def checkout @@ -80,6 +79,5 @@ class User < ActiveRecord::Base where("start_date = end_date").first checked.end_date = Time.now checked.save - puts logs.inspect end end