AJAX_ify StockArticle manipulation; Introduce publish/subscribe pattern for DOM updates
This commit is contained in:
parent
e99752e483
commit
dd08e277c7
22 changed files with 313 additions and 107 deletions
|
|
@ -4,30 +4,62 @@ class StockitController < ApplicationController
|
|||
@stock_articles = StockArticle.undeleted.includes(:supplier, :article_category).
|
||||
order('suppliers.name, article_categories.name, articles.name')
|
||||
end
|
||||
|
||||
def index_on_stock_article_create # See publish/subscribe design pattern in /doc.
|
||||
@stock_article = StockArticle.find(params[:id])
|
||||
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
def index_on_stock_article_update # See publish/subscribe design pattern in /doc.
|
||||
@stock_article = StockArticle.find(params[:id])
|
||||
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
# three possibilites to fill a new_stock_article form
|
||||
# (1) start from blank or use params
|
||||
def new
|
||||
@stock_article = StockArticle.new
|
||||
@stock_article = StockArticle.new(params[:stock_article])
|
||||
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
# (2) StockArticle as template
|
||||
def copy
|
||||
@stock_article = StockArticle.find(params[:stock_article_id]).dup
|
||||
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
# (3) non-stock Article as template
|
||||
def derive
|
||||
@stock_article = Article.find(params[:old_article_id]).becomes(StockArticle).dup
|
||||
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
def create
|
||||
@stock_article = StockArticle.new(params[:stock_article])
|
||||
if @stock_article.save
|
||||
redirect_to stock_articles_path, :notice => I18n.t('stockit.stock_create.notice')
|
||||
if @stock_article.valid? and @stock_article.save
|
||||
render :layout => false
|
||||
else
|
||||
render :action => 'new'
|
||||
render :action => 'new', :layout => false
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@stock_article = StockArticle.find(params[:id])
|
||||
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
def update
|
||||
@stock_article = StockArticle.find(params[:id])
|
||||
if @stock_article.update_attributes(params[:stock_article])
|
||||
redirect_to stock_articles_path, :notice => I18n.t('stockit.stock_update.notice')
|
||||
render :layout => false
|
||||
else
|
||||
render :action => 'edit'
|
||||
render :action => 'edit', :layout => false
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -36,9 +68,15 @@ class StockitController < ApplicationController
|
|||
@stock_changes = @stock_article.stock_changes.order('stock_changes.created_at DESC')
|
||||
end
|
||||
|
||||
def show_on_stock_article_update # See publish/subscribe design pattern in /doc.
|
||||
@stock_article = StockArticle.find(params[:id])
|
||||
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
def destroy
|
||||
@article = StockArticle.find(params[:id])
|
||||
@article.mark_as_deleted
|
||||
@stock_article = StockArticle.find(params[:id])
|
||||
@stock_article.mark_as_deleted
|
||||
render :layout => false
|
||||
rescue => error
|
||||
render :partial => "destroy_fail", :layout => false,
|
||||
|
|
|
|||
|
|
@ -14,4 +14,13 @@ module StockitHelper
|
|||
link_to t('.stock_taking'), stock_taking_path(stock_change.stock_taking)
|
||||
end
|
||||
end
|
||||
|
||||
def stock_article_price_hint(stock_article)
|
||||
t('simple_form.hints.stock_article.edit_stock_article.price',
|
||||
:stock_article_copy_link => link_to(t('.copy_stock_article'),
|
||||
stock_article_copy_path(stock_article),
|
||||
:remote => true
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,18 +1,21 @@
|
|||
= simple_form_for stock_article, :validate => true do |f|
|
||||
= f.association :supplier
|
||||
= f.input :name
|
||||
= f.input :unit
|
||||
= f.input :note
|
||||
|
||||
- if stock_article.new_record?
|
||||
= f.input :price
|
||||
= f.input :tax, :wrapper => :append do
|
||||
= f.input_field :tax
|
||||
%span.add-on %
|
||||
= f.input :deposit
|
||||
- else
|
||||
= f.input :price, :input_html => {:disabled => 'disabled'}, :hint => t('.price_hint')
|
||||
= f.association :article_category
|
||||
.form-actions
|
||||
= f.submit class: 'btn'
|
||||
= link_to t('ui.or_cancel'), stock_articles_path
|
||||
= simple_form_for stock_article, remote: true, :validate => true do |f|
|
||||
.modal-header
|
||||
= link_to t('ui.marks.close').html_safe, '#', class: 'close', data: {dismiss: 'modal'}
|
||||
%h3= title
|
||||
.modal-body
|
||||
= f.association :supplier
|
||||
= f.input :name
|
||||
= f.input :unit
|
||||
= f.input :note
|
||||
- if stock_article.new_record?
|
||||
= f.input :price
|
||||
= f.input :tax, :wrapper => :append do
|
||||
= f.input_field :tax
|
||||
%span.add-on %
|
||||
= f.input :deposit
|
||||
- else
|
||||
= f.input :price, :input_html => {:disabled => 'disabled'}, :hint => stock_article_price_hint(stock_article).html_safe
|
||||
= f.association :article_category
|
||||
.modal-footer
|
||||
= link_to t('ui.close'), '#', class: 'btn', data: {dismiss: 'modal'}
|
||||
= f.submit :class => 'btn btn-primary', 'data-disable-with' => t('ui.please_wait')
|
||||
|
|
|
|||
14
app/views/stockit/_stock_article.html.haml
Normal file
14
app/views/stockit/_stock_article.html.haml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
%tr{:class => stock_article_classes(stock_article), :id => "stockArticle-#{stock_article.id}"}
|
||||
%td= link_to stock_article.name, stock_article
|
||||
%td= stock_article.quantity
|
||||
%td= stock_article.quantity - stock_article.quantity_available
|
||||
%th= stock_article.quantity_available
|
||||
%td= stock_article.unit
|
||||
%td= stock_article.price
|
||||
%td= number_to_percentage stock_article.tax
|
||||
%td= link_to stock_article.supplier.name, stock_article.supplier
|
||||
%td= stock_article.article_category.name
|
||||
%td
|
||||
= link_to t('ui.edit'), edit_stock_article_path(stock_article), remote: true, class: 'btn btn-mini'
|
||||
= link_to t('ui.delete'), stock_article, :method => :delete, :confirm => t('.confirm_delete', :name => stock_article.name),
|
||||
class: 'btn btn-mini btn-danger', :remote => true
|
||||
26
app/views/stockit/_stock_article_details.html.haml
Normal file
26
app/views/stockit/_stock_article_details.html.haml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#stockArticleDetails
|
||||
%dl.dl-horizontal
|
||||
%dt= heading_helper(StockArticle, :supplier)
|
||||
%dd= link_to stock_article.supplier.name, stock_article.supplier
|
||||
%dt= heading_helper(StockArticle, :name)
|
||||
%dd= stock_article.name
|
||||
%dt= heading_helper(StockArticle, :unit)
|
||||
%dd= stock_article.unit
|
||||
%dt= heading_helper(StockArticle, :price)
|
||||
%dd= number_to_currency stock_article.price
|
||||
%dt= heading_helper(StockArticle, :tax)
|
||||
%dd= number_to_percentage stock_article.tax
|
||||
%dt= heading_helper(StockArticle, :deposit)
|
||||
%dd= number_to_currency stock_article.deposit
|
||||
%dt= heading_helper(StockArticle, :fc_price)
|
||||
%dd= number_to_currency stock_article.fc_price
|
||||
%dt= heading_helper(StockArticle, :article_category)
|
||||
%dd= stock_article.article_category.name
|
||||
%dt= heading_helper(StockArticle, :note)
|
||||
%dd= stock_article.note
|
||||
%dt= heading_helper(StockArticle, :quantity)
|
||||
%dd= stock_article.quantity
|
||||
%dt= heading_helper(StockArticle, :quantity_available)
|
||||
%dd= stock_article.quantity_available
|
||||
.form-actions
|
||||
= link_to t('ui.edit'), edit_stock_article_path(stock_article), remote: true, class: 'btn'
|
||||
9
app/views/stockit/copy.js.erb
Normal file
9
app/views/stockit/copy.js.erb
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
$('#modalContainer').html('<%= j(render(
|
||||
:partial => "form",
|
||||
:locals => {
|
||||
:title => t('.title'),
|
||||
:stock_article => @stock_article
|
||||
}
|
||||
)) %>');
|
||||
|
||||
$('#modalContainer').modal();
|
||||
15
app/views/stockit/create.js.erb
Normal file
15
app/views/stockit/create.js.erb
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
$('div.container-fluid').prepend('<%= j(render(
|
||||
:partial => 'shared/alert_success',
|
||||
:locals => {
|
||||
:alert_message => t('.notice', :name => @stock_article.name)
|
||||
}
|
||||
)) %>');
|
||||
|
||||
// Publish database changes.
|
||||
// See publish/subscribe design pattern in /doc.
|
||||
$(document).trigger({
|
||||
type: 'StockArticle#create',
|
||||
stock_article_id: <%= @stock_article.id %>
|
||||
});
|
||||
|
||||
$('#modalContainer').modal('hide');
|
||||
13
app/views/stockit/destroy.js.erb
Normal file
13
app/views/stockit/destroy.js.erb
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
$('div.container-fluid').prepend('<%= j(render(
|
||||
:partial => 'shared/alert_success',
|
||||
:locals => {
|
||||
:alert_message => t('.notice', :name => @stock_article.name)
|
||||
}
|
||||
)) %>');
|
||||
|
||||
// Publish database changes.
|
||||
// See publish/subscribe design pattern in /doc.
|
||||
$(document).trigger({
|
||||
type: 'StockArticle#destroy',
|
||||
stock_article_id: <%= @stock_article.id %>
|
||||
});
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
-# please polish the following line if you know how, same in partial _destroy_fail
|
||||
var successDiv = $('<div class="alert fade in alert-success"><a class="close" data-dismiss="alert" href="#">#{escape_javascript(t('ui.marks.close').html_safe)}</a></div>');
|
||||
|
||||
successDiv.append(document.createTextNode('#{escape_javascript(t('.notice', name: @article.name))}'));
|
||||
$('div.container-fluid').prepend(successDiv);
|
||||
|
||||
$('#stockArticle-#{@article.id}').remove();
|
||||
-# WARNING: Do not use a simple .fadeOut() above, because it conflicts with the show/hide function of unavailable articles.
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
- title t('.title')
|
||||
|
||||
= render :partial => 'form', :locals => {:stock_article => @stock_article}
|
||||
9
app/views/stockit/edit.js.erb
Normal file
9
app/views/stockit/edit.js.erb
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
$('#modalContainer').html('<%= j(render(
|
||||
:partial => "form",
|
||||
:locals => {
|
||||
:title => t('.title'),
|
||||
:stock_article => @stock_article
|
||||
}
|
||||
)) %>');
|
||||
|
||||
$('#modalContainer').modal();
|
||||
|
|
@ -3,6 +3,30 @@
|
|||
:javascript
|
||||
$(function() {
|
||||
$('tr.unavailable').hide();
|
||||
|
||||
// Subscribe to database changes.
|
||||
// See publish/subscribe design pattern in /doc.
|
||||
$(document).on('StockArticle#create', function(e) {
|
||||
$.ajax({
|
||||
url: '#{index_on_stock_article_create_stock_articles_path}',
|
||||
type: 'get',
|
||||
data: {id: e.stock_article_id},
|
||||
contentType: 'application/json; charset=UTF-8'
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('StockArticle#destroy', function(e) {
|
||||
$('#stockArticle-' + e.stock_article_id).remove();
|
||||
});
|
||||
|
||||
$(document).on('StockArticle#update', function(e) {
|
||||
$.ajax({
|
||||
url: '#{index_on_stock_article_update_stock_articles_path}',
|
||||
type: 'get',
|
||||
data: {id: e.stock_article_id},
|
||||
contentType: 'application/json; charset=UTF-8'
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
.well.well-small
|
||||
|
|
@ -17,7 +41,7 @@
|
|||
.btn-group
|
||||
= link_to_if @current_user.role_orders?, t('.order_online'), new_order_path(supplier_id: 0),
|
||||
class: 'btn', class: 'btn btn-primary'
|
||||
= link_to t('.new_stock_article'), new_stock_article_path, class: 'btn'
|
||||
= link_to t('.new_stock_article'), new_stock_article_path, remote: true, class: 'btn'
|
||||
= link_to t('.new_stock_taking'), new_stock_taking_path, class: 'btn'
|
||||
= link_to t('.show_stock_takings'), stock_takings_path, class: 'btn'
|
||||
|
||||
|
|
@ -42,22 +66,9 @@
|
|||
%th= t '.article.supplier'
|
||||
%th= t '.article.category'
|
||||
%th
|
||||
%tbody
|
||||
- for article in @stock_articles
|
||||
%tr{:class => stock_article_classes(article), :id => "stockArticle-#{article.id}"}
|
||||
%td= link_to article.name, article
|
||||
%td= article.quantity
|
||||
%td= article.quantity - article.quantity_available
|
||||
%th= article.quantity_available
|
||||
%td= article.unit
|
||||
%td= article.price
|
||||
%td= number_to_percentage article.tax
|
||||
%td= link_to article.supplier.name, article.supplier
|
||||
%td= article.article_category.name
|
||||
%td
|
||||
= link_to t('ui.edit'), edit_stock_article_path(article), class: 'btn btn-mini'
|
||||
= link_to t('ui.delete'), article, :method => :delete, :confirm => t('.confirm_delete'),
|
||||
class: 'btn btn-mini btn-danger', :remote => true
|
||||
%tbody#articles-tbody
|
||||
- for stock_article in @stock_articles
|
||||
= render :partial => 'stock_article', :locals => {:stock_article => stock_article}
|
||||
%p
|
||||
= t '.stock_worth'
|
||||
= number_to_currency StockArticle.stock_value
|
||||
|
|
|
|||
12
app/views/stockit/index_on_stock_article_create.js.erb
Normal file
12
app/views/stockit/index_on_stock_article_create.js.erb
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// Handle more advanced DOM update after AJAX database manipulation.
|
||||
// See publish/subscribe design pattern in /doc.
|
||||
(function() {
|
||||
var stock_article_row = $('<%= j(render(
|
||||
:partial => 'stock_article',
|
||||
:locals => {
|
||||
:stock_article => @stock_article
|
||||
}
|
||||
)) %>');
|
||||
|
||||
$('#articles-tbody').prepend(stock_article_row);
|
||||
})();
|
||||
12
app/views/stockit/index_on_stock_article_update.js.erb
Normal file
12
app/views/stockit/index_on_stock_article_update.js.erb
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// Handle more advanced DOM update after AJAX database manipulation.
|
||||
// See publish/subscribe design pattern in /doc.
|
||||
(function() {
|
||||
var stock_article_row = $('<%= j(render(
|
||||
:partial => 'stock_article',
|
||||
:locals => {
|
||||
:stock_article => @stock_article
|
||||
}
|
||||
)) %>');
|
||||
|
||||
$('#stockArticle-<%= @stock_article.id %>').replaceWith(stock_article_row);
|
||||
})();
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
- title t('.title')
|
||||
|
||||
- content_for :head do
|
||||
:javascript
|
||||
$(function() {
|
||||
$('#article_search').autocomplete({
|
||||
source: '#{articles_search_stock_articles_path}',
|
||||
select: function(e, ui) {
|
||||
alert(ui.item.value);
|
||||
//location.href = '#{nil}' + ui.item.value;
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
/
|
||||
TODO: Fix this
|
||||
%p
|
||||
= t '.search_text'
|
||||
= text_field_tag 'article_search'
|
||||
#stock_article_form
|
||||
= render :partial => 'form', :locals => {:stock_article => @stock_article}
|
||||
9
app/views/stockit/new.js.erb
Normal file
9
app/views/stockit/new.js.erb
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
$('#modalContainer').html('<%= j(render(
|
||||
:partial => "form",
|
||||
:locals => {
|
||||
:title => t('.title'),
|
||||
:stock_article => @stock_article
|
||||
}
|
||||
)) %>');
|
||||
|
||||
$('#modalContainer').modal();
|
||||
|
|
@ -1,32 +1,22 @@
|
|||
- title @stock_article.name
|
||||
- content_for :javascript do
|
||||
:javascript
|
||||
$(function() {
|
||||
// Subscribe to database changes.
|
||||
// See publish/subscribe design pattern in /doc.
|
||||
$(document).on('StockArticle#update', function(e) {
|
||||
$.ajax({
|
||||
url: '#{show_on_stock_article_update_stock_articles_path}',
|
||||
type: 'get',
|
||||
data: {id: e.stock_article_id},
|
||||
contentType: 'application/json; charset=UTF-8'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
.row-fluid
|
||||
.span6
|
||||
%dl.dl-horizontal
|
||||
%dt= StockArticle.human_attribute_name 'supplier'
|
||||
%dd= link_to @stock_article.supplier.name, @stock_article.supplier
|
||||
%dt= StockArticle.human_attribute_name 'name'
|
||||
%dd= @stock_article.name
|
||||
%dt= StockArticle.human_attribute_name 'unit'
|
||||
%dd= @stock_article.unit
|
||||
%dt= StockArticle.human_attribute_name 'price'
|
||||
%dd= number_to_currency @stock_article.price
|
||||
%dt= StockArticle.human_attribute_name 'tax'
|
||||
%dd= number_to_percentage @stock_article.tax
|
||||
%dt= StockArticle.human_attribute_name 'deposit'
|
||||
%dd= number_to_currency @stock_article.deposit
|
||||
%dt= StockArticle.human_attribute_name 'fc_price'
|
||||
%dd= number_to_currency @stock_article.fc_price
|
||||
%dt= StockArticle.human_attribute_name 'article_category'
|
||||
%dd= @stock_article.article_category.name
|
||||
%dt= StockArticle.human_attribute_name 'note'
|
||||
%dd= @stock_article.note
|
||||
%dt= StockArticle.human_attribute_name 'quantity'
|
||||
%dd= @stock_article.quantity
|
||||
%dt= StockArticle.human_attribute_name 'quantity_available'
|
||||
%dd= @stock_article.quantity_available
|
||||
.form-actions
|
||||
= link_to t('ui.edit'), edit_stock_article_path(@stock_article), class: 'btn'
|
||||
= render :partial => 'stock_article_details', :locals => {:stock_article => @stock_article}
|
||||
|
||||
.span6
|
||||
%h2= t('.stock_changes')
|
||||
|
|
|
|||
13
app/views/stockit/show_on_stock_article_update.js.erb
Normal file
13
app/views/stockit/show_on_stock_article_update.js.erb
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
// Handle more advanced DOM update after AJAX database manipulation.
|
||||
// See publish/subscribe design pattern in /doc.
|
||||
(function() {
|
||||
var stock_article_details = $('<%= j(render(
|
||||
:partial => 'stock_article_details',
|
||||
:locals => {
|
||||
:stock_article => @stock_article
|
||||
}
|
||||
)) %>');
|
||||
|
||||
$('#stockArticleDetails').replaceWith(stock_article_details);
|
||||
$('h1').first().text('<%= j(@stock_article.name) %>');
|
||||
})();
|
||||
15
app/views/stockit/update.js.erb
Normal file
15
app/views/stockit/update.js.erb
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
$('div.container-fluid').prepend('<%= j(render(
|
||||
:partial => 'shared/alert_success',
|
||||
:locals => {
|
||||
:alert_message => t('.notice', :name => @stock_article.name)
|
||||
}
|
||||
)) %>');
|
||||
|
||||
// Publish database changes.
|
||||
// See publish/subscribe design pattern in /doc.
|
||||
$(document).trigger({
|
||||
type: 'StockArticle#update',
|
||||
stock_article_id: <%= @stock_article.id %>
|
||||
});
|
||||
|
||||
$('#modalContainer').modal('hide');
|
||||
Loading…
Add table
Add a link
Reference in a new issue