From 73c207c3243c80339069c131924b6687407b4add Mon Sep 17 00:00:00 2001 From: Benjamin ter Kuile Date: Sat, 29 Feb 2020 11:43:00 -0500 Subject: [PATCH] many important fixes --- app/assets/config/manifest.js | 2 + .../user/foundation/components/_nav_side.sass | 10 +- .../user/foundation/pages/_scanning.sass | 9 +- app/controllers/dashboard_controller.rb | 2 +- .../users/application_controller.rb | 11 +- app/controllers/users/lists_controller.rb | 8 + app/helpers/application_helper.rb | 2 +- app/serializers/users/list_serializer.rb | 2 +- .../users/product_order_serializer.rb | 2 +- app/views/dashboard/demo_both.html.slim | 10 +- bin/set_translations_to_apps.rb | 80 +- config/application.rb | 12 +- config/initializers/devise.rb | 4 +- config/routes.rb | 5 +- drb_counter/Dockerfile | 27 +- drb_counter/Gemfile | 4 +- drb_counter/Gemfile.lock | 201 +---- drb_counter/drb_counter.rb | 7 +- drb_counter/rebuild-docker.sh | 26 + faye-stub.rb | 14 + faye/Dockerfile | 23 +- faye/config.ru | 24 +- faye/rebuild-docker.sh | 26 + lib/qwaiter/employee_base_serializer.rb | 1 + lib/qwaiter/supplier_base_serializer.rb | 5 +- lib/qwaiter/user_base_serializer.rb | 7 +- translations.en.coffee | 399 +++++++++ translations.yml | 782 ++++++++++++++++++ 28 files changed, 1463 insertions(+), 242 deletions(-) create mode 100755 drb_counter/rebuild-docker.sh create mode 100644 faye-stub.rb create mode 100755 faye/rebuild-docker.sh create mode 100644 translations.en.coffee create mode 100644 translations.yml diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js index de01928d..f034327d 100644 --- a/app/assets/config/manifest.js +++ b/app/assets/config/manifest.js @@ -12,3 +12,5 @@ //= link supplier/app/application.js // //= link qr_sheet/application.css +// +//= link user/foundation/application.css diff --git a/app/assets/stylesheets/user/foundation/components/_nav_side.sass b/app/assets/stylesheets/user/foundation/components/_nav_side.sass index 0f35817d..4ffc94db 100644 --- a/app/assets/stylesheets/user/foundation/components/_nav_side.sass +++ b/app/assets/stylesheets/user/foundation/components/_nav_side.sass @@ -12,12 +12,14 @@ $side-menu-width: 222px border-right: 2px solid black &.active left: 0 - +animation(sideMenuActive 0.5s) + animation-name: sideMenuActive + animation-duration: 0.5s .toggle-side-menu right: 5px &.closed &.clicked - +animation(sideMenuClosed 0.3s) + animation-name: sideMenuClosed + animation-duration: 0.3s > ul list-style: none a @@ -65,12 +67,12 @@ $side-menu-width: 222px @extend .fa-lg @extend .fa-bars -+keyframes(sideMenuActive) +@keyframes(sideMenuActive) from left: -$side-menu-width to left: 0 -+keyframes(sideMenuClosed) +@keyframes(sideMenuClosed) from left: 0 to diff --git a/app/assets/stylesheets/user/foundation/pages/_scanning.sass b/app/assets/stylesheets/user/foundation/pages/_scanning.sass index c94dc53b..5b8f1c92 100644 --- a/app/assets/stylesheets/user/foundation/pages/_scanning.sass +++ b/app/assets/stylesheets/user/foundation/pages/_scanning.sass @@ -16,11 +16,12 @@ $scanning-code-height: $scanning-code-width/0.785 position: absolute height: $scanning-code-height border-right: 2px solid #f00 - +animation(scanning 1s infinite) - +animation-direction(alternate) - +animation-timing-function(linear) + animation-name: scanning + animation-duration: 1s infinite + animation-direction: alternate + animation-timing-function: linear -+keyframes(scanning) +@keyframes(scanning) from left: 0 to diff --git a/app/controllers/dashboard_controller.rb b/app/controllers/dashboard_controller.rb index 0c82b4e0..e4808dd2 100644 --- a/app/controllers/dashboard_controller.rb +++ b/app/controllers/dashboard_controller.rb @@ -27,7 +27,7 @@ class DashboardController < ApplicationController if Rails.env.test? @tables = Table.all else - @tables = List.active.map(&:table) | Supplier.find_by_name('Mozo').tables.select{|t| t.number.between? 20, 500}.sample(3) + @tables = List.active.map(&:table) | Supplier.find_by_name('Labrador').tables.select{|t| t.number.between? 20, 500}.sample(3) end respond_to do |format| format.html { render layout: 'phone' } diff --git a/app/controllers/users/application_controller.rb b/app/controllers/users/application_controller.rb index 76ae3a07..2f23367a 100644 --- a/app/controllers/users/application_controller.rb +++ b/app/controllers/users/application_controller.rb @@ -6,10 +6,12 @@ module Users private def user_authentication - if params[:auth_token].present? - user = User.find_by_authentication_token(params[:auth_token]) - sign_in user if user - sign_out current_user if current_user && !user # Other token attempt of logged in user + auth_token = params[:auth_token].presence || request.headers['HTTP_AUTH_TOKEN'].presence + if auth_token.present? + user = User.find_by_authentication_token(auth_token) + + #sign_out current_user if current_user && !user # Other token attempt of logged in user + bypass_sign_in user if user elsif request.format.html? return if Rails.env.test? and action_name == 'index' authenticate_user! @@ -39,6 +41,7 @@ module Users case params[:product_orders] when String then JSON.parse(params[:product_orders]) rescue [] when Hash then params[:product_orders].values + when Array then params[:product_orders] else [] end diff --git a/app/controllers/users/lists_controller.rb b/app/controllers/users/lists_controller.rb index f87946cb..ad9a163c 100644 --- a/app/controllers/users/lists_controller.rb +++ b/app/controllers/users/lists_controller.rb @@ -2,6 +2,7 @@ module Users class ListsController < Users::ApplicationController def index + return current if params[:currentList].present? #lists = current_user.lists.include_relation(:supplier, :table) lists = List.for_user(current_user, page: params[:page], per_page: params[:per_page].presence || 25) #lists.include_relation(:supplier) @@ -25,6 +26,13 @@ module Users render json: @table end + def orders + @list = List.find(params[:id]) + return render json: {ok: false, status: 403}, status: 403 unless @list.user_ids.include?(current_user.id) + @list.orders.include_relations(:product_orders) + render json: @list.orders, serializer: Users::OrderSerializer, is_collection: true, include: %w[product_orders] + end + def show @list ||= List.find(params[:id]) if params[:id] render json: {}, status: :not_found and return unless @list.present? && Array.wrap(@list.user_ids).include?(current_user.id) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index c6d704dc..93c87064 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -24,7 +24,7 @@ module ApplicationHelper def user_root_path case Rails.env - when 'development' then 'http://localhost:4200/' + when 'development' then 'http://localhost:4201/' else '/user/index.html' end end diff --git a/app/serializers/users/list_serializer.rb b/app/serializers/users/list_serializer.rb index f4f306a2..df548c63 100644 --- a/app/serializers/users/list_serializer.rb +++ b/app/serializers/users/list_serializer.rb @@ -6,7 +6,7 @@ class Users::ListSerializer :is_paid, :price, :closed_at has_many :users, serializer: Users::UserSerializer - has_many(:orders, serializer: Users::OrderSerializer) + has_many :orders, serializer: Users::OrderSerializer has_many :join_requests, serializer: Users::JoinRequestSerializer has_one :supplier, serializer: Users::SupplierSerializer has_one :table, serializer: Users::TableSerializer diff --git a/app/serializers/users/product_order_serializer.rb b/app/serializers/users/product_order_serializer.rb index a4b5da80..7bb6e6d5 100644 --- a/app/serializers/users/product_order_serializer.rb +++ b/app/serializers/users/product_order_serializer.rb @@ -1,6 +1,6 @@ class Users::ProductOrderSerializer include Qwaiter::UserBaseSerializer attributes :quantity, :price, :product_name, :product_variant - # belongs_to :product #DO NOT USE THIS, THIS IS NOT NEEDED + # belongs_to :product #DO NOT USE THIS, THIS IS NOT NEEDED, already included in /tables/:id/supplier has_one :order, serializer: Users::OrderSerializer end diff --git a/app/views/dashboard/demo_both.html.slim b/app/views/dashboard/demo_both.html.slim index 83590aa8..e0b80369 100644 --- a/app/views/dashboard/demo_both.html.slim +++ b/app/views/dashboard/demo_both.html.slim @@ -1,5 +1,11 @@ .phone-wrapper -iframe.phone-content-frame src=user_root_path +- if Rails.env.development? + iframe.phone-content-frame src="http://localhost:4201/" +- else + iframe.phone-content-frame src=user_root_path .tablet-wrapper -iframe.tablet-content-frame src=supplier_root_path +- if Rails.env.development? + iframe.tablet-content-frame src="http://localhost:4202/supplier/" +- else + iframe.tablet-content-frame src=supplier_root_path diff --git a/bin/set_translations_to_apps.rb b/bin/set_translations_to_apps.rb index 74a5ec0e..9dc610e9 100755 --- a/bin/set_translations_to_apps.rb +++ b/bin/set_translations_to_apps.rb @@ -2,9 +2,18 @@ #require 'pathname' #require 'active_support/all' #require 'yaml' -#require 'pry' +require 'pry' #$root = Pathname.new File.expand_path('../../', __FILE__) class UserApp + def write_output(locale) + out_file = File.open "#{ENV['MOZO_PATH_USER']}/app/i18n/#{locale}.coffee", 'w+' + out_file.puts "window.$translations ||= {}" + out_file.puts "$translations.#{locale} =" + Proc.new do |output| + out_file.puts output + end + end + def path Pathname.new File.expand_path('../../../mozo-user', __FILE__) end @@ -33,10 +42,77 @@ class UserApp end def write_translations + translations = all_translations # caching + File.write "translations.yml", translations.to_yaml + HashToCS.convert(translations['en'], 2, write_output('en')) + HashToCS.convert(translations['nl'], 2, write_output('nl')) + return File.open path.join('vendor/i18n/translations.js'), 'w+' do |f| - f.puts "$translations = #{JSON.pretty_generate all_translations}" + f.puts "$translations = #{JSON.pretty_generate translations}" end end end + # Franc Paul + # + # convert a ruby hash to coffescript object + ## + +module HashToCS + +=begin + usage: + + proc = Proc.new do |output| + coffee_script_file.puts output + end + HashToCs.convert(ruby_hash, 2, proc) + +=end + + defaultProc = Proc.new do |output| + print output + end + + #input is a Ruby hash + #spaces is an integer count of spaces to be used as a prefix string for whitespace significance + #proc acts on the output + def HashToCS.convert(input, spaces=0, proc=defaultProc) + spaces = " " * spaces + case input + when String + q = if input =~ /\n/ + '"""' + else + '"' + end + proc.call spaces + q + input + q + "\n" + when Array + proc.call spaces + "[\n" + input.each do |a| + convert(a, spaces.size + 2, proc) + end + proc.call spaces + "]\n" + when Hash + #proc.call spaces + "{\n" + input.each do |k, v| + key_string = k =~ /\W/ ? "\"#{k}\"" : "#{k}" + if v.is_a?(String) + if v =~ /\n/ + proc.call spaces + "#{key_string}: \"\"\"\n#{v}\"\"\"\n" + else + proc.call spaces + "#{key_string}: \"#{v}\"\n" + end + else + proc.call spaces + "#{key_string}:\n" + convert(v, spaces.size + 2, proc) + end + end + #proc.call spaces + "}\n" + else + proc.call spaces + input.to_s + "\n" + end + end + +end UserApp.new.write_translations diff --git a/config/application.rb b/config/application.rb index 309fb39a..8b3c0f32 100644 --- a/config/application.rb +++ b/config/application.rb @@ -16,11 +16,13 @@ require File.expand_path('./../../lib/couchbase-setting', __FILE__) Bundler.require(*Rails.groups(assets: %w(development test user_app))) Bundler.require(:assets) if ENV['DEPLOY']=='yes' -class CouchRest::Connection - alias_method :old_execute, :execute - def execute(method, path, options, payload = nil, &block) - Rails.logger.debug "Couch: #{method} #{Rack::Utils.unescape path} #{options}" - old_execute(method, path, options, payload, &block) +if Rails.env.development? + class CouchRest::Connection + alias_method :old_execute, :execute + def execute(method, path, options, payload = nil, &block) + Rails.logger.debug "Couch: #{method} #{Rack::Utils.unescape path} #{options}" + old_execute(method, path, options, payload, &block) + end end end # Bug in actionview error handling, remove for versions > 6.0.2.1 diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 59b1a722..58abf1e7 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -252,11 +252,11 @@ Devise.setup do |config| # config.omniauth :facebook, "505160086210072", "fcc474a3fb13c6bcc0f7c83a92ad1b17", # scope: 'email,user_birthday,publish_actions' config.omniauth :facebook, "653729178057509", "d4cea86f70803f1b75ed03c506a4d78e", - scope: 'email,user_birthday,publish_actions' + scope: 'email,user_birthday,user_gender,user_hometown,user_link,user_location' config.omniauth :instagram, "cd7bdfbee825499b94fb3783d1bc143b", "6b4f9ecf251c462993a696eebc0189be" else config.omniauth :facebook, "168928633304849", "22bc53e1a390c1e62d004195c55fe336", - scope: 'email,user_birthday,publish_actions' + scope: 'email,user_birthday,user_gender,user_hometown,user_link,user_location' config.omniauth :instagram, "81c78b969a7046d6b6b5b5fe3f30929c", "3697c16762ad4f1ca088e829efbaddde" end diff --git a/config/routes.rb b/config/routes.rb index 95421422..5620cc46 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -85,16 +85,17 @@ Qwaiter::Application.routes.draw do end member do get :table + get :orders post :needs_payment post :move_to_table post :order_products post :reject_join_request post :approve_join_request end - resources :orders, only: [:index] + #resources :orders, only: [:index] end - #resources :orders, only: [:create] + resources :orders, only: [:create] resources :tables do member do post :needs_help diff --git a/drb_counter/Dockerfile b/drb_counter/Dockerfile index a13c0178..dcd635a9 100644 --- a/drb_counter/Dockerfile +++ b/drb_counter/Dockerfile @@ -1,7 +1,15 @@ -FROM ruby:2.3.0-slim +FROM ruby:2.7-slim +#NOTE: this file must be built from the parent (../) directory +# look at the +# rebuild-docker.sh +# script as kind of manual on how the drb_counter cointainer is managed and used + # throw errors if Gemfile has been modified since Gemfile.lock -RUN bundle config --global frozen 1 +#RUN bundle config --global frozen 1 +RUN apt update +RUN apt install -y curl +RUN gem install bundler:1.17.3 RUN mkdir -p /usr/src/app @@ -15,14 +23,17 @@ WORKDIR /usr/src/app # Specific #RUN apt-get update && apt-get install -y dos2unix --no-install-recommends && rm -rf /var/lib/apt/lists/* -COPY Gemfile /usr/src/app/ -COPY Gemfile.lock /usr/src/app/ +COPY drb_counter/Gemfile /usr/src/app/ +#COPY drb_counter/Gemfile.lock /usr/src/app/ #COPY vendor/cache /usr/src/app/vendor/cache #RUN bundle install --local -RUN rm -rf /usr/src/app/.bundle -#RUN bundle install +#RUN rm -rf /usr/src/app/.bundle +RUN bundle install -COPY . /usr/src/app +# COPY THE WHOLE DIRECTORY LATER THAN GEMFILE TO AVOID bundle install step on code change +COPY drb_counter /usr/src/app +RUN mkdir -p config +COPY config/couchdb.yml /usr/src/app/config/couchdb.yml EXPOSE 9022 -ENTRYPOINT ["ruby", "drb_counter.rb"] +CMD ["ruby", "drb_counter.rb"] diff --git a/drb_counter/Gemfile b/drb_counter/Gemfile index ea5b79cb..0ef2abef 100644 --- a/drb_counter/Gemfile +++ b/drb_counter/Gemfile @@ -1,4 +1,4 @@ source 'https://rubygems.org' -#gem "couchrest" -#gem "pry" +gem "couchrest" +gem "pry" diff --git a/drb_counter/Gemfile.lock b/drb_counter/Gemfile.lock index 3cd7ec73..4e1df71c 100644 --- a/drb_counter/Gemfile.lock +++ b/drb_counter/Gemfile.lock @@ -1,192 +1,20 @@ GEM remote: https://rubygems.org/ specs: - coderay (1.1.0) - couchrest (1.2.0) - mime-types (~> 1.15) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - multi_json (~> 1.0) - rest-client (~> 1.6.1) - method_source (0.8.2) - mime-types (1.25.1) - multi_json (1.10.1) - pry (0.10.1) + coderay (1.1.2) + couchrest (2.0.1) + httpclient (~> 2.8) + mime-types (>= 1.15) + multi_json (~> 1.7) + httpclient (2.8.3) + method_source (0.9.2) + mime-types (3.3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2019.1009) + multi_json (1.14.1) + pry (0.12.2) coderay (~> 1.1.0) - method_source (~> 0.8.1) - slop (~> 3.4) - rdoc (4.2.0) - rest-client (1.6.8) - mime-types (~> 1.16) - rdoc (>= 2.4.2) - slop (3.6.0) + method_source (~> 0.9.0) PLATFORMS ruby @@ -194,3 +22,6 @@ PLATFORMS DEPENDENCIES couchrest pry + +BUNDLED WITH + 1.17.3 diff --git a/drb_counter/drb_counter.rb b/drb_counter/drb_counter.rb index 59f0e034..fd476846 100755 --- a/drb_counter/drb_counter.rb +++ b/drb_counter/drb_counter.rb @@ -1,5 +1,6 @@ #!/usr/bin/env ruby # Make drb server +# See Dockerfile for run instructions require 'rubygems' require 'drb/drb' #require 'pry' @@ -68,7 +69,7 @@ class InMemoryQCounter puts "Environment: #{environment.inspect}" couch_settings = YAML.load_file(couch_settings_path)[environment] database = couch_settings['database'] - db = CouchRest.database(database) + db = CouchRest.database(database) # for debug: db = CouchPotato.database.couchrest_database design_doc = "_design/order_counter" view_path = File.join design_doc, "_view/by_supplier_id_and_state" tries = 0 @@ -105,6 +106,6 @@ class InMemoryQCounter end end drb_port = 9022 -environment = (%w[production staging development test] & ARGV).first || 'development' -DRb.start_service "druby://:#{drb_port}", InMemoryQCounter.new(reload_stats: false, environment: environment) +environment = (%w[production staging development test] & [ENV['DRB_ENV']]).first || 'development' +DRb.start_service "druby://:#{drb_port}", InMemoryQCounter.new(reload_stats: environment == 'production', environment: environment) DRb.thread.join diff --git a/drb_counter/rebuild-docker.sh b/drb_counter/rebuild-docker.sh new file mode 100755 index 00000000..0646aea3 --- /dev/null +++ b/drb_counter/rebuild-docker.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# This script rebuilds the whole environment and starts a new container + +# 1. ensure this script is run from the project's root, not the drb_counter directory +pwd_dirname=$(basename $(pwd)); +script_dirname="drb_counter"; +if [ "$pwd_dirname" == "$script_dirname" ]; then + echo "PWD DIRNAME: "$pwd_dirname; + echo "You must run this script from the project's root dir (../) for the Dockerfile to have access to the configs to COPY"; + exit 1; +fi + +# 2. stop and remove all running/existing containers +docker rm $(docker stop $(docker ps -a -q --filter ancestor=mozo_drb_counter)) + +# 3. remove the previously built images +docker rmi mozo_drb_counter + +# 4. rebuild a fresh image from the latest code +docker build -f drb_counter/Dockerfile -t mozo_drb_counter . + +# debug docker and enter the bash: +# docker run --network=host --env DRB_ENV=production -t -i --rm mozo_drb_counter bash + +# 5. Spin up the counter container from the generated image +docker run --network=host --env DRB_ENV=production --detach --name=mozo_drb_counter mozo_drb_counter diff --git a/faye-stub.rb b/faye-stub.rb new file mode 100644 index 00000000..e125014a --- /dev/null +++ b/faye-stub.rb @@ -0,0 +1,14 @@ +require 'sinatra' +require 'pry' +# start this server using: +# ruby __FILE__ +Process.setproctitle("faye mock server") + +set :port, 9296 +get '/' do |*args| + "Hello world from /" +end + +get '/faye' do |*args| + "Hello world from /faye" +end diff --git a/faye/Dockerfile b/faye/Dockerfile index f2b3dcbf..e1b42e07 100644 --- a/faye/Dockerfile +++ b/faye/Dockerfile @@ -1,12 +1,22 @@ -FROM ruby:2.2.0 +FROM ruby:2.7-slim +#NOTE: this file must be built from the parent (../) directory +# look at the +# rebuild-docker.sh +# script as kind of manual on how the drb_counter cointainer is managed and used + # throw errors if Gemfile has been modified since Gemfile.lock -RUN bundle config --global frozen 1 +#RUN bundle config --global frozen 1 RUN mkdir -p /usr/src/app WORKDIR /usr/src/app RUN apt-get update +RUN apt install -y build-essential +RUN gem install bundler:1.17.3 + + +RUN mkdir -p /usr/src/app/config # Test #RUN apt-get update && apt-get install -y qt5-default libqt5webkit5-dev --no-install-recommends && rm -rf /var/lib/apt/lists/* # Standard @@ -15,14 +25,15 @@ RUN apt-get update # Specific #RUN apt-get update && apt-get install -y dos2unix --no-install-recommends && rm -rf /var/lib/apt/lists/* -COPY Gemfile /usr/src/app/ -COPY Gemfile.lock /usr/src/app/ +COPY faye/Gemfile /usr/src/app/ +#COPY faye/Gemfile.lock /usr/src/app/ #COPY vendor/cache /usr/src/app/vendor/cache #RUN bundle install --local -RUN rm -rf /usr/src/app/.bundle +#RUN rm -rf /usr/src/app/.bundle RUN bundle install -COPY . /usr/src/app +COPY ./faye /usr/src/app + ENV FAYE_PORT=9296 EXPOSE $FAYE_PORT CMD thin start -R config.ru -p $FAYE_PORT diff --git a/faye/config.ru b/faye/config.ru index e85542f0..85e251ab 100644 --- a/faye/config.ru +++ b/faye/config.ru @@ -1,7 +1,27 @@ require 'faye' -require 'pry' +#require 'pry' +# started using (with extra server contexts of cours like full paths): +# thin start -d -R faye/config.ru -p 9296 --pid tmp/pids/faye.pid +# serve nginx config: +# server { +# listen 443 ssl http2; +# listen [::]:443 ssl http2; +# +# server_name events.mozo.bar; +# +# ssl_certificate /etc/letsencrypt/live/mozo.bar/fullchain.pem; +# ssl_certificate_key /etc/letsencrypt/live/mozo.bar/privkey.pem; +# location / { +# proxy_pass http://127.0.0.1:9296; +# proxy_set_header Host $host; +# proxy_set_header X-Real-IP $remote_addr; +# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +# proxy_set_header X-Forwarded-Proto https; +# } +# } +# #require File.expand_path('../config/initializers/faye_token.rb', __FILE__) -setproctitle('mozo_faye') if respond_to?(:setproctitle) +Process.setproctitle('mozo_faye') if Process.respond_to?(:setproctitle) VALID_TOKENS = ['6be65f9b5e7d21b8ca8de4ccfad5ba24cf40d440b370af79'] class ServerAuth def incoming(message, callback) diff --git a/faye/rebuild-docker.sh b/faye/rebuild-docker.sh new file mode 100755 index 00000000..b05cac2d --- /dev/null +++ b/faye/rebuild-docker.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash +# This script rebuilds the whole environment and starts a new container + +# 1. ensure this script is run from the project's root, not the faye directory +pwd_dirname=$(basename $(pwd)); +script_dirname="faye"; +if [ "$pwd_dirname" == "$script_dirname" ]; then + echo "PWD DIRNAME: "$pwd_dirname; + echo "You must run this script from the project's root dir (../) for the Dockerfile to have access to the configs to COPY"; + exit 1; +fi + +# 2. stop and remove all running/existing containers +docker rm $(docker stop $(docker ps -a -q --filter ancestor=mozo_faye)) + +# 3. remove the previously built images +docker rmi mozo_faye + +# 4. rebuild a fresh image from the latest code +docker build -f faye/Dockerfile -t mozo_faye . + +# debug docker and enter the bash: +# docker run --network=host --env DRB_ENV=production -t -i --rm mozo_faye bash + +# 5. Spin up the counter container from the generated image +docker run --network=host --env DRB_ENV=production --detach --name=mozo_faye mozo_faye diff --git a/lib/qwaiter/employee_base_serializer.rb b/lib/qwaiter/employee_base_serializer.rb index 81cbc81d..dbcbaacd 100644 --- a/lib/qwaiter/employee_base_serializer.rb +++ b/lib/qwaiter/employee_base_serializer.rb @@ -24,6 +24,7 @@ module Qwaiter::EmployeeBaseSerializer #alias_method :default_relationship_related_link, :relationship_related_link def relationship_related_link(attribute_name) super if related_link_for_attributes.include?(attribute_name) + nil end def relationship_self_link(attribute_name) diff --git a/lib/qwaiter/supplier_base_serializer.rb b/lib/qwaiter/supplier_base_serializer.rb index 4f440a35..5baf08b5 100644 --- a/lib/qwaiter/supplier_base_serializer.rb +++ b/lib/qwaiter/supplier_base_serializer.rb @@ -8,7 +8,7 @@ module Qwaiter::SupplierBaseSerializer end def base_url - nil + "/supplier/api/v1" end #def format_name(attribute_name) @@ -21,8 +21,7 @@ module Qwaiter::SupplierBaseSerializer #alias_method :default_relationship_related_link, :relationship_related_link def relationship_related_link(attribute_name) - #super if related_link_for_attributes.include?(attribute_name) - #super + return super if related_link_for_attributes.include?(attribute_name) nil end diff --git a/lib/qwaiter/user_base_serializer.rb b/lib/qwaiter/user_base_serializer.rb index 9c3b4226..e5dd558a 100644 --- a/lib/qwaiter/user_base_serializer.rb +++ b/lib/qwaiter/user_base_serializer.rb @@ -8,8 +8,7 @@ module Qwaiter::UserBaseSerializer end def base_url - "/user" - nil + "/user/api/v1" end def format_name(attribute_name) @@ -24,8 +23,8 @@ module Qwaiter::UserBaseSerializer #alias_method :default_relationship_related_link, :relationship_related_link def relationship_related_link(attribute_name) - #super if related_link_for_attributes.include?(attribute_name) - super + return super if related_link_for_attributes.include?(attribute_name) + nil end def relationship_self_link(attribute_name) diff --git a/translations.en.coffee b/translations.en.coffee new file mode 100644 index 00000000..60aab67f --- /dev/null +++ b/translations.en.coffee @@ -0,0 +1,399 @@ +$translations ||= {} +$translations.en = + total: "Total" + messages: + general_error: "Something went wrong" + cannot_order_on_non_active_list: "You cannot place an order on a closed list" + no_active_list: "There is no active list" + order_is_placed: "Your order has been received in good order" + new_list_created: "A new ${models.list} has been created" + the_list_has_been_closed: "The list has been closed" + illegal_history_list_attempt: "The list you want to access is not yours" + table_not_found: "The requested table cannot be found or is not given" + table_is_occupied: "The table you want to sit on is already occupied" + table_is_reserved: "The table you want to sit on is reserved by someone else" + table_is_closed: "The table you want to sit on is not available for service" + supplier_is_closed: "The owner of this table is currently not handling orders" + table_is_from_other_supplier: "You cannot move to another table when you have an open list" + moved_to_another_table: "You successfully moved to another table" + cannot_identify_table: "The application cannot determine the table number" + unknown_supplier_name: "unknown" + unauthorized: "Unauthorized action detected" + order_could_not_be_processed: "The order could not be processed" + authenticated: "Successfully authenticated" + active_list: + title: "Active list" + needs_payment: "Check please!" + no_orders_explanation: "You did not order anything yet" + not_active: + message: "At the moment there is no active list" + home_button_text: "Back" + join_request: + existing_user: + title: "${models.plural.join_request}" + reject_request: "Reject" + approve_request: "Approve" + no_join_requests_message: "No current join requests for your list" + requestor: + join_this_table: "Join this table" + waiting_for_approval: "Waiting for approval" + join_request_rejected: "Your request to join the table has been rejected" + join_request_approved: "Your request to join the table has been approved" + list_products: + title: "Order" + history_list: + title: "Closed list" + list_history: + title: "Closed lists" + show_products: + title: "Menu" + join_occupied_table: + title: "This table is occupied" + show_the_products: "Show me the menu" + back: "Back" + home: + scan_qr: "Scan qr code" + show_active_list: "Show my orders" + show_active_list_products: "Go to the menu" + basket: + total: "Total" + product_category: + other_name: "Overig" + obtain_token: + title: "Authenticate mozo.bar" + obtain: "Authenticate" + invalid_combination: "The email password combination is incorrect" + move_table: + cannot_move_to_occupied_table: "You cannot move to an occupied table" + moved_to_another_table: "The table is changed." + confirmation_title: "Move to another table?" + confirmation_body: "Do you want to move to table %{number}?" + confirm: + cancel: "Cancel" + confirm: "Yes" + list_needs_help: + help_is_on_its_way: "Help is already on its way" + title: "Request a waiter" + content: "Request a waiter to your table" + list_needs_payment: + payment_already_requested: "You already asked for the bill" + title: "Ask for the check" + content: "Do you want to pay?" + product_orders: + order_button: "Order" + total: "Total" + no_orders: "No products" + back_to_table: "Back to the ${models.table}" + state: + list: + active: "Active" + closed: "Closed" + lists: + show_more: "Show more" + app: + error: + title: "There is a problem with the application" + body: "Please try to restart" + errors: + 404: + model: + message: "Cannot find %{model} with id %{id}" + general: + message: "Cannot find resource" + format: "%{attribute} %{message}" + messages: + model_invalid: "Validation failed: %{errors}" + inclusion: "is not included in the list" + exclusion: "is reserved" + invalid: "is invalid" + confirmation: "doesn't match %{attribute}" + accepted: "must be accepted" + empty: "can't be empty" + blank: "can't be blank" + present: "must be blank" + too_long: + one: "is too long (maximum is 1 character)" + other: "is too long (maximum is %{count} characters)" + too_short: + one: "is too short (minimum is 1 character)" + other: "is too short (minimum is %{count} characters)" + wrong_length: + one: "is the wrong length (should be 1 character)" + other: "is the wrong length (should be %{count} characters)" + not_a_number: "is not a number" + not_an_integer: "must be an integer" + greater_than: "must be greater than %{count}" + greater_than_or_equal_to: "must be greater than or equal to %{count}" + equal_to: "must be equal to %{count}" + less_than: "must be less than %{count}" + less_than_or_equal_to: "must be less than or equal to %{count}" + other_than: "must be other than %{count}" + odd: "must be odd" + even: "must be even" + taken: "is already taken" + no_parent: "should be parent object" + already_confirmed: "was already confirmed, please try signing in" + confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one" + expired: "has expired, please request a new one" + not_found: "not found" + not_locked: "was not locked" + not_saved: + one: "1 error prohibited this %{resource} from being saved:" + other: "%{count} errors prohibited this %{resource} from being saved:" + in_between: "must be in between %{min} and %{max}" + spoofed_media_type: "has contents that are not what they are reported to be" + settings: + title: "Settings" + language: "Language" + reload_application: "Reload application" + about: + title: "About Mozo" + version: "Version" + body: """ +Mozo is an app that allows you to simply order products using your phone.
+The process is as follows: + +Now your order is received behind the bar.

+Feedback of your order is given by one or two checks next to your order. +""" + feedback: + title: "Feedback" + subtitle: "We gladly improve our app using your feedback!" + submit: "Submit feedback" + received: "Thank you for your feedback. We appreciate your opinion!" + empty_content: "No feedback given" + sign_in: + title: "Sign in" + introduction: """ +In order to be recognizable for the place where you want to order you have to authenticate using +a well known identity platform. Your information will be handled with extreme care and not shared +with external parties. +
+""" + footer: "
" + supplier_status_info: + title: "%{name} info" + header: """ +The icons at the top right corner contain information about the place where you +are currently ordering. The number prefixed with # is your table number. +""" + orders_placed_count_explanation: "  means that there are %{count} orders placed and not yet processing or finished" + orders_in_process_count_explanation: "  means that there are %{count} orders currently processing" + close: "Got it" + modal: + info: + close: "Close" + product_variant: + select_on_order: + title: "What variant of %{name} do you want?" + choose: "Choose" + models: + page: "Page" + user: "Guest" + cmtool: + quote: "Quote" + news: "News" + keyword: "Keyword" + faq: "Faq" + contact_form: "Contact request" + newsletter_subscription: "Newsletter subscription" + image: "Image" + directory: "Directory" + yml_file: "Yml file" + plural: + page: "Pages" + user: "Guests" + cmtool: + quote: "Quotes" + news: "News" + keyword: "Keywords" + faq: "Faqs" + contact_form: "Contact requests" + newsletter_subscription: "Newsletter subscriptions" + image: "Images" + directory: "Directories" + yml_file: "Yml files" + supplier: "Restaurants" + new_supplier: "New restaurants" + table: "Tables" + list: "Tabs" + product: "Products" + order: "Orders" + product_category: "Product categories" + product_variant: "Variants" + section: "Sections" + join_request: "Join requests" + user_feedback: "User feedbacks" + employee: "Employees" + employee_shift: "Shifts" + svg_element: "Svg elements" + section_element: "Section elements" + section_area: "Section areas" + supplier: "Restaurant" + new_supplier: "New restaurant" + table: "Table" + list: "Tab" + product: "Product" + order: "Order" + product_category: "Product category" + product_variant: "Variant" + section: "Section" + join_request: "Join request" + user_feedback: "User feedback" + employee: "Employee" + employee_shift: "Shift" + svg_element: "Svg element" + section_element: "Section element" + section_area: "Section area" + attributes: + product_category: + name: "Name" + position: "Position" + week_days: "Availability" + full_day: "Whole day" + start_from: "From" + end_on: "Till" + visible_on: "Active on" + product: + name: "Name" + code: "Code" + price: "Price" + description: "Description" + active: "Active?" + visible: "Visible?" + created_at: "Created" + image: "Image" + product_variant: + name: "Name" + list: + created_at: "Created" + state: "Status" + needs_help: "Needs attention" + needs_payment: "Wants to pay" + closed_at: "Closed at" + price: "Total" + section: + title: "Title" + width: "Width" + height: "Length" + created_at: "Created" + supplier: + name: "${models.supplier} name" + user_message: "Message for ${models.plural.user}" + email: "Email" + password: "Password" + password_confirmation: "Confirmation" + location: "Location" + time_zone: "Time zone" + iens_profile: "Iens profile id" + address: "Addres" + postal_code: "Postal code" + city: "City" + country: "Country" + new_supplier: + supplier_name: "Restaurant name" + email: "E-mail" + password: "Password" + password_confirmation: "Password confirmation" + table: + table_number: "Number" + from_number: "From number" + to_number: "To number" + created_at: "Created" + width: "Width" + height: "Height" + user: + name: "Name" + email: "E-mail" + employee: + name: "Name" + email: "E-mail" + manager: "Manager?" + active: "Active?" + color: "Color" + employee_shift: + description: "Description" + "cmtool/contact_form": + name: "Your name:" + body: "Your question or remarks:" + email: "Your email:*" + male: "Mr." + female: "Ms." + svg_element: + name: "Name" + svg: "SVG" + dpm: "Dots per meter" + box_width: "Box width" + box_height: "Box height" + snap_code: "Snap code" + section_element: + name: "Name" + svg: "SVG" + dpm: "Dots per meter" + box_width: "Box width" + box_height: "Box height" + snap_code: "Snap code" + position_x: "X" + position_y: "Y" + rotation: "Angle" + section_area: + title: "Title" + width: "Width" + height: "Height" + rounded: "Rounded?" + helpers: + select: + prompt: "Please select" + submit: + create: "Add %{model}" + update: "Update %{model}" + submit: "Save %{model}" + page_entries_info: + entry: + zero: "entries" + one: "entry" + other: "entries" + one_page: + display_entries: + zero: "No %{entry_name} found" + one: "Displaying 1 %{entry_name}" + other: "Displaying all %{count} %{entry_name}" + more_pages: + display_entries: "Displaying %{entry_name} %{first} - %{last} of %{total} in total" + links: + are_you_sure: "Are you sure?" + place_order: "Place ${models.order}" + show_active_list: "Show %{list}" + edit: "Edit" + show: "Show" + new: "New" + destroy: "Delete" + back: "Back" + cancel: "Cancel" + index: "Overview" + forms: + errors: + title: "There are problems found during saving (%{count})" + list: + no_records: "There are no items present" + actions: + title: "Actions" + pagination: + first: "« First" + last: "Last »" + previous: "‹ Prev" + next: "Next ›" + truncate: "…" + date: + day_name: + sunday: "Sunday" + monday: "Monday" + tuesday: "Tuesday" + wednesday: "Wednesday" + thursday: "Thursday" + friday: "Friday" + saturday: "Saturday" diff --git a/translations.yml b/translations.yml new file mode 100644 index 00000000..8241d71d --- /dev/null +++ b/translations.yml @@ -0,0 +1,782 @@ +--- +en: + total: Total + messages: + general_error: Something went wrong + cannot_order_on_non_active_list: You cannot place an order on a closed list + no_active_list: There is no active list + order_is_placed: Your order has been received in good order + new_list_created: A new ${models.list} has been created + the_list_has_been_closed: The list has been closed + illegal_history_list_attempt: The list you want to access is not yours + table_not_found: The requested table cannot be found or is not given + table_is_occupied: The table you want to sit on is already occupied + table_is_reserved: The table you want to sit on is reserved by someone else + table_is_closed: The table you want to sit on is not available for service + supplier_is_closed: The owner of this table is currently not handling orders + table_is_from_other_supplier: You cannot move to another table when you have an + open list + moved_to_another_table: You successfully moved to another table + cannot_identify_table: The application cannot determine the table number + unknown_supplier_name: unknown + unauthorized: Unauthorized action detected + order_could_not_be_processed: The order could not be processed + authenticated: Successfully authenticated + active_list: + title: Active list + needs_payment: Check please! + no_orders_explanation: You did not order anything yet + not_active: + message: At the moment there is no active list + home_button_text: Back + join_request: + existing_user: + title: "${models.plural.join_request}" + reject_request: Reject + approve_request: Approve + no_join_requests_message: No current join requests for your list + requestor: + join_this_table: Join this table + waiting_for_approval: Waiting for approval + join_request_rejected: Your request to join the table has been rejected + join_request_approved: Your request to join the table has been approved + list_products: + title: Order + history_list: + title: Closed list + list_history: + title: Closed lists + show_products: + title: Menu + join_occupied_table: + title: This table is occupied + show_the_products: Show me the menu + back: Back + home: + scan_qr: Scan qr code + show_active_list: Show my orders + show_active_list_products: Go to the menu + basket: + total: Total + product_category: + other_name: Overig + obtain_token: + title: Authenticate mozo.bar + obtain: Authenticate + invalid_combination: The email password combination is incorrect + move_table: + cannot_move_to_occupied_table: You cannot move to an occupied table + moved_to_another_table: The table is changed. + confirmation_title: Move to another table? + confirmation_body: Do you want to move to table %{number}? + confirm: + cancel: Cancel + confirm: 'Yes' + list_needs_help: + help_is_on_its_way: Help is already on its way + title: Request a waiter + content: Request a waiter to your table + list_needs_payment: + payment_already_requested: You already asked for the bill + title: Ask for the check + content: Do you want to pay? + product_orders: + order_button: Order + total: Total + no_orders: No products + back_to_table: Back to the ${models.table} + state: + list: + active: Active + closed: Closed + lists: + show_more: Show more + app: + error: + title: There is a problem with the application + body: Please try to restart + errors: + 404: + model: + message: Cannot find %{model} with id %{id} + general: + message: Cannot find resource + format: "%{attribute} %{message}" + messages: + model_invalid: 'Validation failed: %{errors}' + inclusion: is not included in the list + exclusion: is reserved + invalid: is invalid + confirmation: doesn't match %{attribute} + accepted: must be accepted + empty: can't be empty + blank: can't be blank + present: must be blank + too_long: + one: is too long (maximum is 1 character) + other: is too long (maximum is %{count} characters) + too_short: + one: is too short (minimum is 1 character) + other: is too short (minimum is %{count} characters) + wrong_length: + one: is the wrong length (should be 1 character) + other: is the wrong length (should be %{count} characters) + not_a_number: is not a number + not_an_integer: must be an integer + greater_than: must be greater than %{count} + greater_than_or_equal_to: must be greater than or equal to %{count} + equal_to: must be equal to %{count} + less_than: must be less than %{count} + less_than_or_equal_to: must be less than or equal to %{count} + other_than: must be other than %{count} + odd: must be odd + even: must be even + taken: is already taken + no_parent: should be parent object + already_confirmed: was already confirmed, please try signing in + confirmation_period_expired: needs to be confirmed within %{period}, please + request a new one + expired: has expired, please request a new one + not_found: not found + not_locked: was not locked + not_saved: + one: '1 error prohibited this %{resource} from being saved:' + other: "%{count} errors prohibited this %{resource} from being saved:" + in_between: must be in between %{min} and %{max} + spoofed_media_type: has contents that are not what they are reported to be + settings: + title: Settings + language: Language + reload_application: Reload application + about: + title: About Mozo + version: Version + body: | + Mozo is an app that allows you to simply order products using your phone.
+ The process is as follows: + + Now your order is received behind the bar.

+ Feedback of your order is given by one or two checks next to your order. + feedback: + title: Feedback + subtitle: We gladly improve our app using your feedback! + submit: Submit feedback + received: Thank you for your feedback. We appreciate your opinion! + empty_content: No feedback given + sign_in: + title: Sign in + introduction: | + In order to be recognizable for the place where you want to order you have to authenticate using + a well known identity platform. Your information will be handled with extreme care and not shared + with external parties. +
+ footer: "
" + supplier_status_info: + title: "%{name} info" + header: | + The icons at the top right corner contain information about the place where you + are currently ordering. The number prefixed with # is your table number. + orders_placed_count_explanation: "  means that there are %{count} orders + placed and not yet processing or finished" + orders_in_process_count_explanation: "  means that there are %{count} orders + currently processing" + close: Got it + modal: + info: + close: Close + product_variant: + select_on_order: + title: What variant of %{name} do you want? + choose: Choose + models: + page: Page + user: Guest + cmtool: + quote: Quote + news: News + keyword: Keyword + faq: Faq + contact_form: Contact request + newsletter_subscription: Newsletter subscription + image: Image + directory: Directory + yml_file: Yml file + plural: + page: Pages + user: Guests + cmtool: + quote: Quotes + news: News + keyword: Keywords + faq: Faqs + contact_form: Contact requests + newsletter_subscription: Newsletter subscriptions + image: Images + directory: Directories + yml_file: Yml files + supplier: Restaurants + new_supplier: New restaurants + table: Tables + list: Tabs + product: Products + order: Orders + product_category: Product categories + product_variant: Variants + section: Sections + join_request: Join requests + user_feedback: User feedbacks + employee: Employees + employee_shift: Shifts + svg_element: Svg elements + section_element: Section elements + section_area: Section areas + supplier: Restaurant + new_supplier: New restaurant + table: Table + list: Tab + product: Product + order: Order + product_category: Product category + product_variant: Variant + section: Section + join_request: Join request + user_feedback: User feedback + employee: Employee + employee_shift: Shift + svg_element: Svg element + section_element: Section element + section_area: Section area + attributes: + product_category: + name: Name + position: Position + week_days: Availability + full_day: Whole day + start_from: From + end_on: Till + visible_on: Active on + product: + name: Name + code: Code + price: Price + description: Description + active: Active? + visible: Visible? + created_at: Created + image: Image + product_variant: + name: Name + list: + created_at: Created + state: Status + needs_help: Needs attention + needs_payment: Wants to pay + closed_at: Closed at + price: Total + section: + title: Title + width: Width + height: Length + created_at: Created + supplier: + name: "${models.supplier} name" + user_message: Message for ${models.plural.user} + email: Email + password: Password + password_confirmation: Confirmation + location: Location + time_zone: Time zone + iens_profile: Iens profile id + address: Addres + postal_code: Postal code + city: City + country: Country + new_supplier: + supplier_name: Restaurant name + email: E-mail + password: Password + password_confirmation: Password confirmation + table: + table_number: Number + from_number: From number + to_number: To number + created_at: Created + width: Width + height: Height + user: + name: Name + email: E-mail + employee: + name: Name + email: E-mail + manager: Manager? + active: Active? + color: Color + employee_shift: + description: Description + cmtool/contact_form: + name: 'Your name:' + body: 'Your question or remarks:' + email: Your email:* + male: Mr. + female: Ms. + svg_element: + name: Name + svg: SVG + dpm: Dots per meter + box_width: Box width + box_height: Box height + snap_code: Snap code + section_element: + name: Name + svg: SVG + dpm: Dots per meter + box_width: Box width + box_height: Box height + snap_code: Snap code + position_x: X + position_y: Y + rotation: Angle + section_area: + title: Title + width: Width + height: Height + rounded: Rounded? + helpers: + select: + prompt: Please select + submit: + create: Add %{model} + update: Update %{model} + submit: Save %{model} + page_entries_info: + entry: + zero: entries + one: entry + other: entries + one_page: + display_entries: + zero: No %{entry_name} found + one: Displaying 1 %{entry_name} + other: Displaying all %{count} %{entry_name} + more_pages: + display_entries: Displaying %{entry_name} %{first} - %{last} + of %{total} in total + links: + are_you_sure: Are you sure? + place_order: Place ${models.order} + show_active_list: Show %{list} + edit: Edit + show: Show + new: New + destroy: Delete + back: Back + cancel: Cancel + index: Overview + forms: + errors: + title: There are problems found during saving (%{count}) + list: + no_records: There are no items present + actions: + title: Actions + pagination: + first: "« First" + last: Last » + previous: "‹ Prev" + next: Next › + truncate: "…" + date: + day_name: + sunday: Sunday + monday: Monday + tuesday: Tuesday + wednesday: Wednesday + thursday: Thursday + friday: Friday + saturday: Saturday +nl: + total: Totaal + messages: + general_error: Er is iets misgegaan + cannot_order_on_non_active_list: Je kan niet bestellen op een gesloten lijst + no_active_list: Er is momenteel geen lijst actief + order_is_placed: Je bestelling is in goede orde aangekomen + new_list_created: Een nieuwe ${models.list} is aangemaakt + the_list_has_been_closed: De lijst is afgesloten + illegal_history_list_attempt: Je probeert een lijst op te vragen die niet van + jou is + table_not_found: De gezochte tafel kan niet worden gevonden of is niet opgegeven + table_is_occupied: De tafel waar je aan wil gaan zitten is reeds bezet + table_is_reserved: De tafel waar je aan wil gaan zitten is gereserveerd + table_is_closed: De tafel waar je aan wil gaan zitten is niet beschikbaar voor + bediening + supplier_is_closed: De eigenaar van deze tafel is momenteel gesloten + table_is_from_other_supplier: Je kan geen lijst openen bij een andere zaak zolang + je huidige lijst nog niet is afgesloten + moved_to_another_table: De tafel is gewijzigd + cannot_identify_table: De applicatie kan niet bepalen om welke tafel het gaat + unknown_supplier_name: onbekend + unauthorized: Niet toegestane actie + order_could_not_be_processed: De bestelling kan niet worden uitgevoerd + authenticated: Succesvolle login + active_list: + title: Actieve lijst + needs_payment: Rekening vragen! + no_orders_explanation: Je hebt nog niks besteld + not_active: + message: Momenteel is er geen lijst actief + home_button_text: Terug + list_products: + title: Bestel + join_request: + existing_user: + title: "${models.plural.join_request}" + reject_request: Afwijzen + approve_request: Toestaan + no_join_requests_message: Geen deelname verzoeken voor de huidige ${models.list} + requestor: + waiting_for_approval: Wachten op toestemming + join_this_table: Ik wil ook bestellen bij deze tafel + join_request_rejected: Je verzoek om deel te nemen aan de ${models.list|downcase} + is afgewezen + join_request_approved: Je verzoek om deel te nemen aan de ${models.list|downcase} + is goedgekeurd + history_list: + title: Afgesloten lijst + list_history: + title: Afgesloten lijsten + show_products: + title: Menu + join_occupied_table: + title: Deze tafel is bezet + show_the_products: Laat me het menu zien + back: Terug + home: + scan_qr: Scan qr code + show_active_list: Toon mijn bestellingen + show_active_list_products: Ga naar het menu + basket: + total: Totaal + product_category: + other_name: Overig + obtain_token: + title: Aanmelden bij mozo.bar + obtain: Aanmelden + invalid_combination: De inloggegevens zijn onjuist + move_table: + cannot_move_to_occupied_table: Je kan niet verhuizen naar een tafel die reeds + gebruikt wordt. + moved_to_another_table: De tafel is gewijzigd. + confirmation_title: Naar een andere tafel verhuizen? + confirmation_body: Wil je verplaatsen naar tafel %{number}? + confirm: + cancel: Annuleer + confirm: Ja + list_needs_help: + help_is_on_its_way: Er wordt al iemand naar je tafel gestuurd + title: Ik heb een vraag + content: Wil je een vraag stellen? + list_needs_payment: + payment_already_requested: De rekening is reeds gevraagd + title: Vraag om de rekening + content: Wil je betalen? + product_orders: + order_button: Bestel + total: Totaal + no_orders: Geen bestellingen + back_to_table: Terug naar de ${models.table} + state: + list: + active: Actief + closed: Afgesloten + lists: + show_more: Meer tonen + app: + error: + title: Er is een probleem met de applicatie + body: Herstart de applicatie om het op te lossen + errors: + 404: + model: + message: "%{model} met id %{id} kan niet worden gevonden" + general: + message: Data niet beschikbaar + messages: + already_confirmed: was reeds bevestigd + confirmation_period_expired: moet binnen %{period} worden bevestigd, plaats + a.u.b. een nieuw verzoek + expired: is verlopen, vraag een nieuwe aan + not_found: bestaat niet + not_locked: was niet vergrendeld + not_saved: + one: 'Een fout verhinderde het uitvoeren van de actie:' + other: "%{count} fouten verhinderden het uitvoeren van de actie:" + accepted: moet worden geaccepteerd + blank: moet opgegeven zijn + confirmation: komt niet met de bevestiging overeen + empty: moet opgegeven zijn + equal_to: moet gelijk zijn aan %{count} + even: moet even zijn + exclusion: is niet beschikbaar + greater_than: moet groter zijn dan %{count} + greater_than_or_equal_to: moet groter dan of gelijk zijn aan %{count} + inclusion: is niet in de lijst opgenomen + invalid: is ongeldig + less_than: moet minder zijn dan %{count} + less_than_or_equal_to: moet minder dan of gelijk zijn aan %{count} + not_a_number: is geen getal + not_an_integer: moet een geheel getal zijn + odd: moet oneven zijn + record_invalid: 'Validatie mislukt: %{errors}' + taken: is al in gebruik + too_long: is te lang (maximaal %{count} tekens) + too_short: is te kort (minimaal %{count} tekens) + wrong_length: heeft onjuiste lengte (moet %{count} tekens lang zijn) + format: "%{attribute} %{message}" + template: + body: 'Controleer de volgende velden:' + header: + one: "%{model} niet opgeslagen: 1 fout gevonden" + other: "%{model} niet opgeslagen: %{count} fouten gevonden" + settings: + title: Settings + language: Taal + reload_application: Applicatie herstarten + about: + title: Over Mozo + version: Versie + body: | + Mozo is een app waarme je producten kan bestellen met je telefoon.
+ Het proces is als volgt: + + Nu komt je bestelling achter de bar binnen.

+ Feedback van je bestelling krijg je dmv een of twee vinkjes naast je bestelling. + feedback: + title: Feedback + subtitle: We verbeteren graag de app aan de hand van jouw feedback! + submit: Geef feedback + received: Dank je voor het meedenken! + empty_content: Geen feedback gegeven + sign_in: + title: Aanmelden + introduction: "Om herkenbaar te zijn voor de horeca ondernemer is de aanmelding + via een bekend identiteits platform.\nJe gegevens worden niet gedeeld met andere + partijen, behalve basisinformatie zoals je naam voor de \nhoreca onderneming + waar je wat bestelt.\n
\n" + footer: "
" + supplier_status_info: + title: "%{name} info" + header: | + De icoontjes rechtsboven geven informatie over de plek waar je aan het bestellen bent. + Het getal met # is je tafelnummer. + orders_placed_count_explanation: "  betekent dat er %{count} nog niet in + behandeling of afgesloten bestellingen zijn" + orders_in_process_count_explanation: "  betekent dat er %{count} bestellingen + in behandeling zijn" + close: Got it + modal: + info: + close: Sluit + product_variant: + select_on_order: + title: Selecteer welke variant %{name} je wilt + choose: Kies + models: + page: Page + user: Gast + cmtool: + quote: Quote + news: News + keyword: Keyword + faq: Faq + contact_form: Contact request + newsletter_subscription: Newsletter subscription + image: Image + directory: Directory + plural: + page: Pages + user: Gasten + cmtool: + quote: Quotes + news: News + keyword: Keywords + faq: Faqs + contact_form: Contact requests + newsletter_subscription: Newsletter subscriptions + image: Images + directory: Directories + supplier: Restaurants + new_supplier: Nieuwe restaurants + table: Tafels + list: Bonnen + product: Producten + order: Bestellingen + product_category: Product categorieen + product_variant: Varianten + section: Afdelingen + join_request: Deelname verzoeken + employee: Werknemers + employee_shift: Shifts + svg_element: Svg element + section_element: Ruimte elementen + section_area: Ruimte blokken + supplier: Restaurant + new_supplier: Nieuw restaurant + table: Tafel + list: Bon + product: Product + order: Bestelling + product_category: Product categorie + product_variant: Variant + section: Afdeling + join_request: Deelname verzoek + employee: Werknemer + employee_shift: Shift + svg_element: Svg element + section_element: Ruimte element + section_area: Ruimte blok + attributes: + product_category: + name: Naam + position: Positie + week_days: Beschikbaarheid + full_day: De hele dag + start_from: Van + end_on: Tot + visible_on: Actief op + product: + name: Naam + code: Code + price: Prijs + description: Omschrijving + visible: Zichtbaar? + active: Actief? + created_at: Aangemaakt + image: Afbeelding + product_variant: + name: Naam + list: + created_at: Aangemaakt + state: Status + needs_help: Vraag actief + needs_payment: Rekening gevraagd + closed_at: Afgesloten op + price: Totaal + section: + title: Titel + width: Breedte + height: Lengte + created_at: Aangemaakt + supplier: + name: "${models.supplier} naam" + user_message: Bericht voor ${models.plural.user} + email: E-mail + password: Wachtwoord + password_confirmation: Bevestiging + location: Locatie + time_zone: Tijdzone + iens_profile: Iens profiel id + address: Addres + postal_code: Postcode + city: Stad + country: Land + new_supplier: + supplier_name: Restaurant name + email: E-mail + password: Wachtwoord + password_confirmation: Nogmaals wachtwoord + table: + table_number: Nummer + from_number: Vanaf nummer + to_number: Tot nummer + created_at: Aangemaakt + width: Breedte + height: Hoogte + user: + name: Naam + email: E-mail + employee: + name: Naam + email: E-mail + manager: Manager? + active: Actief? + color: Kleur + employee_shift: + description: Toelichting + cmtool/contact_form: + name: 'Je naam:' + body: 'Je vraag of opmerking:' + email: E-mail:* + male: Dhr. + female: Mvr. + svg_element: + name: Name + svg: SVG + dpm: Dots per meter + box_width: Box width + box_height: Box height + snap_code: Snap code + section_element: + name: Name + svg: SVG + dpm: Dots per meter + box_width: Box width + box_height: Box height + snap_code: Snap code + position_x: X + position_y: Y + rotation: Angle + section_area: + title: Titel + width: Breedte + height: Hoogte + rounded: Rond? + helpers: + links: + are_you_sure: Weet je dit zeker? + place_order: Bestellen + show_active_list: Toon %{list} + edit: Bewerk + show: Toon + new: Nieuw + destroy: Verwijder + back: Terug + cancel: Terug + index: Overzicht + forms: + errors: + title: De actie kon niet worden uitgevoerd. %{count} fout(en) + submit: + create: "%{model} toevoegen" + update: "%{model} bewaren" + submit: "%{model} opslaan" + list: + no_records: Er zijn geen items aanwezig + actions: + title: Acties + select: + prompt: Selecteer + pagination: + first: "« Eerste" + last: Laatste » + previous: "‹ Vorige" + next: Volgende › + truncate: "…" + date: + day_name: + sunday: zondag + monday: maandag + tuesday: dinsdag + wednesday: woensdag + thursday: donderdag + friday: vrijdag + saturday: zaterdag