Merge branch 'master' of github.com:ZeusWPI/Tab
This commit is contained in:
commit
edef683f86
144 changed files with 1843 additions and 985 deletions
1
.capistrano/metrics
Normal file
1
.capistrano/metrics
Normal file
|
@ -0,0 +1 @@
|
|||
full
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -18,3 +18,7 @@
|
|||
# Avatars of producst
|
||||
public/system/products
|
||||
public/system/users
|
||||
|
||||
.project
|
||||
|
||||
/coverage
|
||||
|
|
7
.simplecov
Normal file
7
.simplecov
Normal file
|
@ -0,0 +1,7 @@
|
|||
require 'simplecov'
|
||||
require 'coveralls'
|
||||
|
||||
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
||||
SimpleCov.start do
|
||||
add_filter 'config/'
|
||||
end
|
18
.travis.yml
Normal file
18
.travis.yml
Normal file
|
@ -0,0 +1,18 @@
|
|||
language: ruby
|
||||
rvm:
|
||||
- 2.1.0
|
||||
|
||||
before_script:
|
||||
- "RAILS_ENV=test bundle exec rake db:create"
|
||||
- "RAILS_ENV=test bundle exec rake db:schema:load"
|
||||
|
||||
script: bundle exec rake
|
||||
|
||||
notifications:
|
||||
slack: zeuswpi:1pHNpPMD56jXSGG1w3Ysa9rd
|
||||
|
||||
email:
|
||||
recipients:
|
||||
- tab@zeus.ugent.be
|
||||
on_success: never
|
||||
on_failure: change
|
30
Gemfile
30
Gemfile
|
@ -2,7 +2,7 @@ source 'https://rubygems.org'
|
|||
|
||||
|
||||
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
|
||||
gem 'rails', '4.1.7'
|
||||
gem 'rails', '4.2'
|
||||
# Use sqlite3 as the database for Active Record
|
||||
gem 'sqlite3'
|
||||
# Use SCSS for stylesheets
|
||||
|
@ -29,14 +29,9 @@ gem 'spring', group: :development
|
|||
# add annotations of schema inside models
|
||||
gem 'annotate'
|
||||
|
||||
# Use ActiveModel has_secure_password
|
||||
# gem 'bcrypt', '~> 3.1.7'
|
||||
|
||||
# Use unicorn as the app server
|
||||
# gem 'unicorn'
|
||||
|
||||
# Use Capistrano for deployment
|
||||
# gem 'capistrano-rails', group: :development
|
||||
# Deployment
|
||||
gem 'capistrano', '~> 3.1'
|
||||
gem 'capistrano-rails', '~> 1.1'
|
||||
|
@ -46,9 +41,12 @@ group :production do
|
|||
gem 'mysql2' # Database
|
||||
end
|
||||
|
||||
# Use debugger
|
||||
# gem 'debugger', group: [:development, :test]
|
||||
|
||||
group :test do
|
||||
gem 'capybara'
|
||||
gem 'launchy'
|
||||
gem "codeclimate-test-reporter", require: nil
|
||||
gem 'faker', '1.4.2'
|
||||
end
|
||||
|
||||
#bootstrap
|
||||
gem 'bootstrap-sass', '3.2.0.0'
|
||||
|
@ -56,9 +54,6 @@ gem 'bootstrap-sass', '3.2.0.0'
|
|||
#debug stuff
|
||||
gem 'byebug'
|
||||
|
||||
#passwords
|
||||
gem 'bcrypt', '3.1.7'
|
||||
|
||||
#paginate stuff
|
||||
gem 'will_paginate', '3.0.7'
|
||||
gem 'bootstrap-will_paginate', '0.0.10'
|
||||
|
@ -72,5 +67,12 @@ gem 'devise'
|
|||
# Use cancancan for authorization
|
||||
gem 'cancancan'
|
||||
|
||||
#ik wil test data maken dus dit
|
||||
gem 'faker', '1.4.2'
|
||||
# Safety first
|
||||
gem 'paper_trail', '~> 4.0.0.beta'
|
||||
|
||||
# Windoos sux
|
||||
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw]
|
||||
|
||||
gem 'coveralls', require: false
|
||||
|
||||
gem 'omniauth-oauth2'
|
||||
|
|
231
Gemfile.lock
231
Gemfile.lock
|
@ -1,37 +1,48 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actionmailer (4.1.7)
|
||||
actionpack (= 4.1.7)
|
||||
actionview (= 4.1.7)
|
||||
actionmailer (4.2.0)
|
||||
actionpack (= 4.2.0)
|
||||
actionview (= 4.2.0)
|
||||
activejob (= 4.2.0)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
actionpack (4.1.7)
|
||||
actionview (= 4.1.7)
|
||||
activesupport (= 4.1.7)
|
||||
rack (~> 1.5.2)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
actionpack (4.2.0)
|
||||
actionview (= 4.2.0)
|
||||
activesupport (= 4.2.0)
|
||||
rack (~> 1.6.0)
|
||||
rack-test (~> 0.6.2)
|
||||
actionview (4.1.7)
|
||||
activesupport (= 4.1.7)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.1)
|
||||
actionview (4.2.0)
|
||||
activesupport (= 4.2.0)
|
||||
builder (~> 3.1)
|
||||
erubis (~> 2.7.0)
|
||||
activemodel (4.1.7)
|
||||
activesupport (= 4.1.7)
|
||||
rails-dom-testing (~> 1.0, >= 1.0.5)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.0.1)
|
||||
activejob (4.2.0)
|
||||
activesupport (= 4.2.0)
|
||||
globalid (>= 0.3.0)
|
||||
activemodel (4.2.0)
|
||||
activesupport (= 4.2.0)
|
||||
builder (~> 3.1)
|
||||
activerecord (4.1.7)
|
||||
activemodel (= 4.1.7)
|
||||
activesupport (= 4.1.7)
|
||||
arel (~> 5.0.0)
|
||||
activesupport (4.1.7)
|
||||
i18n (~> 0.6, >= 0.6.9)
|
||||
activerecord (4.2.0)
|
||||
activemodel (= 4.2.0)
|
||||
activesupport (= 4.2.0)
|
||||
arel (~> 6.0)
|
||||
activesupport (4.2.0)
|
||||
i18n (~> 0.7)
|
||||
json (~> 1.7, >= 1.7.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.1)
|
||||
thread_safe (~> 0.3, >= 0.3.4)
|
||||
tzinfo (~> 1.1)
|
||||
addressable (2.3.7)
|
||||
annotate (2.6.5)
|
||||
activerecord (>= 2.3.0)
|
||||
rake (>= 0.8.7)
|
||||
arel (5.0.1.20140414130214)
|
||||
bcrypt (3.1.7)
|
||||
arel (6.0.0)
|
||||
bcrypt (3.1.10)
|
||||
bcrypt (3.1.10-x64-mingw32)
|
||||
bootstrap-sass (3.2.0.0)
|
||||
sass (~> 3.2)
|
||||
bootstrap-will_paginate (0.0.10)
|
||||
|
@ -41,12 +52,13 @@ GEM
|
|||
columnize (~> 0.8)
|
||||
debugger-linecache (~> 1.2)
|
||||
slop (~> 3.6)
|
||||
cancancan (1.9.2)
|
||||
capistrano (3.2.1)
|
||||
cancancan (1.10.1)
|
||||
capistrano (3.3.5)
|
||||
capistrano-stats (~> 1.1.0)
|
||||
i18n
|
||||
rake (>= 10.0.0)
|
||||
sshkit (~> 1.3)
|
||||
capistrano-bundler (1.1.3)
|
||||
capistrano-bundler (1.1.4)
|
||||
capistrano (~> 3.1)
|
||||
sshkit (~> 1.2)
|
||||
capistrano-rails (1.1.2)
|
||||
|
@ -55,19 +67,34 @@ GEM
|
|||
capistrano-rvm (0.1.2)
|
||||
capistrano (~> 3.0)
|
||||
sshkit (~> 1.2)
|
||||
capistrano-stats (1.1.1)
|
||||
capybara (2.4.4)
|
||||
mime-types (>= 1.16)
|
||||
nokogiri (>= 1.3.3)
|
||||
rack (>= 1.0.0)
|
||||
rack-test (>= 0.5.4)
|
||||
xpath (~> 2.0)
|
||||
climate_control (0.0.3)
|
||||
activesupport (>= 3.0)
|
||||
cocaine (0.5.4)
|
||||
cocaine (0.5.5)
|
||||
climate_control (>= 0.0.3, < 1.0)
|
||||
codeclimate-test-reporter (0.4.7)
|
||||
simplecov (>= 0.7.1, < 1.0.0)
|
||||
coffee-rails (4.0.1)
|
||||
coffee-script (>= 2.2.0)
|
||||
railties (>= 4.0.0, < 5.0)
|
||||
coffee-script (2.3.0)
|
||||
coffee-script-source
|
||||
execjs
|
||||
coffee-script-source (1.8.0)
|
||||
colorize (0.7.3)
|
||||
columnize (0.8.9)
|
||||
coffee-script-source (1.9.0)
|
||||
colorize (0.7.5)
|
||||
columnize (0.9.0)
|
||||
coveralls (0.7.11)
|
||||
multi_json (~> 1.10)
|
||||
rest-client (>= 1.6.8, < 2)
|
||||
simplecov (~> 0.9.1)
|
||||
term-ansicolor (~> 1.3)
|
||||
thor (~> 0.19.1)
|
||||
debugger-linecache (1.2.0)
|
||||
devise (3.4.1)
|
||||
bcrypt (~> 3.0)
|
||||
|
@ -76,102 +103,169 @@ GEM
|
|||
responders
|
||||
thread_safe (~> 0.1)
|
||||
warden (~> 1.2.3)
|
||||
docile (1.1.5)
|
||||
erubis (2.7.0)
|
||||
execjs (2.2.2)
|
||||
execjs (2.3.0)
|
||||
faker (1.4.2)
|
||||
i18n (~> 0.5)
|
||||
faraday (0.9.1)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffi (1.9.6-x64-mingw32)
|
||||
globalid (0.3.2)
|
||||
activesupport (>= 4.1.0)
|
||||
hashie (3.4.0)
|
||||
hike (1.2.3)
|
||||
i18n (0.6.11)
|
||||
jbuilder (2.2.5)
|
||||
i18n (0.7.0)
|
||||
jbuilder (2.2.6)
|
||||
activesupport (>= 3.0.0, < 5)
|
||||
multi_json (~> 1.2)
|
||||
jquery-rails (3.1.2)
|
||||
railties (>= 3.0, < 5.0)
|
||||
jquery-rails (4.0.3)
|
||||
rails-dom-testing (~> 1.0)
|
||||
railties (>= 4.2.0)
|
||||
thor (>= 0.14, < 2.0)
|
||||
json (1.8.1)
|
||||
json (1.8.2)
|
||||
jwt (1.4.1)
|
||||
launchy (2.4.3)
|
||||
addressable (~> 2.3)
|
||||
loofah (2.0.1)
|
||||
nokogiri (>= 1.5.9)
|
||||
mail (2.6.3)
|
||||
mime-types (>= 1.16, < 3)
|
||||
mime-types (2.4.3)
|
||||
minitest (5.4.3)
|
||||
mini_portile (0.6.2)
|
||||
minitest (5.5.1)
|
||||
multi_json (1.10.1)
|
||||
multi_xml (0.5.5)
|
||||
multipart-post (2.0.0)
|
||||
mysql2 (0.3.17)
|
||||
net-scp (1.2.1)
|
||||
net-ssh (>= 2.6.5)
|
||||
net-ssh (2.9.1)
|
||||
net-ssh (2.9.2)
|
||||
netrc (0.10.3)
|
||||
nokogiri (1.6.6.2)
|
||||
mini_portile (~> 0.6.0)
|
||||
nokogiri (1.6.6.2-x64-mingw32)
|
||||
mini_portile (~> 0.6.0)
|
||||
oauth2 (1.0.0)
|
||||
faraday (>= 0.8, < 0.10)
|
||||
jwt (~> 1.0)
|
||||
multi_json (~> 1.3)
|
||||
multi_xml (~> 0.5)
|
||||
rack (~> 1.2)
|
||||
omniauth (1.2.2)
|
||||
hashie (>= 1.2, < 4)
|
||||
rack (~> 1.0)
|
||||
omniauth-oauth2 (1.2.0)
|
||||
faraday (>= 0.8, < 0.10)
|
||||
multi_json (~> 1.3)
|
||||
oauth2 (~> 1.0)
|
||||
omniauth (~> 1.2)
|
||||
orm_adapter (0.5.0)
|
||||
paperclip (4.2.0)
|
||||
paper_trail (4.0.0.beta2)
|
||||
activerecord (>= 3.0, < 6.0)
|
||||
activesupport (>= 3.0, < 6.0)
|
||||
paperclip (4.2.1)
|
||||
activemodel (>= 3.0.0)
|
||||
activesupport (>= 3.0.0)
|
||||
cocaine (~> 0.5.3)
|
||||
mime-types
|
||||
rack (1.5.2)
|
||||
rack-test (0.6.2)
|
||||
rack (1.6.0)
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rails (4.1.7)
|
||||
actionmailer (= 4.1.7)
|
||||
actionpack (= 4.1.7)
|
||||
actionview (= 4.1.7)
|
||||
activemodel (= 4.1.7)
|
||||
activerecord (= 4.1.7)
|
||||
activesupport (= 4.1.7)
|
||||
rails (4.2.0)
|
||||
actionmailer (= 4.2.0)
|
||||
actionpack (= 4.2.0)
|
||||
actionview (= 4.2.0)
|
||||
activejob (= 4.2.0)
|
||||
activemodel (= 4.2.0)
|
||||
activerecord (= 4.2.0)
|
||||
activesupport (= 4.2.0)
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 4.1.7)
|
||||
sprockets-rails (~> 2.0)
|
||||
railties (4.1.7)
|
||||
actionpack (= 4.1.7)
|
||||
activesupport (= 4.1.7)
|
||||
railties (= 4.2.0)
|
||||
sprockets-rails
|
||||
rails-deprecated_sanitizer (1.0.3)
|
||||
activesupport (>= 4.2.0.alpha)
|
||||
rails-dom-testing (1.0.5)
|
||||
activesupport (>= 4.2.0.beta, < 5.0)
|
||||
nokogiri (~> 1.6.0)
|
||||
rails-deprecated_sanitizer (>= 1.0.1)
|
||||
rails-html-sanitizer (1.0.1)
|
||||
loofah (~> 2.0)
|
||||
railties (4.2.0)
|
||||
actionpack (= 4.2.0)
|
||||
activesupport (= 4.2.0)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rake (10.3.2)
|
||||
rdoc (4.1.2)
|
||||
rake (10.4.2)
|
||||
rdoc (4.2.0)
|
||||
json (~> 1.4)
|
||||
responders (1.1.2)
|
||||
railties (>= 3.2, < 4.2)
|
||||
responders (2.1.0)
|
||||
railties (>= 4.2.0, < 5)
|
||||
rest-client (1.7.3)
|
||||
mime-types (>= 1.16, < 3.0)
|
||||
netrc (~> 0.7)
|
||||
rest-client (1.7.3-x64-mingw32)
|
||||
ffi (~> 1.9)
|
||||
mime-types (>= 1.16, < 3.0)
|
||||
netrc (~> 0.7)
|
||||
sass (3.2.19)
|
||||
sass-rails (4.0.4)
|
||||
sass-rails (4.0.5)
|
||||
railties (>= 4.0.0, < 5.0)
|
||||
sass (~> 3.2.2)
|
||||
sprockets (~> 2.8, < 2.12)
|
||||
sprockets (~> 2.8, < 3.0)
|
||||
sprockets-rails (~> 2.0)
|
||||
sdoc (0.4.1)
|
||||
json (~> 1.7, >= 1.7.7)
|
||||
rdoc (~> 4.0)
|
||||
simplecov (0.9.2)
|
||||
docile (~> 1.1.0)
|
||||
multi_json (~> 1.0)
|
||||
simplecov-html (~> 0.9.0)
|
||||
simplecov-html (0.9.0)
|
||||
slop (3.6.0)
|
||||
spring (1.2.0)
|
||||
sprockets (2.11.3)
|
||||
spring (1.3.1)
|
||||
sprockets (2.12.3)
|
||||
hike (~> 1.2)
|
||||
multi_json (~> 1.0)
|
||||
rack (~> 1.0)
|
||||
tilt (~> 1.1, != 1.3.0)
|
||||
sprockets-rails (2.2.0)
|
||||
sprockets-rails (2.2.4)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
sprockets (>= 2.8, < 4.0)
|
||||
sqlite3 (1.3.10)
|
||||
sshkit (1.5.1)
|
||||
colorize
|
||||
sqlite3 (1.3.10-x64-mingw32)
|
||||
sshkit (1.6.1)
|
||||
colorize (>= 0.7.0)
|
||||
net-scp (>= 1.1.2)
|
||||
net-ssh (>= 2.8.0)
|
||||
term-ansicolor (1.3.0)
|
||||
tins (~> 1.0)
|
||||
thor (0.19.1)
|
||||
thread_safe (0.3.4)
|
||||
tilt (1.4.1)
|
||||
turbolinks (2.5.2)
|
||||
tins (1.3.5)
|
||||
turbolinks (2.5.3)
|
||||
coffee-rails
|
||||
tzinfo (1.2.2)
|
||||
thread_safe (~> 0.1)
|
||||
uglifier (2.5.3)
|
||||
tzinfo-data (1.2015.1)
|
||||
tzinfo (>= 1.0.0)
|
||||
uglifier (2.7.0)
|
||||
execjs (>= 0.3.0)
|
||||
json (>= 1.8.0)
|
||||
warden (1.2.3)
|
||||
rack (>= 1.0)
|
||||
will_paginate (3.0.7)
|
||||
xpath (2.0.0)
|
||||
nokogiri (~> 1.3)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
x64-mingw32
|
||||
|
||||
DEPENDENCIES
|
||||
annotate
|
||||
bcrypt (= 3.1.7)
|
||||
bootstrap-sass (= 3.2.0.0)
|
||||
bootstrap-will_paginate (= 0.0.10)
|
||||
byebug
|
||||
|
@ -179,18 +273,25 @@ DEPENDENCIES
|
|||
capistrano (~> 3.1)
|
||||
capistrano-rails (~> 1.1)
|
||||
capistrano-rvm
|
||||
capybara
|
||||
codeclimate-test-reporter
|
||||
coffee-rails (~> 4.0.0)
|
||||
coveralls
|
||||
devise
|
||||
faker (= 1.4.2)
|
||||
jbuilder (~> 2.0)
|
||||
jquery-rails
|
||||
launchy
|
||||
mysql2
|
||||
omniauth-oauth2
|
||||
paper_trail (~> 4.0.0.beta)
|
||||
paperclip
|
||||
rails (= 4.1.7)
|
||||
rails (= 4.2)
|
||||
sass-rails (~> 4.0.3)
|
||||
sdoc (~> 0.4.0)
|
||||
spring
|
||||
sqlite3
|
||||
turbolinks
|
||||
tzinfo-data
|
||||
uglifier (>= 1.3.0)
|
||||
will_paginate (= 3.0.7)
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
Tab
|
||||
===
|
||||
[![Code Climate](https://codeclimate.com/github/ZeusWPI/Tab/badges/gpa.svg)](https://codeclimate.com/github/ZeusWPI/Tab)
|
||||
[![Travis CI](https://travis-ci.org/ZeusWPI/Tab.svg)](https://travis-ci.org/ZeusWPI/Tab)
|
||||
[![Coverage Status](https://coveralls.io/repos/ZeusWPI/Tab/badge.svg?branch=master)](https://coveralls.io/r/ZeusWPI/Tab?branch=master)
|
||||
|
||||
Yes. We have to drink. But we also have to pay. This combines both.
|
3
app/assets/javascripts/callbacks.js.coffee
Normal file
3
app/assets/javascripts/callbacks.js.coffee
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Place all the behaviors and hooks related to the matching controller here.
|
||||
# All this logic will automatically be available in application.js.
|
||||
# You can use CoffeeScript in this file: http://coffeescript.org/
|
|
@ -8,19 +8,33 @@ ready = ->
|
|||
$('.btn-dec').on 'click', ->
|
||||
increment($(this), -1)
|
||||
|
||||
$('.btn-dec').prop("disabled", true)
|
||||
$('.form_row').each((index, row) ->
|
||||
disIfNec(row)
|
||||
$(row).on('input', recalculate)
|
||||
)
|
||||
|
||||
recalculate()
|
||||
|
||||
disIfNec = (row) ->
|
||||
counter = parseInt($(row).find('.row_counter').val())
|
||||
$(row).find('.btn-dec').prop('disabled', counter == 0);
|
||||
$(row).find('.btn-inc').prop('disabled', counter == parseInt($(row).find('.stock').val()))
|
||||
|
||||
recalculate = () ->
|
||||
value = ($(row).find('.row_counter').val() * $(row).find('.price').val() for row in $('.form_row')).reduce (a, b) -> a+b
|
||||
$('#order_price').val((value / 100.0).toFixed(2))
|
||||
|
||||
increment = (button, n) ->
|
||||
row = $(button).closest('.form_row')
|
||||
|
||||
# Fix the counter
|
||||
counter = $(button).closest('.form_row').find('.row_counter')
|
||||
counter = $(row).find('.row_counter')
|
||||
counter.val(parseInt(counter.val()) + n)
|
||||
|
||||
# Enable or disable the dec button
|
||||
counter.parent().find('.btn-dec').prop("disabled", counter.val() == '0');
|
||||
# Disable buttons if necessary
|
||||
disIfNec(row)
|
||||
|
||||
# Update the price
|
||||
oldVal = parseFloat($('#order_total_price').val())
|
||||
$('#order_total_price').val(parseFloat(oldVal + counter.parent().find('.price').val() * n).toFixed(2))
|
||||
recalculate()
|
||||
|
||||
$(document).ready(ready)
|
||||
$(document).on('page:load', ready)
|
||||
|
|
|
@ -29,76 +29,58 @@ $gray-medium-light: #eaeaea;
|
|||
}
|
||||
|
||||
/* miscellaneous */
|
||||
|
||||
.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
|
||||
/* boostrap */
|
||||
body {
|
||||
padding-top: 80px;
|
||||
}
|
||||
|
||||
/* footer */
|
||||
footer {
|
||||
margin-top: 45px;
|
||||
padding-top: 5px;
|
||||
border-top: 1px solid #eaeaea;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: #555;
|
||||
}
|
||||
|
||||
footer a:hover {
|
||||
color: #222;
|
||||
}
|
||||
|
||||
footer small {
|
||||
float: left;
|
||||
}
|
||||
|
||||
footer ul {
|
||||
float: right;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
footer ul li {
|
||||
float: left;
|
||||
margin-left: 15px;
|
||||
}
|
||||
|
||||
.overview{
|
||||
//margin-left: 2px;
|
||||
width: 50%;
|
||||
float: left;
|
||||
border-radius: 0px;
|
||||
margin-bottom: 0px;
|
||||
border: 0px;
|
||||
|
||||
.btn{
|
||||
margin-top: -55px;
|
||||
width: 100%;
|
||||
border-color: #444;
|
||||
}
|
||||
|
||||
.dagschotel{
|
||||
float:left;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.avatar{
|
||||
height: 190px;
|
||||
width: 190px;
|
||||
}
|
||||
}
|
||||
|
||||
.center{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.form-field{
|
||||
margin-bottom: 15px;
|
||||
text-align: bottom;
|
||||
}
|
||||
|
||||
/* bootstrap */
|
||||
|
||||
body {
|
||||
padding-top: 80px;
|
||||
}
|
||||
|
||||
/* footer */
|
||||
|
||||
footer {
|
||||
margin-top: 45px;
|
||||
padding-top: 5px;
|
||||
border-top: 1px solid $gray-medium-light;
|
||||
color: #777;
|
||||
a {
|
||||
color: #555;
|
||||
&:hover {
|
||||
color: #222;
|
||||
}
|
||||
}
|
||||
small {
|
||||
float: left;
|
||||
}
|
||||
ul {
|
||||
float: right;
|
||||
list-style: none;
|
||||
li {
|
||||
float: left;
|
||||
margin-left: 15px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.debug_dump{
|
||||
width: 100%;
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.nav-logo{
|
||||
margin:10px;
|
||||
font-size:30px;
|
||||
}
|
||||
|
|
3
app/assets/stylesheets/callbacks.css.scss
Normal file
3
app/assets/stylesheets/callbacks.css.scss
Normal file
|
@ -0,0 +1,3 @@
|
|||
// Place all the styles related to the callbacks controller here.
|
||||
// They will automatically be included in application.css.
|
||||
// You can use Sass (SCSS) here: http://sass-lang.com/
|
|
@ -1,3 +1,30 @@
|
|||
// Place all the styles related to the Orders controller here.
|
||||
// They will automatically be included in application.css.
|
||||
// You can use Sass (SCSS) here: http://sass-lang.com/
|
||||
|
||||
.big-form-button {
|
||||
height: 65px;
|
||||
width: 65px;
|
||||
}
|
||||
|
||||
.form-control.big-form-field {
|
||||
height: 65px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.form_row_image {
|
||||
height: 100px;
|
||||
width: 100px;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
position: relative;
|
||||
img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
top: 0;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
21
app/assets/stylesheets/overview.css.scss
Normal file
21
app/assets/stylesheets/overview.css.scss
Normal file
|
@ -0,0 +1,21 @@
|
|||
.overviewthumbnail {
|
||||
margin-bottom: 0px;
|
||||
border: 0px;
|
||||
|
||||
.btn{
|
||||
margin-top: -55px;
|
||||
width: 80%;
|
||||
margin-left:10%;
|
||||
border: 0px;
|
||||
}
|
||||
|
||||
.dagschotel{
|
||||
float:left;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.avatar{
|
||||
height: 150px;
|
||||
width: 150px;
|
||||
}
|
||||
}
|
|
@ -5,3 +5,20 @@
|
|||
.orders .thumbnail {
|
||||
min-height: 200px;
|
||||
}
|
||||
|
||||
.pic img {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
.caption{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.caption h3 {
|
||||
margin: 8px 0;
|
||||
}
|
||||
|
||||
.caption h6 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
|
|
73
app/assets/stylesheets/profile.css.scss
Normal file
73
app/assets/stylesheets/profile.css.scss
Normal file
|
@ -0,0 +1,73 @@
|
|||
/* User profile */
|
||||
|
||||
.user_info {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.user_info h2 {
|
||||
line-height: 45px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.user_info h5 {
|
||||
margin-right: 10px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.user_info .button_to input[type="submit"] {
|
||||
font-size: 16px;
|
||||
color: #FFF;
|
||||
padding: 12px 50px 12px 50px;
|
||||
border: 1px solid #999;
|
||||
width: 60%;
|
||||
font-family: monospace;
|
||||
|
||||
text-shadow: 0px 1px 1px #666;
|
||||
text-decoration: none;
|
||||
|
||||
border-radius: 4px;
|
||||
-moz-border-radius: 4px;
|
||||
-webkit-border-radius: 4px;
|
||||
|
||||
background: #64a724;
|
||||
background: -moz-linear-gradient(top, #64a724 0%, #579727 50%, #58982a 51%, #498c25 100%);
|
||||
background: -webkit-gradient(linear, left top, left bottom, from(#64a724), to(#498c25), color-stop(0.4, #579727), color-stop(0.5, #58982a), color-stop(.9, #498c25), color-stop(0.9, #498c25));
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#64a724', endColorstr='#498c25', GradientType=0 );
|
||||
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.debt {
|
||||
padding: 12px 0;
|
||||
text-align: center;
|
||||
font-family: monospace;
|
||||
font-size: 16px;
|
||||
width: 60%;
|
||||
margin: auto;
|
||||
margin-top: 10px;
|
||||
background-color: #FF7F00;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.stats{
|
||||
width: 60%;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.stats h4 {
|
||||
text-transform: uppercase;
|
||||
font-family: monospace;
|
||||
background-color: #333;
|
||||
color: white;
|
||||
padding: 5px 10px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.stats ul {
|
||||
list-style-type: none;
|
||||
padding: 0 0 0 15px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.stats li {
|
||||
}
|
|
@ -3,6 +3,16 @@
|
|||
// You can use Sass (SCSS) here: http://sass-lang.com/
|
||||
|
||||
|
||||
//signin
|
||||
.sign-in{
|
||||
.checkbox label{
|
||||
padding-left: 0px;
|
||||
}
|
||||
#user_remember_me{
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.users .thumbnail {
|
||||
padding: 0px;
|
||||
min-height: 280px;
|
||||
|
@ -37,11 +47,6 @@
|
|||
background-color: #f5f5dc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* sidebar */
|
||||
|
||||
aside {
|
||||
|
@ -69,3 +74,36 @@ aside {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.orders {
|
||||
margin-top: -10px;
|
||||
line-height: 140%;
|
||||
& tr:nth-child(even){
|
||||
border-bottom: 1px solid #bbb;
|
||||
td {
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
}
|
||||
& tr:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
& tr:nth-child(odd) td {
|
||||
padding-top: 10px;
|
||||
}
|
||||
& td.order_date {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.product_dagschotel {
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
#users-table td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
require 'csv'
|
||||
class AdminsController < ApplicationController
|
||||
|
||||
def schulden
|
||||
@users = User.all
|
||||
authorize! :schulden, :admins
|
||||
@users = User.members
|
||||
respond_to do |format|
|
||||
format.csv do
|
||||
headers['Content-Disposition'] = "attachment; filename=\"zeus-schulden\""
|
||||
|
|
|
@ -4,24 +4,28 @@ class ApplicationController < ActionController::Base
|
|||
protect_from_forgery with: :exception
|
||||
before_action :configure_permitted_parameters, if: :devise_controller?
|
||||
|
||||
rescue_from CanCan::AccessDenied do |exception|
|
||||
redirect_to root_path, flash: { error: exception.message }
|
||||
end
|
||||
|
||||
def after_sign_in_path_for(resource)
|
||||
root_path
|
||||
end
|
||||
|
||||
def after_sign_up_path_for(resource)
|
||||
new_user_session_path
|
||||
root_path
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def configure_permitted_parameters
|
||||
devise_parameter_sanitizer.for(:sign_up) { |u| u.permit(
|
||||
:nickname, :name, :last_name, :password, :password_confirmation,
|
||||
:current_password, :avatar
|
||||
:nickname, :password, :password_confirmation,
|
||||
:avatar
|
||||
) }
|
||||
|
||||
devise_parameter_sanitizer.for(:account_update) { |u| u.permit(
|
||||
:password, :password_confirmation, :current_password, :avatar
|
||||
) }
|
||||
end
|
||||
|
||||
end
|
||||
|
|
7
app/controllers/callbacks_controller.rb
Normal file
7
app/controllers/callbacks_controller.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
class CallbacksController < Devise::OmniauthCallbacksController
|
||||
def zeuswpi
|
||||
@user = User.from_omniauth(request.env["omniauth.auth"])
|
||||
@user.save
|
||||
sign_in_and_redirect @user
|
||||
end
|
||||
end
|
|
@ -1,49 +1,74 @@
|
|||
class OrdersController < ApplicationController
|
||||
include ActionView::Helpers::NumberHelper
|
||||
|
||||
load_and_authorize_resource
|
||||
|
||||
def new
|
||||
@user = User.find(params[:user_id])
|
||||
init
|
||||
@order = @user.orders.build
|
||||
@products = Product.all
|
||||
@order_products = @order.order_products
|
||||
|
||||
@products.each do |p|
|
||||
@order_products.build(product: p)
|
||||
end
|
||||
# products = @user.products.select("products.*", "sum(order_items.count) as count").group(:product_id).order("count desc")
|
||||
# @order.g_order_items(products)
|
||||
@order.g_order_items Product.all
|
||||
end
|
||||
|
||||
def create
|
||||
@user = User.find(params[:user_id])
|
||||
@order = @user.orders.build(order_params)
|
||||
@products = Product.all
|
||||
@order_products = @order.order_products
|
||||
init
|
||||
@order = @user.orders.build order_params
|
||||
|
||||
if @order.save
|
||||
flash[:success] = "Ordered things! Get your stuff!"
|
||||
flash[:success] = "#{@order.to_sentence} ordered. Enjoy it!"
|
||||
redirect_to root_path
|
||||
else
|
||||
@order.g_order_items Product.all
|
||||
render 'new'
|
||||
end
|
||||
end
|
||||
|
||||
def index
|
||||
@users_by_name = User.all.order(:name)
|
||||
@users_by_order = User.all.order(:orders_count).reverse_order
|
||||
def destroy
|
||||
order = Order.find(params[:id])
|
||||
if order.created_at > 5.minutes.ago
|
||||
order.cancel
|
||||
flash[:success] = "Order has been removed."
|
||||
else
|
||||
flash[:error] = "This order has been placed too long ago, it can't be removed. Please contact a sysadmin."
|
||||
end
|
||||
redirect_to root_path
|
||||
end
|
||||
|
||||
def overview
|
||||
@users = User.members.order(:nickname)
|
||||
end
|
||||
|
||||
def quickpay
|
||||
@user = User.find(params[:user_id])
|
||||
order = @user.orders.build
|
||||
order.products << @user.dagschotel
|
||||
user = User.find(params[:user_id])
|
||||
order = user.orders.build
|
||||
order.order_items << OrderItem.new(count: 1, product: user.dagschotel, order: order)
|
||||
if order.save
|
||||
flash[:success] = "Quick pay succeeded"
|
||||
flash[:success] = "Quick pay succeeded. #{view_context.link_to("Undo", [user, order], method: :delete)}."
|
||||
else
|
||||
flash[:error] = "Quick pay went wrong ... Sorry!"
|
||||
flash[:error] = order.errors.full_messages.first
|
||||
end
|
||||
redirect_to root_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def init
|
||||
@user = User.find(params[:user_id])
|
||||
|
||||
if @user.koelkast?
|
||||
flash[:error] = "Koelkast can't order things."
|
||||
redirect_to root_path
|
||||
end
|
||||
|
||||
unless current_user.koelkast? || current_user.admin? || current_user == @user
|
||||
flash[:error] = "Please don't order stuff for other people"
|
||||
redirect_to root_path
|
||||
end
|
||||
end
|
||||
|
||||
def order_params
|
||||
params.require(:order).permit(order_products_attributes: [:product_id, :count])
|
||||
params.require(:order).permit(order_items_attributes: [:count, :price, product_attributes: [:id]])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
class ProductsController < ApplicationController
|
||||
load_and_authorize_resource
|
||||
|
||||
def new
|
||||
@product = Product.new
|
||||
end
|
||||
|
@ -6,14 +8,15 @@ class ProductsController < ApplicationController
|
|||
def create
|
||||
@product = Product.new(product_params)
|
||||
if @product.save
|
||||
redirect_to action: :index
|
||||
redirect_to products_path
|
||||
else
|
||||
render :new
|
||||
render 'new'
|
||||
end
|
||||
end
|
||||
|
||||
def index
|
||||
@products = Product.all
|
||||
@categories = Product.categories
|
||||
end
|
||||
|
||||
def edit
|
||||
|
@ -24,7 +27,7 @@ class ProductsController < ApplicationController
|
|||
@product = Product.find(params[:id])
|
||||
if @product.update_attributes(product_params)
|
||||
flash[:success] = "Succesfully updated product"
|
||||
redirect_to action: :index
|
||||
redirect_to products_path
|
||||
else
|
||||
render 'edit'
|
||||
end
|
||||
|
@ -36,10 +39,22 @@ class ProductsController < ApplicationController
|
|||
redirect_to products_path
|
||||
end
|
||||
|
||||
def stock
|
||||
@products = Product.all
|
||||
end
|
||||
|
||||
def update_stock
|
||||
@products = Product.all
|
||||
@products.each do |product|
|
||||
stock_inc = params[:products][product.id.to_s][:stock_inc].to_i
|
||||
product.increment!(:stock, stock_inc) if stock_inc > 0
|
||||
end
|
||||
redirect_to products_path
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def product_params
|
||||
params.require(:product).permit(:name, :price, :avatar)
|
||||
params.require(:product).permit(:name, :price, :avatar, :category, :stock)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,23 +1,66 @@
|
|||
class UsersController < ApplicationController
|
||||
load_and_authorize_resource
|
||||
|
||||
def show
|
||||
@user = User.find(params[:id])
|
||||
@orders = @user.orders.paginate(page: params[:page])
|
||||
@user = User.find_by_id(params[:id]) || current_user
|
||||
@orders = @user.orders
|
||||
.active
|
||||
.order(:created_at)
|
||||
.reverse_order
|
||||
.paginate(page: params[:page])
|
||||
@products = @user.products
|
||||
.select("products.*", "sum(order_items.count) as count")
|
||||
.where("orders.cancelled = ?", false)
|
||||
.group(:product_id)
|
||||
.order("count")
|
||||
.reverse_order
|
||||
@categories = @user.products
|
||||
.select("products.category", "sum(order_items.count) as count")
|
||||
.where("orders.cancelled = ?", false)
|
||||
.group(:category)
|
||||
end
|
||||
|
||||
def index
|
||||
@users = User.all
|
||||
@users = User.members
|
||||
end
|
||||
|
||||
def destroy
|
||||
User.find(params[:id]).destroy
|
||||
@user = User.find(params[:id])
|
||||
@user.destroy
|
||||
flash[:success] = "Succesfully removed user"
|
||||
redirect_to users_path
|
||||
end
|
||||
|
||||
def dagschotel
|
||||
user = User.find(params[:user_id])
|
||||
user.dagschotel = Product.find(params[:product_id])
|
||||
user.save
|
||||
redirect_to edit_user_registration_path(user)
|
||||
def edit_dagschotel
|
||||
@user = User.find(params[:user_id])
|
||||
@dagschotel = @user.dagschotel
|
||||
|
||||
@products = Product.all
|
||||
@categories = Product.categories
|
||||
end
|
||||
|
||||
def update_dagschotel
|
||||
@user = User.find(params[:user_id])
|
||||
@user.dagschotel = Product.find(params[:product_id])
|
||||
|
||||
@products = Product.all
|
||||
@categories = Product.categories
|
||||
|
||||
if @user.save
|
||||
flash[:success] = "Succesfully updated dagschotel"
|
||||
redirect_to @user
|
||||
else
|
||||
flash[:error] = "Error updating dagschotel"
|
||||
@dagschotel = @user.reload.dagschotel
|
||||
render 'edit_dagschotel'
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def init
|
||||
@user = User.find(params[:user_id])
|
||||
redirect_to root_path, error: "You are not authorized to access this page." unless @user == current_user || current_user.admin?
|
||||
end
|
||||
end
|
||||
|
|
185
app/form_builders/formatted_form_builder.rb
Normal file
185
app/form_builders/formatted_form_builder.rb
Normal file
|
@ -0,0 +1,185 @@
|
|||
class FormattedFormBuilder < ActionView::Helpers::FormBuilder
|
||||
include ActionView::Helpers::TextHelper
|
||||
include ActionView::Context
|
||||
include ActionView::Helpers::NumberHelper
|
||||
|
||||
FIELD_HELPERS = %w[text_field number_field file_field password_field]
|
||||
|
||||
delegate :content_tag, to: :@template
|
||||
|
||||
def initialize(object_name, object, template, options)
|
||||
@inline_errors = true
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
FIELD_HELPERS.each do |method_name|
|
||||
with_method_name = "#{method_name}_with_format"
|
||||
without_method_name = "#{method_name}_without_format"
|
||||
|
||||
define_method(with_method_name) do |name, options = {}|
|
||||
form_group_builder(name, options) do
|
||||
send(without_method_name, name, options)
|
||||
end
|
||||
end
|
||||
|
||||
alias_method_chain method_name, :format
|
||||
end
|
||||
|
||||
def price_field(name, options = {})
|
||||
options[:min] ||= 0
|
||||
options[:step] ||= 0.01
|
||||
# if object.is_a?(ActiveRecord::Base)
|
||||
# options[:value] ||= object[name]
|
||||
if object.respond_to?(name)
|
||||
options[:value] ||= object.send name
|
||||
end
|
||||
options[:value] = number_with_precision(options[:value], precision: 2)
|
||||
|
||||
form_group_builder(name, options) do
|
||||
number_field_without_format(name, options)
|
||||
end
|
||||
end
|
||||
|
||||
def check_box_with_format(name, options = {}, checked_value = "1", unchecked_value = "0", &block)
|
||||
options.symbolize_keys!
|
||||
|
||||
checkbox = check_box_without_format(name, options.except(:label), checked_value, unchecked_value)
|
||||
label_content = block_given? ? capture(&block) : options[:label]
|
||||
|
||||
content_tag :div, class: control_wrapper_class do
|
||||
checkbox + " " + label(name, label_content)
|
||||
end
|
||||
end
|
||||
|
||||
def counter(name, options = {})
|
||||
form_group_builder(name, options) do
|
||||
counter_button("btn-dec", "glyphicon-minus") +
|
||||
text_field_without_format(name, options.merge({class: 'form-control row_counter big-form-field'})) +
|
||||
counter_button("btn-inc", "glyphicon-plus")
|
||||
end
|
||||
end
|
||||
|
||||
alias_method_chain :check_box, :format
|
||||
|
||||
def collection_select_with_format(name, collection, value_method = :to_s, text_method = :titlecase, options = {}, html_options = {})
|
||||
form_group_builder(name, options, html_options) do
|
||||
collection_select_without_format(name, collection, value_method, text_method, options, html_options)
|
||||
end
|
||||
end
|
||||
|
||||
alias_method_chain :collection_select, :format
|
||||
|
||||
def submit_with_format(name = nil, options = {})
|
||||
options[:class] = submit_class unless options[:class]
|
||||
content_tag :div, class: submit_wrapper_class do
|
||||
submit_without_format(name, options)
|
||||
end
|
||||
end
|
||||
|
||||
alias_method_chain :submit, :format
|
||||
|
||||
def error_messages
|
||||
if object.errors.any?
|
||||
content_tag :div, class: "panel panel-danger form-errors" do
|
||||
content_tag(:div, class: "panel-body") do
|
||||
error_header + error_body
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def error_header
|
||||
content_tag(:div, class: "panel-heading") do
|
||||
"#{pluralize(object.errors.count, "error")} prohibited this #{object.class.name.downcase} from being saved:"
|
||||
end
|
||||
end
|
||||
|
||||
def error_body
|
||||
content_tag :ul do
|
||||
object.errors.full_messages.map do |msg|
|
||||
content_tag :li, msg
|
||||
end.join.html_safe
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def label_class
|
||||
"control-label"
|
||||
end
|
||||
|
||||
def control_class
|
||||
"form-control"
|
||||
end
|
||||
|
||||
def control_wrapper_class
|
||||
"form-group"
|
||||
end
|
||||
|
||||
def submit_class
|
||||
"btn btn-primary"
|
||||
end
|
||||
|
||||
def submit_wrapper_class
|
||||
"actions"
|
||||
end
|
||||
|
||||
def form_group(*args, &block)
|
||||
options = args.extract_options!
|
||||
name = args.first
|
||||
|
||||
options[:class] = [control_wrapper_class, options[:class]].compact.join(' ')
|
||||
|
||||
content_tag(:div, options.except(:label)) do
|
||||
label = generate_label(name, options[:label]) if options[:label]
|
||||
control = capture(&block).to_s
|
||||
|
||||
if label
|
||||
label + control
|
||||
else
|
||||
control
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def form_group_builder(method, options, html_options = nil)
|
||||
options.symbolize_keys!
|
||||
|
||||
css_options = html_options || options
|
||||
css_options[:class] = [control_class, css_options[:class]].compact.join(" ")
|
||||
|
||||
wrapper_class = css_options.delete(:wrapper_class)
|
||||
wrapper_options = css_options.delete(:wrapper)
|
||||
|
||||
form_group_options = {
|
||||
class: wrapper_class
|
||||
}
|
||||
|
||||
if wrapper_options.is_a?(Hash)
|
||||
form_group_options.merge!(wrapper_options)
|
||||
end
|
||||
|
||||
unless options.delete(:skip_label)
|
||||
form_group_options.reverse_merge!(label: {
|
||||
text: options.delete(:label),
|
||||
class: label_class
|
||||
})
|
||||
end
|
||||
|
||||
form_group(method, form_group_options) do
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
def generate_label(name, options = {})
|
||||
label("#{name}:", options[:text], options)
|
||||
end
|
||||
|
||||
def counter_button(button, glyphicon)
|
||||
content_tag :span, class: "input-group-btn" do
|
||||
content_tag :button, class: "btn btn-default btn-lg #{button}", type: "button" do
|
||||
content_tag :span, "", class: "glyphicon btn-lg #{glyphicon}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,2 +0,0 @@
|
|||
module AdminsHelper
|
||||
end
|
|
@ -10,57 +10,11 @@ module ApplicationHelper
|
|||
end
|
||||
|
||||
def euro(f)
|
||||
"€#{number_with_precision f, precision: 2}"
|
||||
number_to_currency(f, unit: '€')
|
||||
end
|
||||
|
||||
#tijdelijk voor layout
|
||||
def koelkast(status)
|
||||
@koelkast ||= status
|
||||
def f_form_for(record, options = {}, &block)
|
||||
options[:builder] = FormattedFormBuilder
|
||||
form_for(record, options, &block)
|
||||
end
|
||||
|
||||
# Form helpers
|
||||
def form_errors(object)
|
||||
render partial: "form_errors", locals: {object: object}
|
||||
end
|
||||
|
||||
def form_text_field(f, tag)
|
||||
render partial: "form_text_field", locals: {f: f, tag: tag}
|
||||
end
|
||||
|
||||
def form_password_field(f, tag)
|
||||
render partial: "form_password_field", locals: {f: f, tag: tag}
|
||||
end
|
||||
|
||||
def form_text_area(f, tag)
|
||||
render partial: "form_text_area", locals: {f: f, tag: tag}
|
||||
end
|
||||
|
||||
def form_fancy_text_area(f, tag)
|
||||
render partial: "form_fancy_text_area", locals: {f: f, tag: tag}
|
||||
end
|
||||
|
||||
def form_email_field(f, tag)
|
||||
render partial: "form_email_field", locals: {f: f, tag: tag}
|
||||
end
|
||||
|
||||
def form_date_field(f, tag, id, value)
|
||||
render partial: "form_date_field", locals: {f: f, tag: tag, id: id, value: value}
|
||||
end
|
||||
|
||||
def form_number_field(f, tag)
|
||||
render partial: "form_number_field", locals: {f: f, tag: tag}
|
||||
end
|
||||
|
||||
def form_collection_select(f, *args)
|
||||
# This line enable passing optional arguments such as include_blank to the
|
||||
# partial. If nothing is passed, an empty options hash is appended.
|
||||
args << {} if args.length < 5
|
||||
|
||||
render partial: "form_collection_select", locals: {f: f, args: args}
|
||||
end
|
||||
|
||||
def form_check_box(f, tag)
|
||||
render partial: "form_check_box", locals: {f: f, tag: tag}
|
||||
end
|
||||
|
||||
end
|
||||
|
|
2
app/helpers/callbacks_helper.rb
Normal file
2
app/helpers/callbacks_helper.rb
Normal file
|
@ -0,0 +1,2 @@
|
|||
module CallbacksHelper
|
||||
end
|
|
@ -1,21 +0,0 @@
|
|||
module DeviseHelper
|
||||
|
||||
def devise_error_messages!
|
||||
return '' if resource.errors.empty?
|
||||
|
||||
messages = resource.errors.full_messages.map { |msg| content_tag(:li, msg) }.join
|
||||
sentence = I18n.t('errors.messages.not_saved',
|
||||
count: resource.errors.count,
|
||||
resource: resource.class.model_name.human.downcase)
|
||||
|
||||
html = <<-HTML
|
||||
<div class="alert alert-danger alert-dismissable">
|
||||
<button type="button" class="close" data-dismiss="alert">×</button>
|
||||
<strong>Error!</strong> #{sentence}
|
||||
#{messages}
|
||||
</div>
|
||||
HTML
|
||||
|
||||
html.html_safe
|
||||
end
|
||||
end
|
|
@ -1,2 +0,0 @@
|
|||
module OrdersHelper
|
||||
end
|
|
@ -1,2 +0,0 @@
|
|||
module ProductsHelper
|
||||
end
|
|
@ -1,2 +0,0 @@
|
|||
module UsersHelper
|
||||
end
|
|
@ -5,8 +5,15 @@ class Ability
|
|||
user ||= User.new # guest user (not logged in)
|
||||
if user.admin?
|
||||
can :manage, :all
|
||||
else
|
||||
can :schulden, :admins
|
||||
elsif user.koelkast?
|
||||
can :manage, Order
|
||||
elsif user[:id]
|
||||
can :read, :all
|
||||
can :update, User
|
||||
can :edit_dagschotel, User
|
||||
can :update_dagschotel, User
|
||||
can :create, Order
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,47 +2,63 @@
|
|||
#
|
||||
# Table name: orders
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# cost :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# price_cents :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# cancelled :boolean default("f")
|
||||
#
|
||||
|
||||
class Order < ActiveRecord::Base
|
||||
after_initialize { self.total_price = 0 }
|
||||
after_create :pay_price
|
||||
include ActionView::Helpers::TextHelper
|
||||
|
||||
after_create { self.user.increment!(:debt_cents, price_cents) }
|
||||
|
||||
belongs_to :user, counter_cache: true
|
||||
has_many :order_products
|
||||
has_many :products, { through: :order_products} do
|
||||
def << (product)
|
||||
if proxy_association.owner.products.include?(product)
|
||||
proxy_association.owner.order_products.find_by(product: product).increment!(:count, 1)
|
||||
has_many :order_items, dependent: :destroy
|
||||
has_many :products, through: :order_items
|
||||
|
||||
scope :active, -> { where(cancelled: false) }
|
||||
|
||||
validates :user, presence: true
|
||||
validates :order_items, presence: true, in_stock: true
|
||||
|
||||
accepts_nested_attributes_for :order_items, reject_if: proc { |oi| oi[:count].to_i <= 0 }
|
||||
|
||||
def price_cents
|
||||
self.order_items.map{ |oi| oi.count * oi.product.price_cents }.sum
|
||||
end
|
||||
|
||||
def price
|
||||
self.price_cents / 100.0
|
||||
end
|
||||
|
||||
def price=(_)
|
||||
write_attribute(:price_cents, price_cents)
|
||||
end
|
||||
|
||||
def cancel
|
||||
return if self.cancelled
|
||||
user.decrement!(:debt_cents, price_cents)
|
||||
User.decrement_counter(:orders_count, user.id)
|
||||
update_attribute(:cancelled, true)
|
||||
self.order_items.each(&:cancel)
|
||||
end
|
||||
|
||||
def to_sentence
|
||||
self.order_items.map {
|
||||
|oi| pluralize(oi.count, oi.product.name)
|
||||
}.to_sentence
|
||||
end
|
||||
|
||||
def g_order_items(products)
|
||||
products.each do |p|
|
||||
if (oi = self.order_items.select { |t| t.product == p }).size > 0
|
||||
oi.first.count = [oi.first.product.stock, oi.first.count].min
|
||||
else
|
||||
super
|
||||
self.order_items.build(product: p)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
attr_accessor :total_price
|
||||
|
||||
validates :user, presence: true
|
||||
validates :order_products, presence: true
|
||||
|
||||
accepts_nested_attributes_for :order_products, reject_if: proc { |op| op[:count].to_i <= 0 }
|
||||
|
||||
def price
|
||||
price = 0
|
||||
order_products.each do |op|
|
||||
price += op.count * op.product.read_attribute(:price)
|
||||
end
|
||||
price
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def pay_price
|
||||
user.pay(price)
|
||||
end
|
||||
end
|
||||
|
|
36
app/models/order_item.rb
Normal file
36
app/models/order_item.rb
Normal file
|
@ -0,0 +1,36 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: order_items
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# order_id :integer
|
||||
# product_id :integer not null
|
||||
# count :integer default("0")
|
||||
#
|
||||
|
||||
class OrderItem < ActiveRecord::Base
|
||||
belongs_to :order
|
||||
belongs_to :product
|
||||
|
||||
validates :product, presence: true
|
||||
validates :count, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
|
||||
|
||||
after_create :remove_from_stock
|
||||
|
||||
accepts_nested_attributes_for :product
|
||||
|
||||
def product_attributes=(attributes)
|
||||
self.product = Product.find(attributes[:id])
|
||||
super
|
||||
end
|
||||
|
||||
def cancel
|
||||
self.product.increment!(:stock, self.count)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def remove_from_stock
|
||||
product.decrement!(:stock, count)
|
||||
end
|
||||
end
|
|
@ -1,19 +0,0 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: order_products
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# order_id :integer
|
||||
# product_id :integer
|
||||
# count :integer default(1)
|
||||
#
|
||||
|
||||
class OrderProduct < ActiveRecord::Base
|
||||
belongs_to :order
|
||||
belongs_to :product
|
||||
|
||||
validates :product, presence: true
|
||||
validates :count, numericality: { greater_than_or_equal_to: 0 }
|
||||
|
||||
accepts_nested_attributes_for :product
|
||||
end
|
|
@ -3,36 +3,37 @@
|
|||
# Table name: products
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# name :string(255)
|
||||
# price :integer
|
||||
# name :string not null
|
||||
# price_cents :integer default("0"), not null
|
||||
# created_at :datetime
|
||||
# updated_at :datetime
|
||||
# avatar_file_name :string(255)
|
||||
# avatar_content_type :string(255)
|
||||
# avatar_file_name :string
|
||||
# avatar_content_type :string
|
||||
# avatar_file_size :integer
|
||||
# avatar_updated_at :datetime
|
||||
# category :integer default("0")
|
||||
# stock :integer default("0"), not null
|
||||
#
|
||||
|
||||
class Product < ActiveRecord::Base
|
||||
has_many :order_products
|
||||
has_attached_file :avatar, styles: { medium: "100x100>" }, default_style: :medium
|
||||
has_many :order_items
|
||||
has_attached_file :avatar, styles: { dagschotel: "80x80>", medium: "100x100>" }, default_style: :medium
|
||||
|
||||
enum category: %w(food beverages other)
|
||||
|
||||
validates :name, presence: true
|
||||
validates :price, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
|
||||
validates_attachment :avatar, presence: true, content_type: { content_type: ["image/jpeg", "image/gif", "image/png"] },
|
||||
default_url: "http://babeholder.pixoil.com/img/190/190"
|
||||
|
||||
def count(order)
|
||||
order_products.find_by(order: order).count
|
||||
end
|
||||
validates :price_cents, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
|
||||
validates :stock, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
|
||||
validates_attachment :avatar,
|
||||
presence: true,
|
||||
content_type: { content_type: ["image/jpeg", "image/gif", "image/png"] }
|
||||
|
||||
def price
|
||||
(read_attribute(:price) || 0) / 100.0
|
||||
self.price_cents / 100.0
|
||||
end
|
||||
|
||||
def price=(value)
|
||||
if value.is_a? String then value.sub!(',', '.') end
|
||||
write_attribute(:price, (value.to_f * 100).to_int)
|
||||
self.price_cents = (value.to_f * 100).to_int
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -3,52 +3,76 @@
|
|||
# Table name: users
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# name :string(255)
|
||||
# last_name :string(255)
|
||||
# balance :integer default(0)
|
||||
# nickname :string(255)
|
||||
# debt_cents :integer default("0"), not null
|
||||
# nickname :string
|
||||
# created_at :datetime
|
||||
# updated_at :datetime
|
||||
# encrypted_password :string(255) default(""), not null
|
||||
# encrypted_password :string default(""), not null
|
||||
# remember_created_at :datetime
|
||||
# sign_in_count :integer default(0), not null
|
||||
# sign_in_count :integer default("0"), not null
|
||||
# current_sign_in_at :datetime
|
||||
# last_sign_in_at :datetime
|
||||
# current_sign_in_ip :string(255)
|
||||
# last_sign_in_ip :string(255)
|
||||
# dagschotel :reference
|
||||
# current_sign_in_ip :string
|
||||
# last_sign_in_ip :string
|
||||
# admin :boolean
|
||||
# dagschotel_id :integer
|
||||
# avatar_file_name :string
|
||||
# avatar_content_type :string
|
||||
# avatar_file_size :integer
|
||||
# avatar_updated_at :datetime
|
||||
# orders_count :integer default("0")
|
||||
# koelkast :boolean default("f")
|
||||
# provider :string
|
||||
# uid :string
|
||||
#
|
||||
|
||||
class User < ActiveRecord::Base
|
||||
devise :database_authenticatable, :registerable,
|
||||
:rememberable, :trackable
|
||||
has_attached_file :avatar, styles: { medium: "100x100>" }, default_style: :medium, default_url: "http://babeholder.pixoil.com/img/70/70"
|
||||
devise :database_authenticatable, :registerable, :rememberable, :trackable, :validatable, :omniauthable, :omniauth_providers => [:zeuswpi]
|
||||
|
||||
has_paper_trail only: [:debt_cents, :admin, :orders_count, :koelkast]
|
||||
|
||||
has_attached_file :avatar, styles: { large: "150x150>", medium: "100x100>", small: "40x40>" }, default_style: :medium
|
||||
|
||||
has_many :orders, -> { includes :products }
|
||||
has_many :products, through: :orders
|
||||
belongs_to :dagschotel, class_name: 'Product'
|
||||
|
||||
validates :nickname, presence: true, uniqueness: true
|
||||
validates :name, presence: true
|
||||
validates :last_name, presence: true
|
||||
validates :password, length: { in: 8..128 }, confirmation: true, on: :create
|
||||
validates_attachment :avatar, presence: true, content_type: { content_type: ["image/jpeg", "image/gif", "image/png"] }
|
||||
validates_attachment :avatar,
|
||||
presence: true,
|
||||
content_type: { content_type: ["image/jpeg", "image/gif", "image/png"] }
|
||||
|
||||
def full_name
|
||||
"#{name} #{last_name}"
|
||||
scope :members, -> { where koelkast: false }
|
||||
|
||||
def self.from_omniauth(auth)
|
||||
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
|
||||
user.provider = auth.provider
|
||||
user.uid = auth.uid
|
||||
end
|
||||
end
|
||||
|
||||
def pay(amount)
|
||||
write_attribute(:balance, read_attribute(:balance) - amount)
|
||||
self.save
|
||||
def debt
|
||||
self.debt_cents / 100.0
|
||||
end
|
||||
|
||||
def balance
|
||||
(read_attribute(:balance) || 0) / 100.0
|
||||
end
|
||||
|
||||
def balance=(value)
|
||||
def debt=(value)
|
||||
if value.is_a? String then value.sub!(',', '.') end
|
||||
write_attribute(:balance, (value.to_f * 100).to_int)
|
||||
self.debt_cents = (value.to_f * 100).to_int
|
||||
end
|
||||
|
||||
# Change URL params for User
|
||||
|
||||
def to_param
|
||||
"#{id} #{nickname}".parameterize
|
||||
end
|
||||
|
||||
# This is needed so Devise doesn't try to validate :email
|
||||
|
||||
def email_required?
|
||||
false
|
||||
end
|
||||
|
||||
def email_changed?
|
||||
false
|
||||
end
|
||||
end
|
||||
|
|
9
app/validators/in_stock_validator.rb
Normal file
9
app/validators/in_stock_validator.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
class InStockValidator < ActiveModel::Validator
|
||||
def validate(record)
|
||||
p_short = []
|
||||
record.order_items.each do |oi|
|
||||
p_short.append oi.product.name if oi.count > oi.product.stock
|
||||
end
|
||||
record.errors.add(:base, "There is not enough stock for your order of the following products: #{p_short.join(', ')}") if p_short.size > 0
|
||||
end
|
||||
end
|
|
@ -1,5 +1,3 @@
|
|||
<%- headers = ['nickname', 'schulden'] -%>
|
||||
<%= CSV.generate_line headers %>
|
||||
<%- @users.each do |user| -%>
|
||||
<%= CSV.generate_line([user.nickname, user.balance]) %>
|
||||
<%- end -%>
|
||||
<%= CSV.generate_line headers -%>
|
||||
<% @users.each do |user| %><%= CSV.generate_line([user.nickname, user.debt]) %><% end %>
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
<span class="input-group-btn">
|
||||
<button class="btn btn-default btn-dec" type="button">
|
||||
<span class="glyphicon glyphicon-minus"></span>
|
||||
</button>
|
||||
</span>
|
|
@ -1,5 +0,0 @@
|
|||
<span class="input-group-btn">
|
||||
<button class="btn btn-default btn-inc" type="button">
|
||||
<span class="glyphicon glyphicon-plus"></span>
|
||||
</button>
|
||||
</span>
|
|
@ -1,14 +0,0 @@
|
|||
<% if model.errors.any? %>
|
||||
<div class="panel panel-danger form-errors">
|
||||
<div class="panel-heading">
|
||||
<%= pluralize(model.errors.count, "error") %> prohibited this <%= model.class.name.downcase %> from being saved:
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<ul>
|
||||
<% model.errors.full_messages.each do |msg| %>
|
||||
<li><%= msg %></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
|
@ -8,7 +8,7 @@
|
|||
<% if flash[:success] %>
|
||||
<div class="alert alert-success alert-dismissable">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
||||
<strong>Success!</strong> <%= flash[:success] %>
|
||||
<strong>Success!</strong> <%= raw flash[:success] %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if flash[:notice] %>
|
||||
|
@ -23,4 +23,10 @@
|
|||
<strong>Warning!</strong> <%= flash[:warning] %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if flash[:alert] %>
|
||||
<div class="alert alert-danger alert-dismissable">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
||||
<strong>Error!</strong> <%= flash[:alert] %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
<div class="checkbox">
|
||||
<label>
|
||||
<%= f.label tag %>
|
||||
</label>
|
||||
<%= f.check_box tag %>
|
||||
</div>
|
|
@ -1,5 +0,0 @@
|
|||
<%# To pass options to the collection_select, add {options} as the last argument %>
|
||||
<div class="form-group">
|
||||
<%= f.label args.first %>:
|
||||
<%= f.collection_select *args, {class: 'form-control'} %>
|
||||
</div>
|
|
@ -1,7 +0,0 @@
|
|||
<div class="form-group">
|
||||
<%= f.label tag %>:
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
|
||||
<%= f.text_field tag, class: 'form-control', id: id, value: value %>
|
||||
</div>
|
||||
</div>
|
|
@ -1,4 +0,0 @@
|
|||
<div class="form-group">
|
||||
<%= f.label tag %>:
|
||||
<%= f.email_field tag, class: 'form-control' %>
|
||||
</div>
|
|
@ -1,14 +0,0 @@
|
|||
<% if object.errors.any? %>
|
||||
<div class="panel panel-danger form-errors">
|
||||
<div class="panel-heading">
|
||||
<%= pluralize(object.errors.count, "error") %> prohibited this <%= object.class.name.downcase %> from being saved:
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<ul>
|
||||
<% object.errors.full_messages.each do |msg| %>
|
||||
<li><%= msg %></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
|
@ -1,4 +0,0 @@
|
|||
<div class="form-group">
|
||||
<%= f.label tag %>:
|
||||
<%= f.text_area tag, class: 'form-control ckeditor' %>
|
||||
</div>
|
|
@ -1,4 +0,0 @@
|
|||
<div class="form-group">
|
||||
<%= f.label tag %>:
|
||||
<%= f.number_field tag, class: 'form-control', min: 0 %>
|
||||
</div>
|
|
@ -1,4 +0,0 @@
|
|||
<div class="form-group">
|
||||
<%= f.label tag %>:
|
||||
<%= f.password_field tag, class: 'form-control' %>
|
||||
</div>
|
|
@ -1,4 +0,0 @@
|
|||
<div class="form-group">
|
||||
<%= f.label tag %>:
|
||||
<%= f.text_area tag, class: 'form-control' %>
|
||||
</div>
|
|
@ -1,4 +0,0 @@
|
|||
<div class="form-group">
|
||||
<%= f.label tag %>:
|
||||
<%= f.text_field tag, class: 'form-control' %>
|
||||
</div>
|
|
@ -1,16 +0,0 @@
|
|||
<h2>Resend confirmation instructions</h2>
|
||||
|
||||
<%= form_for(resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post }) do |f| %>
|
||||
<%= devise_error_messages! %>
|
||||
|
||||
<div class="field">
|
||||
<%= f.label :email %><br />
|
||||
<%= f.email_field :email, autofocus: true %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<%= f.submit "Resend confirmation instructions" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render "devise/shared/links" %>
|
|
@ -1,5 +0,0 @@
|
|||
<p>Welcome <%= @email %>!</p>
|
||||
|
||||
<p>You can confirm your account email through the link below:</p>
|
||||
|
||||
<p><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></p>
|
|
@ -1,8 +0,0 @@
|
|||
<p>Hello <%= @resource.email %>!</p>
|
||||
|
||||
<p>Someone has requested a link to change your password. You can do this through the link below.</p>
|
||||
|
||||
<p><%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %></p>
|
||||
|
||||
<p>If you didn't request this, please ignore this email.</p>
|
||||
<p>Your password won't change until you access the link above and create a new one.</p>
|
|
@ -1,7 +0,0 @@
|
|||
<p>Hello <%= @resource.email %>!</p>
|
||||
|
||||
<p>Your account has been locked due to an excessive number of unsuccessful sign in attempts.</p>
|
||||
|
||||
<p>Click the link below to unlock your account:</p>
|
||||
|
||||
<p><%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %></p>
|
|
@ -1,16 +0,0 @@
|
|||
<h2>Change your password</h2>
|
||||
|
||||
<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :put }) do |f| %>
|
||||
<%= devise_error_messages! %>
|
||||
<%= f.hidden_field :reset_password_token %>
|
||||
|
||||
<div><%= f.label :password, "New password" %><br />
|
||||
<%= f.password_field :password, :autofocus => true %></div>
|
||||
|
||||
<div><%= f.label :password_confirmation, "Confirm new password" %><br />
|
||||
<%= f.password_field :password_confirmation %></div>
|
||||
|
||||
<div><%= f.submit "Change my password" %></div>
|
||||
<% end %>
|
||||
|
||||
<%= render "devise/shared/links" %>
|
|
@ -1,10 +0,0 @@
|
|||
<h2>Forgot your password?</h2>
|
||||
|
||||
<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f| %>
|
||||
<%= devise_error_messages! %>
|
||||
|
||||
<%= form_email_field f, :email %>
|
||||
<%= f.submit "Send me reset password instructions", class: "btn btn-primary" %>
|
||||
<% end %>
|
||||
|
||||
<%= render "devise/shared/links" %>
|
|
@ -1,31 +1,15 @@
|
|||
<h2>Edit <%= resource_name.to_s.humanize %></h2>
|
||||
<%= render 'flash' %>
|
||||
|
||||
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
|
||||
<%= devise_error_messages! %>
|
||||
<%= f_form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %>
|
||||
<%= f.error_messages %>
|
||||
|
||||
<% if devise_mapping.confirmable? && resource.pending_reconfirmation? %>
|
||||
<div>Currently waiting confirmation for: <%= resource.unconfirmed_email %></div>
|
||||
<% end %>
|
||||
<%= f.password_field :password %>
|
||||
<%= f.password_field :password_confirmation %>
|
||||
|
||||
<%= form_password_field f, :password %>
|
||||
<%= form_password_field f, :password_confirmation %>
|
||||
<%= f.password_field :current_password %>
|
||||
|
||||
<%= form_password_field f, :current_password %>
|
||||
|
||||
<%= f.label :avatar %>
|
||||
<%= f.file_field :avatar %>
|
||||
|
||||
<%= f.submit "Update", class: 'btn btn-primary' %>
|
||||
<% end %>
|
||||
|
||||
<% if current_user.dagschotel.present? %>
|
||||
<h3>Current Dagschotel:</h3>
|
||||
<div>
|
||||
<%= image_tag current_user.dagschotel.avatar %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<h4>Choose new Dagschotel:</h4>
|
||||
<% Product.all.each do |p| %>
|
||||
<%= link_to image_tag(p.avatar), user_dagschotel_path(current_user, p) %>
|
||||
<%= f.submit "Update" %>
|
||||
<% end %>
|
||||
|
|
|
@ -1,20 +1,16 @@
|
|||
<h2>Sign up</h2>
|
||||
|
||||
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
|
||||
<%= devise_error_messages! %>
|
||||
<%= f_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
|
||||
<%= f.error_messages %>
|
||||
|
||||
<%= form_text_field f, :nickname %>
|
||||
<%= form_text_field f, :name %>
|
||||
<%= form_text_field f, :last_name %>
|
||||
<%= f.text_field :nickname %>
|
||||
|
||||
<%= form_password_field f, :password %>
|
||||
<%= form_password_field f, :password_confirmation %>
|
||||
<%= f.password_field :password %>
|
||||
<%= f.password_field :password_confirmation %>
|
||||
|
||||
<%= f.label :avatar %>
|
||||
<%= f.file_field :avatar %>
|
||||
|
||||
<br />
|
||||
<%= f.submit "Sign up", class: 'btn btn-primary' %>
|
||||
<%= f.submit "Sign up" %>
|
||||
<% end %>
|
||||
|
||||
<%= render "devise/shared/links" %>
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
<h2>Sign in</h2>
|
||||
<div class="alert alert-info">Partners sign in using the link sent by email.</div>
|
||||
<%= render partial: 'flash' %>
|
||||
|
||||
<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
|
||||
<div class="sign-in">
|
||||
<%= f_form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %>
|
||||
<%= f.text_field :nickname %>
|
||||
<%= f.password_field :password %>
|
||||
|
||||
<%= form_text_field f, :nickname %>
|
||||
<%= form_password_field f, :password %>
|
||||
<% if devise_mapping.rememberable? %>
|
||||
<%= f.check_box :remember_me %>
|
||||
<% end %>
|
||||
|
||||
<% if devise_mapping.rememberable? %>
|
||||
<%= form_check_box f, :remember_me %>
|
||||
<%= f.submit "Sign in" %>
|
||||
<% end %>
|
||||
|
||||
<%= f.submit "Sign in", class: "btn btn-primary" %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= render "devise/shared/links" %>
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
<%- if controller_name != 'sessions' %>
|
||||
<%= link_to "Sign in", new_session_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<% if devise_mapping.registerable? && controller_name != 'registrations' %>
|
||||
<% link_to "Sign up", new_registration_path(resource_name) %>
|
||||
<% end %>
|
||||
|
||||
<%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %>
|
||||
<%= link_to "Forgot your password?", new_password_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
|
||||
<%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %>
|
||||
<%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %><br />
|
||||
<% end -%>
|
||||
|
||||
<%- if devise_mapping.omniauthable? %>
|
||||
<%- resource_class.omniauth_providers.each do |provider| %>
|
||||
<%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider) %><br />
|
||||
<% end -%>
|
||||
<% end -%>
|
|
@ -1,16 +0,0 @@
|
|||
<h2>Resend unlock instructions</h2>
|
||||
|
||||
<%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %>
|
||||
<%= devise_error_messages! %>
|
||||
|
||||
<div class="field">
|
||||
<%= f.label :nickname %><br />
|
||||
<%= f.email_field :nickname, autofocus: true %>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<%= f.submit "Resend unlock instructions" %>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%= render "devise/shared/links" %>
|
|
@ -1,7 +1,8 @@
|
|||
<footer class="footer">
|
||||
<% unless current_user && current_user.koelkast? %>
|
||||
<footer class="footer">
|
||||
<small>
|
||||
<%= link_to "Tab", root_path %></a>
|
||||
by <%= link_to "Zeus WPI", "//zeus.ugent.be" %>
|
||||
by <%= link_to "Zeus WPI", "//zeus.ugent.be" %>
|
||||
</small>
|
||||
<nav>
|
||||
<ul>
|
||||
|
@ -10,3 +11,4 @@
|
|||
</ul>
|
||||
</nav>
|
||||
</footer>
|
||||
<% end %>
|
||||
|
|
|
@ -7,60 +7,66 @@
|
|||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<%= link_to "Taþ", root_path, class: "navbar-brand" %>
|
||||
<%= link_to "Taþ", root_path, class: "navbar-brand nav-logo" %>
|
||||
</div>
|
||||
|
||||
<!-- Collect the nav links, forms, and other content for toggling -->
|
||||
<div class="collapse navbar-collapse">
|
||||
<div class="hidden-xs navbar-form navbar-right">
|
||||
<div class="form-group">
|
||||
<% if user_signed_in? %>
|
||||
<%= button_to "Logout", destroy_user_session_path, class: "btn btn-default form-control", method: :delete %>
|
||||
<% else %>
|
||||
<%= link_to "Login", new_user_session_path, class: "btn btn-success form-control" %>
|
||||
<%= link_to "Register", new_user_registration_path, class: "btn btn-default form-control" %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><%= mail_to "tab@zeus.ugent.be", "Send feedback" %></li>
|
||||
<% if user_signed_in? %>
|
||||
<% if can? :manage, :all %>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Products <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><%= link_to "List", products_path %></li>
|
||||
<li><%= link_to "Add product" , new_product_path %></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Users <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><%= link_to "List" , users_path %></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><%= link_to 'Download schulden', admins_schulden_path(format: :csv) %>/li>
|
||||
<% unless current_user && current_user.koelkast? %>
|
||||
<div class="collapse navbar-collapse">
|
||||
<div class="hidden-xs navbar-form navbar-right">
|
||||
<div class="form-group">
|
||||
<% if user_signed_in? %>
|
||||
<%= button_to "Logout", destroy_user_session_path, class: "btn btn-default form-control", method: :delete %>
|
||||
<% else %>
|
||||
<%= link_to "Login", new_user_session_path, class: "btn btn-success form-control" %>
|
||||
<%= link_to "Register", new_user_registration_path, class: "btn btn-default form-control" %>
|
||||
<% end %>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Logged in as <%= current_user.nickname %> <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><%= link_to "Edit password", edit_user_registration_path %></li>
|
||||
</ul>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
|
||||
<div class="visible-xs navbar-form">
|
||||
<div class="form-group">
|
||||
<% if user_signed_in? %>
|
||||
<%= button_to "Logout", destroy_user_session_path, class: "btn btn-default form-control", method: :delete %>
|
||||
<% else %>
|
||||
<%= link_to "Login", new_user_session_path, class: "btn btn-success form-control" %>
|
||||
<%= link_to "Register", new_user_registration_path, class: "btn btn-default form-control" %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><%= mail_to "tab@zeus.ugent.be", "Send feedback" %></li>
|
||||
<% if user_signed_in? %>
|
||||
<% if can? :manage, :all %>
|
||||
<li>
|
||||
<%= link_to "Place order", orders_path %>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Products <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><%= link_to "List", products_path %></li>
|
||||
<li><%= link_to "Add product" , new_product_path %></li>
|
||||
<li><%= link_to "Add stock", stock_products_path %></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Users <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><%= link_to "List" , users_path %></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><%= link_to 'Download schulden', admins_schulden_path(format: :csv) %></li>
|
||||
<% end %>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Logged in as <%= current_user.nickname %> <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><%= link_to "Edit password", edit_user_registration_path %></li>
|
||||
</ul>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
|
||||
<div class="visible-xs navbar-form">
|
||||
<div class="form-group">
|
||||
<% if user_signed_in? %>
|
||||
<%= button_to "Logout", destroy_user_session_path, class: "btn btn-default form-control", method: :delete %>
|
||||
<% else %>
|
||||
<%= link_to "Login", new_user_session_path, class: "btn btn-success form-control" %>
|
||||
<%= link_to "Register", new_user_registration_path, class: "btn btn-default form-control" %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
</div><!-- /.navbar-collapse -->
|
||||
</div><!-- /.container-fluid -->
|
||||
|
|
|
@ -7,19 +7,18 @@
|
|||
<%= csrf_meta_tags %>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<%= render "layouts/header" %>
|
||||
<% if current_user && current_user.koelkast? && !Rails.env.development? %>
|
||||
<body oncontextmenu="return false">
|
||||
<% else %>
|
||||
<body>
|
||||
<% end %>
|
||||
<%= render 'layouts/header' %>
|
||||
<div class="container">
|
||||
<div class="container" >
|
||||
<%= yield %>
|
||||
<div class="container">
|
||||
<%= yield %>
|
||||
</div>
|
||||
<%= render "layouts/footer" %>
|
||||
<%= render 'layouts/footer' %>
|
||||
<%= debug(params) if Rails.env.development? %>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
17
app/views/order_items/_order_item.html.erb
Normal file
17
app/views/order_items/_order_item.html.erb
Normal file
|
@ -0,0 +1,17 @@
|
|||
<div class="col-md-3 form_products">
|
||||
<div class="thumbnail ">
|
||||
<div class="form_row center">
|
||||
<div class="form_row_image">
|
||||
<%= image_tag product.avatar %>
|
||||
</div>
|
||||
<div class="caption">
|
||||
<%= content_tag :h4, "#{product.name} (#{euro(product.price)})" %>
|
||||
<%= f.counter :count, skip_label: true, wrapper_class: "input-group", class: "row_counter" %>
|
||||
<%= f.fields_for :product do |product| %>
|
||||
<%= product.hidden_field :price_cents, class: :price %>
|
||||
<%= product.hidden_field :stock, class: :stock %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,19 +0,0 @@
|
|||
<div class="col-md-3 form_products">
|
||||
<div class="thumbnail ">
|
||||
<div class="form_row center">
|
||||
<%= image_tag f.object.product.avatar %>
|
||||
<div class="caption">
|
||||
<h3><%= f.object.product.name %> - <%= content_tag :span, euro(f.object.product.price), class: "price" %></h3>
|
||||
<p>
|
||||
<div class="input-group">
|
||||
<%= render 'btn_dec', id: f.object.product_id %>
|
||||
<%= f.text_field :count, class: 'form-control row_counter', value: 0 %>
|
||||
<%= f.hidden_field :price, value: f.object.product.price, class: :price %>
|
||||
<%= render 'btn_inc', id: f.object.product_id %>
|
||||
<%= f.hidden_field :product_id %>
|
||||
</div>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,8 +0,0 @@
|
|||
<%= f.label :total_price %>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">€</span>
|
||||
<%= f.number_field :total_price, step: :any, class: 'form-control input-lg' %>
|
||||
<span class="input-group-btn">
|
||||
<%= f.submit "Order!", class: "btn btn-primary input-lg" %>
|
||||
</span>
|
||||
</div>
|
|
@ -1,5 +1,13 @@
|
|||
<p>
|
||||
<% order.products.each do |p| %>
|
||||
<%= p.count(order).to_s + " " + p.name %>
|
||||
<% end %>
|
||||
</p>
|
||||
<tr>
|
||||
<td class="order_date">
|
||||
<%= order.created_at.strftime("%d %b %Y at %H:%M") %>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<%= order.to_sentence %>
|
||||
</td>
|
||||
<td>
|
||||
<%= euro(order.price) %>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
10
app/views/orders/_price.html.erb
Normal file
10
app/views/orders/_price.html.erb
Normal file
|
@ -0,0 +1,10 @@
|
|||
<div class="col-md-3 form_total">
|
||||
<%= f.label :total_price %>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">€</span>
|
||||
<%= f.number_field :price, skip_label: true, step: :any, class: 'form-control big-form-field' %>
|
||||
<span class="input-group-btn">
|
||||
<%= f.submit "Order!", class: "btn btn-primary big-form-button" %>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
|
@ -1,9 +0,0 @@
|
|||
<% users.each do |user| %>
|
||||
<div class="thumbnail overview">
|
||||
<%= link_to image_tag(user.dagschotel.avatar, class: "img-circle dagschotel"), user_quickpay_path(user) unless user.dagschotel.nil? %>
|
||||
<%= link_to image_tag(user.avatar , class: "img-circle avatar"), new_user_order_path(user) %>
|
||||
|
||||
<%= link_to user.name , new_user_order_path(user), class: "btn btn-info",
|
||||
style: get_color_style(user) %>
|
||||
</div>
|
||||
<% end %>
|
|
@ -1,11 +0,0 @@
|
|||
<%= render partial: 'flash' %>
|
||||
|
||||
<div class="col-md-6">
|
||||
<h3 class="center" >sort by name</h3>
|
||||
<%= render 'orders/user_list', users: @users_by_name %>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<h3 class="center" >sort by order</h3>
|
||||
<%= render 'orders/user_list', users: @users_by_order %>
|
||||
</div>
|
|
@ -1,18 +1,15 @@
|
|||
<h3>Order for <%= @user.nickname %></h3>
|
||||
<h3>Order for <%= @user.nickname %> (Huidige schuld: <%= euro(@user.debt) %>)</h3>
|
||||
|
||||
<div class="row">
|
||||
<%= form_for @order, url: user_orders_path(@user) do |f| %>
|
||||
<%= render 'application/errors', model: @order %>
|
||||
<%= f_form_for [@user, @order] do |f| %>
|
||||
<%= f.error_messages %>
|
||||
|
||||
<div class="col-md-12">
|
||||
<%= f.fields_for :order_products do |op_field| %>
|
||||
<%= render 'order_products/form_row', f: op_field %>
|
||||
<% end %>
|
||||
<%= f.fields_for :order_items do |op_field| %>
|
||||
<%= render op_field.object, f: op_field, product: op_field.object.product %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class="col-md-3 form_total">
|
||||
<%= render 'order_products/total_price', f: f %>
|
||||
</div>
|
||||
|
||||
<% end %>
|
||||
<%= render 'orders/price', f: f %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
7
app/views/orders/overview.html.erb
Normal file
7
app/views/orders/overview.html.erb
Normal file
|
@ -0,0 +1,7 @@
|
|||
<%= render partial: 'flash' %>
|
||||
|
||||
<div class="row">
|
||||
<% @users.each do |user| %>
|
||||
<%= render 'users/new_order', user: user %>
|
||||
<% end %>
|
||||
</div>
|
|
@ -1,17 +1,15 @@
|
|||
<div class="row">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<%= form_for @product, html: { multipart: true } do |f| %>
|
||||
<%= render 'application/errors', model: @product %>
|
||||
<div class="col-md-6 col-md-offset-3 sign-in">
|
||||
<%= f_form_for @product, html: { multipart: true } do |f| %>
|
||||
<%= f.error_messages %>
|
||||
|
||||
<%= form_text_field f, :name %>
|
||||
|
||||
<%= f.label :price %>
|
||||
<%= f.number_field :price, value: number_with_precision(f.object.price, precision: 2), class: 'form-control', placeholder: "0.00", step: :any %>
|
||||
|
||||
<%= f.label :avatar %>
|
||||
<%= f.text_field :name %>
|
||||
<%= f.price_field :price %>
|
||||
<%= f.collection_select :category, Product.categories.keys %>
|
||||
<%= f.number_field :stock %>
|
||||
<%= f.file_field :avatar %>
|
||||
|
||||
<%= f.submit class: "btn btn-primary" %>
|
||||
<%= f.submit %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
|
22
app/views/products/_index.html.erb
Normal file
22
app/views/products/_index.html.erb
Normal file
|
@ -0,0 +1,22 @@
|
|||
<div role="tabpanel">
|
||||
<!-- Nav tabs -->
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li role="presentation" class="active"><a href="#all" role="tab" data-toggle="tab">All</a></li>
|
||||
<% @categories.each do |o, i| %>
|
||||
<li role="presentation"><a href="#<%= o %>" aria-controls="<%= o %>" role="tab" data-toggle="tab"><%= o.titleize %></a></li>
|
||||
<% end %>
|
||||
</ul>
|
||||
|
||||
<!-- Tab panes -->
|
||||
<div class="tab-content">
|
||||
<br />
|
||||
<div role="tabpanel" class="tab-pane active" id="all">
|
||||
<%= render @products %>
|
||||
</div>
|
||||
<% @categories.each do |o, i| %>
|
||||
<div role="tabpanel" class="tab-pane" id="<%= o %>">
|
||||
<%= render @products.where(category: i) %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
14
app/views/products/_links.html.erb
Normal file
14
app/views/products/_links.html.erb
Normal file
|
@ -0,0 +1,14 @@
|
|||
<%- if controller_name == 'products' && current_user && current_user.admin? %>
|
||||
<%= link_to "Edit", edit_product_path(product), class: "btn btn-default" %>
|
||||
<%= link_to "Delete", product_path(product), method: :delete, class: "btn btn-danger", data: {confirm: 'Are you sure?'} %>
|
||||
<% end -%>
|
||||
|
||||
<%- if controller_name == 'users' %>
|
||||
<div class="product_dagschotel">
|
||||
<% if current_user.dagschotel != product %>
|
||||
<%= link_to "Make dagschotel", user_dagschotel_path(current_user, product), class: "btn btn-default" %>
|
||||
<% else %>
|
||||
<%= link_to "Huidige dagschotel", user_dagschotel_path(current_user, product), class: "btn btn-success", disabled: true %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end -%>
|
|
@ -1,12 +1,13 @@
|
|||
<div class="col-md-3">
|
||||
<div class="thumbnail">
|
||||
<%= image_tag product.avatar %>
|
||||
<div class="thumbnail pic">
|
||||
<div class="form_row_image">
|
||||
<%= image_tag product.avatar %>
|
||||
</div>
|
||||
<div class="caption">
|
||||
<h3><%= product.name %> - <%= euro(product.price) %></h3>
|
||||
<p>
|
||||
<%= link_to "Edit", edit_product_path(product), class: "btn btn-default" %>
|
||||
<%= link_to "Delete", product_path(product), method: :delete, class: "btn btn-danger", data: {confirm: 'Are you sure?'} %>
|
||||
</p>
|
||||
<h4><%= product.name %></h4>
|
||||
<h3><%= euro(product.price) %></h3>
|
||||
<h6>(In stock: <%= product.stock %>)</h6>
|
||||
<%= render 'products/links', product: product %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
<h1>All products</h1>
|
||||
<%= render partial: 'flash' %>
|
||||
|
||||
<div class="row products">
|
||||
<div class="col-md-12">
|
||||
<%= render @products %>
|
||||
</div>
|
||||
</div>
|
||||
<%= render 'products/index' %>
|
||||
|
|
14
app/views/products/stock.html.erb
Normal file
14
app/views/products/stock.html.erb
Normal file
|
@ -0,0 +1,14 @@
|
|||
<div class="row">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<%= form_tag do %>
|
||||
<% @products.each do |product| %>
|
||||
<%= fields_for "products[]", product do |form| %>
|
||||
<%= image_tag product.avatar %>
|
||||
<%= form.number_field :stock_inc, value: 0, class: 'form-control' %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%= submit_tag "Insert stock", class: 'btn btn-primary' %>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
10
app/views/users/_new_order.html.erb
Normal file
10
app/views/users/_new_order.html.erb
Normal file
|
@ -0,0 +1,10 @@
|
|||
<div class="col-md-2 overviewthumbnail">
|
||||
<% unless user.dagschotel.nil? %>
|
||||
<%= link_to user_quickpay_path(user) do %>
|
||||
<%= image_tag user.dagschotel.avatar(:dagschotel), class: "img-circle dagschotel" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%= link_to image_tag(user.avatar(:large) , class: "img-circle avatar"), new_user_order_path(user) %>
|
||||
<%= link_to user.nickname , new_user_order_path(user), class: "btn btn-info", style: get_color_style(user) %>
|
||||
</div>
|
|
@ -1,18 +1,11 @@
|
|||
<div class="col-md-3">
|
||||
<div class="thumbnail monopoly">
|
||||
<h3 class="header" style="background-color: #<%=get_color(user)%>;" ><%= user.full_name %></h3>
|
||||
<div class="caption">
|
||||
<%= image_tag(user.avatar , class: "img-circle avatar") %>
|
||||
<p><strong>Name:</strong> <%= user.name %></p>
|
||||
<p><strong>Last name:</strong> <%= user.last_name %></p>
|
||||
<p><strong>Nickname:</strong> <%= user.nickname %></p>
|
||||
<p><strong>Balance:</strong> <%= euro(user.balance) %></p>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<p>
|
||||
<%= link_to "Delete", user_path(user), method: :delete, class: "btn btn-danger", data: {confirm: 'Are you sure?'} %>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<tr>
|
||||
<td><%= user.id %></td>
|
||||
<td><%= image_tag user.avatar(:small) %></td>
|
||||
<td><%= user.nickname %></td>
|
||||
<td><%= euro(user.debt) %></td>
|
||||
<% if current_user.admin? %>
|
||||
<td>
|
||||
<%= link_to "Delete", user_path(user), method: :delete, class: "btn btn-danger", data: { confirm: "Are you sure?" } %>
|
||||
</td>
|
||||
<% end %>
|
||||
</tr>
|
||||
|
|
2
app/views/users/edit_dagschotel.html.erb
Normal file
2
app/views/users/edit_dagschotel.html.erb
Normal file
|
@ -0,0 +1,2 @@
|
|||
<h3>Choose new Dagschotel</h4>
|
||||
<%= render 'products/index' %>
|
|
@ -1,8 +1,17 @@
|
|||
<h1>All users</h1>
|
||||
<%= render partial: 'flash' %>
|
||||
|
||||
<div class="row users">
|
||||
<div class="col-md-12">
|
||||
<%= render @users %>
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<h1>All users</h1>
|
||||
<%= render partial: 'flash' %>
|
||||
|
||||
<table id="users-table" class="table table-striped">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th></th>
|
||||
<th>Nickname</th>
|
||||
<th>Debt</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<%= render @users %>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,25 +1,30 @@
|
|||
<%= render partial: 'flash' %>
|
||||
<div class="row">
|
||||
<aside class="col-md-4">
|
||||
<section class="user_info">
|
||||
<h1>Name: <%= @user.name %></h1>
|
||||
<h1>Last name: <%= @user.last_name %></h1>
|
||||
<h1>Nickname: <%= @user.nickname %></h1>
|
||||
<h1>Balance: <%= @user.balance %></h1>
|
||||
<h1>User id: <%= @user.id %></h1>
|
||||
<p>
|
||||
<%= link_to "edit" , edit_user_registration_path %>
|
||||
</p>
|
||||
|
||||
</section>
|
||||
</aside>
|
||||
|
||||
<div class="col-md-8">
|
||||
<% if @user.orders.any? %>
|
||||
<h3>Orders (<%= @user.orders.count %>)</h3>
|
||||
<ol class="orders">
|
||||
<%= render @orders %>
|
||||
</ol>
|
||||
<%= will_paginate @orders %>
|
||||
<div class="user_info">
|
||||
<% if current_user == @user %>
|
||||
<h5>
|
||||
<%= link_to "[Edit dagschotel]" , user_edit_dagschotel_path(@user) %>
|
||||
<%= link_to "[Edit profile]" , edit_user_registration_path %>
|
||||
</h5>
|
||||
<% end %>
|
||||
<h2><%= @user.nickname %></h2>
|
||||
<%= button_to "PLACE ORDER!", new_user_order_path(@user), method: :get if current_user == @user %>
|
||||
<div class="debt">DEBT: <%= euro(@user.debt) %></div>
|
||||
</div>
|
||||
|
||||
<% if @orders.any? %>
|
||||
<div class="stats">
|
||||
<h4>Total products</h4>
|
||||
Total: <br/><ul><li><%= @categories.map{|c| pluralize(c.count, c.category)}.join(", ")%></li></ul>
|
||||
<br/>
|
||||
Specifics:<br/>
|
||||
<ul>
|
||||
<%= @products.map{ |p| content_tag(:li, pluralize(p.count, p.name)) }.join("\n").html_safe %>
|
||||
</ul>
|
||||
|
||||
<h4>All orders (<%= @user.orders_count %>)</h4>
|
||||
<table class="orders"><%= render @orders %></table>
|
||||
<%= will_paginate @orders %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
#!/usr/bin/env ruby
|
||||
begin
|
||||
load File.expand_path("../spring", __FILE__)
|
||||
rescue LoadError
|
||||
end
|
||||
APP_PATH = File.expand_path('../../config/application', __FILE__)
|
||||
require_relative '../config/boot'
|
||||
require 'rails/commands'
|
||||
|
|
4
bin/rake
4
bin/rake
|
@ -1,8 +1,4 @@
|
|||
#!/usr/bin/env ruby
|
||||
begin
|
||||
load File.expand_path("../spring", __FILE__)
|
||||
rescue LoadError
|
||||
end
|
||||
require_relative '../config/boot'
|
||||
require 'rake'
|
||||
Rake.application.run
|
||||
|
|
|
@ -19,5 +19,6 @@ module Tab002
|
|||
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
||||
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
||||
# config.i18n.default_locale = :de
|
||||
config.active_record.raise_in_transactional_callbacks = true
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,7 +13,7 @@ Rails.application.configure do
|
|||
config.eager_load = false
|
||||
|
||||
# Configure static asset server for tests with Cache-Control for performance.
|
||||
config.serve_static_assets = true
|
||||
config.serve_static_files = true
|
||||
config.static_cache_control = 'public, max-age=3600'
|
||||
|
||||
# Show full error reports and disable caching.
|
||||
|
@ -34,6 +34,8 @@ Rails.application.configure do
|
|||
# Print deprecation notices to the stderr.
|
||||
config.active_support.deprecation = :stderr
|
||||
|
||||
config.active_support.test_order = :random
|
||||
|
||||
# Raises error for missing translations
|
||||
# config.action_view.raise_on_missing_translations = true
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# Use this hook to configure devise mailer, warden hooks and so forth.
|
||||
# Many of these configuration options can be set straight in your model.
|
||||
# require 'yaml'
|
||||
Devise.setup do |config|
|
||||
# The secret key used by Devise. Devise uses this key to generate
|
||||
# random tokens. Changing this key will render invalid all existing
|
||||
|
@ -232,7 +233,7 @@ Devise.setup do |config|
|
|||
# ==> OmniAuth
|
||||
# Add a new OmniAuth provider. Check the wiki for more information on setting
|
||||
# up on your models and hooks.
|
||||
# config.omniauth :github, 'APP_ID', 'APP_SECRET', scope: 'user,public_repo'
|
||||
config.omniauth :zeuswpi, Rails.application.secrets.omniauth_client_id, Rails.application.secrets.omniauth_client_secret
|
||||
|
||||
# ==> Warden configuration
|
||||
# If you want to use other strategies, that are not supported by Devise, or
|
||||
|
|
44
config/initializers/zeuswpi.rb
Normal file
44
config/initializers/zeuswpi.rb
Normal file
|
@ -0,0 +1,44 @@
|
|||
require 'omniauth-oauth2'
|
||||
|
||||
module OmniAuth
|
||||
module Strategies
|
||||
class Zeuswpi < OmniAuth::Strategies::OAuth2
|
||||
|
||||
option :provider_ignores_state, true
|
||||
|
||||
# Give your strategy a name.
|
||||
option :name, "zeuswpi"
|
||||
|
||||
# This is where you pass the options you would pass when
|
||||
# initializing your consumer from the OAuth gem.
|
||||
option :client_options, {
|
||||
site: "http://kelder.zeus.ugent.be",
|
||||
authorize_url: "/oauth/oauth2/authorize/",
|
||||
token_url: "/oauth/oauth2/token/",
|
||||
}
|
||||
|
||||
# These are called after authentication has succeeded. If
|
||||
# possible, you should try to set the UID without making
|
||||
# additional calls (if the user id is returned with the token
|
||||
# or as a URI parameter). This may not be possible with all
|
||||
# providers.
|
||||
uid{ raw_info['username'] }
|
||||
|
||||
info do
|
||||
{
|
||||
# :nickname => raw_info['username'],
|
||||
}
|
||||
end
|
||||
|
||||
extra do
|
||||
{
|
||||
'raw_info' => raw_info
|
||||
}
|
||||
end
|
||||
|
||||
def raw_info
|
||||
@raw_info ||= access_token.get('/oauth/api/current_user/').parsed
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,16 +1,34 @@
|
|||
Rails.application.routes.draw do
|
||||
devise_for :users, controllers: { omniauth_callbacks: "callbacks" }
|
||||
|
||||
root "orders#index"
|
||||
|
||||
devise_for :users
|
||||
|
||||
resources :users do
|
||||
resources :orders, only: [:new, :create, :index] do
|
||||
devise_scope :user do
|
||||
unauthenticated :user do
|
||||
root to: 'devise/sessions#new'
|
||||
end
|
||||
|
||||
authenticated :user, ->(u) { u.koelkast? } do
|
||||
root to: 'orders#overview', as: :koelkast_root
|
||||
end
|
||||
|
||||
authenticated :user, ->(u) { !u.koelkast? } do
|
||||
root to: 'users#show', as: :user_root
|
||||
end
|
||||
end
|
||||
|
||||
resources :users do
|
||||
resources :orders
|
||||
get 'quickpay' => 'orders#quickpay'
|
||||
get 'dagschotel/edit' => 'users#edit_dagschotel', as: 'edit_dagschotel'
|
||||
get 'dagschotel/:product_id' => 'users#update_dagschotel', as: 'dagschotel'
|
||||
end
|
||||
|
||||
resources :products do
|
||||
collection do
|
||||
get 'stock' => 'products#stock', as: 'stock'
|
||||
post 'stock' => 'products#update_stock', as: 'update_stock'
|
||||
end
|
||||
get 'quickpay' => 'orders#quickpay'
|
||||
get 'dagschotel/:product_id' => 'users#dagschotel', as: "dagschotel"
|
||||
end
|
||||
|
||||
resources :products
|
||||
get 'admins' => 'admins#schulden', as: "admins_schulden"
|
||||
get 'overview' => 'orders#overview', as: "orders"
|
||||
end
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
development:
|
||||
secret_key_base: 5d40610321e19e4f71ee2ba8af4f426fe15096c405da3800c6b33bed6779f2d11f55a0edc455974b19a01fd71f6cd508dba980305dbc55ff82521a2d12f891d8
|
||||
omniauth_client_id: "client_id"
|
||||
omniauth_client_secret: "client_secret"
|
||||
|
||||
test:
|
||||
secret_key_base: 961437e28e7d6055ffaad9cf1f8d614354f57f10cb2d7601c9d6ede72a03b9c9535ad9e63507e3eb31252c4895970a63117493408f2e9a46c7a0c4a5a7836b81
|
||||
|
@ -20,3 +22,6 @@ test:
|
|||
# instead read values from the environment.
|
||||
production:
|
||||
secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>
|
||||
omniauth_client_id: ""
|
||||
omniauth_client_secret: ""
|
||||
|
||||
|
|
5
db/migrate/20141210200008_add_category_to_products.rb
Normal file
5
db/migrate/20141210200008_add_category_to_products.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class AddCategoryToProducts < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :products, :category, :integer, default: 0
|
||||
end
|
||||
end
|
5
db/migrate/20141217063222_add_koelkast_to_users.rb
Normal file
5
db/migrate/20141217063222_add_koelkast_to_users.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class AddKoelkastToUsers < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :users, :koelkast, :boolean, default: false
|
||||
end
|
||||
end
|
5
db/migrate/20150113155744_add_stock_to_products.rb
Normal file
5
db/migrate/20150113155744_add_stock_to_products.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class AddStockToProducts < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :products, :stock, :integer, default: 0
|
||||
end
|
||||
end
|
5
db/migrate/20150204155216_change_price_to_price_cents.rb
Normal file
5
db/migrate/20150204155216_change_price_to_price_cents.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class ChangePriceToPriceCents < ActiveRecord::Migration
|
||||
def change
|
||||
rename_column :products, :price, :price_cents
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class ChangeDefaultOrderProductCountToZero < ActiveRecord::Migration
|
||||
def change
|
||||
change_column_default :order_products, :count, 0
|
||||
end
|
||||
end
|
13
db/migrate/20150209113630_create_versions.rb
Normal file
13
db/migrate/20150209113630_create_versions.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
class CreateVersions < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :versions do |t|
|
||||
t.string :item_type, :null => false
|
||||
t.integer :item_id, :null => false
|
||||
t.string :event, :null => false
|
||||
t.string :whodunnit
|
||||
t.text :object
|
||||
t.datetime :created_at
|
||||
end
|
||||
add_index :versions, [:item_type, :item_id]
|
||||
end
|
||||
end
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue