From dd70b84ef0161ddb33c781d7951f7924c669a07a Mon Sep 17 00:00:00 2001 From: Julius Date: Wed, 26 Jun 2013 15:16:52 +0200 Subject: [PATCH] Linearize and clean up delivery form --- app/assets/javascripts/application.js | 3 - .../bootstrap_and_overrides.css.less | 6 + app/controllers/deliveries_controller.rb | 5 +- app/helpers/deliveries_helper.rb | 23 +-- app/views/deliveries/_form.html.haml | 144 +++++++++--------- .../_stock_article_for_adding.html.haml | 13 +- .../deliveries/_stock_article_form.html.haml | 11 +- app/views/deliveries/_stock_change.html.haml | 18 +-- .../deliveries/_stock_change_fields.html.haml | 9 ++ app/views/deliveries/add_stock_change.js.erb | 38 ++--- ...cle.js.erb => create_stock_article.js.erb} | 0 .../deliveries/update_stock_article.js.erb | 13 +- config/initializers/simple_form.rb | 15 -- config/initializers/simple_form_bootstrap.rb | 13 +- config/locales/de.yml | 12 +- config/routes.rb | 2 +- 16 files changed, 170 insertions(+), 155 deletions(-) create mode 100644 app/views/deliveries/_stock_change_fields.html.haml rename app/views/deliveries/{add_stock_article.js.erb => create_stock_article.js.erb} (100%) diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index a11f5567..c49e5d9d 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -142,9 +142,6 @@ $(function() { // Sort tables with a default sort $('.sorter-bar.default-sort-asc button:nth-child(1)').trigger('click'); $('.sorter-bar.default-sort-desc button:nth-child(2)').trigger('click'); - - // Translate Select2 messages - could be done in another place, right? - $.fn.select2.defaults.formatNoMatches = function () { return "-"; }; }); // compare two elements interpreted as text diff --git a/app/assets/stylesheets/bootstrap_and_overrides.css.less b/app/assets/stylesheets/bootstrap_and_overrides.css.less index 20b287bf..a87a4017 100644 --- a/app/assets/stylesheets/bootstrap_and_overrides.css.less +++ b/app/assets/stylesheets/bootstrap_and_overrides.css.less @@ -48,6 +48,12 @@ body { font-size: @baseFontSize; } +// Do not use additional margin for input in table +.form-horizontal .control-group.control-group-intable, +.form-horizontal .controls.controls-intable { + margin: 0; +} + @mainRedColor: #ED0606; .logo { diff --git a/app/controllers/deliveries_controller.rb b/app/controllers/deliveries_controller.rb index 7ca7777e..cc535b07 100644 --- a/app/controllers/deliveries_controller.rb +++ b/app/controllers/deliveries_controller.rb @@ -13,6 +13,7 @@ class DeliveriesController < ApplicationController def new @delivery = @supplier.deliveries.build + @delivery.delivered_on = Date.today #TODO: move to model/database end def create @@ -60,12 +61,12 @@ class DeliveriesController < ApplicationController unless old_article.nil? @stock_article = old_article.dup else - @stock_article = @supplier.stock_articles.build + @stock_article = @supplier.stock_articles.build(params[:stock_article]) end render :layout => false end - def add_stock_article + def create_stock_article @stock_article = StockArticle.new(params[:stock_article]) if @stock_article.valid? and @stock_article.save diff --git a/app/helpers/deliveries_helper.rb b/app/helpers/deliveries_helper.rb index 614c637a..bf641344 100644 --- a/app/helpers/deliveries_helper.rb +++ b/app/helpers/deliveries_helper.rb @@ -1,5 +1,5 @@ module DeliveriesHelper - + def link_to_invoice(delivery) if delivery.invoice link_to number_to_currency(delivery.invoice.amount), [:finance, delivery.invoice], @@ -9,17 +9,20 @@ module DeliveriesHelper class: 'btn btn-mini' end end - - def stock_articles_for_select(supplier) - supplier.stock_articles.undeleted.reorder('articles.name ASC').map {|a| ["#{a.name} (#{number_to_currency a.price}/#{a.unit})", a.id] } + + def articles_for_select2(supplier) + supplier.articles.undeleted.reorder('articles.name ASC').map {|a| {:id => a.id, :text => "#{a.name} (#{number_to_currency a.price}/#{a.unit})"} } end - - def articles_for_select(supplier) - supplier.articles.undeleted.reorder('articles.name ASC').map {|a| ["#{a.name} (#{number_to_currency a.price}/#{a.unit})", a.id] }.unshift(['', nil]) - end - + def stock_articles_for_table(supplier) supplier.stock_articles.undeleted.reorder('articles.name COLLATE NOCASE ASC') end - + + def stock_change_remove_link(stock_change_form) + return link_to t('.remove_article'), "#", :class => 'remove_new_stock_change btn btn-small' if stock_change_form.object.new_record? + output = stock_change_form.hidden_field :_destroy + output += link_to t('.remove_article'), "#", :class => 'destroy_stock_change btn btn-small' + return output.html_safe + end + end diff --git a/app/views/deliveries/_form.html.haml b/app/views/deliveries/_form.html.haml index f84d94e5..9169a367 100644 --- a/app/views/deliveries/_form.html.haml +++ b/app/views/deliveries/_form.html.haml @@ -16,18 +16,48 @@ unmark_article_unavailable_for_delivery( stock_change.data('id') ); return false; }) - $('#copy_from_article').select2({ - placeholder: '#{t '.copy_order_article'}', - allowClear: true + + $('#new_stock_article').removeAttr('disabled').select2({ + placeholder: '#{t '.create_stock_article'}', + data: #{articles_for_select2(@supplier).to_json}, + createSearchChoice: function(term) { + return { + id: 'new', + text: term + }; + }, + formatResult: function(result, container, query, escapeMarkup) { + if(result.id == 'new') { + return result.text + ' (#{t '.create_from_blank'})'; + } + var markup=[]; + Select2.util.markMatch(result.text, query.term, markup, escapeMarkup); + return markup.join(""); + } }).on('change', function(e) { - if(e.val != '') { + var selectedArticle = $(e.currentTarget).select2('data'); + if(!selectedArticle) { + return false; + } + if('new' == selectedArticle.id) { $.ajax({ url: '#{new_stock_article_supplier_deliveries_path(@supplier)}', type: 'get', - data: {old_article_id: e.val}, + data: {stock_article: {name: selectedArticle.text}}, contentType: 'application/json; charset=UTF-8' }); - $('#copy_from_article').select2('data', null); + $('#new_stock_article').select2('data', null); + return true; + } + if('' != selectedArticle.id) { + $.ajax({ + url: '#{new_stock_article_supplier_deliveries_path(@supplier)}', + type: 'get', + data: {old_article_id: selectedArticle.id}, + contentType: 'application/json; charset=UTF-8' + }); + $('#new_stock_article').select2('data', null); + return true; } }); }); @@ -47,67 +77,45 @@ return articleTr.hasClass('unavailable'); } --# remove validate true for the form, because it disabled html5 validation --# is there anything broken with the simple_form validation? (bootstrap issue?) -= simple_form_for [@supplier, @delivery] do |f| += simple_form_for [@supplier, @delivery], validate: true do |f| = f.hidden_field :supplier_id - .row-fluid - - .span6 - %h2= t '.title_select_stock_articles' - .well.well-small - .btn-toolbar - .btn-group - = link_to t('.new_stock_article'), new_stock_article_supplier_deliveries_path(@supplier), remote: true, class: 'btn' - = select_tag(:copy_from_article, options_for_select(articles_for_select(@supplier))) - %table.table.table-condensed.table-hover#stock_articles_for_adding - %thead - %tr - %th - = t '.article' - %span.sorter-bar.default-sort-asc{:data => {'compare-function' => 'compareText', 'sort-criterion' => 'sort-by-name'}} - %th= t '.unit' - %th= t '.price' - %th= t '.vat' - %th - = t '.category' - %span.sorter-bar{:data => {'compare-function' => 'compareText', 'sort-criterion' => 'sort-by-category'}} - %th= t '.actions' - %tbody - - for article in stock_articles_for_table(@supplier) - = render :partial => 'stock_article_for_adding', :locals => {:article => article} + %h2= t '.title_select_stock_articles' + .well.well-small + .btn-toolbar + .btn-group + %input#new_stock_article{:style => 'width: 500px;'} + %table.table.table-condensed.table-hover#stock_articles_for_adding + %thead + %tr + %th + = t '.article' + %span.sorter-bar.default-sort-asc{:data => {'compare-function' => 'compareText', 'sort-criterion' => 'sort-by-name'}} + %th= t '.price' + %th + = t '.category' + %span.sorter-bar{:data => {'compare-function' => 'compareText', 'sort-criterion' => 'sort-by-category'}} + %th= t '.actions' + %tbody + - for article in stock_articles_for_table(@supplier) + = render :partial => 'stock_article_for_adding', :locals => {:article => article} - .span6 - %h2= t '.title_fill_quantities' - - %table.table.table-condensed#stock_changes - %thead - %tr - %th - = t '.article' - %span.sorter-bar.default-sort-asc{:data => {'compare-function' => 'compareText', 'sort-criterion' => 'sort-by-name'}} - %th= t '.price_per_unit' - %th= t '.quantity' - %th= t '.actions' - %tbody - -# see also the partial 'stock_change' which is used for AJAX updates! - -# see also the partial 'stock_change' which is used for AJAX updates! - -# see also the partial 'stock_change' which is used for AJAX updates! - = f.simple_fields_for :stock_changes do |stock_change_form| - - stock_change = stock_change_form.object - %tr{:id => "stock_change_stock_article_#{stock_change.stock_article.id}", :data => {:id => stock_change.stock_article.id}} - %td.sort-by-name - = stock_change_form.association :stock_article, :as => :hidden - %span.stock_article_name= stock_change.stock_article.name - %td.numeric.price-per-unit #{number_to_currency stock_change.stock_article.price}/#{stock_change.stock_article.unit} - %td= stock_change_form.input :quantity, :wrapper => :intable, :input_html => {:class => 'stock-change-quantity', :autocomplete => :off} - %td - = stock_change_form.hidden_field :_destroy - = link_to t('.remove_article'), "#", :class => 'destroy_stock_change btn btn-small' - - %h2= t '.title_finish_delivery' - = f.input :delivered_on, as: :date_picker - = f.input :note, input_html: {size: '35x4'} - .form-actions - = f.submit class: 'btn btn-primary' - = link_to t('ui.or_cancel'), supplier_deliveries_path(@supplier) + %h2= t '.title_fill_quantities' + %table.table.table-condensed#stock_changes + %thead + %tr + %th + = t '.article' + %span.sorter-bar.default-sort-asc{:data => {'compare-function' => 'compareText', 'sort-criterion' => 'sort-by-name'}} + %th= t '.price' + %th= t '.quantity' + %th= t '.actions' + %tbody + = f.simple_fields_for :stock_changes do |stock_change_form| + = render :partial => 'stock_change_fields', :locals => {:f => stock_change_form} + + %h2= t '.title_finish_delivery' + = f.input :delivered_on, as: :date_picker + = f.input :note, input_html: {size: '35x4'} + .form-actions + = f.submit class: 'btn btn-primary' + = link_to t('ui.or_cancel'), supplier_deliveries_path(@supplier) diff --git a/app/views/deliveries/_stock_article_for_adding.html.haml b/app/views/deliveries/_stock_article_for_adding.html.haml index 5aba3245..19c8d14d 100644 --- a/app/views/deliveries/_stock_article_for_adding.html.haml +++ b/app/views/deliveries/_stock_article_for_adding.html.haml @@ -1,16 +1,11 @@ - css_class = ( @delivery and @delivery.includes_article? article ) ? ( 'unavailable' ) : ( false ) %tr{:id => "stock_article_#{article.id}", :class => css_class} - %td.sort-by-name - = article.name - %td.numeric= article.unit - %td.numeric= number_to_currency article.price - %td.numeric= number_to_percentage article.tax + %td.sort-by-name= article.name + %td #{number_to_currency article.price}/#{article.unit} %td.sort-by-category= article.article_category.name %td .btn-group = link_to t('.action_edit'), edit_stock_article_supplier_deliveries_path(@supplier, :stock_article_id => article.id), remote: true, class: 'btn btn-mini' = link_to t('.action_other_price'), new_stock_article_supplier_deliveries_path(@supplier, :old_stock_article_id => article.id), remote: true, class: 'btn btn-mini' - - if @delivery and @delivery.includes_article? article - = link_to t('.action_add_to_delivery'), add_stock_change_supplier_deliveries_path(@supplier, :stock_article_id => article.id), :method => :post, remote: true, class: 'button-add-stock-change btn btn-mini', disabled: 'disabled' - - else - = link_to t('.action_add_to_delivery'), add_stock_change_supplier_deliveries_path(@supplier, :stock_article_id => article.id), :method => :post, remote: true, class: 'button-add-stock-change btn btn-mini' + - deliver_button_disabled = ( @delivery and @delivery.includes_article? article ) ? ( 'disabled' ) : ( false ) + = link_to t('.action_add_to_delivery'), add_stock_change_supplier_deliveries_path(@supplier, :stock_article_id => article.id), :method => :post, remote: true, class: 'button-add-stock-change btn btn-mini btn-primary', disabled: deliver_button_disabled diff --git a/app/views/deliveries/_stock_article_form.html.haml b/app/views/deliveries/_stock_article_form.html.haml index edd46c0e..d096f633 100644 --- a/app/views/deliveries/_stock_article_form.html.haml +++ b/app/views/deliveries/_stock_article_form.html.haml @@ -1,8 +1,7 @@ -- url = ( stock_article.new_record? ) ? ( add_stock_article_supplier_deliveries_path(@supplier) ) : ( update_stock_article_supplier_deliveries_path(@supplier) ) -= simple_form_for stock_article, url: url, remote: true do |f| - = f.hidden_field :supplier_id - - unless stock_article.new_record? - = f.hidden_field :id +- url = ( stock_article.new_record? ) ? ( create_stock_article_supplier_deliveries_path(@supplier) ) : ( update_stock_article_supplier_deliveries_path(@supplier) ) += simple_form_for stock_article, url: url, remote: true, validate: true do |f| + = f.association :supplier, :as => :hidden + = f.hidden_field :id unless stock_article.new_record? .modal-header = link_to t('ui.marks.close').html_safe, '#', class: 'close', data: {dismiss: 'modal'} %h3= t 'activerecord.models.stock_article' @@ -21,4 +20,4 @@ = f.association :article_category .modal-footer = link_to t('ui.close'), '#', class: 'btn', data: {dismiss: 'modal'} - = f.submit class: 'btn btn-primary' + = f.submit :class => 'btn btn-primary', 'data-disable-with' => t('ui.please_wait') diff --git a/app/views/deliveries/_stock_change.html.haml b/app/views/deliveries/_stock_change.html.haml index f4230b65..a4a91a78 100644 --- a/app/views/deliveries/_stock_change.html.haml +++ b/app/views/deliveries/_stock_change.html.haml @@ -1,12 +1,6 @@ --# see also the partial 'form' which is used for existing stock_changes when loading the edit! --# see also the partial 'form' which is used for existing stock_changes when loading the edit! --# see also the partial 'form' which is used for existing stock_changes when loading the edit! -= simple_fields_for "delivery[new_stock_changes][]", stock_change, validate: true do |f| - - f.object.quantity = '' if 0 == f.object.quantity - %tr{:id => "stock_change_stock_article_#{stock_change.stock_article.id}", :data => {:id => stock_change.stock_article.id}} - %td.sort-by-name - = f.association :stock_article, :as => :hidden - %span.stock_article_name= stock_change.stock_article.name - %td.numeric.price-per-unit #{number_to_currency stock_change.stock_article.price}/#{stock_change.stock_article.unit} - %td= f.input :quantity, :wrapper => :intable, :input_html => {:class => 'stock-change-quantity', :autocomplete => :off} - %td= link_to t('.remove_article'), "#", :class => 'remove_new_stock_change btn btn-small' +- if stock_change.stock_article.new_record? + = simple_fields_for "delivery[new_stock_changes_new_stock_article][]", stock_change do |f| + = render :partial => 'stock_change_fields', :locals => {:f => f} +- else + = simple_fields_for "delivery[new_stock_changes][]", stock_change do |f| + = render :partial => 'stock_change_fields', :locals => {:f => f} diff --git a/app/views/deliveries/_stock_change_fields.html.haml b/app/views/deliveries/_stock_change_fields.html.haml new file mode 100644 index 00000000..b1d94601 --- /dev/null +++ b/app/views/deliveries/_stock_change_fields.html.haml @@ -0,0 +1,9 @@ +- stock_change = f.object +- stock_article = stock_change.stock_article +%tr{:id => "stock_change_stock_article_#{stock_article.id}", :data => {:id => stock_article.id}} + %td.sort-by-name + %span.stock_article_name= stock_change.stock_article.name + = f.association :stock_article, :as => :hidden + %td.price-per-unit #{number_to_currency stock_article.price}/#{stock_change.stock_article.unit} + %td= f.input :quantity, :wrapper => :intable, :input_html => {:class => 'stock-change-quantity', :autocomplete => :off} + %td= stock_change_remove_link f diff --git a/app/views/deliveries/add_stock_change.js.erb b/app/views/deliveries/add_stock_change.js.erb index dd9efcf5..30d7daaf 100644 --- a/app/views/deliveries/add_stock_change.js.erb +++ b/app/views/deliveries/add_stock_change.js.erb @@ -1,20 +1,24 @@ -if(!is_article_unavailable_for_delivery(<%= @stock_change.stock_article.id %>)) { - <%# would be easier to return in the opposite case, but how? %> +(function(w) { + if(is_article_unavailable_for_delivery(<%= @stock_change.stock_article.id %>)) { + return false; + } mark_article_unavailable_for_delivery(<%= @stock_change.stock_article.id %>); - (function(w) { - $('#stock_changes tr').removeClass('success'); - - var stock_change = $( - '<%= j(render(:partial => 'stock_change', :locals => {:stock_change => @stock_change})) %>' - ).addClass('success'); - - $('#stock_changes').append(stock_change); - updateSort('#stock_changes'); - - var quantity = w.prompt('<%= j(t('.how_many_units', :unit => @stock_change.stock_article.unit, :name => @stock_change.stock_article.name)) %>'); <%# how to properly escape here? %> - $('input.stock-change-quantity', stock_change).val(quantity); - })(window); - -} + var quantity = w.prompt('<%= j(t('.how_many_units', :unit => @stock_change.stock_article.unit, :name => @stock_change.stock_article.name)) %>'); <%# how to properly escape here? %> + if(null === quantity) { + unmark_article_unavailable_for_delivery(<%= @stock_change.stock_article.id %>); // think wisely before changing this: What about double clicks on "deliver" button? + return false; + } + + $('#stock_changes tr').removeClass('success'); + + var stock_change = $( + '<%= j(render(:partial => 'stock_change', :locals => {:stock_change => @stock_change})) %>' + ).addClass('success'); + + $('input.stock-change-quantity', stock_change).val(quantity); + + $('#stock_changes').append(stock_change); + updateSort('#stock_changes'); +})(window); diff --git a/app/views/deliveries/add_stock_article.js.erb b/app/views/deliveries/create_stock_article.js.erb similarity index 100% rename from app/views/deliveries/add_stock_article.js.erb rename to app/views/deliveries/create_stock_article.js.erb diff --git a/app/views/deliveries/update_stock_article.js.erb b/app/views/deliveries/update_stock_article.js.erb index 81fde972..af0f7e7c 100644 --- a/app/views/deliveries/update_stock_article.js.erb +++ b/app/views/deliveries/update_stock_article.js.erb @@ -3,6 +3,8 @@ $('div.container-fluid').prepend( ); (function() { + // update entry in stock_article table + $('#stock_articles_for_adding tr').removeClass('success'); var old_entry = $('#stock_article_<%= @stock_article.id %>'); @@ -11,14 +13,15 @@ $('div.container-fluid').prepend( '<%= j(render(:partial => 'stock_article_for_adding', :locals => {:article => @stock_article, :delivery => @delivery})) %>' ).addClass('success'); - if(unavailable) { - stock_article_for_adding.addClass('unavailable'); - $('.button-add-stock-change', stock_article_for_adding).attr('disabled', 'disabled'); - } - old_entry.replaceWith(stock_article_for_adding); updateSort('#stock_articles_for_adding'); + if(unavailable) { + mark_article_unavailable_for_delivery(<%= @stock_article.id %>); + } + + // update entry in stock_changes table + $('#stock_changes tr').removeClass('success'); var stock_change_entry = $('#stock_change_stock_article_<%= @stock_article.id %>'); diff --git a/config/initializers/simple_form.rb b/config/initializers/simple_form.rb index 4d8dc014..b4cb19de 100644 --- a/config/initializers/simple_form.rb +++ b/config/initializers/simple_form.rb @@ -44,21 +44,6 @@ SimpleForm.setup do |config| b.use :hint, :wrap_with => { :tag => :span, :class => :hint } b.use :error, :wrap_with => { :tag => :span, :class => :error } end - - config.wrappers :intable, :class => 'control-group', - :error_class => :error do |b| - b.use :html5 - b.use :placeholder - b.optional :maxlength - b.optional :pattern - b.optional :min_max - b.optional :readonly - - b.use :input - b.use :hint - b.use :error, :wrap_with => { :tag => :span, :class => 'help-inline' } - end - # The default wrapper to be used by the FormBuilder. config.default_wrapper = :default diff --git a/config/initializers/simple_form_bootstrap.rb b/config/initializers/simple_form_bootstrap.rb index 1a229676..5c581107 100644 --- a/config/initializers/simple_form_bootstrap.rb +++ b/config/initializers/simple_form_bootstrap.rb @@ -36,7 +36,18 @@ SimpleForm.setup do |config| input.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' } end end - + + # Do not use the label in tables + config.wrappers :intable, :tag => 'div', :class => 'control-group control-group-intable', :error_class => 'error' do |b| + b.use :html5 + b.use :placeholder + b.wrapper :tag => 'div', :class => 'controls controls-intable' do |ba| + ba.use :input + ba.use :error, :wrap_with => { :tag => 'span', :class => 'help-inline' } + ba.use :hint, :wrap_with => { :tag => 'p', :class => 'help-block' } + end + end + # Wrappers for forms and inputs using the Twitter Bootstrap toolkit. # Check the Bootstrap docs (http://twitter.github.com/bootstrap) # to learn about the different styles for forms and inputs, diff --git a/config/locales/de.yml b/config/locales/de.yml index 5e93510b..fd401fa0 100644 --- a/config/locales/de.yml +++ b/config/locales/de.yml @@ -418,10 +418,10 @@ de: deliveries: add_stock_change: how_many_units: Wie viele Einheiten (%{unit}) des Artikels »%{name}« liefern? - add_stock_article: - notice: Neuer Lagerartikel »%{name}« gespeichert. create: notice: Lieferung wurde erstellt. Bitte nicht vergessen die Rechnung anzulegen! + create_stock_article: + notice: Neuer Lagerartikel »%{name}« gespeichert. destroy: notice: Lieferung wurde gelöscht. edit: @@ -430,12 +430,11 @@ de: actions: Optionen article: Artikel category: Kategorie - copy_order_article: Kopiere Bestellartikel - new_stock_article: Neuen Lagerartikel anlegen + create_from_blank: Ohne Vorlage anlegen + create_stock_article: Lagerartikel anlegen price: Preis (netto) price_per_unit: Preis/Einheit quantity: Menge - remove_article: Artikel aus Lieferung entfernen title_fill_quantities: 2. Liefermenge angeben title_finish_delivery: 3. Lieferung abschließen title_select_stock_articles: 1. Lagerartikel auswählen @@ -464,7 +463,7 @@ de: action_add_to_delivery: 'Liefern' action_edit: 'Bearbeiten' action_other_price: 'Anderer Preis' - stock_change: + stock_change_fields: remove_article: Artikel aus Lieferung entfernen suppliers_overview: Lieferantenübersicht update: @@ -1846,6 +1845,7 @@ de: close: ! '×' success: ! '' or_cancel: oder abbrechen + please_wait: Bitte warten... save: Speichern show: Anzeigen views: diff --git a/config/routes.rb b/config/routes.rb index 5719d4ce..180968eb 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -105,7 +105,7 @@ Foodsoft::Application.routes.draw do post :add_stock_change, :on => :collection get :new_stock_article, :on => :collection - post :add_stock_article, :on => :collection + post :create_stock_article, :on => :collection get :edit_stock_article, :on => :collection put :update_stock_article, :on => :collection