From e3c189d187adb1665538110eae389507255fff55 Mon Sep 17 00:00:00 2001 From: Benjamin ter Kuile Date: Fri, 24 Aug 2012 13:46:59 +0200 Subject: [PATCH] add testing device images and a lot more, before bootstrap:themed --- Gemfile | 4 + Gemfile.lock | 11 + app/assets/images/.DS_Store | Bin 0 -> 6148 bytes app/assets/images/frames/.DS_Store | Bin 0 -> 6148 bytes app/assets/images/frames/smartphone.png | Bin 0 -> 12556 bytes app/assets/images/frames/smartphone.svg | 685 ++++++++++++++ app/assets/images/frames/tablet.png | Bin 0 -> 34115 bytes app/assets/images/frames/tablet.svg | 894 ++++++++++++++++++ app/assets/javascripts/qrammer.js.coffee | 10 +- app/assets/stylesheets/application.css | 2 +- app/assets/stylesheets/phone/application.css | 13 + .../stylesheets/phone/structure.css.sass | 7 + app/assets/stylesheets/structure.css.sass | 30 + app/controllers/dashboard_controller.rb | 32 +- app/controllers/suppliers_controller.rb | 14 +- app/models/list.rb | 8 + app/views/dashboard/home.html.slim | 18 +- app/views/dashboard/phone_home.html.slim | 11 + app/views/dashboard/show_products.html.slim | 37 +- app/views/dashboard/user_history.html.slim | 2 + app/views/layouts/phone.html.slim | 55 ++ app/views/layouts/tablet.html.slim | 56 ++ app/views/suppliers/active_lists.html.slim | 3 +- ...list.html.slim => active_orders.html.slim} | 4 +- config/environments/development.rb | 7 + config/locales/en.yml | 3 + config/routes.rb | 7 +- spec/factories/list_factory.rb | 5 + spec/factories/supplier_factory.rb | 5 + spec/factories/table_factory.rb | 6 + spec/models/list_spec.rb | 17 + spec/spec_helper.rb | 65 ++ spec/support/end_with_matcher.rb | 43 + 33 files changed, 2003 insertions(+), 51 deletions(-) create mode 100644 app/assets/images/.DS_Store create mode 100644 app/assets/images/frames/.DS_Store create mode 100644 app/assets/images/frames/smartphone.png create mode 100644 app/assets/images/frames/smartphone.svg create mode 100644 app/assets/images/frames/tablet.png create mode 100644 app/assets/images/frames/tablet.svg create mode 100644 app/assets/stylesheets/phone/application.css create mode 100644 app/assets/stylesheets/phone/structure.css.sass create mode 100644 app/views/dashboard/phone_home.html.slim create mode 100644 app/views/dashboard/user_history.html.slim create mode 100644 app/views/layouts/phone.html.slim create mode 100644 app/views/layouts/tablet.html.slim rename app/views/suppliers/{active_order_list.html.slim => active_orders.html.slim} (65%) create mode 100644 spec/factories/list_factory.rb create mode 100644 spec/factories/supplier_factory.rb create mode 100644 spec/factories/table_factory.rb create mode 100644 spec/models/list_spec.rb create mode 100644 spec/spec_helper.rb create mode 100644 spec/support/end_with_matcher.rb diff --git a/Gemfile b/Gemfile index 65c8ac7c..f554c89a 100644 --- a/Gemfile +++ b/Gemfile @@ -46,6 +46,10 @@ end group :test do gem 'rspec-rails' + #gem 'minitest' + gem 'turn', :require => false + gem 'factory_girl_rails' + gem 'selenium-webdriver' #, '2.21.1' # 2.21.2 gives trouble, remove this line when this is solved since this is a dependency of capybara gem 'capybara' end diff --git a/Gemfile.lock b/Gemfile.lock index d3788551..ba7e4797 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -47,6 +47,7 @@ GEM i18n (~> 0.6) multi_json (~> 1.0) addressable (2.3.2) + ansi (1.4.3) arel (3.0.2) bcrypt-ruby (3.0.1) builder (3.0.0) @@ -85,6 +86,11 @@ GEM eventmachine (0.12.10) execjs (1.4.0) multi_json (~> 1.0) + factory_girl (4.0.0) + activesupport (>= 3.0.0) + factory_girl_rails (4.0.0) + factory_girl (~> 4.0.0) + railties (>= 3.0.0) ffi (1.1.5) haml (3.1.7) haml-rails (0.3.4) @@ -203,6 +209,8 @@ GEM treetop (1.4.10) polyglot polyglot (>= 0.3.1) + turn (0.9.6) + ansi twitter-bootstrap-rails (2.1.3) actionpack (>= 3.1) less-rails (~> 2.2.3) @@ -226,6 +234,7 @@ DEPENDENCIES couch_potato! devise (= 2.0.4) devise_simply_stored + factory_girl_rails haml-rails jquery-rails mini_magick @@ -234,8 +243,10 @@ DEPENDENCIES rqrcode-rails3 rspec-rails sass-rails (~> 3.2.3) + selenium-webdriver simply_stored! slim-rails thin + turn twitter-bootstrap-rails uglifier (>= 1.0.3) diff --git a/app/assets/images/.DS_Store b/app/assets/images/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..1c767137623b445aa828cc2cce535da026e49921 GIT binary patch literal 6148 zcmeHK%}T>S5T3QQMpVc}=rMRM(iE&04>UGPD6q05DJq1sM%O?#9rLP9_v`j2Yy?DqjR~8Z->_ z7hUx29e98Ye0YNT_kRY9ILeED|4Zz&+Pj@S1Lbf!iIOl~x#=#a_tv$j7WQ&rZL)6ojr-dVt!|K*K7N1(6i3%P0w1}{oxSp!Em$LM=?K) zcQk5CdG@j-PLoIUS2a~GBQwAZFaylM7Bip^1><0g zIpC!;1I$1(1GGO_sDzHjQlZ>Bu%YWS#oL4=XwzGQ(9-B=EEQq|MW|9lRVwroL#T4} zTRP9tSSnQIAmq$Aj-I)Cya+iv`Yo9b!coXAGr$bg8EC1lN$3A1{xXe^{CWxZm;q+s zpD`fXBX8v5qV(DNV|jGeTB!G^B$QW@fr57J5`Z1rN4heo;uhJM=V&Yy(kSGY<%oO{ Mkc4o<4EzEE-;Q%hRR910 literal 0 HcmV?d00001 diff --git a/app/assets/images/frames/.DS_Store b/app/assets/images/frames/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..987a514359dcebe5315af0a1c3ec4682c7fd0c54 GIT binary patch literal 6148 zcmeHK%Syvg5Iv(^6b0!lIj_qFP%Ft|xCj z&T)@p>yW!-_9c~nVa^q?K-tY)u6i?B3Q>dtp+G1Q3j9L_cxJ1O4;`Zn1ww&P;8OwJ zA2PaPp0IJWt%HR<0f>5yHe+3{$;!zR<_Q}|j?l!ZM5ju6Vu;h(pQX4wVdLm@NP2uo zTKVJgBDOl`&nz60J4P7_gaTa!_PsgL^Z%T`%-|!xONmw}5DNS;1!Oe8p3nGE>1^Hk zJUweO`VC!8;~K5dSnpf{*wB6C#0Gsl(>mkwgpH%lqWwlE#znvci6RvE0R`Rx7V$`X literal 0 HcmV?d00001 diff --git a/app/assets/images/frames/smartphone.png b/app/assets/images/frames/smartphone.png new file mode 100644 index 0000000000000000000000000000000000000000..2da9384451982e14c0feff2a5c5c07a0852fe117 GIT binary patch literal 12556 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 TC4>K5faqxGt5@H%fBC-v(VZbQ literal 0 HcmV?d00001 diff --git a/app/assets/images/frames/smartphone.svg b/app/assets/images/frames/smartphone.svg new file mode 100644 index 00000000..3785ef65 --- /dev/null +++ b/app/assets/images/frames/smartphone.svg @@ -0,0 +1,685 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + V + + + odafone + + + + 11:45 + + + pm + + \ No newline at end of file diff --git a/app/assets/images/frames/tablet.png b/app/assets/images/frames/tablet.png new file mode 100644 index 0000000000000000000000000000000000000000..489388ac19205b3957bb5985c65f90378492e1ff GIT binary patch literal 34115 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 WucALG{N>0bw9o0E%{y&-@BaWAQb1Y& literal 0 HcmV?d00001 diff --git a/app/assets/images/frames/tablet.svg b/app/assets/images/frames/tablet.svg new file mode 100644 index 00000000..629e4f12 --- /dev/null +++ b/app/assets/images/frames/tablet.svg @@ -0,0 +1,894 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/assets/javascripts/qrammer.js.coffee b/app/assets/javascripts/qrammer.js.coffee index 52d6b836..c95afdc1 100644 --- a/app/assets/javascripts/qrammer.js.coffee +++ b/app/assets/javascripts/qrammer.js.coffee @@ -59,8 +59,8 @@ root.Qrammer = return window.location = '/' if res['message'] && !res['ok'] window.location = '/view_active_list' if res['ok'] - load_active_order_list: (supplier_id) -> - $.get('/suppliers/'+supplier_id+'/active_order_list.json', (res) -> + load_active_orders: (supplier_id) -> + $.get('/suppliers/'+supplier_id+'/active_orders.json', (res) -> body = $('#active-orders-table tbody') body.find('tr').remove() foot = $('#active-orders-table tfoot') @@ -112,7 +112,11 @@ root.Qrammer = )(list, row) close_btn.click(close_callback) - row.append($('').text(list._id)) + icons_td = $('').appendTo(row) + icons_td.append('
  • ') if list.need_help # or icon-bell + icons_td.append('
  • ') if list.needs_payment + + row.append($('').text(list.table_number)) row.append($('').html(Qrammer.currency(list.total_amount))) td_buttons = $('') td_buttons.append(close_btn) diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 3192ec89..0f96e07c 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -9,5 +9,5 @@ * compiled file, but it's generally better to create a new file per style scope. * *= require_self - *= require_tree . + *= require_directory . */ diff --git a/app/assets/stylesheets/phone/application.css b/app/assets/stylesheets/phone/application.css new file mode 100644 index 00000000..0f96e07c --- /dev/null +++ b/app/assets/stylesheets/phone/application.css @@ -0,0 +1,13 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, + * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the top of the + * compiled file, but it's generally better to create a new file per style scope. + * + *= require_self + *= require_directory . + */ diff --git a/app/assets/stylesheets/phone/structure.css.sass b/app/assets/stylesheets/phone/structure.css.sass new file mode 100644 index 00000000..59ee6ae5 --- /dev/null +++ b/app/assets/stylesheets/phone/structure.css.sass @@ -0,0 +1,7 @@ +body + padding-left: 0px + padding-right: 0px + //padding-top: 50px + .navbar-fixed-top + margin-left: 0px + margin-right: 0px diff --git a/app/assets/stylesheets/structure.css.sass b/app/assets/stylesheets/structure.css.sass index f2020f5d..b3d14642 100644 --- a/app/assets/stylesheets/structure.css.sass +++ b/app/assets/stylesheets/structure.css.sass @@ -31,3 +31,33 @@ table td &:first-child background-image: image-url('icons/order-doublecheck.png') +.phone-wrapper + position: absolute + top: 60px + left: 20px + width: 353px + height: 693px + background-image: image-url('frames/smartphone.png') + background-repeat: no-repeat +.phone-content-frame + position: absolute + left: 40px + top: 182px + height: 482px + width: 310px + + +.tablet-wrapper + position: absolute + top: 60px + left: 393px + width: 1002px + height: 670px + background-image: image-url('frames/tablet.png') + background-repeat: no-repeat +.tablet-content-frame + position: absolute + left: 433px + top: 100px + width: 880px + height: 590px diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 5d734330..b128434f 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -4,10 +4,14 @@ class DashboardController < ApplicationController def home end + def phone_home + render layout: 'phone' + end # Testing action def select_qrcode @tables = Table.all + render layout: 'phone' end def create_list @@ -25,8 +29,7 @@ class DashboardController < ApplicationController def show_products @supplier = Supplier.first - - + render layout: 'phone' end def order_active_list @@ -50,6 +53,29 @@ class DashboardController < ApplicationController def view_active_list redirect_to(root_path, alert: t('messages.there_is_no_list_active')) and return unless session[:active_list_id].present? - + render layout: 'phone' + end + + ## + # Displays the closed lists of the user + def user_history + render layout: 'phone' + end + + def list_info + respond_to do |format| + format.json do + render json: {list_active: false} and return unless session[:active_list_id].present? + render json: active_list.as_json.merge(list_active: true) + end + end + end + + def supplier_home + redirect_to active_orders_supplier_path(Supplier.first) + end + + def supplier_lists + redirect_to active_lists_supplier_path(Supplier.first) end end diff --git a/app/controllers/suppliers_controller.rb b/app/controllers/suppliers_controller.rb index 943ff279..83b93934 100644 --- a/app/controllers/suppliers_controller.rb +++ b/app/controllers/suppliers_controller.rb @@ -99,12 +99,12 @@ class SuppliersController < ApplicationController end end - # GET /suppliers/1/active_order_list - # GET /suppliers/1/active_order_list.json - def active_order_list + # GET /suppliers/1/active_orders + # GET /suppliers/1/active_orders.json + def active_orders @supplier = Supplier.find(params[:id]) respond_to do |format| - format.html + format.html { render layout: 'tablet' } format.json do h = @supplier.as_json h[:orders] = [] @@ -124,7 +124,7 @@ class SuppliersController < ApplicationController h[:orders] << ho end h[:total_amount] = list_total.round(2) - render json: h + render json: h, layout: 'tablet' end end end @@ -134,7 +134,7 @@ class SuppliersController < ApplicationController def active_lists @supplier = Supplier.find(params[:id]) respond_to do |format| - format.html + format.html { render layout: 'tablet' } format.json do h = @supplier.as_json h[:lists] = [] @@ -146,7 +146,7 @@ class SuppliersController < ApplicationController h[:lists] << hl end h[:total_amount] = grand_total.round(2) - render json: h + render json: h, layout: 'tablet' end end end diff --git a/app/models/list.rb b/app/models/list.rb index 6b29e5f6..17e35f52 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -22,6 +22,10 @@ class List table.supplier end + def table_number + @table_number ||= table.number + end + def active? state == 'active' end @@ -35,4 +39,8 @@ class List ProductOrder.create order: @order, product_id: product_id, amount: number if number > 0 end end + + def as_json + super.merge(table_number: table_number) + end end diff --git a/app/views/dashboard/home.html.slim b/app/views/dashboard/home.html.slim index ae7f30df..ae518566 100644 --- a/app/views/dashboard/home.html.slim +++ b/app/views/dashboard/home.html.slim @@ -1,15 +1,5 @@ -.page-header= title 'Home' -ul.nav.nav-tabs.nav-stacked - - if list_open? - li= link_to 'Place order', '/show_products?supplier_id=' + active_list.supplier.id - li= link_to 'Active list', view_active_list_path - li= link_to 'Request bill', '#' - li= link_to 'I have a question', '#' - - else - li= link_to 'Place order', '/select_qrcode' - li= link_to 'Subscribe to list', '#' - li= link_to 'Check out menu', '#' - -ul.nav.nav-tabs.nav-stacked - li= link_to 'View history', '#' +.phone-wrapper +iframe.phone-content-frame src=phone_root_path +.tablet-wrapper +iframe.tablet-content-frame src=supplier_root_path diff --git a/app/views/dashboard/phone_home.html.slim b/app/views/dashboard/phone_home.html.slim new file mode 100644 index 00000000..55f3673d --- /dev/null +++ b/app/views/dashboard/phone_home.html.slim @@ -0,0 +1,11 @@ +ul.nav.nav-tabs.nav-stacked + - if list_open? + li= link_to 'Place order', '/show_products?supplier_id=' + active_list.supplier.id + li= link_to 'Active list', view_active_list_path + li= link_to 'Request bill', '#' + li= link_to 'Move table', '#' + li= link_to 'I have a question', '#' + - else + li= link_to 'Place order', '/select_qrcode' + li= link_to 'Subscribe to list', '#' + li= link_to 'Check out menu', '#' diff --git a/app/views/dashboard/show_products.html.slim b/app/views/dashboard/show_products.html.slim index 33eaa156..8c008dfa 100644 --- a/app/views/dashboard/show_products.html.slim +++ b/app/views/dashboard/show_products.html.slim @@ -1,24 +1,23 @@ -button onClick='Qrammer.build_product_list()' class='btn btn-inverse'Lijst table#products-table.table.table-striped.table-hover tbody -- content_for :sidebar do - table#active-order-table.table.hide - thead - tr - th Product - th # - th.currency Total - th - tbody - tfoot - tr - td colspan=2 - button class="btn btn-primary" onClick="Qrammer.order_active_list('/order_active_list')" Bestellen - |  - button class="btn btn btn-warning" onClick="Qrammer.clear_active_list()" Clear - td.currency - strong#active-order-total - td +-# content_for :sidebar do +table#active-order-table.table.table-striped.hide + thead + tr + th Product + th # + th.currency Total + th + tbody + tfoot + tr + td colspan=2 + button class="btn btn-primary" onClick="Qrammer.order_active_list('/order_active_list')" Bestellen + |  + button class="btn btn btn-warning" onClick="Qrammer.clear_active_list()" Clear + td.currency + strong#active-order-total + td - content_for :footer do javascript: jQuery(function(){ diff --git a/app/views/dashboard/user_history.html.slim b/app/views/dashboard/user_history.html.slim new file mode 100644 index 00000000..a89aef96 --- /dev/null +++ b/app/views/dashboard/user_history.html.slim @@ -0,0 +1,2 @@ +.page-header= title 'User history' +p Todo diff --git a/app/views/layouts/phone.html.slim b/app/views/layouts/phone.html.slim new file mode 100644 index 00000000..9e7e84ed --- /dev/null +++ b/app/views/layouts/phone.html.slim @@ -0,0 +1,55 @@ +doctype html +html lang="en" + head + meta charset="utf-8" + meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" + meta name="viewport" content="width=device-width, initial-scale=1.0" + title= content_for?(:title) ? yield(:title) : "Qrammer" + = csrf_meta_tags + + /! Le HTML5 shim, for IE6-8 support of HTML elements + /[if lt IE 9] + = javascript_include_tag "http://html5shim.googlecode.com/svn/trunk/html5.js" + = stylesheet_link_tag "application", :media => "all" + = stylesheet_link_tag "phone/application", :media => "all" + link href="images/apple-touch-icon-144x144.png" rel="apple-touch-icon-precomposed" sizes="144x144" + link href="images/apple-touch-icon-114x114.png" rel="apple-touch-icon-precomposed" sizes="114x114" + link href="images/apple-touch-icon-72x72.png" rel="apple-touch-icon-precomposed" sizes="72x72" + link href="images/apple-touch-icon.png" rel="apple-touch-icon-precomposed" + link href="images/favicon.ico" rel="shortcut icon" + javascript: + var active_list_id = #{session[:active_list_id] ? "'#{session[:active_list_id]}'" : 'null'}; + + body + .navbar.navbar-fixed-top + .navbar-inner + .container + a.btn.btn-navbar data-target=".nav-collapse" data-toggle="collapse" + span.icon-bar + span.icon-bar + span.icon-bar + a.brand href=phone_root_path Qrammer + .container.nav-collapse + ul.nav#top-navigation-list + li= link_to 'View history', user_history_path + + .container + + .content + - if flash[:alert].present? + .alert.alert-error + a.close data-dismiss="alert" × + div= flash[:alert] + - if flash[:notice].present? + .alert.alert-success + a.close data-dismiss="alert" × + div= flash[:notice] + .row + .span12 + = yield + /! + Javascripts + \================================================== + /! Placed at the end of the document so the pages load faster + = javascript_include_tag "application" + = yield :footer diff --git a/app/views/layouts/tablet.html.slim b/app/views/layouts/tablet.html.slim new file mode 100644 index 00000000..0ced2b9a --- /dev/null +++ b/app/views/layouts/tablet.html.slim @@ -0,0 +1,56 @@ +doctype html +html lang="en" + head + meta charset="utf-8" + meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" + meta name="viewport" content="width=device-width, initial-scale=1.0" + title= content_for?(:title) ? yield(:title) : "Qrammer" + = csrf_meta_tags + + /! Le HTML5 shim, for IE6-8 support of HTML elements + /[if lt IE 9] + = javascript_include_tag "http://html5shim.googlecode.com/svn/trunk/html5.js" + = stylesheet_link_tag "application", :media => "all" + = stylesheet_link_tag "phone/application", :media => "all" + link href="images/apple-touch-icon-144x144.png" rel="apple-touch-icon-precomposed" sizes="144x144" + link href="images/apple-touch-icon-114x114.png" rel="apple-touch-icon-precomposed" sizes="114x114" + link href="images/apple-touch-icon-72x72.png" rel="apple-touch-icon-precomposed" sizes="72x72" + link href="images/apple-touch-icon.png" rel="apple-touch-icon-precomposed" + link href="images/favicon.ico" rel="shortcut icon" + javascript: + var active_list_id = #{session[:active_list_id] ? "'#{session[:active_list_id]}'" : 'null'}; + + body + .navbar.navbar-fixed-top.navbar-inverse + .navbar-inner + .container + a.btn.btn-navbar data-target=".nav-collapse" data-toggle="collapse" + span.icon-bar + span.icon-bar + span.icon-bar + a.brand href=supplier_root_path Qrammer + .container.nav-collapse-disabled + ul.nav#top-navigation-list + li= link_to t('supplier.menu.active_orders', orders: Order.model_name.human_plural), supplier_orders_path + li= link_to t('supplier.menu.active_lists', lists: List.model_name.human_plural), supplier_lists_path + + .container + + .content + - if flash[:alert].present? + .alert.alert-error + a.close data-dismiss="alert" × + div= flash[:alert] + - if flash[:notice].present? + .alert.alert-success + a.close data-dismiss="alert" × + div= flash[:notice] + .row + .span12 + = yield + /! + Javascripts + \================================================== + /! Placed at the end of the document so the pages load faster + = javascript_include_tag "application" + = yield :footer diff --git a/app/views/suppliers/active_lists.html.slim b/app/views/suppliers/active_lists.html.slim index d3b6b082..1f5ad339 100644 --- a/app/views/suppliers/active_lists.html.slim +++ b/app/views/suppliers/active_lists.html.slim @@ -1,7 +1,8 @@ .page-header= title 'Active lists' -table#active-lists-table.table +table#active-lists-table.table.table-striped thead tr + th.status-icons th.number Table number th.currency Price th.actions diff --git a/app/views/suppliers/active_order_list.html.slim b/app/views/suppliers/active_orders.html.slim similarity index 65% rename from app/views/suppliers/active_order_list.html.slim rename to app/views/suppliers/active_orders.html.slim index e9e37c6c..1a81fcde 100644 --- a/app/views/suppliers/active_order_list.html.slim +++ b/app/views/suppliers/active_orders.html.slim @@ -10,7 +10,7 @@ table#active-orders-table.table - content_for :footer do javascript: jQuery(function(){ - Qrammer.load_active_order_list('#{@supplier.id}') - setInterval( "Qrammer.load_active_order_list('#{@supplier.id}')", 7500); + Qrammer.load_active_orders('#{@supplier.id}') + setInterval( "Qrammer.load_active_orders('#{@supplier.id}')", 7500); }); diff --git a/config/environments/development.rb b/config/environments/development.rb index 02d7998c..011eb157 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -5,6 +5,13 @@ Qrammer::Application.configure do # every request. This slows down response time but is perfect for development # since you don't have to restart the web server when you make code changes. config.cache_classes = false + silence_warnings do + begin + require 'pry' + IRB = Pry + rescue LoadError + end + end # Log error messages when you accidentally call methods on nil. config.whiny_nils = true diff --git a/config/locales/en.yml b/config/locales/en.yml index 81b22893..573220a0 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -43,3 +43,6 @@ en: list: Lists product: Products product_category: Product categories + supplier: + menu: + active_lists: Active %{lists} diff --git a/config/routes.rb b/config/routes.rb index ed62b2f1..a629d80f 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -14,7 +14,7 @@ Qrammer::Application.routes.draw do resources :suppliers do member do get :product_list - get :active_order_list + get :active_orders get :active_lists end end @@ -29,6 +29,11 @@ Qrammer::Application.routes.draw do match "/:action", controller: 'dashboard' match '/view_active_list' => 'dashboard#view_active_list', as: :view_active_list + match '/phone_home' => 'dashboard#phone_home', as: :phone_root + match '/supplier_home' => 'dashboard#supplier_home', as: :supplier_root + match '/supplier_home' => 'dashboard#supplier_home', as: :supplier_orders + match '/supplier_lists' => 'dashboard#supplier_lists', as: :supplier_lists + match '/user_history' => 'dashboard#user_history', as: :user_history # The priority is based upon order of creation: # first created -> highest priority. diff --git a/spec/factories/list_factory.rb b/spec/factories/list_factory.rb new file mode 100644 index 00000000..81dfb3fb --- /dev/null +++ b/spec/factories/list_factory.rb @@ -0,0 +1,5 @@ +FactoryGirl.define do + factory :list do + association :table + end +end diff --git a/spec/factories/supplier_factory.rb b/spec/factories/supplier_factory.rb new file mode 100644 index 00000000..d9ed20cd --- /dev/null +++ b/spec/factories/supplier_factory.rb @@ -0,0 +1,5 @@ +FactoryGirl.define do + factory :supplier do + sequence(:name){|i| "Supplier #{i}"} + end +end diff --git a/spec/factories/table_factory.rb b/spec/factories/table_factory.rb new file mode 100644 index 00000000..b13d9555 --- /dev/null +++ b/spec/factories/table_factory.rb @@ -0,0 +1,6 @@ +FactoryGirl.define do + factory :table do + number 22 + association :supplier + end +end diff --git a/spec/models/list_spec.rb b/spec/models/list_spec.rb new file mode 100644 index 00000000..a7968129 --- /dev/null +++ b/spec/models/list_spec.rb @@ -0,0 +1,17 @@ +require 'spec_helper' + + +describe List do + before :each do + @list = create :list + end + describe :as_json do + it 'should include _id in as_json serialization' do + @list.as_json.keys.map(&:to_sym).should include :_id + end + it 'should include table_number in as_json serialization' do + @list.as_json.keys.should include :table_number + end + end + +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 00000000..d028ab1f --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,65 @@ +# This file is copied to spec/ when you run 'rails generate rspec:install' +ENV["RAILS_ENV"] ||= 'test' +require File.expand_path("../../config/environment", __FILE__) +require 'rspec/rails' +require 'rspec/autorun' + +# Requires supporting ruby files with custom matchers and macros, etc, +# in spec/support/ and its subdirectories. +Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} +#Dir[Rails.root.join("spec/factories/**/*.rb")].each {|f| require f } + +I18n.locale = :en +Devise.stretches = 1 +Capybara.default_driver = :selenium +RSpec.configure do |config| + # == Mock Framework + # + # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: + # + # config.mock_with :mocha + # config.mock_with :flexmock + # config.mock_with :rr + config.mock_with :rspec + config.include FactoryGirl::Syntax::Methods + config.include Devise::TestHelpers, :type => :controller + config.include EndWithMatcher + #config.use_transactional_fixtures = true + config.infer_base_class_for_anonymous_controllers = true + config.render_views = true + + # Use color in STDOUT + config.color_enabled = true + + # Use color not only in STDOUT but also in pagers and files + config.tty = true + + # Use the specified formatter + config.formatter = :documentation # :progress, :html, :textmate + + # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures + #config.fixture_path = "#{::Rails.root}/spec/fixtures" + + # If you're not using ActiveRecord, or you'd prefer not to run each of your + # examples within a transaction, remove the following line or assign false + # instead of true. + #config.use_transactional_fixtures = true + + config.before :each do + CouchPotato.couchrest_database.recreate! + end + config.before :each, type: :request do + #Capybara.current_driver = :selenium + #sign_in_user_through_request + end + # If true, the base class of anonymous controllers will be inferred + # automatically. This will be the default behavior in future versions of + # rspec-rails. + #config.infer_base_class_for_anonymous_controllers = true + def sign_in_user_through_request + visit "/users/sign_in" + fill_in 'user[email]', with: @user.email + fill_in 'user[password]', with: @user.password + click_on 'Inloggen' + end +end diff --git a/spec/support/end_with_matcher.rb b/spec/support/end_with_matcher.rb new file mode 100644 index 00000000..3f45566b --- /dev/null +++ b/spec/support/end_with_matcher.rb @@ -0,0 +1,43 @@ +module EndWithMatcher + class EndWith + def initialize(expected) + @expected = expected + end + + def matches?(target) + @target = target + @target =~ /#{@expected}$/ + end + + def failure_message + "expected <#{to_string(@target)}> to " + + "end with <#{to_string(@expected)}>" + end + + def negative_failure_message + "expected <#{to_string(@target)}> not to " + + "end with <#{to_string(@expected)}>" + end + + # Returns string representation of an object. + def to_string(value) + # indicate a nil + if value.nil? + 'nil' + end + + # join arrays + if value.class == Array + return value.join(", ") + end + + # otherwise return to_s() instead of inspect() + return value.to_s + end + end + + # Actual matcher that is exposed. + def end_with(expected) + EndWith.new(expected) + end +end