mirror of
				https://github.com/fspc/BikeShed-1.git
				synced 2025-10-31 00:45:35 -04:00 
			
		
		
		
	merging master
This commit is contained in:
		
						commit
						b450baa3dc
					
				| @ -12,5 +12,4 @@ | ||||
| //
 | ||||
| //= require jquery
 | ||||
| //= require jquery_ujs
 | ||||
| //= require twitter/bootstrap
 | ||||
| //= require_tree .
 | ||||
| //= require custom_netzke_helpers
 | ||||
|  | ||||
| @ -3,3 +3,150 @@ Ext.Ajax.on('requestexception', function(conn, response, options) { | ||||
|   if (response.status === 401) { window.location = '/users/sign_in'; } | ||||
| }, this); | ||||
| 
 | ||||
| Ext.define('Ext.ux.form.field.ColorCombo', { | ||||
|     extend:'Ext.form.FieldContainer', | ||||
|     mixins:{ | ||||
|         field:'Ext.form.field.Field' | ||||
|     }, | ||||
|     alias: 'widget.xcolorcombo', | ||||
| 
 | ||||
|     //configurables
 | ||||
|     combineErrors: true, | ||||
|     msgTarget: 'under', | ||||
|     layout: 'hbox', | ||||
|     readOnly: false, | ||||
| 
 | ||||
|     // properties
 | ||||
|     colorValue: null, | ||||
|     /** | ||||
|      * @property dateField | ||||
|      * @type Ext.form.field.Date | ||||
|      */ | ||||
|     colorField: null, | ||||
| 
 | ||||
|     initComponent: function(){ | ||||
|         var me = this | ||||
|             ,i = 0 | ||||
|             ,key | ||||
|             ,tab; | ||||
| 
 | ||||
|         me.items = me.items || []; | ||||
| 
 | ||||
|         me.colorField = Ext.create('Ext.form.field.Trigger', { | ||||
|             flex:1, | ||||
|             isFormField:false, //exclude from field query's
 | ||||
|             submitValue:false, | ||||
|             readOnly: me.readOnly, | ||||
|             onTriggerClick: function() { | ||||
|               //needs to be called twice because?
 | ||||
|               me.picker.alignTo(me.colorField.inputEl); | ||||
|               me.picker.show(); | ||||
|               me.picker.alignTo(me.colorField.inputEl); | ||||
|               me.picker.show(); | ||||
|             } | ||||
|         }); | ||||
|         me.items.push(me.colorField); | ||||
| 
 | ||||
|         me.picker = Ext.create('Ext.picker.Color', { | ||||
|           renderTo: document.body, | ||||
|           floating: true, | ||||
|           hidden: true, | ||||
|           style: { | ||||
|             backgroundColor: "#fff" | ||||
|           }, | ||||
|           listeners: { | ||||
|             scope:this, | ||||
|             select: function(field, value, opts){ | ||||
|               me.setValue(value); | ||||
|               me.picker.hide(); | ||||
|             } | ||||
|           } | ||||
|         }); | ||||
|         me.items.push(me.picker); | ||||
| 
 | ||||
|         for (; i < me.items.length; i++) { | ||||
|             me.items[i].on('focus', Ext.bind(me.onItemFocus, me)); | ||||
|             me.items[i].on('blur', Ext.bind(me.onItemBlur, me)); | ||||
|             me.items[i].on('specialkey', function(field, event){ | ||||
|                 key = event.getKey(); | ||||
|                 tab = key == event.TAB; | ||||
| 
 | ||||
|                 if (tab && me.focussedItem == me.dateField) { | ||||
|                     event.stopEvent(); | ||||
|                     me.timeField.focus(); | ||||
|                     return; | ||||
|                 } | ||||
| 
 | ||||
|                 me.fireEvent('specialkey', field, event); | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         me.callParent(); | ||||
| 
 | ||||
|         // this dummy is necessary because Ext.Editor will not check whether an inputEl is present or not
 | ||||
|         this.inputEl = { | ||||
|             dom: document.createElement('div'), | ||||
|             swallowEvent:function(){} | ||||
|         }; | ||||
| 
 | ||||
|         me.initField(); | ||||
|     }, | ||||
|     focus:function(){ | ||||
|         this.callParent(arguments); | ||||
|         this.colorField.focus(); | ||||
|         var me = this; | ||||
|     }, | ||||
| 
 | ||||
|     onItemFocus:function(item){ | ||||
|         if (this.blurTask){ | ||||
|             this.blurTask.cancel(); | ||||
|         } | ||||
|         this.focussedItem = item; | ||||
|     }, | ||||
| 
 | ||||
|     onItemBlur:function(item, e){ | ||||
|         var me = this; | ||||
|         if (item != me.focussedItem){ return; } | ||||
|         // 100ms to focus a new item that belongs to us, otherwise we will assume the user left the field
 | ||||
|         me.blurTask = new Ext.util.DelayedTask(function(){ | ||||
|             me.picker.hide(); | ||||
|             me.fireEvent('blur', me, e); | ||||
|         }); | ||||
|         me.blurTask.delay(100); | ||||
|     }, | ||||
| 
 | ||||
|     getValue: function(){ | ||||
|         var value = null | ||||
|             ,color = this.colorField.getSubmitValue(); | ||||
| 
 | ||||
|         if (color){ | ||||
|           value = this.colorField.getValue(); | ||||
|         } | ||||
|         return value; | ||||
|     }, | ||||
| 
 | ||||
|     getSubmitValue: function(){ | ||||
| //        var value = this.getValue();
 | ||||
| //        return value ? Ext.Date.format(value, this.dateTimeFormat) : null;
 | ||||
| 
 | ||||
|         var me = this | ||||
|             ,value = me.getValue(); | ||||
| 
 | ||||
|         return value; | ||||
|     }, | ||||
| 
 | ||||
|     setValue: function(value){ | ||||
|         this.colorField.setValue(value); | ||||
|     }, | ||||
|     // Bug? A field-mixin submits the data from getValue, not getSubmitValue
 | ||||
|     getSubmitData: function(){ | ||||
|         var me = this | ||||
|             ,data = null; | ||||
| 
 | ||||
|         if (!me.disabled && me.submitValue && !me.isFileUpload()) { | ||||
|             data = {}; | ||||
|             data[me.getName()] = '' + me.getSubmitValue(); | ||||
|         } | ||||
|         return data; | ||||
|     } | ||||
| }); | ||||
|  | ||||
							
								
								
									
										51
									
								
								app/assets/javascripts/devise/registrations.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								app/assets/javascripts/devise/registrations.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,51 @@ | ||||
| $(document).ready(function(){ | ||||
|   var MIN_LEN = 3; | ||||
|   var MAX_SUBMITS = 3; | ||||
|   var submit_count = 0; | ||||
|   $("input[name=commit]").click( function(e){ | ||||
|     console.log("clicked"); | ||||
|     submit_count += 1; | ||||
|     //IDs of contact info
 | ||||
|     var contact_info_ids = [ | ||||
|       "user_email", | ||||
|       "user_user_profiles_attributes_0_addrStreet1", | ||||
|       "user_user_profiles_attributes_0_addrCity", | ||||
|       "user_user_profiles_attributes_0_addrState", | ||||
|       "user_user_profiles_attributes_0_addrZip", | ||||
|       "user_user_profiles_attributes_0_phone" | ||||
|     ]; | ||||
|     var contact_vals = ""; | ||||
|     var index = 0; | ||||
|     //see if any contact info exists
 | ||||
|     for( var index in contact_info_ids){ | ||||
|       contact_vals += $("#"+contact_info_ids[index]).val(); | ||||
|     } | ||||
|     if( contact_vals.length >= MIN_LEN || submit_count > MAX_SUBMITS){ | ||||
| 
 | ||||
|       if( submit_count > MAX_SUBMITS ){ | ||||
|         alert("Fine."); | ||||
|       } | ||||
|       return true; | ||||
| 
 | ||||
|     }else{ | ||||
| 
 | ||||
|       switch(submit_count){ | ||||
|         case 1: | ||||
|           alert("It appears you have not entered any contact information.  " + | ||||
|             "Please do."); | ||||
|           break; | ||||
|         case 2: | ||||
|           alert("It is highly recommended that you enter at least one form of" + | ||||
|             " contact information.  It is in your best interest."); | ||||
|           break; | ||||
|         case 3: | ||||
|           alert("If something happens to your bicycle, we will not be able to" + | ||||
|             " notify you.  Please enter at least one form of contact."); | ||||
|           break; | ||||
|         default: | ||||
|           alert("Please enter at least one form of contact."); | ||||
|       } | ||||
|       return false; | ||||
|     } | ||||
|   }); | ||||
| }); | ||||
							
								
								
									
										0
									
								
								app/assets/javascripts/devise/sessions.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								app/assets/javascripts/devise/sessions.js
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										0
									
								
								app/assets/javascripts/site.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								app/assets/javascripts/site.js
									
									
									
									
									
										Normal file
									
								
							| @ -3,7 +3,7 @@ class AppTabPanel < Netzke::Basepack::TabPanel | ||||
| 
 | ||||
|   action :sign_out do |c| | ||||
|     c.icon = :door_out | ||||
|     c.text = "Sign out #{controller.current_user.email}" if controller.current_user | ||||
|     c.text = "Exit" | ||||
|   end | ||||
| 
 | ||||
|   action :check_out do |c| | ||||
| @ -11,6 +11,11 @@ class AppTabPanel < Netzke::Basepack::TabPanel | ||||
|     c.text = "CHECK OUT" if controller.current_user | ||||
|   end | ||||
| 
 | ||||
|   action :change_account_info do |c| | ||||
|     c.icon = :user_edit | ||||
|     c.text = "Change Email/Password" | ||||
|   end | ||||
| 
 | ||||
|   def configure(c) | ||||
| 
 | ||||
|     #all users | ||||
| @ -48,7 +53,9 @@ class AppTabPanel < Netzke::Basepack::TabPanel | ||||
|     if can? :manage, Role | ||||
|       @@app_tab_panel_items.concat [{ layout: :fit, | ||||
|                                       wrappedComponent: :user_role_joins, | ||||
|                                       title: "User Roles"}] | ||||
|                                       title: "User Roles"}, | ||||
|                                       :check_ins | ||||
|                                       ] | ||||
|     end | ||||
| 
 | ||||
|     @@app_tab_panel_items.each do |item| | ||||
| @ -59,7 +66,7 @@ class AppTabPanel < Netzke::Basepack::TabPanel | ||||
|       end | ||||
|     end | ||||
|     c.prevent_header = true | ||||
|     c.tbar = [:sign_out, :check_out] | ||||
|     c.tbar = [:sign_out, :check_out, :change_account_info] | ||||
|     c.items = @@app_tab_panel_items | ||||
|     super | ||||
|   end | ||||
|  | ||||
| @ -17,5 +17,8 @@ | ||||
|          }); | ||||
|        } | ||||
|     }); | ||||
|   }, | ||||
|   onChangeAccountInfo: function(){ | ||||
|     window.location.href="users/edit"; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -16,7 +16,8 @@ class Bikes < Netzke::Basepack::Grid | ||||
|                     end | ||||
|                   } | ||||
|       }, | ||||
|       :color, | ||||
|       #needs to have type :action or else won't work in grid, because... netzke | ||||
|       { :name => "color", :text => "Frame Color", :type => :action, :editor => { :xtype => "xcolorcombo"}, :renderer => :color_block}, | ||||
|       { :name => :bike_style__style, :text => 'Style' }, | ||||
|       { :name => :seat_tube_height, :text => 'Seat Tube (in)'}, | ||||
|       { :name => :top_tube_length, :text => 'Top Tube (in)'}, | ||||
| @ -32,6 +33,23 @@ class Bikes < Netzke::Basepack::Grid | ||||
|     ] | ||||
|   end | ||||
| 
 | ||||
|   def default_fields_for_forms | ||||
|     [ | ||||
|       { :name => :shop_id, :field_label => 'Shop ID'}, | ||||
|       :serial_number, | ||||
|       { :name => :bike_brand__brand, :field_label => 'Brand' }, | ||||
|       { :name => :bike_model__model, :field_label => 'Model'}, | ||||
|       { :name => "color", :xtype => "xcolorcombo"}, | ||||
|       { :name => :bike_style__style, :field_label => 'Style' }, | ||||
|       { :name => :seat_tube_height, :field_label => 'Seat Tube (in)'}, | ||||
|       { :name => :top_tube_length, :field_label => 'Top Tube (in)'}, | ||||
|       { :name => :wheel_size, :field_label => 'Wheel Size (in)'}, | ||||
|       :value, | ||||
|       { :name => :bike_condition__condition, :field_label => 'Condition'}, | ||||
|       { :name => :bike_status__status, :field_label => 'Status'} | ||||
|     ] | ||||
|   end | ||||
| 
 | ||||
|   #override with nil to remove actions | ||||
|   def default_bbar | ||||
|     [ :apply, :add_in_form, :search ] | ||||
|  | ||||
| @ -9,5 +9,8 @@ | ||||
|       // The beauty of using Ext.Direct: calling 3 endpoints in a row, which results in a single call to the server!
 | ||||
|       this.selectBikeBrand({bike_brand_id: record.get('bike_brand__brand')}); | ||||
|     }, this); | ||||
|   }, | ||||
|   colorBlock: function(value){ | ||||
|     return Ext.String.format('<div style="display:inline-block">{1}</div><div style="background-color:#{0};width:50px;height:10px;display:inline-block;margin:0 5px 0 5px;border:solid;border-color:gray;border-width:1px;"></div>', value, value); | ||||
|   } | ||||
| } | ||||
|  | ||||
							
								
								
									
										23
									
								
								app/components/check_ins.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								app/components/check_ins.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| class CheckIns < Netzke::Basepack::Grid | ||||
| 
 | ||||
|   def configure(c) | ||||
|     super | ||||
|     c.header = false | ||||
|     c.model = "ActsAsLoggable::Log" | ||||
|     c.scope = lambda { |rel| rel.where(:log_action_type => ::ActsAsLoggable::UserAction). | ||||
|                                  where(:loggable_type => "User"). | ||||
|                                  where(:log_action_id => ::ActsAsLoggable::UserAction.find_by_action("CHECKIN")). | ||||
|                                  where("start_date >= ?", Time.zone.now.beginning_of_day); | ||||
|                      } | ||||
|     c.columns = [ | ||||
|       { :name => :name, :getter => lambda{ |rec| | ||||
|                                                 user = User.find_by_id(rec.loggable_id) | ||||
|                                                 user.nil? ? "" : "#{user.first_name} #{user.last_name}" | ||||
|                                               } | ||||
|       }, | ||||
|       { :name => "Status", :getter => lambda{ |rec| rec.start_date == rec.end_date ? "Checked In" : "Checked Out" } }, | ||||
|       :start_date, | ||||
|       :end_date, | ||||
|     ] | ||||
|   end | ||||
| end | ||||
| @ -4,6 +4,7 @@ class UserStats < Netzke::Base | ||||
|     bike = user.bike | ||||
|     %Q( | ||||
|       <div id="user_stats_page"> | ||||
|         <p>Username: #{user.username}</p> | ||||
|         <p>Total Hours Worked: #{user.total_hours}</p> | ||||
|         <p>Hours worked in #{Time.now.strftime('%B')}: #{user.current_month_hours}</p> | ||||
|         <p>Current bike Shop ID: #{bike.shop_id if bike}</p> | ||||
|  | ||||
| @ -1,16 +1,28 @@ | ||||
| class Users < Netzke::Basepack::Grid | ||||
|   include Netzke::Basepack::ActionColumn | ||||
| 
 | ||||
|   column :reset do |c| | ||||
|     c.type = :action | ||||
|     c.actions = [{name: :reset_password, icon: :lock_break}] | ||||
|     c.header = "" | ||||
|     c.width = 20 | ||||
|   end | ||||
| 
 | ||||
|   def configure(c) | ||||
|     super | ||||
|     c.header = false | ||||
|     c.model = "User" | ||||
| 
 | ||||
|     c.columns = [ | ||||
|       :username, | ||||
|       :first_name, | ||||
|       :last_name, | ||||
|       :nickname, | ||||
|       :email, | ||||
|       :bike__shop_id | ||||
|     ] | ||||
| 
 | ||||
|     c.columns << :reset if can? :manage, User | ||||
|   end | ||||
| 
 | ||||
|   #override with nil to remove actions | ||||
|  | ||||
| @ -4,8 +4,32 @@ | ||||
|     this.callParent(); | ||||
|     this.getView().on('itemclick', function(view, record){ | ||||
|       // The beauty of using Ext.Direct: calling 3 endpoints in a row, which results in a single call to the server!
 | ||||
|       console.log("user: " + record.get('id') ); | ||||
|       this.selectCustomer({customer_id: record.get('id'), customer_type: 'User'}); | ||||
|     }, this); | ||||
|   }, | ||||
|   onResetPassword: function(record){ | ||||
|     user = record.data; | ||||
|     Ext.Msg.confirm( | ||||
|       "Reset Password", | ||||
|       "Are you sure you want to reset "+user.first_name+" "+user.last_name+"'s password?", | ||||
|       function(butt_id){ | ||||
|         if( butt_id === "yes" ){ | ||||
|           $.ajax({ | ||||
|             type: 'POST', | ||||
|             url: '/api/v1/reset', | ||||
|             dataType: 'json', | ||||
|             contentType: 'application/json', | ||||
|             processData: false, | ||||
|             data: JSON.stringify({"user_id": user.id}), | ||||
|             complete: function() { }, | ||||
|             success: function(data) { | ||||
|               Ext.Msg.alert("Success", "New Password: "+data.password); | ||||
|             }, | ||||
|             error: function(data,textStatus) { | ||||
|               Ext.Msg.alert( "Error", JSON.parse(data.responseText)["error"]); | ||||
|             } | ||||
|           }); | ||||
|         } | ||||
|       }); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -9,7 +9,7 @@ class UsersAndProfilesBorder < Netzke::Base | ||||
|     super | ||||
|     c.header = false | ||||
|     c.items = [ | ||||
|      { netzke_component: :users, header: "Users", region: :center, width: 300, split: true }, | ||||
|      { netzke_component: :users, header: "Users", region: :center, width: 350, split: true }, | ||||
|      { netzke_component: :user_profiles, region: :south, height: 150, split: true}, | ||||
|      { netzke_component: :user_logs, region: :east, split: true} | ||||
|     ] | ||||
| @ -25,5 +25,5 @@ class UsersAndProfilesBorder < Netzke::Base | ||||
|     # store selected boss id in the session for this component's instance | ||||
|     session[:selected_user_id] = params[:user_id] | ||||
|   end | ||||
|    | ||||
| 
 | ||||
| end | ||||
|  | ||||
							
								
								
									
										28
									
								
								app/controllers/api/v1/users_controller.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								app/controllers/api/v1/users_controller.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| require 'securerandom' | ||||
| class Api::V1::UsersController < Api::V1::BaseController | ||||
| 
 | ||||
|   def password_reset | ||||
|     if can? :manage, User | ||||
|       user = User.find_by_id(params[:user_id]) | ||||
|       render :json => { "error" => "User not found"}, :status => 404 and return if user.nil? | ||||
|       render :json => { "error" => "Not allowed to reset your own password in this fashion."}, :status => 403 and return if user.id == current_user.id | ||||
| 
 | ||||
|       new_pass = SecureRandom.hex[0,8] | ||||
|       user.password = new_pass | ||||
|       user.save | ||||
|       render :json => { "password" => new_pass}, :status => 200 and return | ||||
|     else | ||||
|       render :json => { "error" => "You do not have the permission"}, :status => 403 and return | ||||
|     end | ||||
|   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 | ||||
|       @current_user.checkout | ||||
|       render :nothing => true, :status => 204 and return | ||||
|     end | ||||
|   end | ||||
| end | ||||
							
								
								
									
										23
									
								
								app/helpers/devise_helper.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								app/helpers/devise_helper.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| module DeviseHelper | ||||
|   # A simple way to show error messages for the current devise resource. If you need | ||||
|   # to customize this method, you can either overwrite it in your application helpers or | ||||
|   # copy the views to your application. | ||||
|   # | ||||
|   # This method is intended to stay simple and it is unlikely that we are going to change | ||||
|   # it to add more behavior or options. | ||||
|   def devise_error_messages! | ||||
|     return "" if resource.errors.empty? | ||||
| 
 | ||||
|     messages = resource.errors.full_messages.map { |msg| content_tag(:p, msg, :class => "alert") }.join | ||||
|     sentence = I18n.t("errors.messages.not_saved", | ||||
|                       :count => resource.errors.count, | ||||
|                       :resource => resource.class.model_name.human.downcase) | ||||
| 
 | ||||
|     html = <<-HTML | ||||
|     <p>#{sentence}</p> | ||||
|     #{messages} | ||||
|     HTML | ||||
| 
 | ||||
|     html.html_safe | ||||
|   end | ||||
| end | ||||
| @ -8,7 +8,7 @@ class User < ActiveRecord::Base | ||||
|   # Setup accessible (or protected) attributes for your model | ||||
|   attr_accessible :email, :password, :password_confirmation, :remember_me, | ||||
|     :first_name, :last_name, :nickname, :bike_id, | ||||
|     :user_profiles_attributes | ||||
|     :user_profiles_attributes, :username | ||||
| 
 | ||||
|   has_many :transactions | ||||
|   has_many :user_profiles | ||||
| @ -26,6 +26,10 @@ class User < ActiveRecord::Base | ||||
|     "#{first_name} #{last_name}" | ||||
|   end | ||||
| 
 | ||||
|   def email_required? | ||||
|     false | ||||
|   end | ||||
| 
 | ||||
|   def full_name | ||||
|     to_s | ||||
|   end | ||||
|  | ||||
| @ -1,16 +1,15 @@ | ||||
| class UserProfile < ActiveRecord::Base | ||||
|   # Setup accessible (or protected) attributes for your model | ||||
|   attr_accessible :user_id, :addrStreet1, :addrStreet2, :addrCity, | ||||
|     :addrState, :addrZip, :phone | ||||
|    | ||||
| 
 | ||||
|   belongs_to :user | ||||
|   belongs_to :bike | ||||
| 
 | ||||
|  #validates :addrStreet1 , :presence => true | ||||
|  #validates :addrCity , :presence => true | ||||
|  #validates :addrState , :presence => true | ||||
|  #validates :addrZip , :presence => true | ||||
|   validates :phone, :presence => true | ||||
|   #validates :addrStreet1 , :presence => true | ||||
|   #validates :addrCity , :presence => true | ||||
|   #validates :addrState , :presence => true | ||||
|   #validates :addrZip , :presence => true | ||||
|   #validates :phone, :presence => true | ||||
| 
 | ||||
|   def to_s | ||||
|     [addrStreet1, addrStreet2, addrCity, addrState, addrZip, phone].join(" - ") | ||||
|  | ||||
| @ -1,3 +1,5 @@ | ||||
| <%= stylesheet_link_tag "bootstrap_and_overrides", :media => "all" %> | ||||
| 
 | ||||
| <h2>Edit <%= resource_name.to_s.humanize %></h2> | ||||
| 
 | ||||
| <%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %> | ||||
|  | ||||
| @ -1,6 +1,11 @@ | ||||
| = stylesheet_link_tag "bootstrap_and_overrides", :media => "all" | ||||
| %h2 Sign up | ||||
| = form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| | ||||
|   = devise_error_messages! | ||||
|   %div | ||||
|     = f.label :username | ||||
|     %br/ | ||||
|     = f.text_field :username | ||||
|   %div | ||||
|     = f.label :first_name | ||||
|     %br/ | ||||
| @ -18,7 +23,8 @@ | ||||
|     %br/ | ||||
|     = f.email_field :email | ||||
|   %div | ||||
|     = f.fields_for :user_profiles, UserProfile.new do |builder| | ||||
|     - profile_builder = resource.user_profiles.empty? ? resource.user_profiles.build : resource.user_profiles | ||||
|     = f.fields_for :user_profiles, profile_builder do |builder| | ||||
|       = render 'user_profile_fields', f: builder | ||||
|   %div | ||||
|     = f.label :password | ||||
|  | ||||
| @ -3,8 +3,8 @@ | ||||
| <h2>Velocipede</h2> | ||||
| 
 | ||||
| <%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %> | ||||
|   <div><%= f.label :email %><br /> | ||||
|     <%= f.email_field :email %></div> | ||||
|   <div><%= f.label :username%><br /> | ||||
|     <%= f.text_field :username%></div> | ||||
| 
 | ||||
|   <div><%= f.label :password %><br /> | ||||
|     <%= f.password_field :password %></div> | ||||
| @ -28,9 +28,9 @@ | ||||
| <% if Rails.env.development? %> | ||||
|   <% User.all.each do |user| %> | ||||
|     <%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %> | ||||
|       <%= f.hidden_field :email, :value => user.email %></div> | ||||
|       <%= f.hidden_field :username, :value => user.username%></div> | ||||
|       <%= f.hidden_field :password, :value => 'password' %></div> | ||||
|       <div><%= f.submit "Sign in as #{user.email}" %></div> | ||||
|       <div><%= f.submit "Sign in as #{user.username}" %></div> | ||||
|     <% end %> | ||||
|   <% end %> | ||||
| <% end %> | ||||
|  | ||||
| @ -28,3 +28,4 @@ | ||||
|         %p © Velocipede 2013 | ||||
| 
 | ||||
|     = javascript_include_tag "application" | ||||
|     = javascript_include_tag params[:controller]  | ||||
|  | ||||
| @ -26,7 +26,7 @@ Devise.setup do |config| | ||||
|   # session. If you need permissions, you should implement that in a before filter. | ||||
|   # You can also supply a hash where the value is a boolean determining whether | ||||
|   # or not authentication should be aborted when the value is not present. | ||||
|   # config.authentication_keys = [ :email ] | ||||
|   config.authentication_keys = [ :username ] | ||||
| 
 | ||||
|   # Configure parameters from the request object used for authentication. Each entry | ||||
|   # given should be a request method and it will automatically be passed to the | ||||
| @ -38,12 +38,12 @@ Devise.setup do |config| | ||||
|   # Configure which authentication keys should be case-insensitive. | ||||
|   # These keys will be downcased upon creating or modifying a user and when used | ||||
|   # to authenticate or find a user. Default is :email. | ||||
|   config.case_insensitive_keys = [ :email ] | ||||
|   config.case_insensitive_keys = [ :username ] | ||||
| 
 | ||||
|   # Configure which authentication keys should have whitespace stripped. | ||||
|   # These keys will have whitespace before and after removed upon creating or | ||||
|   # modifying a user and when used to authenticate or find a user. Default is :email. | ||||
|   config.strip_whitespace_keys = [ :email ] | ||||
|   config.strip_whitespace_keys = [ :username ] | ||||
| 
 | ||||
|   # Tell if authentication through request.params is enabled. True by default. | ||||
|   # It can be set to an array that will enable params authentication only for the | ||||
|  | ||||
| @ -10,6 +10,7 @@ Velocipede::Application.routes.draw do | ||||
|     scope 'v1', :module => :v1 do | ||||
|       post 'checkin' => "logs#checkin", :as => "api_checkin" | ||||
|       post 'checkout' => "logs#checkout", :as => "api_checkout" | ||||
|       post 'reset' => "users#password_reset", :as => "api_password_reset" | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										6
									
								
								db/migrate/20130525143240_add_username_to_user.rb
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								db/migrate/20130525143240_add_username_to_user.rb
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,6 @@ | ||||
| class AddUsernameToUser < ActiveRecord::Migration | ||||
|   def change | ||||
|     add_column :users, :username, :string | ||||
|     add_index :users, :username, :unique => true | ||||
|   end | ||||
| end | ||||
							
								
								
									
										10
									
								
								db/schema.rb
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								db/schema.rb
									
									
									
									
									
								
							| @ -11,7 +11,7 @@ | ||||
| # | ||||
| # It's strongly recommended to check this file into your version control system. | ||||
| 
 | ||||
| ActiveRecord::Schema.define(:version => 20130424005701) do | ||||
| ActiveRecord::Schema.define(:version => 20130525143240) do | ||||
| 
 | ||||
|   create_table "bike_actions", :force => true do |t| | ||||
|     t.string   "action",     :limit => 128, :null => false | ||||
| @ -155,9 +155,9 @@ ActiveRecord::Schema.define(:version => 20130424005701) do | ||||
|   end | ||||
| 
 | ||||
|   create_table "user_role_joins", :force => true do |t| | ||||
|     t.integer  "role_id" | ||||
|     t.datetime "created_at", :null => false | ||||
|     t.datetime "updated_at", :null => false | ||||
|     t.integer  "role_id",    :limit => 255 | ||||
|     t.datetime "created_at",                :null => false | ||||
|     t.datetime "updated_at",                :null => false | ||||
|     t.datetime "ends" | ||||
|     t.integer  "user_id" | ||||
|   end | ||||
| @ -182,10 +182,12 @@ ActiveRecord::Schema.define(:version => 20130424005701) do | ||||
|     t.string   "first_name",             :default => "", :null => false | ||||
|     t.string   "last_name",              :default => "", :null => false | ||||
|     t.string   "nickname" | ||||
|     t.string   "username" | ||||
|   end | ||||
| 
 | ||||
|   add_index "users", ["bike_id"], :name => "index_users_on_bike_id", :unique => true | ||||
|   add_index "users", ["email"], :name => "index_users_on_email", :unique => true | ||||
|   add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true | ||||
|   add_index "users", ["username"], :name => "index_users_on_username", :unique => true | ||||
| 
 | ||||
| end | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| FactoryGirl.define do | ||||
|   factory :user do | ||||
|     sequence(:username) { |n| "user_#{n}" } | ||||
|     sequence(:email) { |n| "user_#{n}@example.com" } | ||||
|     password 'password' | ||||
|     password_confirmation { password } | ||||
| @ -11,6 +12,7 @@ FactoryGirl.define do | ||||
|     end | ||||
| 
 | ||||
|     factory :staff do | ||||
|       username "staff" | ||||
|       first_name 'Staff' | ||||
|       after_build do |r| | ||||
|         r.roles << (Role.find_by_role("staff") || FactoryGirl.create(:role_staff)) | ||||
| @ -18,6 +20,7 @@ FactoryGirl.define do | ||||
|     end | ||||
| 
 | ||||
|     factory :admin do | ||||
|       username "admin" | ||||
|       first_name 'Admin' | ||||
|       after_build do |r| | ||||
|         r.roles << (Role.find_by_role("admin") || FactoryGirl.create(:role_admin)) | ||||
| @ -25,6 +28,7 @@ FactoryGirl.define do | ||||
|     end | ||||
| 
 | ||||
|     factory :bike_admin do | ||||
|       username "bike_admin" | ||||
|       first_name 'BikeAdmin' | ||||
|       after_build do |r| | ||||
|         r.roles << (Role.find_by_role("bike_admin") || FactoryGirl.create(:role_bike_admin)) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user