mirror of
https://github.com/fspc/BikeShed-1.git
synced 2026-09-17 00:41:38 -04:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
01d1dcdcf1 |
@@ -7,6 +7,4 @@ tmp/
|
|||||||
.rbenv-version
|
.rbenv-version
|
||||||
.DS_Store
|
.DS_Store
|
||||||
public/extjs
|
public/extjs
|
||||||
public/assets
|
|
||||||
public/images/icons
|
public/images/icons
|
||||||
config/database.yml
|
|
||||||
|
|||||||
@@ -14,12 +14,13 @@ gem 'decent_exposure', '~> 1.0.1'
|
|||||||
gem 'devise', '~> 2.0.4'
|
gem 'devise', '~> 2.0.4'
|
||||||
gem 'haml-rails', '~> 0.3.4'
|
gem 'haml-rails', '~> 0.3.4'
|
||||||
gem 'jquery-rails', '~> 2.0'
|
gem 'jquery-rails', '~> 2.0'
|
||||||
gem 'pg'
|
gem 'sqlite3', '~> 1.3.5'
|
||||||
gem 'will_paginate', '~> 3.0.3'
|
gem 'will_paginate', '~> 3.0.3'
|
||||||
|
|
||||||
# Gems used only for assets and not required
|
# Gems used only for assets and not required
|
||||||
# in production environments by default.
|
# in production environments by default.
|
||||||
group :assets do
|
group :assets do
|
||||||
|
gem 'sass-rails', '~> 3.2.3'
|
||||||
gem 'coffee-rails', '~> 3.2.1'
|
gem 'coffee-rails', '~> 3.2.1'
|
||||||
gem "twitter-bootstrap-rails", "~> 2.0.3"
|
gem "twitter-bootstrap-rails", "~> 2.0.3"
|
||||||
|
|
||||||
@@ -33,7 +34,6 @@ group :development, :test do
|
|||||||
gem 'rspec-rails', '~> 2.8.1'
|
gem 'rspec-rails', '~> 2.8.1'
|
||||||
gem 'factory_girl_rails', '~> 1.2'
|
gem 'factory_girl_rails', '~> 1.2'
|
||||||
gem 'pry', '~> 0.9.8'
|
gem 'pry', '~> 0.9.8'
|
||||||
gem 'faker'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
|
|||||||
+14
-13
@@ -1,6 +1,6 @@
|
|||||||
GIT
|
GIT
|
||||||
remote: https://github.com/spacemunkay/acts_as_loggable.git
|
remote: https://github.com/spacemunkay/acts_as_loggable.git
|
||||||
revision: 8484dc1f7a58699705c5ffb593ebdf700a9f374a
|
revision: 6033fe5a44878bb374f73fe473fed9a3396ddc74
|
||||||
specs:
|
specs:
|
||||||
acts_as_loggable (0.0.7)
|
acts_as_loggable (0.0.7)
|
||||||
activerecord (>= 3.0)
|
activerecord (>= 3.0)
|
||||||
@@ -77,8 +77,6 @@ GEM
|
|||||||
factory_girl_rails (1.7.0)
|
factory_girl_rails (1.7.0)
|
||||||
factory_girl (~> 2.6.0)
|
factory_girl (~> 2.6.0)
|
||||||
railties (>= 3.0.0)
|
railties (>= 3.0.0)
|
||||||
faker (1.2.0)
|
|
||||||
i18n (~> 0.5)
|
|
||||||
ffi (1.6.0)
|
ffi (1.6.0)
|
||||||
formatador (0.2.4)
|
formatador (0.2.4)
|
||||||
gherkin (2.11.6)
|
gherkin (2.11.6)
|
||||||
@@ -124,18 +122,17 @@ GEM
|
|||||||
treetop (~> 1.4.8)
|
treetop (~> 1.4.8)
|
||||||
method_source (0.8.1)
|
method_source (0.8.1)
|
||||||
mime-types (1.22)
|
mime-types (1.22)
|
||||||
multi_json (1.8.2)
|
multi_json (1.7.2)
|
||||||
netzke-basepack (0.8.4)
|
netzke-basepack (0.8.2)
|
||||||
netzke-core (~> 0.8.2)
|
netzke-core (~> 0.8.2)
|
||||||
netzke-cancan (0.8.2)
|
netzke-cancan (0.8.2)
|
||||||
cancan
|
cancan
|
||||||
netzke-core
|
netzke-core
|
||||||
netzke-core (0.8.4)
|
netzke-core (0.8.3)
|
||||||
execjs
|
execjs
|
||||||
uglifier
|
uglifier
|
||||||
nokogiri (1.5.9)
|
nokogiri (1.5.9)
|
||||||
orm_adapter (0.0.7)
|
orm_adapter (0.0.7)
|
||||||
pg (0.15.1)
|
|
||||||
polyglot (0.3.3)
|
polyglot (0.3.3)
|
||||||
pry (0.9.12)
|
pry (0.9.12)
|
||||||
coderay (~> 1.0.5)
|
coderay (~> 1.0.5)
|
||||||
@@ -164,7 +161,6 @@ GEM
|
|||||||
rdoc (~> 3.4)
|
rdoc (~> 3.4)
|
||||||
thor (>= 0.14.6, < 2.0)
|
thor (>= 0.14.6, < 2.0)
|
||||||
rake (10.0.4)
|
rake (10.0.4)
|
||||||
rb-fsevent (0.9.3)
|
|
||||||
rdoc (3.12.2)
|
rdoc (3.12.2)
|
||||||
json (~> 1.4)
|
json (~> 1.4)
|
||||||
rspec (2.8.0)
|
rspec (2.8.0)
|
||||||
@@ -181,6 +177,11 @@ GEM
|
|||||||
railties (>= 3.0)
|
railties (>= 3.0)
|
||||||
rspec (~> 2.8.0)
|
rspec (~> 2.8.0)
|
||||||
rubyzip (0.9.9)
|
rubyzip (0.9.9)
|
||||||
|
sass (3.2.7)
|
||||||
|
sass-rails (3.2.6)
|
||||||
|
railties (~> 3.2.0)
|
||||||
|
sass (>= 3.1.10)
|
||||||
|
tilt (~> 1.3)
|
||||||
selenium-webdriver (2.31.0)
|
selenium-webdriver (2.31.0)
|
||||||
childprocess (>= 0.2.5)
|
childprocess (>= 0.2.5)
|
||||||
multi_json (~> 1.0)
|
multi_json (~> 1.0)
|
||||||
@@ -194,6 +195,7 @@ GEM
|
|||||||
multi_json (~> 1.0)
|
multi_json (~> 1.0)
|
||||||
rack (~> 1.0)
|
rack (~> 1.0)
|
||||||
tilt (~> 1.1, != 1.3.0)
|
tilt (~> 1.1, != 1.3.0)
|
||||||
|
sqlite3 (1.3.7)
|
||||||
therubyracer (0.10.2)
|
therubyracer (0.10.2)
|
||||||
libv8 (~> 3.3.10)
|
libv8 (~> 3.3.10)
|
||||||
thor (0.18.1)
|
thor (0.18.1)
|
||||||
@@ -209,8 +211,8 @@ GEM
|
|||||||
less-rails (~> 2.2.2)
|
less-rails (~> 2.2.2)
|
||||||
railties (>= 3.1)
|
railties (>= 3.1)
|
||||||
therubyracer (~> 0.10.1)
|
therubyracer (~> 0.10.1)
|
||||||
tzinfo (0.3.38)
|
tzinfo (0.3.37)
|
||||||
uglifier (2.1.2)
|
uglifier (1.3.0)
|
||||||
execjs (>= 0.3.0)
|
execjs (>= 0.3.0)
|
||||||
multi_json (~> 1.0, >= 1.0.2)
|
multi_json (~> 1.0, >= 1.0.2)
|
||||||
warden (1.1.1)
|
warden (1.1.1)
|
||||||
@@ -233,7 +235,6 @@ DEPENDENCIES
|
|||||||
decent_exposure (~> 1.0.1)
|
decent_exposure (~> 1.0.1)
|
||||||
devise (~> 2.0.4)
|
devise (~> 2.0.4)
|
||||||
factory_girl_rails (~> 1.2)
|
factory_girl_rails (~> 1.2)
|
||||||
faker
|
|
||||||
guard-rspec
|
guard-rspec
|
||||||
guard-spork
|
guard-spork
|
||||||
haml-rails (~> 0.3.4)
|
haml-rails (~> 0.3.4)
|
||||||
@@ -242,13 +243,13 @@ DEPENDENCIES
|
|||||||
netzke-basepack (~> 0.8.0)
|
netzke-basepack (~> 0.8.0)
|
||||||
netzke-cancan
|
netzke-cancan
|
||||||
netzke-core (~> 0.8.0)
|
netzke-core (~> 0.8.0)
|
||||||
pg
|
|
||||||
pry (~> 0.9.8)
|
pry (~> 0.9.8)
|
||||||
rails (= 3.2.13)
|
rails (= 3.2.13)
|
||||||
rb-fsevent
|
|
||||||
rspec-rails (~> 2.8.1)
|
rspec-rails (~> 2.8.1)
|
||||||
|
sass-rails (~> 3.2.3)
|
||||||
shoulda-matchers (~> 1.0.0)
|
shoulda-matchers (~> 1.0.0)
|
||||||
spork
|
spork
|
||||||
|
sqlite3 (~> 1.3.5)
|
||||||
turnip (~> 0.3.0)
|
turnip (~> 0.3.0)
|
||||||
twitter-bootstrap-rails (~> 2.0.3)
|
twitter-bootstrap-rails (~> 2.0.3)
|
||||||
uglifier (>= 1.0.3)
|
uglifier (>= 1.0.3)
|
||||||
|
|||||||
@@ -1,56 +1,22 @@
|
|||||||
# About
|
|
||||||
A web application for bicycle collectives to track bicycles, bicycle work history, volunteer hours, volunteer work history, and volunteers currently in the shop.
|
|
||||||
|
|
||||||
See an overview video of what it looks like and how it works here: https://www.youtube.com/watch?v=0-JjM6d9nK4.
|
|
||||||
|
|
||||||
## Instructions/Guides
|
|
||||||
|
|
||||||
### Adding a User
|
|
||||||
To add a user, a user must sign themselves up from the initial login screen. An admin can later log in to grant that user admin privileges afterward, if desired.
|
|
||||||
|
|
||||||
### Adding a Bike
|
|
||||||
How to add a bike to the database: https://www.youtube.com/watch?v=1IchWUdMQ90.
|
|
||||||
|
|
||||||
## Views
|
|
||||||
The app has two different views. One for "core" volunteers which I consider admins, and another for "customer" volunteers which I consider users. Because of the Netzke/ExtJS framework I used, the current UI is non-intuitive and I feel like is only adequate for admins who can take the time to learn the system. I'm in the process of designing a simpler mobile friendly UI with the essential functionality that's intended for users.
|
|
||||||
|
|
||||||
## Deployment
|
|
||||||
Currently, at the Velocipede collective we have it running on a computer in the shop on the local network. The reason for this, is so that it's only accessible from within the shop. I'm weighing out different methods for ensuring that users can only log in from within the shop (and not from home), such as a shop password that only admins can see and would make visible from within the physical bike shop. I also don't have to worry about security issues while the app is in development. In the future, I'd like to see the app hosted much like http://freehub.bikekitchen.org/.
|
|
||||||
|
|
||||||
## Ideas
|
|
||||||
At Velocipede, with a mobile friendly UI for users, I'm hoping we can get donations of old, unused smart phones, connected via local wifi, that can be used as stations to log a volunteer's work and hours. They can be secured by gluing cables into the earphone jacks to deter theft if necessary. This might be another way that the collective can promote reuse of materials.
|
|
||||||
|
|
||||||
# Developer Setup
|
# Developer Setup
|
||||||
|
|
||||||
1. use rvm
|
1. use rvm
|
||||||
1. allow the .rvmrc file
|
1. allow the .rvmrc file
|
||||||
1. `gem install bundler`
|
1. `gem install bundler`
|
||||||
1. `bundle`
|
1. `bundle`
|
||||||
1. Install Postgres (Mac OSX instructions below)
|
1. `rake db:create db:migrate db:seed`
|
||||||
1. Copy over DB config: `cp config/database.yml.example config/database.yml`
|
1. Download extJS (http://www.sencha.com/products/extjs), unzip, and place where ever you like.
|
||||||
1. Update config with your database (velocipede), user (velocipede), and password.
|
|
||||||
1. `rake db:create db:migrate`
|
|
||||||
1. `rake db:seed`
|
|
||||||
1. Download extJS 4.1 (A version of 4.1 is hosted here: http://my.jasondenney.com/extjs-4.1.1.zip) Latest versions at http://www.sencha.com/products/extjs. Unzip and place where ever you like.
|
|
||||||
1. Link to your extJS folder path under `public/extjs`: (From app root) `ln -s /MY/PATH/extjs/ public/extjs`
|
1. Link to your extJS folder path under `public/extjs`: (From app root) `ln -s /MY/PATH/extjs/ public/extjs`
|
||||||
1. `rails s`
|
1. `rails s`
|
||||||
|
|
||||||
|
|
||||||
# Postgres 9.2 Mac OSX Install
|
|
||||||
1. Install homebrew `ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)"`
|
|
||||||
1. `brew install postgres`
|
|
||||||
1. First time db initialization `initdb /usr/local/var/postgres -E utf8`
|
|
||||||
1. Start Postgres `pg_ctl -D /usr/local/var/postgres -l /usr/local/var/postgres/server.log start`
|
|
||||||
1. Create your PG user `createuser -d -P velocipede`
|
|
||||||
1. Create your database `createdb -U velocipede --owner=velocipede velocipede`
|
|
||||||
|
|
||||||
# Optional
|
# Optional
|
||||||
Add icons
|
Add icons
|
||||||
|
|
||||||
1. Download icons from http://www.famfamfam.com/lab/icons/silk/
|
1. Download icons from http://www.famfamfam.com/lab/icons/silk/
|
||||||
1. Link to the icons under `public/images/icons`: (From app root) `ln -s /MY/PATH/famfamfam_silk_icons/icons public/images/icons`
|
1. Link to the icons under `public/images/icons`: (From app root) `ln -s /MY/PATH/famfamfam_silk_icons/icons public/images/icons`
|
||||||
|
|
||||||
# License
|
|
||||||
Velocipede is released under the MIT license (http://opensource.org/licenses/MIT)
|
|
||||||
|
|
||||||
<a href="http://madewithloveinbaltimore.org">Made with ♥ in Baltimore</a>
|
## Mailcatcher
|
||||||
|
|
||||||
|
Use mailcatcher to see what emails look like in development.
|
||||||
|
Follow the instructions from http://mailcatcher.me/ to create an rvm wrapper so you don't install it all over your gemsets
|
||||||
|
|||||||
@@ -12,20 +12,16 @@ require File.expand_path('../config/application', __FILE__)
|
|||||||
|
|
||||||
Velocipede::Application.load_tasks
|
Velocipede::Application.load_tasks
|
||||||
|
|
||||||
unless Rails.env.production?
|
namespace :spec do
|
||||||
|
|
||||||
namespace :spec do
|
|
||||||
desc 'Run all acceptance specs'
|
desc 'Run all acceptance specs'
|
||||||
RSpec::Core::RakeTask.new(:acceptance => 'db:test:prepare') do |t|
|
RSpec::Core::RakeTask.new(:acceptance => 'db:test:prepare') do |t|
|
||||||
t.pattern = '**/*.feature'
|
t.pattern = '**/*.feature'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Rake.application.remove_task 'spec'
|
Rake.application.remove_task 'spec'
|
||||||
|
|
||||||
desc 'Run all specs'
|
desc 'Run all specs'
|
||||||
RSpec::Core::RakeTask.new(:spec => 'db:test:prepare') do |t|
|
RSpec::Core::RakeTask.new(:spec => 'db:test:prepare') do |t|
|
||||||
t.pattern = '**/*{_spec.rb,.feature}'
|
t.pattern = '**/*{_spec.rb,.feature}'
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -12,4 +12,5 @@
|
|||||||
//
|
//
|
||||||
//= require jquery
|
//= require jquery
|
||||||
//= require jquery_ujs
|
//= require jquery_ujs
|
||||||
//= require custom_netzke_helpers
|
//= require twitter/bootstrap
|
||||||
|
//= require_tree .
|
||||||
|
|||||||
@@ -3,374 +3,3 @@ Ext.Ajax.on('requestexception', function(conn, response, options) {
|
|||||||
if (response.status === 401) { window.location = '/users/sign_in'; }
|
if (response.status === 401) { window.location = '/users/sign_in'; }
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
//Override default netzke time entry field
|
|
||||||
Ext.define('Ext.ux.form.field.DateTime', {
|
|
||||||
extend:'Ext.form.FieldContainer',
|
|
||||||
mixins:{
|
|
||||||
field:'Ext.form.field.Field'
|
|
||||||
},
|
|
||||||
alias: 'widget.xdatetime',
|
|
||||||
|
|
||||||
//configurables
|
|
||||||
|
|
||||||
combineErrors: true,
|
|
||||||
msgTarget: 'under',
|
|
||||||
layout: 'hbox',
|
|
||||||
readOnly: false,
|
|
||||||
|
|
||||||
dateFormat: 'Y-m-d',
|
|
||||||
dateSubmitFormat: 'Y-m-d',
|
|
||||||
timeFormat: 'H:i:s',
|
|
||||||
timeSubmitFormat: 'H:i:s',
|
|
||||||
dateConfig:{},
|
|
||||||
timeConfig:{},
|
|
||||||
|
|
||||||
|
|
||||||
// properties
|
|
||||||
|
|
||||||
dateValue: null, // Holds the actual date
|
|
||||||
|
|
||||||
dateField: null,
|
|
||||||
|
|
||||||
hourField: null,
|
|
||||||
minuteField: null,
|
|
||||||
ampmField: null,
|
|
||||||
|
|
||||||
initComponent: function(){
|
|
||||||
var me = this
|
|
||||||
,i = 0
|
|
||||||
,key
|
|
||||||
,tab;
|
|
||||||
|
|
||||||
me.items = me.items || [];
|
|
||||||
|
|
||||||
me.dateField = Ext.create('Ext.form.field.Date', Ext.apply({
|
|
||||||
format:me.dateFormat,
|
|
||||||
flex:1,
|
|
||||||
isFormField:false, //exclude from field query's
|
|
||||||
submitValue:false,
|
|
||||||
submitFormat: me.dateSubmitFormat,
|
|
||||||
readOnly: me.readOnly
|
|
||||||
}, me.dateConfig));
|
|
||||||
me.items.push(me.dateField);
|
|
||||||
|
|
||||||
me.hourField = Ext.create('Ext.form.field.Number', {
|
|
||||||
maxWidth: 25,
|
|
||||||
allowBlank: false,
|
|
||||||
allowOnlyWhitespace: false,
|
|
||||||
blankText: "Hour cannot be blank.",
|
|
||||||
allowDecimals: false,
|
|
||||||
maxValue: 12,
|
|
||||||
minValue: 1,
|
|
||||||
maxLength: 2,
|
|
||||||
enforceMaxLength: 2,
|
|
||||||
hideTrigger: true,
|
|
||||||
submitValue:false,
|
|
||||||
flex:1,
|
|
||||||
fieldStyle: "text-align:right;",
|
|
||||||
isFormField:false, //exclude from field query's
|
|
||||||
});
|
|
||||||
me.items.push(me.hourField);
|
|
||||||
|
|
||||||
me.colon = Ext.create('Ext.draw.Text', {
|
|
||||||
text: ':',
|
|
||||||
padding: '3 3 0 3'
|
|
||||||
});
|
|
||||||
me.items.push(me.colon);
|
|
||||||
|
|
||||||
me.minuteField = Ext.create('Ext.form.field.Text', {
|
|
||||||
maxWidth: 30,
|
|
||||||
allowBlank: false,
|
|
||||||
allowOnlyWhitespace: false,
|
|
||||||
blankText: "Minutes cannot be blank.",
|
|
||||||
regex: /[012345]\d/,
|
|
||||||
maxLength: 2,
|
|
||||||
enforceMaxLength: 2,
|
|
||||||
submitValue:false,
|
|
||||||
flex:1,
|
|
||||||
isFormField:false, //exclude from field query's
|
|
||||||
});
|
|
||||||
me.items.push(me.minuteField);
|
|
||||||
|
|
||||||
|
|
||||||
me.ampmField = Ext.create('Ext.form.ComboBox', {
|
|
||||||
maxWidth: 45,
|
|
||||||
value: 'PM',
|
|
||||||
store: ['AM', 'PM'],
|
|
||||||
forceSelection: true,
|
|
||||||
flex:1,
|
|
||||||
editable: false
|
|
||||||
});
|
|
||||||
|
|
||||||
me.items.push(me.ampmField);
|
|
||||||
|
|
||||||
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.dateField.focus();
|
|
||||||
},
|
|
||||||
|
|
||||||
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.fireEvent('blur', me, e);
|
|
||||||
});
|
|
||||||
me.blurTask.delay(100);
|
|
||||||
},
|
|
||||||
|
|
||||||
getValue: function(){
|
|
||||||
var value = null
|
|
||||||
,date = this.dateField.getSubmitValue()
|
|
||||||
,time = null
|
|
||||||
,format;
|
|
||||||
|
|
||||||
hour = this.hourField.getValue();
|
|
||||||
minute = this.minuteField.getValue();
|
|
||||||
ampm = this.ampmField.getValue();
|
|
||||||
time = Ext.Date.parse(hour + " " + minute + " " + ampm, 'g i A');
|
|
||||||
time = Ext.Date.format(time, this.timeSubmitFormat);
|
|
||||||
|
|
||||||
if (date){
|
|
||||||
if (time){
|
|
||||||
format = this.getFormat();
|
|
||||||
value = Ext.Date.parse(date + ' ' + time, format);
|
|
||||||
} else {
|
|
||||||
value = this.dateField.getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
},
|
|
||||||
|
|
||||||
getSubmitValue: function(){
|
|
||||||
// var value = this.getValue();
|
|
||||||
// return value ? Ext.Date.format(value, this.dateTimeFormat) : null;
|
|
||||||
|
|
||||||
var me = this
|
|
||||||
,format = me.getFormat()
|
|
||||||
,value = me.getValue();
|
|
||||||
|
|
||||||
return value ? Ext.Date.format(value, format) : null;
|
|
||||||
},
|
|
||||||
|
|
||||||
setValue: function(value){
|
|
||||||
if (Ext.isString(value) || Ext.isDate(value)){
|
|
||||||
|
|
||||||
if( Ext.isDate(value)){
|
|
||||||
dt = value;
|
|
||||||
}else{
|
|
||||||
dt = new Date(value);
|
|
||||||
value = Ext.Date.parse(value, this.getFormat()); //this.dateTimeFormat
|
|
||||||
}
|
|
||||||
this.dateField.setValue(value);
|
|
||||||
|
|
||||||
hour = Ext.Date.format(dt, 'g');
|
|
||||||
minute = Ext.Date.format(dt, 'i');
|
|
||||||
ampm = Ext.Date.format(dt, 'A');
|
|
||||||
|
|
||||||
this.hourField.setValue(hour);
|
|
||||||
this.minuteField.setRawValue(minute);
|
|
||||||
this.ampmField.setValue(ampm);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
getFormat: function(){
|
|
||||||
value = (this.dateField.submitFormat || this.dateField.format) + " " + (this.timeSubmitFormat || this.timeFormat);
|
|
||||||
return 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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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() {
|
|
||||||
//show renders, so put first
|
|
||||||
me.picker.show();
|
|
||||||
me.picker.alignTo(me.colorField.inputEl);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,51 +0,0 @@
|
|||||||
$(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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
$(document).ready(function(){
|
|
||||||
$("#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"]);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,56 +1,45 @@
|
|||||||
class AppTabPanel < Netzke::Basepack::TabPanel
|
class AppTabPanel < Netzke::Basepack::TabPanel
|
||||||
|
|
||||||
|
|
||||||
action :sign_out do |c|
|
action :sign_out do |c|
|
||||||
c.icon = :door_out
|
c.icon = :door_out
|
||||||
c.text = "Exit"
|
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
|
|
||||||
|
|
||||||
action :change_account_info do |c|
|
|
||||||
c.icon = :user_edit
|
|
||||||
c.text = "Change Email/Password"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def configure(c)
|
def configure(c)
|
||||||
|
|
||||||
#all users
|
#all users
|
||||||
# (had to use hash for borders to get the title to display properly)
|
# (had to use hash for borders to get the title to display properly)
|
||||||
@@app_tab_panel_items = [ :bikes_border ]
|
@@app_tab_panel_items = [ :bikes_border,
|
||||||
|
{ layout: :fit,
|
||||||
|
wrappedComponent: :brands_and_models_border,
|
||||||
|
title: "Brands/Models"}
|
||||||
|
]
|
||||||
|
|
||||||
#for users only
|
#for users
|
||||||
if not controller.current_user.role?(:admin)
|
if controller.current_user.role?(:user)
|
||||||
|
# (had to use hash for borders to get the title to display properly)
|
||||||
@@app_tab_panel_items.concat [{ layout: :fit,
|
@@app_tab_panel_items.concat [{ layout: :fit,
|
||||||
wrappedComponent: :user_profile_border,
|
wrappedComponent: :user_profile_border,
|
||||||
title: "My Profile"},
|
title: "Profile"},
|
||||||
{ layout: :fit,
|
{ layout: :fit,
|
||||||
wrappedComponent: :user_transactions_border,
|
wrappedComponent: :user_transactions_border,
|
||||||
title: "My Transactions"}
|
title: "Transactions"}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
#for admins
|
#for admins
|
||||||
if can? :manage, User
|
if controller.current_user.role?(:admin)
|
||||||
|
# (had to use hash for borders to get the title to display properly)
|
||||||
@@app_tab_panel_items.concat [{ layout: :fit,
|
@@app_tab_panel_items.concat [{ layout: :fit,
|
||||||
wrappedComponent: :users_and_profiles_border,
|
wrappedComponent: :users_and_profiles_border,
|
||||||
title: "Users/Profiles"}]
|
title: "Users/Profiles"},
|
||||||
end
|
{ layout: :fit,
|
||||||
if can? :manage, Transaction
|
|
||||||
@@app_tab_panel_items.concat [{ layout: :fit,
|
|
||||||
wrappedComponent: :transactions_border,
|
wrappedComponent: :transactions_border,
|
||||||
title: "Users/Transactions"}]
|
title: "Transactions"},
|
||||||
end
|
:logs,
|
||||||
if can? :manage, Role
|
:user_roles]
|
||||||
@@app_tab_panel_items.concat [{ layout: :fit,
|
|
||||||
wrappedComponent: :user_role_joins,
|
|
||||||
title: "User Roles"},
|
|
||||||
]
|
|
||||||
end
|
|
||||||
if can? :manage, ::ActsAsLoggable::Log.all
|
|
||||||
@@app_tab_panel_items.concat [:check_ins, :logs]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@app_tab_panel_items.each do |item|
|
@@app_tab_panel_items.each do |item|
|
||||||
if item.kind_of?(Symbol)
|
if item.kind_of?(Symbol)
|
||||||
self.class.component item
|
self.class.component item
|
||||||
@@ -58,8 +47,9 @@ class AppTabPanel < Netzke::Basepack::TabPanel
|
|||||||
self.class.component item[:wrappedComponent]
|
self.class.component item[:wrappedComponent]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
c.prevent_header = true
|
c.prevent_header = true
|
||||||
c.tbar = [:sign_out, :check_out, :change_account_info]
|
c.tbar = [:sign_out]
|
||||||
c.items = @@app_tab_panel_items
|
c.items = @@app_tab_panel_items
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
@@ -68,5 +58,6 @@ class AppTabPanel < Netzke::Basepack::TabPanel
|
|||||||
#gets js from app_tab_panel/javascripts/sign_out.js
|
#gets js from app_tab_panel/javascripts/sign_out.js
|
||||||
c.mixin :sign_out
|
c.mixin :sign_out
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -5,20 +5,5 @@
|
|||||||
url: '/users/sign_out',
|
url: '/users/sign_out',
|
||||||
method: 'DELETE'
|
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'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
onChangeAccountInfo: function(){
|
|
||||||
window.location.href="users/edit";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ class BikeBrands < Netzke::Basepack::Grid
|
|||||||
super
|
super
|
||||||
c.model = "BikeBrand"
|
c.model = "BikeBrand"
|
||||||
c.title = "Brands"
|
c.title = "Brands"
|
||||||
c.force_fit = true
|
|
||||||
|
|
||||||
c.prohibit_update = true if cannot? :update, BikeBrand
|
c.prohibit_update = true if cannot? :update, BikeBrand
|
||||||
c.prohibit_create = true if cannot? :create, BikeBrand
|
c.prohibit_create = true if cannot? :create, BikeBrand
|
||||||
|
|||||||
+33
-14
@@ -6,7 +6,6 @@ class BikeLogs < Netzke::Basepack::Grid
|
|||||||
|
|
||||||
c.model = "ActsAsLoggable::Log"
|
c.model = "ActsAsLoggable::Log"
|
||||||
c.title = "Bike History"
|
c.title = "Bike History"
|
||||||
c.force_fit = true
|
|
||||||
c.data_store = {auto_load: false}
|
c.data_store = {auto_load: false}
|
||||||
c.scope = lambda { |rel| rel.where(:loggable_type => 'Bike',:loggable_id => session[:selected_bike_id]);}
|
c.scope = lambda { |rel| rel.where(:loggable_type => 'Bike',:loggable_id => session[:selected_bike_id]);}
|
||||||
c.strong_default_attrs = {
|
c.strong_default_attrs = {
|
||||||
@@ -19,36 +18,57 @@ class BikeLogs < Netzke::Basepack::Grid
|
|||||||
|
|
||||||
c.columns = [
|
c.columns = [
|
||||||
{ :name => :start_date, :format => "g:ia - D, M j - Y", :width => 165, :default_value => Time.now.to_formatted_s(:db) },
|
{ :name => :start_date, :format => "g:ia - D, M j - Y", :width => 165, :default_value => Time.now.to_formatted_s(:db) },
|
||||||
{ :name => :end_date, :format => "g:ia - D, M j - Y", :width => 165, :default_value => Time.now.to_formatted_s(:db) },
|
{ :name => :end_date, :hidden => true, :default_value => Time.now.to_formatted_s(:db) },
|
||||||
|
{ :name => :hours, :getter => lambda { |rec| (rec.end_date - rec.start_date)/3600 }, :sorting_scope => :sort_by_duration},
|
||||||
:description,
|
:description,
|
||||||
{ :name => :bike_action__action, :text => 'Action', :default_value => ::ActsAsLoggable::BikeAction.first.id},
|
{ :name => :bike_action__action, :text => 'Action'},
|
||||||
|
{ :name => :created_at, :read_only => true},
|
||||||
|
{ :name => :updated_at, :read_only => true},
|
||||||
{ :name => :logged_by, :getter => lambda{ |rec|
|
{ :name => :logged_by, :getter => lambda{ |rec|
|
||||||
user = User.find_by_id(rec.logger_id)
|
user = User.find_by_id(rec.logger_id)
|
||||||
user.nil? ? "" : "#{user.first_name} #{user.last_name}"
|
user.nil? ? "" : "#{user.first_name} #{user.last_name}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@bike_logs = ::ActsAsLoggable::Log.where(:loggable_type => "Bike").all
|
|
||||||
c.prohibit_update = true if cannot? :update, @bike_logs
|
|
||||||
c.prohibit_create = true if cannot? :create, @bike_logs
|
|
||||||
c.prohibit_delete = true if cannot? :delete, @bike_logs
|
|
||||||
=begin
|
=begin
|
||||||
#TODO: fix GUI so it actually respects this
|
#TODO: fix GUI so it actually respects this
|
||||||
current_bike = Bike.find_by_id(session[:selected_bike_id])
|
current_bike = Bike.find_by_id(session[:selected_bike_id])
|
||||||
if cannot? :update, current_bike
|
if can? :manage, current_bike
|
||||||
|
puts "\n\n\nCAN MANAGE!\n\n\n"
|
||||||
|
c.bbar = default_bbar
|
||||||
|
else
|
||||||
|
puts "\n\n\nCANNNOT MANAGE!\n\n\n"
|
||||||
# if you can't update the bike, you can't do anything to the log
|
# if you can't update the bike, you can't do anything to the log
|
||||||
c.prohibit_update = c.prohibit_create = c.prohibit_delete = true
|
#c.prohibit_update = c.prohibit_create = c.prohibit_delete = true
|
||||||
|
c.bbar = [ :search ]
|
||||||
end
|
end
|
||||||
=end
|
=end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
endpoint :set_read_only do |params, this|
|
||||||
|
current_bike = Bike.find_by_id(session[:selected_bike_id])
|
||||||
|
puts "\n\n\nREAD!\n\n\n"
|
||||||
|
if can? :manage, current_bike
|
||||||
|
puts "\n\n\nCAN MANAGE!\n\n\n"
|
||||||
|
#calls this.setDisabled()
|
||||||
|
this.set_disabled(false)
|
||||||
|
#sets the return value of this function
|
||||||
|
#this.netzke_set_result(true)
|
||||||
|
else
|
||||||
|
puts "\n\n\nCANNNOT MANAGE!\n\n\n"
|
||||||
|
#sets the return value of this function
|
||||||
|
#this.netzke_set_result(true)
|
||||||
|
this.set_disabled(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def default_fields_for_forms
|
def default_fields_for_forms
|
||||||
[
|
[
|
||||||
{ :name => :start_date},
|
{ :name => :start_date},
|
||||||
|
{ :name => :end_date},
|
||||||
{ :name => :description},
|
{ :name => :description},
|
||||||
#had to hack acts_as_loggable/log.rb to get this to work
|
#had to hack acts_as_loggable/log.rb to get this to work
|
||||||
{ :name => :bike_action__action, :field_label => 'Action', :min_chars => 1 }
|
{ :name => :bike_action__action, :field_label => 'Action'}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -56,9 +76,8 @@ class BikeLogs < Netzke::Basepack::Grid
|
|||||||
#override with nil to remove actions
|
#override with nil to remove actions
|
||||||
def default_bbar
|
def default_bbar
|
||||||
bbar = [ :search ]
|
bbar = [ :search ]
|
||||||
bbar.concat [ :apply ] if can? :update, ::ActsAsLoggable::Log
|
bbar.concat [ :apply ] #if can? :update, ::ActsAsLoggable::Log
|
||||||
bbar.concat [ :add_in_form ] if can? :create, ::ActsAsLoggable::Log
|
bbar.concat [ :add_in_form ] #if can? :create, ::ActsAsLoggable::Log
|
||||||
bbar
|
bbar
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
class BikeLogsAndTasksAccordian < Netzke::Basepack::Accordion
|
||||||
|
component :bike_logs
|
||||||
|
component :tasks
|
||||||
|
|
||||||
|
def configure(c)
|
||||||
|
c.prevent_header = true
|
||||||
|
c.items = [ :bike_logs, :tasks ]
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
class BikeLowerTabs < Netzke::Basepack::TabPanel
|
|
||||||
component :bike_logs
|
|
||||||
component :tasks
|
|
||||||
component :brands_and_models_border
|
|
||||||
|
|
||||||
def configure(c)
|
|
||||||
c.prevent_header = true
|
|
||||||
c.items = [ :bike_logs, :tasks,
|
|
||||||
{netzke_component: :brands_and_models_border, title: "Brands and Models"} ]
|
|
||||||
super
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -4,7 +4,6 @@ class BikeModels < Netzke::Basepack::Grid
|
|||||||
|
|
||||||
c.model = "BikeModel"
|
c.model = "BikeModel"
|
||||||
c.title = "Models"
|
c.title = "Models"
|
||||||
c.force_fit = true
|
|
||||||
c.data_store = {auto_load: false}
|
c.data_store = {auto_load: false}
|
||||||
c.scope = lambda { |rel| rel.where(:bike_brand_id => session[:selected_bike_brand_id]);}
|
c.scope = lambda { |rel| rel.where(:bike_brand_id => session[:selected_bike_brand_id]);}
|
||||||
c.strong_default_attrs = {
|
c.strong_default_attrs = {
|
||||||
|
|||||||
+11
-40
@@ -2,15 +2,12 @@ class Bikes < Netzke::Basepack::Grid
|
|||||||
def configure(c)
|
def configure(c)
|
||||||
super
|
super
|
||||||
c.model = "Bike"
|
c.model = "Bike"
|
||||||
c.force_fit = true
|
|
||||||
|
|
||||||
# columns with :id set, have :min_chars set in init_component
|
|
||||||
# See: http://stackoverflow.com/questions/17738962/netzke-grid-filtering
|
|
||||||
c.columns = [
|
c.columns = [
|
||||||
{ :name => :shop_id, :text => 'Shop ID', :default_value => Bike.last.id.to_i + 1},
|
{ :name => :shop_id, :text => 'Shop ID'},
|
||||||
:serial_number,
|
:serial_number,
|
||||||
{ :id => :bike_brand__brand, :name => :bike_brand__brand, :text => 'Brand'},
|
{ :name => :bike_brand__brand, :text => 'Brand' },
|
||||||
{ :name => :model, :text => 'Model',
|
{ :name => :bike_model__model, :text => 'Model',
|
||||||
:scope => lambda { |rel|
|
:scope => lambda { |rel|
|
||||||
if session[:selected_bike_brand_id]
|
if session[:selected_bike_brand_id]
|
||||||
rel.where(:bike_brand_id => session[:selected_bike_brand_id])
|
rel.where(:bike_brand_id => session[:selected_bike_brand_id])
|
||||||
@@ -19,48 +16,22 @@ class Bikes < Netzke::Basepack::Grid
|
|||||||
end
|
end
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
#needs to have type :action or else won't work in grid, because... netzke
|
:color,
|
||||||
{ :name => "color", :text => "Frame Color", :type => :action, :editor => { :xtype => "xcolorcombo"}, :renderer => :color_block,
|
{ :name => :bike_style__style, :text => 'Style' },
|
||||||
:default_value => '000000'},
|
:seat_tube_height,
|
||||||
{ :id => :bike_style__style, :name => :bike_style__style, :text => 'Style', :default_value => BikeStyle.first.id},
|
:top_tube_length,
|
||||||
{ :name => :seat_tube_height, :text => 'Seat Tube (in)'},
|
:wheel_size,
|
||||||
{ :name => :top_tube_length, :text => 'Top Tube (in)'},
|
|
||||||
{ :name => :bike_wheel_size__display_string, :text => 'Wheel Size'},
|
|
||||||
:value,
|
:value,
|
||||||
{ :id => :bike_condition__condition, :name => :bike_condition__condition, :text => 'Condition', :default_value => BikeCondition.first.id},
|
{ :name => :bike_condition__condition, :text => 'Condition'},
|
||||||
{ :id => :bike_purpose__purpose, :name => :bike_purpose__purpose, :text => 'Purpose', :default_value => BikePurpose.first.id},
|
{ :name => :bike_status__status, :text => 'Status'},
|
||||||
{ :name => :owner, :getter => lambda { |rec|
|
{ :name => :owner, :getter => lambda { |rec|
|
||||||
user = rec.owner
|
user = rec.owner
|
||||||
user.nil? ? "" : "#{user.first_name} #{user.last_name}"
|
user.nil? ? "" : "#{user.first_name} #{user.last_name}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
# Default the sorting to ASC on shop_id
|
|
||||||
c.data_store.sorters = [{ property: 'shop_id', direction: 'ASC' }]
|
|
||||||
|
|
||||||
@bike = Bike.all
|
|
||||||
c.prohibit_update = true if cannot? :update, @bike
|
|
||||||
c.prohibit_create = true if cannot? :create, @bike
|
|
||||||
c.prohibit_delete = true if cannot? :delete, @bike
|
|
||||||
end
|
|
||||||
def default_fields_for_forms
|
|
||||||
# :field_label MUST be defined in order for search to work
|
|
||||||
[
|
|
||||||
{ :name => :bike_brand__brand, :field_label => 'Brand', :min_chars => 1 },
|
|
||||||
{ :name => :model, :field_label => 'Model'},
|
|
||||||
{ :name => :shop_id, :field_label => 'Shop ID'},
|
|
||||||
{ :name => :serial_number, :field_label => 'Serial Number'},
|
|
||||||
{ :name => "color", :xtype => "xcolorcombo"},
|
|
||||||
{ :name => :bike_style__style, :field_label => 'Style', :min_chars => 1},
|
|
||||||
{ :name => :seat_tube_height, :field_label => 'Seat Tube (in)'},
|
|
||||||
{ :name => :top_tube_length, :field_label => 'Top Tube (in)'},
|
|
||||||
{ :name => :bike_wheel_size__display_string, :field_label => 'Wheel Size'},
|
|
||||||
{ :name => :value, :field_label => 'Value'},
|
|
||||||
{ :name => :bike_condition__condition, :field_label => 'Condition', :min_chars => 1},
|
|
||||||
{ :name => :bike_purpose__purpose, :field_label => 'Purpose', :min_chars => 1}
|
|
||||||
]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
#override with nil to remove actions
|
#override with nil to remove actions
|
||||||
def default_bbar
|
def default_bbar
|
||||||
[ :apply, :add_in_form, :search ]
|
[ :apply, :add_in_form, :search ]
|
||||||
|
|||||||
@@ -3,24 +3,11 @@
|
|||||||
// calling superclass's initComponent
|
// calling superclass's initComponent
|
||||||
this.callParent();
|
this.callParent();
|
||||||
|
|
||||||
//due to Netzke bug, :min_chars attribute doesn't work
|
|
||||||
var min_char_columns = [
|
|
||||||
"bike_brand__brand",
|
|
||||||
"bike_style__style",
|
|
||||||
"bike_condition__condition",
|
|
||||||
"bike_purpose__purpose"]
|
|
||||||
Ext.each(min_char_columns, function(column, index) {
|
|
||||||
Ext.ComponentManager.get(column).editor.minChars = 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
// setting the 'rowclick' event
|
// setting the 'rowclick' event
|
||||||
var view = this.getView();
|
var view = this.getView();
|
||||||
view.on('itemclick', function(view, record){
|
view.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!
|
// 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.selectBikeBrand({bike_brand_id: record.get('bike_brand__brand')});
|
||||||
}, this);
|
}, 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ class BikesBorder < Netzke::Base
|
|||||||
# Remember regions collapse state and size
|
# Remember regions collapse state and size
|
||||||
include Netzke::Basepack::ItemPersistence
|
include Netzke::Basepack::ItemPersistence
|
||||||
component :bikes
|
component :bikes
|
||||||
component :bike_lower_tabs
|
component :bike_logs_and_tasks_accordian
|
||||||
|
|
||||||
def configure(c)
|
def configure(c)
|
||||||
super
|
super
|
||||||
@@ -10,7 +10,7 @@ class BikesBorder < Netzke::Base
|
|||||||
c.title = "Bikes"
|
c.title = "Bikes"
|
||||||
c.items = [
|
c.items = [
|
||||||
{ netzke_component: :bikes, region: :center, split: true },
|
{ netzke_component: :bikes, region: :center, split: true },
|
||||||
{ netzke_component: :bike_lower_tabs, region: :south, height: 300, split: true}
|
{ netzke_component: :bike_logs_and_tasks_accordian, region: :south, height: 300, split: true}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -5,30 +5,19 @@
|
|||||||
|
|
||||||
// setting the 'rowclick' event
|
// setting the 'rowclick' event
|
||||||
var view = this.getComponent('bikes').getView();
|
var view = this.getComponent('bikes').getView();
|
||||||
|
|
||||||
//disable until a bike is clicked
|
|
||||||
var bike_logs_comp = this.queryById('bike_logs');
|
|
||||||
if( bike_logs_comp){
|
|
||||||
bike_logs_comp.disable();
|
|
||||||
}
|
|
||||||
var bike_tasks_comp = this.queryById('tasks');
|
|
||||||
if( bike_tasks_comp ){
|
|
||||||
bike_tasks_comp.disable();
|
|
||||||
}
|
|
||||||
|
|
||||||
view.on('itemclick', function(view, record){
|
view.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!
|
// The beauty of using Ext.Direct: calling 3 endpoints in a row, which results in a single call to the server!
|
||||||
this.selectBike({bike_id: record.get('id')});
|
this.selectBike({bike_id: record.get('id')});
|
||||||
// query for these components again, can change if not visible because of accordian
|
if( this.queryById('bike_logs') ){
|
||||||
var bike_logs_comp = this.queryById('bike_logs');
|
this.queryById('bike_logs').getStore().load();
|
||||||
var bike_tasks_comp = this.queryById('tasks');
|
this.queryById('bike_logs').setReadOnly({}, function(arg, arg1, arg2){
|
||||||
if( bike_logs_comp ){
|
console.log(arg);
|
||||||
bike_logs_comp.getStore().load();
|
console.log(this.getDockedItems());
|
||||||
bike_logs_comp.enable();
|
});
|
||||||
|
this.queryById('bike_logs').setDisabled(true);
|
||||||
}
|
}
|
||||||
if( bike_tasks_comp ){
|
if( this.queryById('tasks') ){
|
||||||
bike_tasks_comp.getStore().load();
|
this.queryById('tasks').getStore().load();
|
||||||
bike_tasks_comp.enable();
|
|
||||||
}
|
}
|
||||||
}, this);
|
}, this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
class CheckIns < Netzke::Basepack::Grid
|
|
||||||
|
|
||||||
def configure(c)
|
|
||||||
super
|
|
||||||
c.header = false
|
|
||||||
c.model = "ActsAsLoggable::Log"
|
|
||||||
c.force_fit = true
|
|
||||||
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,
|
|
||||||
]
|
|
||||||
c.prohibit_update = true
|
|
||||||
c.prohibit_create = true
|
|
||||||
c.prohibit_delete = true
|
|
||||||
end
|
|
||||||
|
|
||||||
def default_bbar
|
|
||||||
[ :search ]
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
class Customers < Netzke::Basepack::Grid
|
class Customers < Netzke::Basepack::Grid
|
||||||
def configure(c)
|
def configure(c)
|
||||||
c.model = "Customer"
|
c.model = "Customer"
|
||||||
c.force_fit = true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
#override with nil to remove actions
|
#override with nil to remove actions
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
this.callParent();
|
this.callParent();
|
||||||
this.getView().on('itemclick', function(view, record){
|
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!
|
// 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: 'Customer'});
|
this.selectCustomer({customer_id: record.get('id'), customer_type: 'Customer'});
|
||||||
}, this);
|
}, this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ class Logs < Netzke::Basepack::Grid
|
|||||||
super
|
super
|
||||||
c.header = false
|
c.header = false
|
||||||
c.model = "ActsAsLoggable::Log"
|
c.model = "ActsAsLoggable::Log"
|
||||||
c.force_fit = true
|
|
||||||
c.columns = [
|
c.columns = [
|
||||||
:loggable_id,
|
:loggable_id,
|
||||||
:loggable_type,
|
:loggable_type,
|
||||||
@@ -23,25 +22,4 @@ class Logs < Netzke::Basepack::Grid
|
|||||||
{ :name => :hours, :getter => lambda { |rec| (rec.end_date - rec.start_date)/3600 }, :sorting_scope => :sort_by_duration}
|
{ :name => :hours, :getter => lambda { |rec| (rec.end_date - rec.start_date)/3600 }, :sorting_scope => :sort_by_duration}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
def default_fields_for_forms
|
|
||||||
[
|
|
||||||
:loggable_id,
|
|
||||||
:loggable_type,
|
|
||||||
:logger_id,
|
|
||||||
:logger_type,
|
|
||||||
:context,
|
|
||||||
:start_date,
|
|
||||||
:end_date,
|
|
||||||
:description,
|
|
||||||
:log_action_id,
|
|
||||||
:log_action_type,
|
|
||||||
:created_at,
|
|
||||||
:updated_at
|
|
||||||
].map{ |x| { :name => x, :field_label => x.to_s.humanize} }
|
|
||||||
end
|
|
||||||
|
|
||||||
def default_bbar
|
|
||||||
[ :apply, :add_in_form, :search ]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ class Tasks < Netzke::Basepack::Grid
|
|||||||
def configure(c)
|
def configure(c)
|
||||||
super
|
super
|
||||||
|
|
||||||
#disable by default, will be enabled once bike is clicked
|
|
||||||
c.disabled = true
|
|
||||||
task_list_id = nil
|
task_list_id = nil
|
||||||
if session[:selected_bike_id]
|
if session[:selected_bike_id]
|
||||||
task_list_id = Bike.find_by_id(session[:selected_bike_id]).task_list.id
|
task_list_id = Bike.find_by_id(session[:selected_bike_id]).task_list.id
|
||||||
@@ -11,7 +9,6 @@ class Tasks < Netzke::Basepack::Grid
|
|||||||
|
|
||||||
c.header = false
|
c.header = false
|
||||||
c.model = "Task"
|
c.model = "Task"
|
||||||
c.force_fit = true
|
|
||||||
c.scope = lambda{ |rel|
|
c.scope = lambda{ |rel|
|
||||||
if session[:selected_bike_id]
|
if session[:selected_bike_id]
|
||||||
rel.where(:task_list_id => Bike.find_by_id(session[:selected_bike_id]).task_list.id)
|
rel.where(:task_list_id => Bike.find_by_id(session[:selected_bike_id]).task_list.id)
|
||||||
@@ -24,9 +21,9 @@ class Tasks < Netzke::Basepack::Grid
|
|||||||
:task_list_id => task_list_id
|
:task_list_id => task_list_id
|
||||||
}
|
}
|
||||||
c.columns = [
|
c.columns = [
|
||||||
:done,
|
|
||||||
:task,
|
:task,
|
||||||
:notes
|
:notes,
|
||||||
|
:done
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -34,9 +31,9 @@ class Tasks < Netzke::Basepack::Grid
|
|||||||
fields = []
|
fields = []
|
||||||
fields << { :no_binding => true, :xtype => 'displayfield', :fieldLabel => "No Bike Selected", :value => "Select a Bike First!"}
|
fields << { :no_binding => true, :xtype => 'displayfield', :fieldLabel => "No Bike Selected", :value => "Select a Bike First!"}
|
||||||
fields.concat( [
|
fields.concat( [
|
||||||
:done,
|
|
||||||
:task,
|
:task,
|
||||||
:notes
|
:notes,
|
||||||
|
:done
|
||||||
])
|
])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ class TransactionLogs < Netzke::Basepack::Grid
|
|||||||
|
|
||||||
c.model = "ActsAsLoggable::Log"
|
c.model = "ActsAsLoggable::Log"
|
||||||
c.title = "Transaction Payments"
|
c.title = "Transaction Payments"
|
||||||
c.force_fit = true
|
|
||||||
c.data_store = {auto_load: false}
|
c.data_store = {auto_load: false}
|
||||||
c.scope = lambda { |rel| rel.where(:loggable_type => 'Transaction',:loggable_id => session[:selected_transaction_id]);}
|
c.scope = lambda { |rel| rel.where(:loggable_type => 'Transaction',:loggable_id => session[:selected_transaction_id]);}
|
||||||
c.strong_default_attrs = {
|
c.strong_default_attrs = {
|
||||||
@@ -21,7 +20,7 @@ class TransactionLogs < Netzke::Basepack::Grid
|
|||||||
c.columns = [
|
c.columns = [
|
||||||
{ :name => :start_date, :format => "g:ia - D, M j - Y", :width => 165, :default_value => Time.now.to_formatted_s(:db), :text => 'Date' },
|
{ :name => :start_date, :format => "g:ia - D, M j - Y", :width => 165, :default_value => Time.now.to_formatted_s(:db), :text => 'Date' },
|
||||||
{ :name => :description, :text => "Amount"} ,
|
{ :name => :description, :text => "Amount"} ,
|
||||||
{ :name => :transaction_action__action, :text => 'Method', :default_value => ::ActsAsLoggable::TransactionAction.first.id},
|
{ :name => :transaction_action__action, :text => 'Method'},
|
||||||
{ :name => :logged_by, :getter => lambda{ |rec|
|
{ :name => :logged_by, :getter => lambda{ |rec|
|
||||||
user = User.find_by_id(rec.logger_id)
|
user = User.find_by_id(rec.logger_id)
|
||||||
user.nil? ? "" : "#{user.first_name} #{user.last_name}"
|
user.nil? ? "" : "#{user.first_name} #{user.last_name}"
|
||||||
@@ -30,27 +29,28 @@ class TransactionLogs < Netzke::Basepack::Grid
|
|||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
@transaction_logs = ::ActsAsLoggable::Log.where(:loggable_type => "Transaction").all
|
c.prohibit_update = true if cannot? :update, ::ActsAsLoggable::Log
|
||||||
c.prohibit_update = true if cannot? :update, @transaction_logs
|
c.prohibit_create = true if cannot? :create, ::ActsAsLoggable::Log
|
||||||
c.prohibit_create = true if cannot? :create, @transaction_logs
|
c.prohibit_delete = true if cannot? :delete, ::ActsAsLoggable::Log
|
||||||
c.prohibit_delete = true if cannot? :delete, @transaction_logs
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def default_fields_for_forms
|
def default_fields_for_forms
|
||||||
customer = "No Customer Selected"
|
customer = nil
|
||||||
item = "No Item Selected"
|
item = nil
|
||||||
|
if session[:selected_transaction_id]
|
||||||
trans = Transaction.find_by_id(session[:selected_transaction_id])
|
trans = Transaction.find_by_id(session[:selected_transaction_id])
|
||||||
if trans
|
|
||||||
customer = trans.customer
|
customer = trans.customer
|
||||||
item = trans.item
|
item = trans.item
|
||||||
end
|
end
|
||||||
|
customer = "No Customer Selected" if customer.nil?
|
||||||
|
item = "No Item Selected" if item.nil?
|
||||||
[
|
[
|
||||||
{ :no_binding => true, :xtype => 'displayfield', :fieldLabel => "Payment from:", :value => "#{customer.to_s}"},
|
{ :no_binding => true, :xtype => 'displayfield', :fieldLabel => "Payment from:", :value => "#{customer.to_s}"},
|
||||||
{ :no_binding => true, :xtype => 'displayfield', :fieldLabel => "Payment for:", :value => "#{item.to_s}"},
|
{ :no_binding => true, :xtype => 'displayfield', :fieldLabel => "Payment for:", :value => "#{item.to_s}"},
|
||||||
{ :name => :description, :xtype => 'numberfield', :field_label => 'Amount'},
|
{ :name => :description, :xtype => 'numberfield', :field_label => 'Amount'},
|
||||||
#had to hack acts_as_loggable/log.rb to get this to work
|
#had to hack acts_as_loggable/log.rb to get this to work
|
||||||
{ :name => :transaction_action__action, :field_label => 'Payment Method', :min_chars => 1}
|
{ :name => :transaction_action__action, :field_label => 'Payment Method'}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -58,8 +58,8 @@ class TransactionLogs < Netzke::Basepack::Grid
|
|||||||
#override with nil to remove actions
|
#override with nil to remove actions
|
||||||
def default_bbar
|
def default_bbar
|
||||||
bbar = [ :search ]
|
bbar = [ :search ]
|
||||||
bbar.concat [ :apply ] if can? :update, @transaction_logs
|
bbar.concat [ :apply ] if can? :update, ::ActsAsLoggable::Log
|
||||||
bbar.concat [:add_in_form ] if can? :create, @transaction_logs
|
bbar.concat [:add_in_form ] if can? :create, ::ActsAsLoggable::Log
|
||||||
bbar
|
bbar
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ class Transactions < Netzke::Basepack::Grid
|
|||||||
def configure(c)
|
def configure(c)
|
||||||
super
|
super
|
||||||
c.model = "Transaction"
|
c.model = "Transaction"
|
||||||
c.force_fit = true
|
|
||||||
c.strong_default_attrs = {
|
c.strong_default_attrs = {
|
||||||
:vendor_id => controller.current_user.id,
|
:vendor_id => controller.current_user.id,
|
||||||
:customer_id => session[:selected_customer_id],
|
:customer_id => session[:selected_customer_id],
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ class TransactionsBorder < Netzke::Base
|
|||||||
component :transactions
|
component :transactions
|
||||||
component :transaction_logs
|
component :transaction_logs
|
||||||
#users and customers components are required for the transactions form
|
#users and customers components are required for the transactions form
|
||||||
component :users_and_customers_lower_tabs
|
component :users_and_customers_accordian
|
||||||
|
|
||||||
def configure(c)
|
def configure(c)
|
||||||
super
|
super
|
||||||
@@ -13,7 +13,7 @@ class TransactionsBorder < Netzke::Base
|
|||||||
c.items = [
|
c.items = [
|
||||||
{ netzke_component: :transactions, region: :center, height: 300, split: true },
|
{ netzke_component: :transactions, region: :center, height: 300, split: true },
|
||||||
{ netzke_component: :transaction_logs, region: :east, width: 300, split: true },
|
{ netzke_component: :transaction_logs, region: :east, width: 300, split: true },
|
||||||
{ netzke_component: :users_and_customers_lower_tabs, region: :south, height: 300, split: true }
|
{ netzke_component: :users_and_customers_accordian, region: :south, height: 300, split: true }
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -5,19 +5,10 @@
|
|||||||
|
|
||||||
// setting the 'rowclick' event
|
// setting the 'rowclick' event
|
||||||
var view = this.getComponent('transactions').getView();
|
var view = this.getComponent('transactions').getView();
|
||||||
|
|
||||||
if( this.queryById('transaction_logs')){
|
|
||||||
this.queryById('transaction_logs').disable();
|
|
||||||
}
|
|
||||||
|
|
||||||
view.on('itemclick', function(view, record){
|
view.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!
|
// The beauty of using Ext.Direct: calling 3 endpoints in a row, which results in a single call to the server!
|
||||||
this.selectTransaction({transaction_id: record.get('id')});
|
this.selectTransaction({transaction_id: record.get('id')});
|
||||||
this.getComponent('transaction_logs').getStore().load();
|
this.getComponent('transaction_logs').getStore().load();
|
||||||
|
|
||||||
if( this.queryById('transaction_logs')){
|
|
||||||
this.queryById('transaction_logs').enable();
|
|
||||||
}
|
|
||||||
}, this);
|
}, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
class UserAndProfilesLowerTabs < Netzke::Basepack::TabPanel
|
|
||||||
component :user_profiles
|
|
||||||
component :user_logs
|
|
||||||
component :user_stats
|
|
||||||
|
|
||||||
def configure(c)
|
|
||||||
c.prevent_header = true
|
|
||||||
c.items = [ :user_logs,
|
|
||||||
{ netzke_component: :user_profiles, title: "User Profiles" },
|
|
||||||
{ netzke_component: :user_stats, title: "User Stats" }]
|
|
||||||
super
|
|
||||||
end
|
|
||||||
end
|
|
||||||
+10
-15
@@ -14,16 +14,10 @@ class UserLogs < Netzke::Basepack::Grid
|
|||||||
:copy_action_id => 4
|
:copy_action_id => 4
|
||||||
}
|
}
|
||||||
|
|
||||||
#this seems inefficient
|
if can? :manage, ::ActsAsLoggable::Log
|
||||||
if can? :manage, ::ActsAsLoggable::Log.where(:loggable_type => "User").all
|
|
||||||
#admins and staff
|
#admins and staff
|
||||||
|
user_log_scope = lambda { |rel| rel.where(:loggable_type => 'User',:loggable_id => session[:selected_user_id]);}
|
||||||
#if selected user nil, then the admin is viewing their own profile
|
user_log_strong_default_attrs.merge!( { :loggable_id => session[:selected_user_id] } )
|
||||||
selected_user = User.find_by_id(session[:selected_user_id])
|
|
||||||
selected_user = controller.current_user if selected_user.nil?
|
|
||||||
|
|
||||||
user_log_scope = lambda { |rel| rel.where(:loggable_type => 'User',:loggable_id => selected_user.id );}
|
|
||||||
user_log_strong_default_attrs.merge!( { :loggable_id => selected_user.id } )
|
|
||||||
user_log_data_store = {auto_load: true }
|
user_log_data_store = {auto_load: true }
|
||||||
else
|
else
|
||||||
#just users
|
#just users
|
||||||
@@ -33,18 +27,19 @@ class UserLogs < Netzke::Basepack::Grid
|
|||||||
end
|
end
|
||||||
|
|
||||||
c.model = "ActsAsLoggable::Log"
|
c.model = "ActsAsLoggable::Log"
|
||||||
c.title = "User Timesheet"
|
c.title = "User History"
|
||||||
c.force_fit = true
|
|
||||||
c.data_store = user_log_data_store
|
c.data_store = user_log_data_store
|
||||||
c.scope = user_log_scope
|
c.scope = user_log_scope
|
||||||
c.strong_default_attrs = user_log_strong_default_attrs
|
c.strong_default_attrs = user_log_strong_default_attrs
|
||||||
|
|
||||||
c.columns = [
|
c.columns = [
|
||||||
{ :name => :start_date, :format => "g:ia - D, M j - Y", :width => 165, :default_value => Time.now.to_formatted_s(:db) },
|
{ :name => :start_date, :format => "g:ia - D, M j - Y", :width => 165, :default_value => Time.now.to_formatted_s(:db) },
|
||||||
{ :name => :end_date, :format => "g:ia - D, M j - Y", :default_value => Time.now.to_formatted_s(:db) },
|
{ :name => :end_date, :hidden => true, :default_value => Time.now.to_formatted_s(:db) },
|
||||||
{ :name => :hours, :getter => lambda { |rec| (rec.end_date - rec.start_date)/3600 }, :sorting_scope => :sort_by_duration},
|
{ :name => :hours, :getter => lambda { |rec| (rec.end_date - rec.start_date)/3600 }, :sorting_scope => :sort_by_duration},
|
||||||
:description,
|
:description,
|
||||||
{ :id => :user_action__action, :name => :user_action__action, :text => 'Action', :default_value => ::ActsAsLoggable::UserAction.all.first.id },
|
{ :name => :user_action__action, :text => 'Action' },
|
||||||
|
:created_at,
|
||||||
|
:updated_at,
|
||||||
{ :name => :logged_by, :getter => lambda{ |rec|
|
{ :name => :logged_by, :getter => lambda{ |rec|
|
||||||
user = User.find_by_id(rec.logger_id)
|
user = User.find_by_id(rec.logger_id)
|
||||||
user.nil? ? "" : "#{user.first_name} #{user.last_name}"
|
user.nil? ? "" : "#{user.first_name} #{user.last_name}"
|
||||||
@@ -58,13 +53,13 @@ class UserLogs < Netzke::Basepack::Grid
|
|||||||
bike_store = Bike.all.map { |b| [b.id, b.shop_id] }
|
bike_store = Bike.all.map { |b| [b.id, b.shop_id] }
|
||||||
current_user ||= User.find_by_id(session[:selected_user_id]) || controller.current_user
|
current_user ||= User.find_by_id(session[:selected_user_id]) || controller.current_user
|
||||||
bike_id = current_user.bike.nil? ? nil : current_user.bike.id
|
bike_id = current_user.bike.nil? ? nil : current_user.bike.id
|
||||||
|
action_id = current_user.user_role.id
|
||||||
[
|
[
|
||||||
{ :no_binding => true, :xtype => 'displayfield', :fieldLabel => "Log for:", :value => "#{current_user.to_s}"},
|
|
||||||
{ :name => :start_date},
|
{ :name => :start_date},
|
||||||
{ :name => :end_date},
|
{ :name => :end_date},
|
||||||
{ :name => :description},
|
{ :name => :description},
|
||||||
#had to hack acts_as_loggable/log.rb to get this to work
|
#had to hack acts_as_loggable/log.rb to get this to work
|
||||||
{ :name => :user_action__action, :field_label => 'Action', :min_chars => 1},
|
{ :name => :user_action__action, :field_label => 'Action', :value => action_id},
|
||||||
{ :name => :for_bike, :checkboxName => :copy_log, :inputValue => true, :title => "Copy description to a Bike's History?", :xtype => 'fieldset', :checkboxToggle => true, :collapsed => true, :items => [
|
{ :name => :for_bike, :checkboxName => :copy_log, :inputValue => true, :title => "Copy description to a Bike's History?", :xtype => 'fieldset', :checkboxToggle => true, :collapsed => true, :items => [
|
||||||
{:xtype => 'combo', :no_binding => true, :name => :copy_id, :title => 'Bike', :fieldLabel => 'Bike', :store => bike_store, :value => bike_id}
|
{:xtype => 'combo', :no_binding => true, :name => :copy_id, :title => 'Bike', :fieldLabel => 'Bike', :store => bike_store, :value => bike_id}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
initComponent: function(){
|
|
||||||
// calling superclass's initComponent
|
|
||||||
this.callParent();
|
|
||||||
|
|
||||||
//due to Netzke bug, :min_chars attribute doesn't work
|
|
||||||
var min_char_columns = [
|
|
||||||
"user_action__purpose"]
|
|
||||||
Ext.each(min_char_columns, function(column, index) {
|
|
||||||
Ext.ComponentManager.get(column).editor.minChars = 1;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -19,7 +19,6 @@ class UserProfiles < Netzke::Basepack::Grid
|
|||||||
|
|
||||||
c.model = "UserProfile"
|
c.model = "UserProfile"
|
||||||
c.title = "Profile"
|
c.title = "Profile"
|
||||||
c.force_fit = true
|
|
||||||
c.data_store = user_profiles_data_store
|
c.data_store = user_profiles_data_store
|
||||||
c.scope = user_profiles_scope
|
c.scope = user_profiles_scope
|
||||||
c.strong_default_attrs = user_profile_strong_default_attrs
|
c.strong_default_attrs = user_profile_strong_default_attrs
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
class UserRoleJoins < Netzke::Basepack::Grid
|
|
||||||
def configure(c)
|
|
||||||
super
|
|
||||||
c.model = "UserRoleJoin"
|
|
||||||
c.force_fit = true
|
|
||||||
c.header = false
|
|
||||||
c.title = "User Roles"
|
|
||||||
c.data_store.sorters = [{ :property => :user__username, :direction => :ASC}]
|
|
||||||
c.columns = [
|
|
||||||
{ :name => :user__username, :text => "Username", :read_only => true},
|
|
||||||
{ :name => :name, :getter => lambda{ |rec|
|
|
||||||
user = User.find_by_id(rec.user_id)
|
|
||||||
user.nil? ? "" : "#{user.first_name} #{user.last_name}"
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ :name => :role__role, :text => "Role", :default_value => Role.exists? ? Role.first.id : nil},
|
|
||||||
:created_at,
|
|
||||||
:updated_at,
|
|
||||||
:ends ]
|
|
||||||
end
|
|
||||||
|
|
||||||
def default_fields_for_forms
|
|
||||||
[
|
|
||||||
{ :name => :user__full_name, :field_label => 'Name'},
|
|
||||||
{ :name => :role__role, :field_label => 'Role' },
|
|
||||||
{ :name => :ends }
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
#override with nil to remove actions
|
|
||||||
def default_bbar
|
|
||||||
[ :apply, :add_in_form, :search ]
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
class UserRoles < Netzke::Basepack::Grid
|
||||||
|
|
||||||
|
def configure(c)
|
||||||
|
super
|
||||||
|
c.model = "UserRole"
|
||||||
|
c.title = "User Roles"
|
||||||
|
c.columns = [ :role, :created_at, :updated_at, :ends ]
|
||||||
|
end
|
||||||
|
|
||||||
|
#override with nil to remove actions
|
||||||
|
def default_bbar
|
||||||
|
[ :apply, :add_in_form, :search ]
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -2,29 +2,14 @@ class UserStats < Netzke::Base
|
|||||||
|
|
||||||
def body_content(user)
|
def body_content(user)
|
||||||
bike = user.bike
|
bike = user.bike
|
||||||
completed = user.completed_build_bikes
|
%Q(
|
||||||
#TODO I think it's time to switch to a template
|
<div id="user_stats_page">
|
||||||
body = ""
|
|
||||||
body += %Q(<div id="user_stats_page">)
|
|
||||||
body += %Q(
|
|
||||||
<p>Username: #{user.username}</p>
|
|
||||||
<p>Total Credits Earned: #{user.total_earned_credits}</p>
|
|
||||||
<p>Credits Available: #{user.total_credits}</p>
|
|
||||||
<p>Credits Spent: #{user.total_credits_spent}</p>
|
|
||||||
<p>Total Hours Worked: #{user.total_hours}</p>
|
<p>Total Hours Worked: #{user.total_hours}</p>
|
||||||
<p>Hours worked in #{Time.now.strftime('%B')}: #{user.current_month_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>
|
<p>Current bike Shop ID: #{bike.shop_id if bike}</p>
|
||||||
<p>Current bike S/N: #{bike.serial_number if bike}</p>
|
<p>Current bike S/N: #{bike.serial_number if bike}</p>
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
unless completed.empty?
|
|
||||||
body += %Q(<p>Previously built bikes (#{completed.count}):</p>)
|
|
||||||
body += %Q(<ul>)
|
|
||||||
completed.each do |b|
|
|
||||||
body += %Q(<li>#{b.shop_id}</li>)
|
|
||||||
end
|
|
||||||
body += %Q(</ul>)
|
|
||||||
end
|
|
||||||
body += %Q(</div>)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
js_configure do |c|
|
js_configure do |c|
|
||||||
@@ -40,7 +25,7 @@ class UserStats < Netzke::Base
|
|||||||
|
|
||||||
private
|
private
|
||||||
def user
|
def user
|
||||||
User.find_by_id(session[:selected_user_id]) || controller.current_user
|
controller.current_user
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ class UserTransactions < Netzke::Basepack::Grid
|
|||||||
|
|
||||||
c.model = "Transaction"
|
c.model = "Transaction"
|
||||||
c.title = "Transactions"
|
c.title = "Transactions"
|
||||||
c.force_fit = true
|
|
||||||
c.scope = lambda { |rel| rel.where(:customer_id => controller.current_user.id, :customer_type => 'User');}
|
c.scope = lambda { |rel| rel.where(:customer_id => controller.current_user.id, :customer_type => 'User');}
|
||||||
c.data_store = { auto_load: true }
|
c.data_store = { auto_load: true }
|
||||||
c.columns = [
|
c.columns = [
|
||||||
|
|||||||
@@ -5,18 +5,10 @@
|
|||||||
|
|
||||||
// setting the 'rowclick' event
|
// setting the 'rowclick' event
|
||||||
var view = this.getComponent('user_transactions').getView();
|
var view = this.getComponent('user_transactions').getView();
|
||||||
|
|
||||||
if( this.queryById('transaction_logs')){
|
|
||||||
this.queryById('transaction_logs').disable();
|
|
||||||
}
|
|
||||||
view.on('itemclick', function(view, record){
|
view.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!
|
// The beauty of using Ext.Direct: calling 3 endpoints in a row, which results in a single call to the server!
|
||||||
this.selectTransaction({transaction_id: record.get('id')});
|
this.selectTransaction({transaction_id: record.get('id')});
|
||||||
this.getComponent('transaction_logs').getStore().load();
|
this.getComponent('transaction_logs').getStore().load();
|
||||||
|
|
||||||
if( this.queryById('transaction_logs')){
|
|
||||||
this.queryById('transaction_logs').enable();
|
|
||||||
}
|
|
||||||
}, this);
|
}, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-14
@@ -1,28 +1,17 @@
|
|||||||
class Users < Netzke::Basepack::Grid
|
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)
|
def configure(c)
|
||||||
super
|
super
|
||||||
c.header = false
|
c.header = false
|
||||||
c.model = "User"
|
c.model = "User"
|
||||||
c.force_fit = true
|
|
||||||
|
|
||||||
c.columns = [
|
c.columns = [
|
||||||
{ :name => :username, :read_only => true },
|
|
||||||
:first_name,
|
:first_name,
|
||||||
:last_name,
|
:last_name,
|
||||||
|
:nickname,
|
||||||
:email,
|
:email,
|
||||||
{ :text => "Bike - Shop ID", :id => :bike__shop_id, :name => :bike__shop_id, :default_value => Bike.exists? ? Bike.first.id : nil }
|
:user_role__role,
|
||||||
|
:bike__shop_id
|
||||||
]
|
]
|
||||||
|
|
||||||
c.columns << :reset if can? :manage, User
|
|
||||||
end
|
end
|
||||||
|
|
||||||
#override with nil to remove actions
|
#override with nil to remove actions
|
||||||
|
|||||||
@@ -2,41 +2,10 @@
|
|||||||
initComponent: function(){
|
initComponent: function(){
|
||||||
// calling superclass's initComponent
|
// calling superclass's initComponent
|
||||||
this.callParent();
|
this.callParent();
|
||||||
|
|
||||||
//due to Netzke bug, :min_chars attribute doesn't work
|
|
||||||
var min_char_columns = ["bike__shop_id"]
|
|
||||||
Ext.each(min_char_columns, function(column, index) {
|
|
||||||
Ext.ComponentManager.get(column).editor.minChars = 1;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.getView().on('itemclick', function(view, record){
|
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!
|
// 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.selectCustomer({customer_id: record.get('id'), customer_type: 'User'});
|
||||||
}, this);
|
}, 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"]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,10 +1,10 @@
|
|||||||
class UsersAndCustomersLowerTabs < Netzke::Basepack::TabPanel
|
class UsersAndCustomersAccordian < Netzke::Basepack::Accordion
|
||||||
component :customers
|
component :customers
|
||||||
component :users
|
component :users
|
||||||
|
|
||||||
def configure(c)
|
def configure(c)
|
||||||
c.prevent_header = true
|
c.prevent_header = true
|
||||||
c.items = [ :users, :customers ]
|
c.items = [ :customers, :users ]
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -2,14 +2,16 @@ class UsersAndProfilesBorder < Netzke::Base
|
|||||||
# Remember regions collapse state and size
|
# Remember regions collapse state and size
|
||||||
include Netzke::Basepack::ItemPersistence
|
include Netzke::Basepack::ItemPersistence
|
||||||
component :users
|
component :users
|
||||||
component :user_and_profiles_lower_tabs
|
component :user_profiles
|
||||||
|
component :user_logs
|
||||||
|
|
||||||
def configure(c)
|
def configure(c)
|
||||||
super
|
super
|
||||||
c.header = false
|
c.header = false
|
||||||
c.items = [
|
c.items = [
|
||||||
{ netzke_component: :users, header: "Users", region: :center, width: 350, split: true },
|
{ netzke_component: :users, header: "Users", region: :center, width: 300, split: true },
|
||||||
{ netzke_component: :user_and_profiles_lower_tabs, region: :south, height: 300, split: true}
|
{ netzke_component: :user_profiles, region: :south, height: 150, split: true},
|
||||||
|
{ netzke_component: :user_logs, region: :east, split: true}
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -2,48 +2,18 @@
|
|||||||
initComponent: function(){
|
initComponent: function(){
|
||||||
// calling superclass's initComponent
|
// calling superclass's initComponent
|
||||||
this.callParent();
|
this.callParent();
|
||||||
var stats = this.queryById('user_stats');
|
var stats = this.getComponent('user_stats');
|
||||||
if (stats != undefined){
|
if (stats != undefined){
|
||||||
stats.updateStats();
|
stats.updateStats();
|
||||||
}
|
}
|
||||||
|
|
||||||
if( this.queryById('user_profiles')){
|
|
||||||
this.queryById('user_profiles').disable();
|
|
||||||
}
|
|
||||||
|
|
||||||
if( this.queryById('user_logs')){
|
|
||||||
this.queryById('user_logs').disable();
|
|
||||||
//update user stats
|
|
||||||
var store = this.queryById('user_logs').getStore()
|
|
||||||
store.on('load', function (store, records, operation, success){
|
|
||||||
if( this.queryById('user_stats') ){
|
|
||||||
this.queryById('user_stats').updateStats();
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
}
|
|
||||||
if( this.queryById('user_stats') ){
|
|
||||||
this.queryById('user_stats').disable();
|
|
||||||
}
|
|
||||||
|
|
||||||
// setting the 'rowclick' event
|
// setting the 'rowclick' event
|
||||||
var view = this.getComponent('users').getView();
|
var view = this.getComponent('users').getView();
|
||||||
view.on('itemclick', function(view, record){
|
view.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!
|
// The beauty of using Ext.Direct: calling 3 endpoints in a row, which results in a single call to the server!
|
||||||
this.selectUser({user_id: record.get('id')});
|
this.selectUser({user_id: record.get('id')});
|
||||||
|
this.getComponent('user_profiles').getStore().load();
|
||||||
if( this.queryById('user_profiles')){
|
this.getComponent('user_logs').getStore().load();
|
||||||
this.queryById('user_profiles').getStore().load();
|
|
||||||
this.queryById('user_profiles').enable();
|
|
||||||
}
|
|
||||||
if( this.queryById('user_logs')){
|
|
||||||
this.queryById('user_logs').getStore().load();
|
|
||||||
this.queryById('user_logs').enable();
|
|
||||||
}
|
|
||||||
if( this.queryById('user_stats') ){
|
|
||||||
this.queryById('user_stats').updateStats();
|
|
||||||
this.queryById('user_stats').enable();
|
|
||||||
}
|
|
||||||
}, this);
|
}, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
class Api::V1::BaseController < ActionController::Base
|
|
||||||
respond_to :json
|
|
||||||
|
|
||||||
before_filter :authenticate_user
|
|
||||||
|
|
||||||
private
|
|
||||||
def authenticate_user
|
|
||||||
if params[:username]
|
|
||||||
user = User.find_for_database_authentication( :email => params[:username] )
|
|
||||||
@current_user = user if user && user.valid_password?( params[:password] )
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
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
|
|
||||||
@current_user.checkin
|
|
||||||
render :nothing => true, :status => 204 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
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -3,9 +3,7 @@ class Ability
|
|||||||
|
|
||||||
def initialize(current_user)
|
def initialize(current_user)
|
||||||
@current_user = current_user
|
@current_user = current_user
|
||||||
current_user.roles.each do |role|
|
self.send(current_user.role.to_sym)
|
||||||
self.send(role.role.to_sym)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def admin
|
def admin
|
||||||
@@ -24,7 +22,7 @@ class Ability
|
|||||||
def user
|
def user
|
||||||
can :read, :all
|
can :read, :all
|
||||||
can :manage, Bike, :id => @current_user.bike_id unless @current_user.bike.nil?
|
can :manage, Bike, :id => @current_user.bike_id unless @current_user.bike.nil?
|
||||||
can :manage, ::ActsAsLoggable::Log, :loggable_type => "Bike", :loggable_id => @current_user.bike_id
|
can :manage, ::ActsAsLoggable::Log, { :loggable_type => "Bike", :loggable_id => @current_user.bike_id }
|
||||||
can :manage, ::ActsAsLoggable::Log, :loggable_type => "User", :loggable_id => @current_user.id
|
can :manage, ::ActsAsLoggable::Log, { :loggable_type => "User", :loggable_id => @current_user.id }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
+18
-16
@@ -1,37 +1,43 @@
|
|||||||
class Bike < ActiveRecord::Base
|
class Bike < ActiveRecord::Base
|
||||||
acts_as_loggable
|
acts_as_loggable
|
||||||
attr_accessible :shop_id, :serial_number, :bike_brand_id, :model, :color, :bike_style_id, :seat_tube_height,
|
attr_accessible :shop_id, :serial_number, :bike_brand_id, :bike_model_id, :color, :bike_style_id, :seat_tube_height,
|
||||||
:top_tube_length, :bike_wheel_size_id, :value, :bike_condition_id, :bike_purpose_id
|
:top_tube_length, :wheel_size, :value, :bike_condition_id, :bike_status_id
|
||||||
|
|
||||||
has_many :transactions
|
has_many :transactions
|
||||||
|
|
||||||
has_one :owner, :class_name => 'User'
|
has_one :owner, :class_name => 'User'
|
||||||
has_one :task_list, :as => :item, :dependent => :destroy
|
has_one :task_list, :as => :item, :dependent => :destroy
|
||||||
belongs_to :bike_brand
|
belongs_to :bike_brand
|
||||||
|
belongs_to :bike_model
|
||||||
belongs_to :bike_style
|
belongs_to :bike_style
|
||||||
belongs_to :bike_condition
|
belongs_to :bike_condition
|
||||||
belongs_to :bike_purpose
|
belongs_to :bike_status
|
||||||
belongs_to :bike_wheel_size
|
|
||||||
|
|
||||||
validates :shop_id, :presence => true, :uniqueness => true, :numericality => { :only_integer => true }
|
validates :shop_id, :presence => true, :uniqueness => true, :length => { :minimum => 3 }
|
||||||
validates :serial_number, :length => { :minimum => 3 }
|
validates :serial_number, :uniqueness => true, :length => { :minimum => 3 }
|
||||||
validates :model, :length => { :maximum => 50 }
|
|
||||||
validates :bike_brand_id, :presence => true
|
validates :bike_brand_id, :presence => true
|
||||||
|
validates :bike_model_id, :presence => true
|
||||||
validates :color, :presence => true
|
validates :color, :presence => true
|
||||||
validates :bike_style_id, :presence => true
|
validates :bike_style_id, :presence => true
|
||||||
validates :seat_tube_height, :presence => true
|
validates :seat_tube_height, :presence => true
|
||||||
validates :bike_wheel_size_id, :presence => true
|
validates :top_tube_length, :presence => true
|
||||||
|
validates :wheel_size, :presence => true
|
||||||
|
#validates :value, :presence => true
|
||||||
validates :bike_condition_id, :presence => true
|
validates :bike_condition_id, :presence => true
|
||||||
validates :bike_purpose_id, :presence => true
|
validates :bike_status_id, :presence => true
|
||||||
|
|
||||||
self.per_page = 15
|
self.per_page = 15
|
||||||
|
|
||||||
after_create :create_task_list
|
after_save :create_task_list
|
||||||
|
|
||||||
def brand
|
def brand
|
||||||
self.bike_brand
|
self.bike_brand
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def model
|
||||||
|
self.bike_model
|
||||||
|
end
|
||||||
|
|
||||||
def style
|
def style
|
||||||
self.bike_style
|
self.bike_style
|
||||||
end
|
end
|
||||||
@@ -40,12 +46,8 @@ class Bike < ActiveRecord::Base
|
|||||||
self.bike_condition
|
self.bike_condition
|
||||||
end
|
end
|
||||||
|
|
||||||
def purpose
|
def status
|
||||||
self.bike_purpose
|
self.bike_status
|
||||||
end
|
|
||||||
|
|
||||||
def wheel_size
|
|
||||||
self.bike_wheel_size
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
class BikeModel < ActiveRecord::Base
|
class BikeModel < ActiveRecord::Base
|
||||||
attr_accessible :model, :bike_brand_id
|
attr_accessible :model, :bike_brand_id
|
||||||
|
|
||||||
|
has_many :bikes
|
||||||
belongs_to :bike_brand
|
belongs_to :bike_brand
|
||||||
|
|
||||||
default_scope order('model ASC')
|
default_scope order('model ASC')
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
class BikePurpose < ActiveRecord::Base
|
|
||||||
attr_accessible :purpose
|
|
||||||
|
|
||||||
belongs_to :bike
|
|
||||||
|
|
||||||
def to_s
|
|
||||||
self.purpose
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
class BikeStatus < ActiveRecord::Base
|
||||||
|
attr_accessible :status
|
||||||
|
|
||||||
|
belongs_to :bike
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
self.status
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
class BikeWheelSize < ActiveRecord::Base
|
|
||||||
belongs_to :bike
|
|
||||||
|
|
||||||
def display_string
|
|
||||||
result = []
|
|
||||||
result << "#{twmm}-#{rdmm}" unless twmm.blank? and rdmm.blank?
|
|
||||||
result << "#{rdin}x#{twin}" unless rdin.blank? and twin.blank?
|
|
||||||
result << "#{rdfr}x#{twfr}" unless rdfr.blank? and twfr.blank?
|
|
||||||
result << description unless description.blank?
|
|
||||||
result.join(" | ")
|
|
||||||
end
|
|
||||||
|
|
||||||
def to_s
|
|
||||||
"#{twmm}-#{rdmm} #{rdin}x#{twin} #{rdfr}x#{twfr} '#{description}' #{tire_common_score}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
class CreditConversion < ActiveRecord::Base
|
|
||||||
attr_accessible :conversion
|
|
||||||
end
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
class Role < ActiveRecord::Base
|
|
||||||
attr_accessible :role
|
|
||||||
|
|
||||||
has_many :user_role_joins
|
|
||||||
has_many :users, through: :user_role_joins
|
|
||||||
validates_uniqueness_of :role
|
|
||||||
|
|
||||||
|
|
||||||
def to_s
|
|
||||||
self.role
|
|
||||||
end
|
|
||||||
|
|
||||||
def ==(other)
|
|
||||||
self.role == other.role
|
|
||||||
end
|
|
||||||
end
|
|
||||||
+11
-103
@@ -7,21 +7,16 @@ class User < ActiveRecord::Base
|
|||||||
|
|
||||||
# Setup accessible (or protected) attributes for your model
|
# Setup accessible (or protected) attributes for your model
|
||||||
attr_accessible :email, :password, :password_confirmation, :remember_me,
|
attr_accessible :email, :password, :password_confirmation, :remember_me,
|
||||||
:first_name, :last_name, :bike_id,
|
:first_name, :last_name, :nickname, :user_role_id, :bike_id,
|
||||||
:user_profiles_attributes, :username
|
:user_profiles_attributes
|
||||||
|
|
||||||
has_many :transactions, as: :customer
|
has_many :transactions
|
||||||
has_many :transaction_logs, through: :transactions, source: :logs
|
|
||||||
has_many :user_profiles
|
has_many :user_profiles
|
||||||
accepts_nested_attributes_for :user_profiles, allow_destroy: false
|
accepts_nested_attributes_for :user_profiles, allow_destroy: false
|
||||||
|
|
||||||
has_many :user_role_joins, :conditions => ["ends IS NULL OR ends > ?", Time.now]
|
has_one :user_role
|
||||||
has_many :roles, through: :user_role_joins
|
|
||||||
|
|
||||||
belongs_to :bike
|
belongs_to :bike
|
||||||
|
|
||||||
default_scope order('username ASC')
|
|
||||||
|
|
||||||
validates :first_name, :presence => true
|
validates :first_name, :presence => true
|
||||||
validates :last_name, :presence => true
|
validates :last_name, :presence => true
|
||||||
|
|
||||||
@@ -29,116 +24,29 @@ class User < ActiveRecord::Base
|
|||||||
"#{first_name} #{last_name}"
|
"#{first_name} #{last_name}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def email_required?
|
|
||||||
false
|
|
||||||
end
|
|
||||||
|
|
||||||
def full_name
|
def full_name
|
||||||
to_s
|
to_s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def role
|
||||||
|
user_role.role
|
||||||
|
end
|
||||||
|
|
||||||
def role?(role)
|
def role?(role)
|
||||||
if role.kind_of?(String) or role.kind_of?(Symbol)
|
user_role.to_s == role.to_s
|
||||||
role = Role.find_by_role(role.to_s)
|
|
||||||
end
|
|
||||||
roles.include?(role)
|
|
||||||
end
|
|
||||||
|
|
||||||
### TODO methods below probably belong somewhere else
|
|
||||||
|
|
||||||
def completed_build_bikes
|
|
||||||
#default BUILDBIKE/CLASS ID is 5
|
|
||||||
purpose_id = 5
|
|
||||||
Bike.find_by_sql("
|
|
||||||
SELECT *
|
|
||||||
FROM bikes
|
|
||||||
INNER JOIN(
|
|
||||||
SELECT *
|
|
||||||
FROM transactions
|
|
||||||
WHERE customer_id = #{self.id}
|
|
||||||
) AS transactions ON bikes.id = transactions.bike_id
|
|
||||||
WHERE bike_purpose_id = #{purpose_id}")
|
|
||||||
end
|
|
||||||
|
|
||||||
def total_credits
|
|
||||||
total_earned_credits - total_credits_spent
|
|
||||||
end
|
|
||||||
|
|
||||||
def total_credits_spent
|
|
||||||
log_action = ::ActsAsLoggable::TransactionAction.find_by_action("TIME")
|
|
||||||
transaction_logs.
|
|
||||||
where( "log_action_id = ? AND log_action_type = ?",
|
|
||||||
log_action.id, log_action.class.to_s).
|
|
||||||
sum{ |r| r.description.to_i }.round(2)
|
|
||||||
end
|
|
||||||
|
|
||||||
def total_earned_credits
|
|
||||||
log_action = ::ActsAsLoggable::UserAction.find_by_action("CHECKIN")
|
|
||||||
|
|
||||||
# Find the first credit conversion which has a created_at date before the
|
|
||||||
# log's created_at date and join it to the log's row so we can calculate
|
|
||||||
# the credits earned from that log entry (each log could have a different
|
|
||||||
# conversion rate)
|
|
||||||
#
|
|
||||||
# The DISTINCT ON, and ORDER BY are important to getting the
|
|
||||||
# single conversion rate that applies to the respective log.
|
|
||||||
::ActsAsLoggable::Log.find_by_sql("
|
|
||||||
SELECT DISTINCT ON (logs.created_at) start_date, end_date,
|
|
||||||
conversion.conversion, conversion.created_at
|
|
||||||
FROM logs
|
|
||||||
INNER JOIN(
|
|
||||||
SELECT conversion, created_at
|
|
||||||
FROM credit_conversions
|
|
||||||
) AS conversion ON logs.created_at > conversion.created_at
|
|
||||||
WHERE logs.loggable_id = #{self.id}
|
|
||||||
AND logs.loggable_type = 'User'
|
|
||||||
AND (log_action_id != #{log_action.id} AND log_action_type = '#{log_action.class.to_s}')
|
|
||||||
ORDER BY logs.created_at, conversion.created_at DESC").
|
|
||||||
sum{ |l| ((l.end_date - l.start_date)/3600) * l.conversion.to_i}.round(2)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def total_hours
|
def total_hours
|
||||||
log_action = ::ActsAsLoggable::UserAction.find_by_action("CHECKIN")
|
ActsAsLoggable::Log.where( :loggable_type => self.class.to_s, :loggable_id => self.id).sum { |l| (l.end_date - l.start_date)/3600 }.round(2)
|
||||||
logs.where("log_action_id != ? AND log_action_type = ?", log_action.id, log_action.class.to_s).sum { |l| (l.end_date - l.start_date)/3600 }.round(2)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def current_month_hours
|
def current_month_hours
|
||||||
log_action = ::ActsAsLoggable::UserAction.find_by_action("CHECKIN")
|
|
||||||
#TODO need to prevent users from saving logs across months, force to create a new log if crossing month
|
#TODO need to prevent users from saving logs across months, force to create a new log if crossing month
|
||||||
current_month_range = (Time.now.beginning_of_month..Time.now.end_of_month)
|
current_month_range = (Time.now.beginning_of_month..Time.now.end_of_month)
|
||||||
logs.where("log_action_id != ? AND log_action_type = ?", log_action.id, log_action.class.to_s)
|
ActsAsLoggable::Log.where( :loggable_type => self.class.to_s, :loggable_id => self.id)
|
||||||
.where( :start_date => current_month_range)
|
.where( :start_date => current_month_range)
|
||||||
.where( :end_date => current_month_range)
|
.where( :end_date => current_month_range)
|
||||||
.sum { |l| (l.end_date - l.start_date)/3600 }
|
.sum { |l| (l.end_date - l.start_date)/3600 }
|
||||||
.round(2)
|
.round(2)
|
||||||
end
|
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
|
|
||||||
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
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
class UserProfile < ActiveRecord::Base
|
class UserProfile < ActiveRecord::Base
|
||||||
|
# Setup accessible (or protected) attributes for your model
|
||||||
attr_accessible :user_id, :addrStreet1, :addrStreet2, :addrCity,
|
attr_accessible :user_id, :addrStreet1, :addrStreet2, :addrCity,
|
||||||
:addrState, :addrZip, :phone
|
:addrState, :addrZip, :phone
|
||||||
|
|
||||||
@@ -9,7 +10,7 @@ class UserProfile < ActiveRecord::Base
|
|||||||
#validates :addrCity , :presence => true
|
#validates :addrCity , :presence => true
|
||||||
#validates :addrState , :presence => true
|
#validates :addrState , :presence => true
|
||||||
#validates :addrZip , :presence => true
|
#validates :addrZip , :presence => true
|
||||||
#validates :phone, :presence => true
|
validates :phone, :presence => true
|
||||||
|
|
||||||
def to_s
|
def to_s
|
||||||
[addrStreet1, addrStreet2, addrCity, addrState, addrZip, phone].join(" - ")
|
[addrStreet1, addrStreet2, addrCity, addrState, addrZip, phone].join(" - ")
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
class UserRole < ActiveRecord::Base
|
||||||
|
attr_accessible :role
|
||||||
|
|
||||||
|
belongs_to :user
|
||||||
|
|
||||||
|
self.per_page = 15
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
self.role
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
class UserRoleJoin < ActiveRecord::Base
|
|
||||||
self.table_name = :user_role_joins
|
|
||||||
attr_accessible :role_id, :user_id, :ends
|
|
||||||
|
|
||||||
belongs_to :user
|
|
||||||
belongs_to :role
|
|
||||||
|
|
||||||
validate :role_id, presence: true, numericality: true
|
|
||||||
validate :user_id, presence: true, numericality: true
|
|
||||||
validates_uniqueness_of :user_id, :scope => :role_id
|
|
||||||
|
|
||||||
self.per_page = 15
|
|
||||||
end
|
|
||||||
@@ -1,25 +1,24 @@
|
|||||||
%fieldset
|
%fieldset
|
||||||
.control-group
|
= f.label :addrStreet1
|
||||||
= f.label :addrStreet1, :class => "control-label"
|
%br/
|
||||||
.controls
|
= f.text_field :addrStreet1
|
||||||
= f.text_field :addrStreet1, :class => "control-label"
|
%br/
|
||||||
.control-group
|
= f.label :addrStreet2
|
||||||
= f.label :addrStreet2, :class => "control-label"
|
%br/
|
||||||
.controls
|
= f.text_field :addrStreet2
|
||||||
= f.text_field :addrStreet2, :class => "control-label"
|
%br/
|
||||||
.control-group
|
= f.label :addrCity
|
||||||
= f.label :addrCity, :class => "control-label"
|
%br/
|
||||||
.controls
|
= f.text_field :addrCity
|
||||||
= f.text_field :addrCity, :class => "control-label"
|
%br/
|
||||||
.control-group
|
= f.label :addrState
|
||||||
= f.label :addrState, :class => "control-label"
|
%br/
|
||||||
.controls
|
= f.text_field :addrState
|
||||||
= f.text_field :addrState, :class => "control-label"
|
%br/
|
||||||
.control-group
|
= f.label :addrZip
|
||||||
= f.label :addrZip, :class => "control-label"
|
%br/
|
||||||
.controls
|
= f.text_field :addrZip
|
||||||
= f.text_field :addrZip, :class => "control-label"
|
%br/
|
||||||
.control-group
|
= f.label :phone
|
||||||
= f.label :phone, :class => "control-label"
|
%br/
|
||||||
.controls
|
= f.text_field :phone
|
||||||
= f.text_field :phone, :class => "control-label"
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
<%= stylesheet_link_tag "bootstrap_and_overrides", :media => "all" %>
|
|
||||||
|
|
||||||
<h2>Edit <%= resource_name.to_s.humanize %></h2>
|
<h2>Edit <%= resource_name.to_s.humanize %></h2>
|
||||||
|
|
||||||
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
|
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
|
||||||
|
|||||||
@@ -1,36 +1,32 @@
|
|||||||
= stylesheet_link_tag "bootstrap_and_overrides", :media => "all"
|
%h2 Sign up
|
||||||
= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :class => "form-horizontal"}) do |f|
|
= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f|
|
||||||
= devise_error_messages!
|
= devise_error_messages!
|
||||||
.controls
|
%div
|
||||||
%h2 Sign up
|
= f.label :first_name
|
||||||
.control-group
|
%br/
|
||||||
= f.label :username, :class => "control-label"
|
|
||||||
.controls
|
|
||||||
= f.text_field :username
|
|
||||||
.control-group
|
|
||||||
= f.label :first_name, :class => "control-label"
|
|
||||||
.controls
|
|
||||||
= f.text_field :first_name
|
= f.text_field :first_name
|
||||||
.control-group
|
%div
|
||||||
= f.label :last_name, :class => "control-label"
|
= f.label :last_name
|
||||||
.controls
|
%br/
|
||||||
= f.text_field :last_name
|
= f.text_field :last_name
|
||||||
.control-group
|
%div
|
||||||
= f.label :email, :class => "control-label"
|
= f.label :nickname
|
||||||
.controls
|
%br/
|
||||||
|
= f.text_field :nickname
|
||||||
|
%div
|
||||||
|
= f.label :email
|
||||||
|
%br/
|
||||||
= f.email_field :email
|
= f.email_field :email
|
||||||
- profile_builder = resource.user_profiles.empty? ? resource.user_profiles.build : resource.user_profiles
|
%div
|
||||||
= f.fields_for :user_profiles, profile_builder do |builder|
|
= f.fields_for :user_profiles, UserProfile.new do |builder|
|
||||||
= render 'user_profile_fields', f: builder
|
= render 'user_profile_fields', f: builder
|
||||||
.control-group
|
%div
|
||||||
= f.label :password, :class => "control-label"
|
= f.label :password
|
||||||
.controls
|
%br/
|
||||||
= f.password_field :password
|
= f.password_field :password
|
||||||
.control-group
|
%div
|
||||||
= f.label :password_confirmation, :class => "control-label"
|
= f.label :password_confirmation
|
||||||
.controls
|
%br/
|
||||||
= f.password_field :password_confirmation
|
= f.password_field :password_confirmation
|
||||||
.control-group
|
%div= f.submit "Sign up"
|
||||||
.controls
|
|
||||||
= f.submit "Sign up"
|
|
||||||
= render "links"
|
= render "links"
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
<%= stylesheet_link_tag "bootstrap_and_overrides", :media => "all" %>
|
<h2>Sign in</h2>
|
||||||
|
|
||||||
<h2>Velocipede</h2>
|
|
||||||
<a href="http://madewithloveinbaltimore.org">Made with ♥ in Baltimore</a>
|
|
||||||
<br>
|
|
||||||
<br>
|
|
||||||
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
|
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
|
||||||
<div><%= f.label :username%><br />
|
<div><%= f.label :email %><br />
|
||||||
<%= f.text_field :username%></div>
|
<%= f.email_field :email %></div>
|
||||||
|
|
||||||
<div><%= f.label :password %><br />
|
<div><%= f.label :password %><br />
|
||||||
<%= f.password_field :password %></div>
|
<%= f.password_field :password %></div>
|
||||||
@@ -16,23 +12,17 @@
|
|||||||
<% end -%>
|
<% end -%>
|
||||||
|
|
||||||
<div><%= f.submit "Sign in" %></div>
|
<div><%= f.submit "Sign in" %></div>
|
||||||
|
|
||||||
<div id="checkin_menu"style="display:none;">
|
|
||||||
<input id="checkin" name="checkin" type="button" value="CHECK IN">
|
|
||||||
<input id="checkout" name="checkout" type="button" value="CHECK OUT">
|
|
||||||
</div>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<%= render "links" %>
|
<%= render "links" %>
|
||||||
|
|
||||||
<% if Rails.env.development? %>
|
<% if Rails.env.development? %>
|
||||||
<% User.all.each do |user| %>
|
<% User.all.each do |user| %>
|
||||||
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
|
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
|
||||||
<%= f.hidden_field :username, :value => user.username%></div>
|
<%= f.hidden_field :email, :value => user.email %></div>
|
||||||
<%= f.hidden_field :password, :value => 'password' %></div>
|
<%= f.hidden_field :password, :value => 'password' %></div>
|
||||||
<div><%= f.submit "Sign in as #{user.username}" %></div>
|
<div><%= f.submit "Sign in as #{user.email}" %></div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,6 @@
|
|||||||
body {
|
body {
|
||||||
padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */
|
padding-top: 60px; /* 60px to make the container go all the way to the bottom of the topbar */
|
||||||
}
|
}
|
||||||
.x-boundlist-item {
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
%body
|
%body
|
||||||
.container
|
.container
|
||||||
@@ -31,4 +28,3 @@
|
|||||||
%p © Velocipede 2013
|
%p © Velocipede 2013
|
||||||
|
|
||||||
= javascript_include_tag "application"
|
= javascript_include_tag "application"
|
||||||
= javascript_include_tag params[:controller]
|
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# SQLite version 3.x
|
||||||
|
# gem install sqlite3
|
||||||
|
#
|
||||||
|
# Ensure the SQLite 3 gem is defined in your Gemfile
|
||||||
|
# gem 'sqlite3'
|
||||||
|
development:
|
||||||
|
adapter: sqlite3
|
||||||
|
database: db/development.sqlite3
|
||||||
|
pool: 5
|
||||||
|
timeout: 5000
|
||||||
|
|
||||||
|
# Warning: The database defined as "test" will be erased and
|
||||||
|
# re-generated from your development database when you run "rake".
|
||||||
|
# Do not set this db to the same as development or production.
|
||||||
|
test:
|
||||||
|
adapter: sqlite3
|
||||||
|
database: db/test.sqlite3
|
||||||
|
pool: 5
|
||||||
|
timeout: 5000
|
||||||
|
|
||||||
|
production:
|
||||||
|
adapter: sqlite3
|
||||||
|
database: db/production.sqlite3
|
||||||
|
pool: 5
|
||||||
|
timeout: 5000
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
development:
|
|
||||||
adapter: postgresql
|
|
||||||
database: velocipede
|
|
||||||
username: velocipede
|
|
||||||
password:
|
|
||||||
host: 127.0.0.1
|
|
||||||
|
|
||||||
# Warning: The database defined as "test" will be erased and
|
|
||||||
# re-generated from your development database when you run "rake".
|
|
||||||
# Do not set this db to the same as development or production.
|
|
||||||
test:
|
|
||||||
adapter: postgresql
|
|
||||||
database: velocipede
|
|
||||||
username: velocipede
|
|
||||||
password:
|
|
||||||
host: 127.0.0.1
|
|
||||||
|
|
||||||
production:
|
|
||||||
adapter: postgresql
|
|
||||||
database: velocipede
|
|
||||||
username: velocipede
|
|
||||||
password:
|
|
||||||
host: 127.0.0.1
|
|
||||||
@@ -5,15 +5,20 @@ Velocipede::Application.configure do
|
|||||||
config.cache_classes = true
|
config.cache_classes = true
|
||||||
|
|
||||||
# Full error reports are disabled and caching is turned on
|
# Full error reports are disabled and caching is turned on
|
||||||
config.consider_all_requests_local = true
|
config.consider_all_requests_local = false
|
||||||
config.action_controller.perform_caching = true
|
config.action_controller.perform_caching = true
|
||||||
|
|
||||||
# Disable Rails's static asset server (Apache or nginx will already do this)
|
# Disable Rails's static asset server (Apache or nginx will already do this)
|
||||||
config.serve_static_assets = true
|
config.serve_static_assets = false
|
||||||
|
|
||||||
# Compress JavaScripts and CSS
|
# Compress JavaScripts and CSS
|
||||||
config.assets.compress = false
|
config.assets.compress = true
|
||||||
config.assets.debug = true
|
|
||||||
|
# Don't fallback to assets pipeline if a precompiled asset is missed
|
||||||
|
config.assets.compile = false
|
||||||
|
|
||||||
|
# Generate digests for assets URLs
|
||||||
|
config.assets.digest = true
|
||||||
|
|
||||||
# Defaults to Rails.root.join("public/assets")
|
# Defaults to Rails.root.join("public/assets")
|
||||||
# config.assets.manifest = YOUR_PATH
|
# config.assets.manifest = YOUR_PATH
|
||||||
@@ -40,6 +45,9 @@ Velocipede::Application.configure do
|
|||||||
# Enable serving of images, stylesheets, and JavaScripts from an asset server
|
# Enable serving of images, stylesheets, and JavaScripts from an asset server
|
||||||
# config.action_controller.asset_host = "http://assets.example.com"
|
# config.action_controller.asset_host = "http://assets.example.com"
|
||||||
|
|
||||||
|
# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
|
||||||
|
# config.assets.precompile += %w( search.js )
|
||||||
|
|
||||||
# TODO set to host
|
# TODO set to host
|
||||||
# Disable delivery errors, bad email addresses will be ignored
|
# Disable delivery errors, bad email addresses will be ignored
|
||||||
# config.action_mailer.raise_delivery_errors = false
|
# config.action_mailer.raise_delivery_errors = false
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ Devise.setup do |config|
|
|||||||
# session. If you need permissions, you should implement that in a before filter.
|
# 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
|
# 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.
|
# or not authentication should be aborted when the value is not present.
|
||||||
config.authentication_keys = [ :username ]
|
# config.authentication_keys = [ :email ]
|
||||||
|
|
||||||
# Configure parameters from the request object used for authentication. Each entry
|
# 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
|
# 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.
|
# Configure which authentication keys should be case-insensitive.
|
||||||
# These keys will be downcased upon creating or modifying a user and when used
|
# These keys will be downcased upon creating or modifying a user and when used
|
||||||
# to authenticate or find a user. Default is :email.
|
# to authenticate or find a user. Default is :email.
|
||||||
config.case_insensitive_keys = [ :username ]
|
config.case_insensitive_keys = [ :email ]
|
||||||
|
|
||||||
# Configure which authentication keys should have whitespace stripped.
|
# Configure which authentication keys should have whitespace stripped.
|
||||||
# These keys will have whitespace before and after removed upon creating or
|
# 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.
|
# modifying a user and when used to authenticate or find a user. Default is :email.
|
||||||
config.strip_whitespace_keys = [ :username ]
|
config.strip_whitespace_keys = [ :email ]
|
||||||
|
|
||||||
# Tell if authentication through request.params is enabled. True by default.
|
# 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
|
# It can be set to an array that will enable params authentication only for the
|
||||||
@@ -221,12 +221,3 @@ Devise.setup do |config|
|
|||||||
# manager.default_strategies(:scope => :user).unshift :some_external_strategy
|
# manager.default_strategies(:scope => :user).unshift :some_external_strategy
|
||||||
# end
|
# end
|
||||||
end
|
end
|
||||||
|
|
||||||
#Check in the user if they sign in. (Devise uses Warden)
|
|
||||||
Warden::Manager.after_set_user do |user,auth,opts|
|
|
||||||
# this essentially gets called after every netzke request, but alas,
|
|
||||||
# only using the after_authenticaion callback doesn't get fired after
|
|
||||||
# user creation.
|
|
||||||
user.checkin unless user.checked_in?
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ en:
|
|||||||
devise:
|
devise:
|
||||||
failure:
|
failure:
|
||||||
already_authenticated: 'You are already signed in.'
|
already_authenticated: 'You are already signed in.'
|
||||||
unauthenticated: 'You need to provide your username and password or sign in/sign up before continuing.'
|
unauthenticated: 'You need to sign in or sign up before continuing.'
|
||||||
unconfirmed: 'You have to confirm your account before continuing.'
|
unconfirmed: 'You have to confirm your account before continuing.'
|
||||||
locked: 'Your account is locked.'
|
locked: 'Your account is locked.'
|
||||||
invalid: 'Invalid email or password.'
|
invalid: 'Invalid email or password.'
|
||||||
|
|||||||
@@ -4,14 +4,4 @@ Velocipede::Application.routes.draw do
|
|||||||
netzke
|
netzke
|
||||||
|
|
||||||
root :to => 'site#index'
|
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"
|
|
||||||
post 'reset' => "users#password_reset", :as => "api_password_reset"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,5 +2,6 @@ class AddEndsToUserRoles < ActiveRecord::Migration
|
|||||||
def change
|
def change
|
||||||
add_column(:user_roles, :ends, :timestamp)
|
add_column(:user_roles, :ends, :timestamp)
|
||||||
add_column(:user_roles, :user_id, :integer)
|
add_column(:user_roles, :user_id, :integer)
|
||||||
|
remove_column(:users, :role_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
class AlterUserRoles < ActiveRecord::Migration
|
|
||||||
def up
|
|
||||||
rename_table :user_roles, :user_role_joins
|
|
||||||
change_table :user_role_joins do |t|
|
|
||||||
t.rename :role, :role_id
|
|
||||||
#t.change :role_id, :integer
|
|
||||||
end
|
|
||||||
#for Postgres
|
|
||||||
connection.execute(%q{
|
|
||||||
alter table user_role_joins
|
|
||||||
alter column role_id
|
|
||||||
type integer using cast(role_id as integer)
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
def down
|
|
||||||
rename_table :user_role_joins, :user_roles
|
|
||||||
change_table :user_role_joins do |t|
|
|
||||||
t.rename :role_id, :role
|
|
||||||
t.change :role_id, :string
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
class AddRoles < ActiveRecord::Migration
|
|
||||||
def change
|
|
||||||
create_table(:roles) do |t|
|
|
||||||
t.string :role
|
|
||||||
t.timestamps
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
class AlterUser < ActiveRecord::Migration
|
|
||||||
def change
|
|
||||||
remove_column :users, :user_role_id
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
class AddUsernameToUser < ActiveRecord::Migration
|
|
||||||
def change
|
|
||||||
add_column :users, :username, :string
|
|
||||||
add_index :users, :username, :unique => true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
class RemoveNickname < ActiveRecord::Migration
|
|
||||||
def change
|
|
||||||
remove_column :users, :nickname
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
class CreateCreditConversions < ActiveRecord::Migration
|
|
||||||
def change
|
|
||||||
create_table(:credit_conversions) do |t|
|
|
||||||
t.integer :conversion, :default => 1
|
|
||||||
t.timestamps
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
class BikeConditionIdToInt < ActiveRecord::Migration
|
|
||||||
def up
|
|
||||||
#for Postgres
|
|
||||||
connection.execute(%q{
|
|
||||||
alter table bikes
|
|
||||||
alter column bike_condition_id
|
|
||||||
type integer using cast(bike_condition_id as integer)
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
def down
|
|
||||||
#you really don't want to go back
|
|
||||||
change_column :bikes, :bike_condition_id, :string
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
class BikeStatusToPurpose < ActiveRecord::Migration
|
|
||||||
def change
|
|
||||||
rename_column :bikes, :bike_status_id, :bike_purpose_id
|
|
||||||
rename_column :bike_statuses, :status, :purpose
|
|
||||||
rename_table :bike_statuses, :bike_purposes
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
class AddModelToBike < ActiveRecord::Migration
|
|
||||||
def change
|
|
||||||
add_column :bikes, :model, :string
|
|
||||||
change_column :bikes, :bike_model_id, :integer, :null => true
|
|
||||||
Bike.all.each do |bike|
|
|
||||||
bike.update_attribute(:model, BikeModel.find_by_id(bike['bike_model_id']).model )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
class ChangeBikeShopId < ActiveRecord::Migration
|
|
||||||
# We don't use change_column because we have arbitrary strings we
|
|
||||||
# need to strip the characters from to make the integer values
|
|
||||||
def up
|
|
||||||
bikes = Bike.all
|
|
||||||
remove_column :bikes, :shop_id
|
|
||||||
add_column :bikes, :shop_id, :integer, :unique => true
|
|
||||||
|
|
||||||
# deconflict shop ids
|
|
||||||
bikes.each do |bike|
|
|
||||||
new_id = bike.shop_id.gsub(/[^\d]/, '').to_i rescue 1
|
|
||||||
while bikes.map(&:shop_id).include? new_id
|
|
||||||
new_id += 1
|
|
||||||
end
|
|
||||||
bike.update_attribute(:shop_id, new_id)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def down
|
|
||||||
change_column :bikes, :shop_id, :string
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
class CreateBikeWheelSizes < ActiveRecord::Migration
|
|
||||||
def up
|
|
||||||
create_table(:bike_wheel_sizes) do |t|
|
|
||||||
t.integer :twmm
|
|
||||||
t.integer :rdmm
|
|
||||||
t.string :twin
|
|
||||||
t.string :rdin
|
|
||||||
t.string :twfr
|
|
||||||
t.string :rdfr
|
|
||||||
t.string :description
|
|
||||||
t.string :tire_common_score
|
|
||||||
end
|
|
||||||
|
|
||||||
#create the default undetermined wheel size record
|
|
||||||
BikeWheelSize.create( twmm: 0, rdmm: 0, rdin: 0, twin: 0, rdfr: 0, twfr: 0, description: "UNDETERMINED", tire_common_score: 0)
|
|
||||||
ActiveRecord::Base.connection.execute(IO.read(File.join(Rails.root, "db", "seed", "sql", "common_wheel_sizes.sql")))
|
|
||||||
end
|
|
||||||
|
|
||||||
def down
|
|
||||||
drop_table :bike_wheel_sizes
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
class AlterBikeWheelToId < ActiveRecord::Migration
|
|
||||||
def up
|
|
||||||
add_column :bikes, :bike_wheel_size_id, :integer
|
|
||||||
|
|
||||||
undetermined_id = BikeWheelSize.find_by_rdin("0")
|
|
||||||
Bike.find_each do |bike|
|
|
||||||
wheel_size = BikeWheelSize.find_by_rdin(bike['wheel_size'].to_s)
|
|
||||||
|
|
||||||
if wheel_size.nil?
|
|
||||||
wheel_size_id = undetermined_id
|
|
||||||
else
|
|
||||||
wheel_size_id = wheel_size.id
|
|
||||||
end
|
|
||||||
bike.update_attribute(:bike_wheel_size_id, wheel_size_id)
|
|
||||||
end
|
|
||||||
|
|
||||||
remove_column :bikes, :wheel_size
|
|
||||||
end
|
|
||||||
|
|
||||||
def down
|
|
||||||
|
|
||||||
add_column :bikes, :wheel_size, :integer
|
|
||||||
|
|
||||||
Bike.find_each do |bike|
|
|
||||||
wheel_size = BikeWheelSize.find_by_id(bike['bike_wheel_size_id'])
|
|
||||||
bike.update_attribute(:wheel_size, wheel_size["rdin"].to_i)
|
|
||||||
end
|
|
||||||
|
|
||||||
remove_column :bikes, :bike_wheel_size_id
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
+13
-35
@@ -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 => 20131019170248) do
|
ActiveRecord::Schema.define(:version => 20130419010051) do
|
||||||
|
|
||||||
create_table "bike_actions", :force => true do |t|
|
create_table "bike_actions", :force => true do |t|
|
||||||
t.string "action", :limit => 128, :null => false
|
t.string "action", :limit => 128, :null => false
|
||||||
@@ -34,8 +34,8 @@ ActiveRecord::Schema.define(:version => 20131019170248) do
|
|||||||
t.integer "bike_brand_id", :null => false
|
t.integer "bike_brand_id", :null => false
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "bike_purposes", :force => true do |t|
|
create_table "bike_statuses", :force => true do |t|
|
||||||
t.string "purpose", :null => false
|
t.string "status", :null => false
|
||||||
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
|
||||||
@@ -46,40 +46,24 @@ ActiveRecord::Schema.define(:version => 20131019170248) do
|
|||||||
t.datetime "updated_at", :null => false
|
t.datetime "updated_at", :null => false
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "bike_wheel_sizes", :force => true do |t|
|
|
||||||
t.integer "twmm"
|
|
||||||
t.integer "rdmm"
|
|
||||||
t.string "twin"
|
|
||||||
t.string "rdin"
|
|
||||||
t.string "twfr"
|
|
||||||
t.string "rdfr"
|
|
||||||
t.string "description"
|
|
||||||
t.string "tire_common_score"
|
|
||||||
end
|
|
||||||
|
|
||||||
create_table "bikes", :force => true do |t|
|
create_table "bikes", :force => true do |t|
|
||||||
t.string "serial_number"
|
t.string "serial_number"
|
||||||
t.integer "bike_brand_id", :null => false
|
t.integer "bike_brand_id", :null => false
|
||||||
t.integer "bike_model_id"
|
t.integer "bike_model_id", :null => false
|
||||||
t.string "color"
|
t.string "color"
|
||||||
t.integer "bike_style_id", :null => false
|
t.integer "bike_style_id", :null => false
|
||||||
t.float "seat_tube_height"
|
t.float "seat_tube_height"
|
||||||
t.float "top_tube_length"
|
t.float "top_tube_length"
|
||||||
|
t.integer "wheel_size"
|
||||||
t.float "value"
|
t.float "value"
|
||||||
t.integer "bike_condition_id", :null => false
|
t.string "bike_condition_id", :null => false
|
||||||
t.integer "bike_purpose_id", :null => false
|
t.integer "bike_status_id", :null => false
|
||||||
t.datetime "created_at", :null => false
|
t.datetime "created_at", :null => false
|
||||||
t.datetime "updated_at", :null => false
|
t.datetime "updated_at", :null => false
|
||||||
t.string "model"
|
t.string "shop_id"
|
||||||
t.integer "shop_id"
|
|
||||||
t.integer "bike_wheel_size_id"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "credit_conversions", :force => true do |t|
|
add_index "bikes", ["shop_id"], :name => "index_bikes_on_shop_id", :unique => true
|
||||||
t.integer "conversion", :default => 1
|
|
||||||
t.datetime "created_at", :null => false
|
|
||||||
t.datetime "updated_at", :null => false
|
|
||||||
end
|
|
||||||
|
|
||||||
create_table "customers", :force => true do |t|
|
create_table "customers", :force => true do |t|
|
||||||
t.string "first_name", :null => false
|
t.string "first_name", :null => false
|
||||||
@@ -113,12 +97,6 @@ ActiveRecord::Schema.define(:version => 20131019170248) do
|
|||||||
|
|
||||||
add_index "logs", ["loggable_id", "loggable_type", "context"], :name => "index_logs_on_loggable_id_and_loggable_type_and_context"
|
add_index "logs", ["loggable_id", "loggable_type", "context"], :name => "index_logs_on_loggable_id_and_loggable_type_and_context"
|
||||||
|
|
||||||
create_table "roles", :force => true do |t|
|
|
||||||
t.string "role"
|
|
||||||
t.datetime "created_at", :null => false
|
|
||||||
t.datetime "updated_at", :null => false
|
|
||||||
end
|
|
||||||
|
|
||||||
create_table "task_lists", :force => true do |t|
|
create_table "task_lists", :force => true do |t|
|
||||||
t.integer "item_id", :null => false
|
t.integer "item_id", :null => false
|
||||||
t.string "item_type", :null => false
|
t.string "item_type", :null => false
|
||||||
@@ -170,8 +148,8 @@ ActiveRecord::Schema.define(:version => 20131019170248) do
|
|||||||
t.datetime "updated_at", :null => false
|
t.datetime "updated_at", :null => false
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table "user_role_joins", :force => true do |t|
|
create_table "user_roles", :force => true do |t|
|
||||||
t.integer "role_id"
|
t.string "role"
|
||||||
t.datetime "created_at", :null => false
|
t.datetime "created_at", :null => false
|
||||||
t.datetime "updated_at", :null => false
|
t.datetime "updated_at", :null => false
|
||||||
t.datetime "ends"
|
t.datetime "ends"
|
||||||
@@ -189,6 +167,7 @@ ActiveRecord::Schema.define(:version => 20131019170248) do
|
|||||||
t.datetime "last_sign_in_at"
|
t.datetime "last_sign_in_at"
|
||||||
t.string "current_sign_in_ip"
|
t.string "current_sign_in_ip"
|
||||||
t.string "last_sign_in_ip"
|
t.string "last_sign_in_ip"
|
||||||
|
t.integer "user_role_id", :default => 1, :null => false
|
||||||
t.integer "bike_id"
|
t.integer "bike_id"
|
||||||
t.datetime "created_at", :null => false
|
t.datetime "created_at", :null => false
|
||||||
t.datetime "updated_at", :null => false
|
t.datetime "updated_at", :null => false
|
||||||
@@ -197,12 +176,11 @@ ActiveRecord::Schema.define(:version => 20131019170248) do
|
|||||||
t.datetime "locked_at"
|
t.datetime "locked_at"
|
||||||
t.string "first_name", :default => "", :null => false
|
t.string "first_name", :default => "", :null => false
|
||||||
t.string "last_name", :default => "", :null => false
|
t.string "last_name", :default => "", :null => false
|
||||||
t.string "username"
|
t.string "nickname"
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "users", ["bike_id"], :name => "index_users_on_bike_id", :unique => true
|
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", ["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", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true
|
||||||
add_index "users", ["username"], :name => "index_users_on_username", :unique => true
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -13,8 +13,3 @@ staff:
|
|||||||
action: STAFF
|
action: STAFF
|
||||||
created_at: <%= Time.now %>
|
created_at: <%= Time.now %>
|
||||||
updated_at: <%= Time.now %>
|
updated_at: <%= Time.now %>
|
||||||
checkin:
|
|
||||||
id: 4
|
|
||||||
action: CHECKIN
|
|
||||||
created_at: <%= Time.now %>
|
|
||||||
updated_at: <%= Time.now %>
|
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
undetermined:
|
|
||||||
id: 1
|
|
||||||
purpose: UNDETERMINED
|
|
||||||
scrap:
|
|
||||||
id: 2
|
|
||||||
purpose: SCRAP
|
|
||||||
parts:
|
|
||||||
id: 3
|
|
||||||
purpose: PARTS
|
|
||||||
storage:
|
|
||||||
id: 4
|
|
||||||
purpose: STORAGE
|
|
||||||
buildbike:
|
|
||||||
id: 5
|
|
||||||
purpose: BUILDBIKE
|
|
||||||
sale:
|
|
||||||
id: 6
|
|
||||||
purpose: SALE
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
undetermined:
|
||||||
|
id: 1
|
||||||
|
status: UNDETERMINED
|
||||||
|
scrap:
|
||||||
|
id: 2
|
||||||
|
status: SCRAP
|
||||||
|
parts:
|
||||||
|
id: 3
|
||||||
|
status: PARTS
|
||||||
|
storage:
|
||||||
|
id: 4
|
||||||
|
status: STORAGE
|
||||||
|
buildbike:
|
||||||
|
id: 5
|
||||||
|
status: BUILDBIKE
|
||||||
|
sale:
|
||||||
|
id: 6
|
||||||
|
status: SALE
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
conversion:
|
|
||||||
id: 1
|
|
||||||
conversion: 10
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
user:
|
|
||||||
id: 1
|
|
||||||
role: user
|
|
||||||
bike_admin:
|
|
||||||
id: 2
|
|
||||||
role: bike_admin
|
|
||||||
staff:
|
|
||||||
id: 3
|
|
||||||
role: staff
|
|
||||||
admin:
|
|
||||||
id: 4
|
|
||||||
role: admin
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (54,110,'8 1/2','2','','','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (62,203,'12','1/2 x 2 1/4','320 ','57','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (47,305,'16','1,75 [x 2]','','','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (32,369,'16','1 1/4','','','Moulton',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (47,355,'18','1,75 [ x 2]','','','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (28,406,'20','1 1/8','','','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (37,406,'20','1 3/8','','','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (47,406,'20','1,75 [ x 2]','','','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (47,507,'24','1,75 [ x 2]','600 ','50C','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (37,540,'24','1 3/8 A','600 ','35A','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (25,559,'26','1','','','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (32,559,'26','1,3','','','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (37,559,'26','1,5','','','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (40,559,'26','1,6','','','MTB',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (44,559,'26','1,6','','','City/trekking',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (47,559,'26','1,75 [ x 2]','650 ','50','City/Trekking',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (NULL,NULL,'26','1,9','','','MTB',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (50,'559','26','1,9','','','City/Trekking',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (NULL,NULL,'26','2','','','MTB',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (54,559,'26','2,1','','','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (57,559,'26','2,3 [2,125]','','','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (20,571,'','','650 ','20C','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (23,571,'','','650 ','23C','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (28,584,'26','1 1/8 x 1 1/2 B','','','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (37,584,'26','1 3/8 x 1 1/2 B','650 ','38A','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (37,590,'26','1 3/8','650 [','35] A','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (20,622,'','','700 ','20C','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (23,622,'','','700 ','23C','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (25,622,'','','700 ','25C','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (28,622,'28','1 5/8 x 1 3/8','700 ','28C [700C]','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (32,622,'28','1 1/4 x 1 3/4','700 ','32C [700C Course]','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (37,622,'28','1 3/8 x 1 5/8','700 ','37C [35C]','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (42,622,'28','1,6','700 ','42C [40C]','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (47,622,'28','1,75','700 ','47C [45C]','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (28,630,'27','1 1/8 [1 1/4 fifty]','','','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (32,630,'27','1 1/4','','','',1);
|
|
||||||
INSERT INTO bike_wheel_sizes (TWMM, RDMM,RDIN,TWIN,RDFR,TWFR,DESCRIPTION,tire_common_score) values (40,635,'28','1 1/2 [1 3/8]','700 ','38B [35B]','',1);
|
|
||||||
+9
-30
@@ -14,28 +14,19 @@ end
|
|||||||
|
|
||||||
#Load bike brands and models from sql
|
#Load bike brands and models from sql
|
||||||
if BikeBrand.all.empty? and BikeModel.all.empty?
|
if BikeBrand.all.empty? and BikeModel.all.empty?
|
||||||
# Need to use DEFAULT instead of explicit IDs that are used in the sql file,
|
sql_path = File.join(Rails.root, 'db', 'seed', 'sql', 'bike_brands_and_models.sql')
|
||||||
# so that the PG table ID sequence is incremented
|
system "sqlite3 db/development.sqlite3 < #{sql_path}" if Rails.env.development?
|
||||||
#
|
|
||||||
# Note the drop(1) which assumes we have a junk PRAGMA line at the top
|
|
||||||
load_statements = File.readlines(File.join(Rails.root, 'db', 'seed', 'sql', 'bike_brands_and_models.sql')).drop(1).map do |statement|
|
|
||||||
statement.sub(/VALUES\(\d+,/, 'VALUES(DEFAULT,')
|
|
||||||
end
|
|
||||||
ActiveRecord::Base.connection.execute(load_statements.join)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if Rails.env.development?
|
if Rails.env.development?
|
||||||
|
|
||||||
#create default users
|
#create default admin user
|
||||||
if User.all.empty?
|
if UserRole.all.empty? and User.all.empty?
|
||||||
u = FactoryGirl.create(:user)
|
FactoryGirl.create(:user)
|
||||||
FactoryGirl.create(:user_profile, user_id: u.id)
|
FactoryGirl.create(:staff)
|
||||||
u = FactoryGirl.create(:staff)
|
FactoryGirl.create(:admin)
|
||||||
FactoryGirl.create(:user_profile, user_id: u.id)
|
FactoryGirl.create(:bike_admin)
|
||||||
u = FactoryGirl.create(:bike_admin)
|
FactoryGirl.create(:user_profile)
|
||||||
FactoryGirl.create(:user_profile, user_id: u.id)
|
|
||||||
u = FactoryGirl.create(:admin)
|
|
||||||
FactoryGirl.create(:user_profile, user_id: u.id)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
#create fake bikes
|
#create fake bikes
|
||||||
@@ -44,16 +35,4 @@ if Rails.env.development?
|
|||||||
FactoryGirl.create(:bike)
|
FactoryGirl.create(:bike)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elsif Rails.env.production?
|
|
||||||
|
|
||||||
unless User.find_by_username('admin')
|
|
||||||
#create an admin
|
|
||||||
admin = User.create!( :username => 'admin',
|
|
||||||
:first_name => 'admin',
|
|
||||||
:last_name => 'admin',
|
|
||||||
:email=>'admin@example.com',
|
|
||||||
:password=>'password')
|
|
||||||
admin.roles << Role.find_by_role('admin')
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
+15
-13
@@ -2,19 +2,21 @@
|
|||||||
|
|
||||||
FactoryGirl.define do
|
FactoryGirl.define do
|
||||||
factory :bike do
|
factory :bike do
|
||||||
sequence(:shop_id) {|n| n}
|
sequence :shop_id do |n|
|
||||||
sequence :serial_number do |n|
|
"Shop ID #{n}"
|
||||||
"#{Faker::Code.isbn}-#{n}"
|
|
||||||
end
|
end
|
||||||
bike_brand_id { BikeBrand.all.sample.id }
|
sequence :serial_number do |n|
|
||||||
model { Faker::Commerce.product_name }
|
"S/N# #{n}"
|
||||||
color { sprintf("%06X", Random.rand(16777215) ) }
|
end
|
||||||
bike_style_id { BikeStyle.all.sample.id }
|
bike_brand_id 1
|
||||||
seat_tube_height { Random.rand(25) }
|
bike_model_id 1
|
||||||
top_tube_length { Random.rand(25) }
|
color "FFFFFF"
|
||||||
bike_wheel_size_id { BikeWheelSize.all.sample.id }
|
bike_style_id 1
|
||||||
value { Random.rand(200) }
|
seat_tube_height 5
|
||||||
bike_condition_id { BikeCondition.all.sample.id }
|
top_tube_length 6
|
||||||
bike_purpose_id { BikePurpose.all.sample.id }
|
wheel_size 27
|
||||||
|
value 100
|
||||||
|
bike_condition_id 1
|
||||||
|
bike_status_id 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
FactoryGirl.define do
|
FactoryGirl.define do
|
||||||
factory :user_profile do
|
factory :user_profile do
|
||||||
user_id 1
|
user_id 1
|
||||||
addrStreet1 { Faker::Address.street_address }
|
addrStreet1 "Charles Street"
|
||||||
addrStreet2 { Faker::Address.secondary_address }
|
addrStreet2 "Apt #42"
|
||||||
addrCity { Faker::Address.city }
|
addrCity "Baltimore"
|
||||||
addrState { Faker::Address.state_abbr }
|
addrState "MD"
|
||||||
addrZip { Faker::Address.zip_code }
|
addrZip "21231"
|
||||||
phone { Faker::PhoneNumber.cell_phone }
|
phone "(410)8675309"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
FactoryGirl.define do
|
FactoryGirl.define do
|
||||||
factory :role do
|
factory :user_role do
|
||||||
factory :role_staff do
|
factory :role_staff do
|
||||||
role 'staff'
|
role 'staff'
|
||||||
end
|
end
|
||||||
+4
-17
@@ -1,39 +1,26 @@
|
|||||||
FactoryGirl.define do
|
FactoryGirl.define do
|
||||||
factory :user do
|
factory :user do
|
||||||
|
|
||||||
sequence(:username) { |n| "user_#{n}" }
|
|
||||||
sequence(:email) { |n| "user_#{n}@example.com" }
|
sequence(:email) { |n| "user_#{n}@example.com" }
|
||||||
password 'password'
|
password 'password'
|
||||||
password_confirmation { password }
|
password_confirmation { password }
|
||||||
first_name 'Michael'
|
first_name 'Michael'
|
||||||
last_name 'Scott'
|
last_name 'Scott'
|
||||||
sequence(:bike_id) { |n| n }
|
sequence(:bike_id) { |n| n }
|
||||||
after_build do |r|
|
association :user_role, factory: :role_user
|
||||||
r.roles << (Role.find_by_role("user") || FactoryGirl.create(:role_user))
|
|
||||||
end
|
|
||||||
|
|
||||||
factory :staff do
|
factory :staff do
|
||||||
username "staff"
|
|
||||||
first_name 'Staff'
|
first_name 'Staff'
|
||||||
after_build do |r|
|
association :user_role, factory: :role_staff
|
||||||
r.roles << (Role.find_by_role("staff") || FactoryGirl.create(:role_staff))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
factory :admin do
|
factory :admin do
|
||||||
username "admin"
|
|
||||||
first_name 'Admin'
|
first_name 'Admin'
|
||||||
after_build do |r|
|
association :user_role, factory: :role_admin
|
||||||
r.roles << (Role.find_by_role("admin") || FactoryGirl.create(:role_admin))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
factory :bike_admin do
|
factory :bike_admin do
|
||||||
username "bike_admin"
|
|
||||||
first_name 'BikeAdmin'
|
first_name 'BikeAdmin'
|
||||||
after_build do |r|
|
association :user_role, factory: :role_bike_admin
|
||||||
r.roles << (Role.find_by_role("bike_admin") || FactoryGirl.create(:role_bike_admin))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user