diff --git a/Gemfile b/Gemfile index eb78b384..d5c1c3d7 100644 --- a/Gemfile +++ b/Gemfile @@ -33,6 +33,7 @@ gem 'delayed_job_active_record' gem 'twitter-bootstrap-rails' gem 'simple-navigation' gem 'simple-navigation-bootstrap' +gem 'meta_search' group :production do gem 'exception_notification', :require => 'exception_notifier' diff --git a/Gemfile.lock b/Gemfile.lock index c42a0f33..cd253630 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -36,7 +36,7 @@ GEM i18n (~> 0.6) multi_json (~> 1.0) arel (3.0.2) - builder (3.0.3) + builder (3.0.4) client_side_validations (3.1.4) coffee-rails (3.2.2) coffee-script (>= 2.2.0) @@ -90,6 +90,11 @@ GEM i18n (>= 0.4.0) mime-types (~> 1.16) treetop (~> 1.4.8) + meta_search (1.1.3) + actionpack (~> 3.1) + activerecord (~> 3.1) + activesupport (~> 3.1) + polyamorous (~> 0.5.0) mime-types (1.19) multi_json (1.3.6) mysql2 (0.3.11) @@ -97,6 +102,8 @@ GEM Ascii85 (~> 1.0.0) hashery (~> 2.0) ruby-rc4 + polyamorous (0.5.0) + activerecord (~> 3.0) polyglot (0.3.3) prawn (0.12.0) pdf-reader (>= 0.9.0) @@ -183,6 +190,7 @@ DEPENDENCIES jquery-rails kaminari localize_input! + meta_search mysql2 prawn rails (= 3.2.8) diff --git a/app/assets/stylesheets/bootstrap_and_overrides.css.less b/app/assets/stylesheets/bootstrap_and_overrides.css.less index cb2a06b5..d9b5605d 100644 --- a/app/assets/stylesheets/bootstrap_and_overrides.css.less +++ b/app/assets/stylesheets/bootstrap_and_overrides.css.less @@ -49,6 +49,14 @@ footer { } table { + + th.sortdown a:after { + content: ' \25BC'; + } + th.sortup a:after { + content: ' \25B2'; + } + tr.article-category { background-color: #efefef; td:first-child { diff --git a/app/controllers/articles_controller.rb b/app/controllers/articles_controller.rb index dab8ba48..9ee5039d 100644 --- a/app/controllers/articles_controller.rb +++ b/app/controllers/articles_controller.rb @@ -21,10 +21,9 @@ class ArticlesController < ApplicationController end @articles = @supplier.articles.includes(:article_category).order(sort) - @articles = @articles.where('name LIKE ?', "%#{params[:query]}%") unless params[:query].nil? + @articles = @articles.where('articles.name LIKE ?', "%#{params[:query]}%") unless params[:query].nil? - @total = @articles.size - @articles = @articles.paginate(:page => params[:page], :per_page => @per_page) + @articles = @articles.page(params[:page]).per(@per_page) respond_to do |format| format.html @@ -200,7 +199,7 @@ class ArticlesController < ApplicationController params[:search][:name_contains_all] = params[:search][:name_contains_all].split(' ') if params[:search] # Build search with meta search plugin @search = @supplier.shared_supplier.shared_articles.search(params[:search]) - @articles = @search.paginate :page => params[:page], :per_page => 10 + @articles = @search.page(params[:page]).per(10) render :layout => false end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 5b843b39..b28e0007 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -47,13 +47,13 @@ module ApplicationHelper end def sort_td_class_helper(param) - result = 'class="sortup"' if params[:sort] == param - result = 'class="sortdown"' if params[:sort] == param + "_reverse" + result = 'sortup' if params[:sort] == param.to_s + result = 'sortdown' if params[:sort] == param.to_s + "_reverse" result end def sort_link_helper(text, key, options = {}) - per_page = options[:per_page] || 10 + per_page = options[:per_page] || @per_page remote = options[:remote].nil? ? true : options[:remote] key += "_reverse" if params[:sort] == key url = url_for(:sort => key, :page => nil, :per_page => per_page) diff --git a/app/helpers/articles_helper.rb b/app/helpers/articles_helper.rb index 8df06524..44f1d0d6 100644 --- a/app/helpers/articles_helper.rb +++ b/app/helpers/articles_helper.rb @@ -11,4 +11,9 @@ module ArticlesHelper classes += " just_updated" if article.recently_updated && article.availability classes end + + # Flatten search params, used in import from external database + def search_params + Hash[params[:search].map { |k,v| [k, (v.is_a?(Array) ? v.join(" ") : v)] }] + end end \ No newline at end of file diff --git a/app/models/shared_article.rb b/app/models/shared_article.rb index c75ba4e9..777b7f77 100644 --- a/app/models/shared_article.rb +++ b/app/models/shared_article.rb @@ -3,7 +3,7 @@ class SharedArticle < ActiveRecord::Base # connect to database from sharedLists-Application SharedArticle.establish_connection(FoodsoftConfig[:shared_lists]) # set correct table_name in external DB - set_table_name :articles + self.table_name = 'articles' belongs_to :shared_supplier, :foreign_key => :supplier_id diff --git a/app/models/shared_supplier.rb b/app/models/shared_supplier.rb index 1620ae31..83cdb6b2 100644 --- a/app/models/shared_supplier.rb +++ b/app/models/shared_supplier.rb @@ -3,9 +3,8 @@ class SharedSupplier < ActiveRecord::Base # connect to database from sharedLists-Application SharedSupplier.establish_connection(FoodsoftConfig[:shared_lists]) # set correct table_name in external DB - set_table_name :suppliers - - + self.table_name = 'suppliers' + has_one :supplier has_many :shared_articles, :foreign_key => :supplier_id diff --git a/app/views/articles/_articles.html.haml b/app/views/articles/_articles.html.haml index 7b5aa10c..400ae528 100644 --- a/app/views/articles/_articles.html.haml +++ b/app/views/articles/_articles.html.haml @@ -1,28 +1,19 @@ -%p - Gefundene Artikel: - %b= @total +- if @supplier.articles.count > 20 + = items_per_page += pagination_links_remote @articles -%p - %table{:style => "width:100%"} - %tr - %td - = pagination_links_remote @articles, :params => {:sort => params[:sort]} - %td{:style => "text-align:right"} - - if @total > 30 - = items_per_page :per_page_options => [30, 100, 500] - -%table#articles_table.list.articles +%table#articles_table.table.table-striped %thead %tr %th - %th[sort_td_class_helper("name")] + %th{class: sort_td_class_helper(:name)} = sort_link_helper "Name", "name" %th - %th[sort_td_class_helper("category")] + %th{class: sort_td_class_helper(:category)} = sort_link_helper "Kategorie", "category" - %th[sort_td_class_helper("unit")] + %th{class: sort_td_class_helper(:unit)} = sort_link_helper "Einheit", "unit" - %th[sort_td_class_helper("note")] + %th{class: sort_td_class_helper(:note)} = sort_link_helper "Notiz", "note" %th{:style => "width: 4em;"} Gebgr. %th{:style => "width: 5em;"} Preis @@ -32,7 +23,7 @@ %tbody#listbody - - if @total > 0 + - unless @articles.empty? - for article in @articles = render(article) %tfoot @@ -46,5 +37,4 @@ %option{:value => "setAvailable"} Artikel sind verfügbar = hidden_field_tag 'supplier_id', @supplier.id -%p= pagination_links_remote @articles, :params => {:sort => params[:sort]} -= hidden_field_tag :per_page, params[:per_page] \ No newline at end of file += pagination_links_remote @articles \ No newline at end of file diff --git a/app/views/articles/_form.html.haml b/app/views/articles/_form.html.haml index 6d2caa51..d87cbf79 100644 --- a/app/views/articles/_form.html.haml +++ b/app/views/articles/_form.html.haml @@ -1,18 +1,24 @@ = simple_form_for [@supplier, @article], :validate => true, :remote => true do |f| - = f.input :availability - = f.input :name - = f.input :origin - = f.input :manufacturer - = f.input :unit - = f.input :note - = f.association :article_category - - = f.input :price - = f.input :unit_quantity - = f.input :order_number - = f.input :tax - = f.input :deposit - = f.submit - = f.hidden_field :shared_updated_on - = f.hidden_field :supplier_id \ No newline at end of file + = f.hidden_field :supplier_id + .modal-header + = button_tag "x", class: 'close', data: {dismiss: 'modal'} + %h3 Neuen Artikel einfügen + .modal-body + = f.input :availability + = f.input :name + = f.input :origin + = f.input :manufacturer + = f.input :unit + = f.input :note + = f.association :article_category + + = f.input :price + = f.input :unit_quantity + = f.input :order_number + = f.input :tax + = f.input :deposit + .modal-footer + = button_tag "Schließen", class: 'btn', data: {dismiss: 'modal'} + = f.submit class: 'btn btn-primary' + diff --git a/app/views/articles/_import_search_results.haml b/app/views/articles/_import_search_results.haml index 89c3ce33..1a43165f 100644 --- a/app/views/articles/_import_search_results.haml +++ b/app/views/articles/_import_search_results.haml @@ -1,25 +1,33 @@ -%p= pagination_links_remote @articles, :per_page => 10, :params => {:search => params[:search]} -%table.list - %thead - %tr - %th Name - %th Herkunft - %th Hersteller - %th Notiz - %th{:style => "width:4em"} Preis - %th Einheit - %th GebGröße - %th - %tbody - - for article in @articles - %tr{:class => cycle('even','odd', :name => 'import_search_results')} - %td= highlight article.name, params[:search][:name_contains_all] - %td= article.origin - %td= article.manufacturer - %td= article.note - %td= number_to_currency(article.price) - %td= article.unit - %td= article.unit_quantity - %td= link_to 'importieren', import_supplier_articles_path(@supplier, :shared_article_id => article.id), - :remote => true - \ No newline at end of file +- if @articles.empty? + %p Keine Artikel gefunden +- else + = pagination_links_remote @articles, :params => {:search => search_params} + %table.table.table-striped + %thead + %tr + %th Name + %th Herkunft + %th Hersteller + %th Notiz + %th{:style => "width:4em"} Preis + %th Einheit + %th GebGröße + %th + %tbody + - for article in @articles + %tr + %td= highlight article.name, params[:search][:name_contains_all] + %td= article.origin + %td= article.manufacturer + %td= article.note + %td= number_to_currency(article.price) + %td= article.unit + %td= article.unit_quantity + %td + - logger.debug "[debug] #{article.attributes.inspect}" + - if @supplier.articles.where(order_number: article.number).exists? + %i.icon-ok + schon importiert + - else + = link_to 'importieren', import_supplier_articles_path(@supplier, :shared_article_id => article.id), + :remote => true, class: 'btn btn-small btn-success' diff --git a/app/views/articles/create.js.haml b/app/views/articles/create.js.haml index 9d93b54e..b716d170 100644 --- a/app/views/articles/create.js.haml +++ b/app/views/articles/create.js.haml @@ -1,2 +1,2 @@ +$('#modalContainer').modal('hide'); $('#listbody').prepend('#{escape_javascript(render(@article))}'); -$.fancybox.close(); diff --git a/app/views/articles/edit_all.rhtml b/app/views/articles/edit_all.html.erb similarity index 100% rename from app/views/articles/edit_all.rhtml rename to app/views/articles/edit_all.html.erb diff --git a/app/views/articles/index.haml b/app/views/articles/index.haml index 12e1b2ab..9b1a995c 100644 --- a/app/views/articles/index.haml +++ b/app/views/articles/index.haml @@ -1,66 +1,48 @@ -- title "Artikel von #{@supplier.name}" +- title "Artikel von #{@supplier.name} (#{@supplier.articles.count})" -// import menu -- unless @supplier.shared_supplier.nil? - .menu{:style => 'width: 16em'} - %ul - %li - Zugriff auf externe Datenbank - %ul - %li= link_to "Suchen/Importieren", "#import", 'data-toggle-this' => '#import' - %li= link_to "Synchronisieren", sync_supplier_articles_path(@supplier), :method => :post - - -#change_supplier{:style => "padding:0 0 0.5em 0.7em;"} - %span{:style => "float:left"} - Lieferantin wechseln: - = select_tag :switch_supplier, - options_for_select(Supplier.order(:name).map {|s| [s.name, supplier_articles_url(s)] }, supplier_articles_url(@supplier)), - :style => "font-size: 0.9em;margin-left:1em;", - 'data-redirect-to' => true - -- unless @supplier.shared_supplier.nil? - #import.single_column{:style => "display:none; clear:both"} - .box_title - %h2 Artikel importieren - .column_content - #search{:style => "padding-bottom:3em"} - = form_tag shared_supplier_articles_path(@supplier), :method => :get, :remote => true do - = text_field_tag "search[name_contains_all]", "", :size => 10 - = submit_tag "Suchen" - - if @supplier.shared_supplier.lists - Suche in folgenden Listen: - - @supplier.shared_supplier.lists.each do |token, name| - = check_box_tag "search[list_equals_any][]", token, true - = name - | - Nur aus der Region: - = check_box_tag "search[origin_equals]", "REG", false - #search_results - = link_to "Schließen", "#import", 'data-toggle-this' => '#import' - -.single_column{:style => 'width:100%; clear:both'} - .box_title - .column_content - #links - %b= link_to "Neuer Artikel", new_supplier_article_path(@supplier), :remote => true - | - = link_to "Alle bearbeiten", edit_all_supplier_articles_path(@supplier) - | - = link_to "Artikel hochladen", upload_supplier_articles_path(@supplier) - - if current_user.role_orders? - | - = link_to "Bestellung anlegen", new_order_path(:supplier_id => @supplier) - - #article_filter - #article_search_form{:style=>"display:inline;"} - = form_tag supplier_articles_path(@supplier), :method => :get, :remote => true, 'data-submit-onchange' => true do - %label{:for => 'article_name'} Suche im Artikelnamen: - = text_field_tag :query, params[:query], :size => 10 - = submit_tag "Suchen" - - = form_tag update_selected_supplier_articles_path(@supplier), :id => "articlesInListForm", +.well.well-small + .btn-toolbar + = form_tag supplier_articles_path(@supplier), method: :get, remote: true, class: 'form-search pull-right', 'data-submit-onchange' => true do - #table= render 'articles' + = text_field_tag :query, params[:query], class: 'input-medium search-query', + placeholder: 'Name ...' -#edit_article{:style => "display:none"} + .btn-group + = link_to "Neuer Artikel", new_supplier_article_path(@supplier), remote: true, class: 'btn btn-primary' + = link_to "Alle bearbeiten", edit_all_supplier_articles_path(@supplier), class: 'btn' + = link_to "Artikel hochladen", upload_supplier_articles_path(@supplier), class: 'btn' + - if current_user.role_orders? + = link_to "Bestellung anlegen", new_order_path(supplier_id: @supplier), class: 'btn' + + - unless @supplier.shared_supplier.nil? + .btn-group + = link_to '#', data: {toggle: 'dropdown'}, class: 'btn btn-success dropdown-toggle' do + Externe Datenbank + %span.caret + %ul.dropdown-menu + %li= link_to "Suchen/Importieren", "#import", 'data-toggle-this' => '#import' + %li= link_to "Synchronisieren", sync_supplier_articles_path(@supplier), method: :post + + .btn-group + = link_to '#', data: {toggle: 'dropdown'}, class: 'btn dropdown-toggle' do + Lieferant wechseln .. + %span.caret + %ul.dropdown-menu + - Supplier.where('id != ?', @supplier.id).order('name ASC').each do |supplier| + %li= link_to supplier.name, supplier_articles_path(supplier), tabindex: -1 + +- unless @supplier.shared_supplier.nil? + #import.well.well-small(style="display:none;") + = form_tag shared_supplier_articles_path(@supplier), method: :get, remote: true, class: 'form-search', + 'data-submit-onchange' => true do + %h3 Artikel importieren + = text_field_tag "search[name_contains_all]", "", class: 'input-medium search-query', placeholder: 'Name ...' + %label.checkbox + = check_box_tag "search[origin_equals]", "REG", false + Nur aus der Region + #search_results.clearfix + = link_to "Schließen", "#import", 'data-toggle-this' => '#import' + += form_tag update_selected_supplier_articles_path(@supplier), id: "articlesInListForm", + 'data-submit-onchange' => true do + #table= render 'articles' \ No newline at end of file diff --git a/app/views/articles/new.js.haml b/app/views/articles/new.js.haml index 76013027..735f9589 100644 --- a/app/views/articles/new.js.haml +++ b/app/views/articles/new.js.haml @@ -1 +1,2 @@ -$.fancybox('#{escape_javascript(render("form"))}'); +$('#modalContainer').html('#{escape_javascript(render("form"))}'); +$('#modalContainer').modal(); diff --git a/app/views/invites/_modal_form.html.haml b/app/views/invites/_modal_form.html.haml index 3ef038ea..17a4aaf5 100644 --- a/app/views/invites/_modal_form.html.haml +++ b/app/views/invites/_modal_form.html.haml @@ -1,12 +1,11 @@ -#modalForm.modal(tabindex="-1" role="dialog") - = simple_form_for @invite, remote: true do |form| - .modal-header - = button_tag "x", class: 'close', data: {dismiss: 'modal'} - %h3 Person in die Gruppe #{@invite.group.name} einladen - .modal-body - = form.hidden_field :user_id - = form.hidden_field :group_id - = form.input :email - .modal-footer - = button_tag "Schließen", class: 'btn', data: {dismiss: 'modal'} - = form.submit class: 'btn btn-primary' += simple_form_for @invite, remote: true do |form| + .modal-header + = button_tag "x", class: 'close', data: {dismiss: 'modal'} + %h3 Person in die Gruppe #{@invite.group.name} einladen + .modal-body + = form.hidden_field :user_id + = form.hidden_field :group_id + = form.input :email + .modal-footer + = button_tag "Schließen", class: 'btn', data: {dismiss: 'modal'} + = form.submit class: 'btn btn-primary' diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 607386c3..b3dc0b8d 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -33,4 +33,4 @@ %footer %p Foodsoft, open source software to manage a non-profit food coop. - #modalContainer + #modalContainer.modal(tabindex="-1" role="dialog" style="display:none") diff --git a/app/views/orders/_orders.html.haml b/app/views/orders/_orders.html.haml index 8d88af76..7a7ca614 100644 --- a/app/views/orders/_orders.html.haml +++ b/app/views/orders/_orders.html.haml @@ -2,10 +2,10 @@ %table.table.table-striped %thead %tr - %th[sort_td_class_helper("supplier")] + %th{class: sort_td_class_helper(:supplier)} = sort_link_helper "Lieferantin", "supplier" %th Start - %th[sort_td_class_helper("ends")] + %th{class: sort_td_class_helper(:ends)} = sort_link_helper "Ende", "ends" %th Status %th{:colspan => "2"}