Merge branch 'master' of github.com:ZeusWPI/Tab

This commit is contained in:
Tom Naessens 2015-03-19 22:53:53 +01:00
commit edef683f86
144 changed files with 1843 additions and 985 deletions

1
.capistrano/metrics Normal file
View file

@ -0,0 +1 @@
full

4
.gitignore vendored
View file

@ -18,3 +18,7 @@
# Avatars of producst
public/system/products
public/system/users
.project
/coverage

7
.simplecov Normal file
View 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
View 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
View file

@ -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'

View file

@ -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)

View file

@ -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.

View 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/

View file

@ -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)

View file

@ -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;
}

View 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/

View file

@ -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;
}
}

View 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;
}
}

View file

@ -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;
}

View 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 {
}

View file

@ -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;
}

View file

@ -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\""

View file

@ -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

View 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

View file

@ -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

View file

@ -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

View file

@ -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

View 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

View file

@ -1,2 +0,0 @@
module AdminsHelper
end

View file

@ -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

View file

@ -0,0 +1,2 @@
module CallbacksHelper
end

View file

@ -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">&times;</button>
<strong>Error!</strong> #{sentence}
#{messages}
</div>
HTML
html.html_safe
end
end

View file

@ -1,2 +0,0 @@
module OrdersHelper
end

View file

@ -1,2 +0,0 @@
module ProductsHelper
end

View file

@ -1,2 +0,0 @@
module UsersHelper
end

View file

@ -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

View file

@ -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
View 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

View file

@ -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

View file

@ -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

View file

@ -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

View 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

View file

@ -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 %>

View file

@ -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>

View file

@ -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>

View file

@ -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 %>

View file

@ -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">&times;</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">&times;</button>
<strong>Error!</strong> <%= flash[:alert] %>
</div>
<% end %>
</div>

View file

@ -1,6 +0,0 @@
<div class="checkbox">
<label>
<%= f.label tag %>
</label>
<%= f.check_box tag %>
</div>

View file

@ -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>

View file

@ -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>

View file

@ -1,4 +0,0 @@
<div class="form-group">
<%= f.label tag %>:
<%= f.email_field tag, class: 'form-control' %>
</div>

View file

@ -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 %>

View file

@ -1,4 +0,0 @@
<div class="form-group">
<%= f.label tag %>:
<%= f.text_area tag, class: 'form-control ckeditor' %>
</div>

View file

@ -1,4 +0,0 @@
<div class="form-group">
<%= f.label tag %>:
<%= f.number_field tag, class: 'form-control', min: 0 %>
</div>

View file

@ -1,4 +0,0 @@
<div class="form-group">
<%= f.label tag %>:
<%= f.password_field tag, class: 'form-control' %>
</div>

View file

@ -1,4 +0,0 @@
<div class="form-group">
<%= f.label tag %>:
<%= f.text_area tag, class: 'form-control' %>
</div>

View file

@ -1,4 +0,0 @@
<div class="form-group">
<%= f.label tag %>:
<%= f.text_field tag, class: 'form-control' %>
</div>

View file

@ -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" %>

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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" %>

View file

@ -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" %>

View file

@ -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 %>

View file

@ -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" %>

View file

@ -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" %>

View file

@ -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 -%>

View file

@ -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" %>

View file

@ -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 %>

View file

@ -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 -->

View file

@ -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>

View 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>

View file

@ -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>

View file

@ -1,8 +0,0 @@
<%= f.label :total_price %>
<div class="input-group">
<span class="input-group-addon">&euro;</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>

View file

@ -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>

View 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">&euro;</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>

View file

@ -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 %>

View file

@ -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>

View file

@ -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>

View file

@ -0,0 +1,7 @@
<%= render partial: 'flash' %>
<div class="row">
<% @users.each do |user| %>
<%= render 'users/new_order', user: user %>
<% end %>
</div>

View file

@ -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>

View 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>

View 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 -%>

View file

@ -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>

View file

@ -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' %>

View 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>

View 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>

View file

@ -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>

View file

@ -0,0 +1,2 @@
<h3>Choose new Dagschotel</h4>
<%= render 'products/index' %>

View file

@ -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>

View file

@ -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>

View file

@ -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'

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View 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

View file

@ -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

View file

@ -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: ""

View file

@ -0,0 +1,5 @@
class AddCategoryToProducts < ActiveRecord::Migration
def change
add_column :products, :category, :integer, default: 0
end
end

View file

@ -0,0 +1,5 @@
class AddKoelkastToUsers < ActiveRecord::Migration
def change
add_column :users, :koelkast, :boolean, default: false
end
end

View file

@ -0,0 +1,5 @@
class AddStockToProducts < ActiveRecord::Migration
def change
add_column :products, :stock, :integer, default: 0
end
end

View file

@ -0,0 +1,5 @@
class ChangePriceToPriceCents < ActiveRecord::Migration
def change
rename_column :products, :price, :price_cents
end
end

View file

@ -0,0 +1,5 @@
class ChangeDefaultOrderProductCountToZero < ActiveRecord::Migration
def change
change_column_default :order_products, :count, 0
end
end

View 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