Files
aux-bieaux-legumes/templates/backOffice/default/product-edit.html
2021-01-14 18:04:26 +01:00

812 lines
34 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{extends file="admin-layout.tpl"}
{block name="no-return-functions"}
{$admin_current_location = 'catalog'}
{/block}
{block name="check-resource"}admin.product{/block}
{block name="check-access"}update{/block}
{block name="page-title"}{intl l='Edit product'}{/block}
{block name="main-content"}
<div class="catalog edit-product">
<div id="wrapper" class="container">
{include file="includes/catalog-breadcrumb.html" editing_category="false" editing_product="true"}
{hook name="product-edit.top" product_id=$product_id}
<div class="row">
{loop name="product_edit" type="product" visible="*" id=$product_id backend_context="1" with_prev_next_info=true lang=$edit_language_id}
{* Define close url *}
{assign var='close_url' value="{url path='/admin/catalog' category_id=$DEFAULT_CATEGORY}"}
<div class="col-md-12 general-block-decorator">
<div class="row">
<div class="col-md-7 title">
{intl l='Edit product %title' title={$TITLE}}{if $REF} ({intl l='ref.:'} {$REF}){/if}
</div>
<div class="col-md-5 actions">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#cloneProductModal">
{intl l="Clone"}
</button>
<a {if $HAS_PREVIOUS != 0}href="{url path='/admin/products/update' product_id=$PREVIOUS}"{else}disabled="disabled"{/if} class="btn btn-default" title="{intl l='Edit previous product'}"><span class="glyphicon glyphicon-arrow-left"></span></a>
<a href="{$URL nofilter}" target="_blank" class="btn btn-default" title="{intl l='Preview product page'}"><span class="glyphicon glyphicon-eye-open"></span></a>
<a {if $HAS_NEXT != 0}href="{url path='/admin/products/update' product_id=$NEXT}"{else}disabled="disabled"{/if} class="btn btn-default" title="{intl l='Edit next product'}"><span class="glyphicon glyphicon-arrow-right"></span></a>
</div>
</div>
<div class="row">
<div class="col-md-12">
{hookblock name="product.tab" id="{$product_id}" fields="id,title,href,content"}
{capture "product_tab_tab"}
{forhook rel="product.tab"}
<li>
<a href="#{$id}"
{if $href}data-href="{$href}"{/if}
data-toggle="tab">{$title}
</a>
</li>
{/forhook}
{/capture}
{capture "product_tab_content"}
{forhook rel="product.tab"}
<div class="tab-pane fade" id="{$id}">
{if $href}
{* ajax *}
<div class="text-center"><span class="loading">{intl l="Please wait, loading"}</span></div>
{else}
{$content nofilter}
{/if}
</div>
{/forhook}
{/capture}
{/hookblock}
<ul class="nav nav-tabs" id="tabbed-menu">
<li><a href="#general" data-toggle="tab" data-trigger="#virtual_field::change">{intl l="General"}</a></li>
<li><a href="#seo" data-toggle="tab">{intl l="SEO"}</a></li>
<li><a href="#prices" data-toggle="tab">{intl l="Price"}</a></li>
<li>
<a href="#attributes"
data-href="{url path='/admin/products/attributes/tab' product_id=$ID}"
data-toggle="tab">{intl l="Attributes &amp; Features"}
</a>
</li>
<li>
<a href="#related"
data-href="{url path='/admin/products/related/tab' folder_id=$folder_id accessory_category_id=$accessory_category_id product_id=$ID}"
data-toggle="tab">{intl l="Associations"}
</a>
</li>
<li>
{$imageSuccessUrl ={navigate to="current"}}
<a href="#images"
data-toggle="tab"
data-href="{url path="/admin/image/type/product/%id/form-ajax" id=$ID successUrl=$imageSuccessUrl}"
data-callback="$.imageUploadManager.initImageDropZone">
{intl l="Images"}
</a>
</li>
<li>
<a href="#documents"
id="tab-documents"
data-toggle="tab"
data-href="{url path="/admin/document/type/product/%id/form-ajax" id=$ID}"
data-callback="$.documentUploadManager.initDocumentDropZone">
{intl l="Documents"}
</a>
</li>
{$smarty.capture.product_tab_tab nofilter}
<li><a href="#modules" data-toggle="tab">{intl l="Modules"}</a></li>
</ul>
<div class="tab-content">
<div class="tab-pane fade" id="general">
{include file="includes/product-general-tab.html"}
</div>
<div class="tab-pane fade" id="seo">
{include file="includes/seo-tab.html"
formAction = "{url path='/admin/products/seo/save'}"
pageUrl = "{url path='/admin/products/update' product_id=$ID}"
closeUrl = $close_url
current_id = $product_id
success_url = "{url path='/admin/categories' category_id=$DEFAULT_CATEGORY page=$page}"
seoType = 'product'
}
</div>
<div class="tab-pane fade" id="prices">
{include file="includes/product-prices-tab.html"}
</div>
<div class="tab-pane fade" id="attributes">
<div class="text-center"><span class="loading">{intl l="Please wait, loading"}</span></div>
</div>
<div class="tab-pane fade" id="related">
<div class="text-center"><span class="loading">{intl l="Please wait, loading"}</span></div>
</div>
<div class="tab-pane fade" id="images">
<div class="text-center"><span class="loading">{intl l="Please wait, loading"}</span></div>
</div>
<div class="tab-pane fade" id="documents">
<div class="text-center"><span class="loading">{intl l="Please wait, loading"}</span></div>
</div>
{$smarty.capture.product_tab_content nofilter}
<div class="tab-pane fade" id="modules">
<div class="form-container">
{include
file = "includes/inner-form-toolbar.html"
hide_submit_buttons = true
page_url = {$pageUrl}
close_url = {$closeUrl}
current_tab = "modules"
}
</div>
{* ugly fix : {hook name="product.tab-content" id="{$product_id}" view="product"} *}
{include file="includes/module-tab-content.html" hook="product.tab-content" location="product-edit" id="{$product_id}" view="product"}
</div>
</div>
</div>
</div>
</div>
{/loop}
</div>
{hook name="product-edit.bottom" product_id=$product_id}
</div>
</div>
<div class="modal fade" id="template_notice" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3>{intl l="warning"}</h3>
</div>
<div class="modal-body">
<p>
{intl l="If you change the product template, some of the product attribute combinations may be deleted, and you may have to reconfigure some of product prices."}
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">{intl l="OK"}</button>
</div>
</div>
</div>
</div>
{form name="thelia.admin.product.clone"}
<div class="modal fade{if $form_error} modal-force-show{/if}" id="cloneProductModal" tabindex="-1" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h3>{intl l="Clone product"}</h3>
</div>
<form method="post" action="{url path='/admin/products/clone' product_id=$product_id}" class="form-inline" role="form" {form_enctype form=$form}>
<div class="modal-body">
{if $form_error && $form_error_message}
<div class="alert alert-danger">{$form_error_message}</div>
{/if}
{form_hidden_fields form=$form}
{form_field form=$form field="productId"}
<input type="hidden" name="{$name}" value="{product attr='id'}">
{/form_field}
<div class="form-group">
{form_field form=$form field="newRef"}
<label for="{$label_attr.for}">{$label}</label>
<input type="text" name="{$name}" value="{$value}" id="{$label_attr.for}" class="form-control" required >
{/form_field}
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-default">{intl l="OK"}</button>
</div>
</form>
</div>
</div>
</div>
{/form}
<div class="modal fade js-modal-search-category-product" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="js-btn-dismiss-modal close">×</button>
<h3></h3>
</div>
<div class="modal-body align-center">
<div class="js-form-search">
<div class="form-group">
<div class="input-group">
<div class="input-group-addon">{intl l="Search"}</div>
<input name="search" class="js-input-search form-control" type="text"/>
</div>
</div>
<div class="js-loader text-center hide">{intl l="Please wait, loading"}</div>
<div class="alert alert-warning text-center hide js-alert-no-result">
{intl l="No results found for your search."}
</div>
<div class="form-group js-block-search-result hide">
<select class="form-control" size="10"></select>
</div>
</div>
</div>
<div class="modal-footer">
<a href="#" class="js-btn-dismiss-modal btn btn-default">{intl l="Close"}</a>
<a href="#" class="js-modal-btn-select btn btn-primary">{intl l="Select"}</a>
</div>
</div>
</div>
</div>
{/block}
{block name="javascript-initialization"}
{javascripts file='assets/js/dropzone.js'}
<script src="{$asset_url}"></script>
{/javascripts}
{javascripts file='assets/js/image-upload.js'}
<script src="{$asset_url}"></script>
{/javascripts}
{javascripts file='assets/js/document-upload.js'}
<script src="{$asset_url}"></script>
{/javascripts}
{javascripts file='assets/js/bootstrap-editable/bootstrap-editable.js'}
<script src="{$asset_url}"></script>
{/javascripts}
{javascripts file='assets/js/bootstrap-switch/bootstrap-switch.js'}
<script src="{$asset_url}"></script>
{/javascripts}
{javascripts file='assets/js/jquery.typewatch.js'}
<script src="{$asset_url}"></script>
{/javascripts}
{javascripts file='assets/js/jquery-ui-1.10.3.custom.min.js'}
<script src="{$asset_url}"></script>
{/javascripts}
<script>
$(function() {
// show tab documents
$(".alert-warning a[href^='javascript']").on('click', function () {
eval(this.href);
return false;
});
// Atomatic ajax tab load, if data-href is defined.
$('.nav-tabs a[data-href]').on('shown.bs.tab', function(ev) {
var $this = $(this);
$($this.attr('href')).load($this.data('href'), function(ev) {
if($this.data('callback')) {
eval($this.data('callback') + '();');
}
});
});
$('.nav-tabs a[data-trigger]').on('shown.bs.tab', function(ev) {
var $this = $(this);
var trigger = $this.data('trigger');
var triggers = trigger.split('::');
if (triggers.length == 2) {
$(triggers[0]).trigger(triggers[1]);
}
});
$("body").on("change", "#template_id", function(){
$("#template_notice").modal('show');
});
// Load active tab
$('.nav-tabs a[href="#{$current_tab}"]').trigger("click");
$('.nav-tabs a[href="#general"]').trigger("change");
// vitual product
$('#virtual_field').change(function(event) {
var $virtual = $(this);
if ($virtual.prop("checked")){
var $virtualDocumentsSelector;
$('#virtual-product-file').removeClass("hidden");
$virtualDocumentsSelector = $('#virtual-product-file select');
if ($virtualDocumentsSelector.length > 0){
// update options
$.ajax({
url : '{url path="/admin/product/virtual-documents/"}' +
$virtualDocumentsSelector.data('product') + '/' +
$virtualDocumentsSelector.data('pse'),
type : 'get',
dataType : 'json',
success : function(data) {
var i = 0,
selectedOption = 0,
virtualDocumentsSelector,
option;
virtualDocumentsSelector = $virtualDocumentsSelector.get(0);
virtualDocumentsSelector.options.length = 1;
if (data.length == 0){
$('#virtual-product-message').removeClass('hidden');
} else {
$('#virtual-product-message').addClass('hidden');
for (; i < data.length ; i++ ){
if (data[i].selected){
selectedOption = i + 1;
}
virtualDocumentsSelector.options[virtualDocumentsSelector.options.length]
= new Option(data[i].title + ' (' + data[i].file + ')', data[i].id);
}
virtualDocumentsSelector.selectedIndex = selectedOption;
}
}
});
}
} else {
$('#virtual-product-file').addClass("hidden");
}
});
// -- Product prices management tab ---------------------------------------
// Load value on attribute selection
$('#attribute_id').change(function(event) {
var val = $(this).val();
if (val != "") {
$.ajax({
url : '{url path="/admin/product/%id/attribute-values/" id=$product_id}' + $(this).val() + '.xml',
type : 'get',
dataType : 'json',
success : function(json) {
$('#attribute_value_id :not(:first-child)').remove();
var have_content = false;
$.each(json, function(idx, value) {
$('#attribute_value_id').append($('<option>').text(value.title).attr('value', value.id));
have_content = true; // Lame...
});
if (have_content) {
$('#attribute_value_selector_empty').addClass('hide');
$('#attribute_value_selector').removeClass('hide');
}
else {
$('#attribute_value_selector_empty').removeClass('hide');
$('#attribute_value_selector').addClass('hide');
}
}
});
}
else {
$('#attribute_value_selector_empty').addClass('hide');
$('#attribute_value_selector').addClass('hide');
}
});
// Add selected value to the combination
$('.add-value-to-combination').click(function(event) {
// Hide error message
$('#combination_attributes_error').text('').addClass('hide');
// Select all elements
$('#combination_attributes option').prop('selected', 'selected');
$.ajax({
url : '{url path="/admin/product/%id/add-attribute-value-to-combination/" id=$product_id}'
+ $('#attribute_value_id').val()
+ '/'
+ $('#combination_attributes').val()
+ '.xml',
type : 'get',
dataType : 'json',
success : function(json) {
$('#combination_attributes option').remove();
var have_content = false;
$.each(json, function(idx, value) {
if (idx != 'error')
$('#combination_attributes').append($('<option>').text(value.title).attr('value', value.id));
});
if (json.error)
$('#combination_attributes_error').text(json.error).removeClass('hide');
$('#attribute_id').val('').change();
}
});
event.preventDefault();
});
// Remove selected value from combination
$('.remove-value-from-combination').click(function() {
$('#combination_attributes option:selected').remove();
event.preventDefault();
});
// Set proper category ID in combination delete from
$('a.combination-delete').click(function(ev) {
$('#combination_delete_id').val($(this).data('id'));
});
// In create combination dialog, select all element of conbination list
$('#combination_creation_dialog_ok').click(function() {
$('#combination_attributes option').prop('selected', 'selected');
});
// In proces tab, process exchange rate usage checkbox changes
$('.use_exchange_rate_box').change(function(ev) {
if ($(this).is(':checked')) {
var pse_id = $(this).data('pse-id');
$('.price_field').prop('readonly', true);
// Reload prices
$.ajax({
url : '{url path="/admin/product/load-converted-prices"}',
data : {
product_sale_element_id : pse_id,
currency_id : {$edit_currency_id}
},
type : 'get',
dataType : 'json',
success : function(json) {
$('input[data-pse-id="'+pse_id+'"][data-price-type="price-with-tax"]').val(json.price_with_tax);
$('input[data-pse-id="'+pse_id+'"][data-price-type="price-without-tax"]').val(json.price_without_tax);
$('input[data-pse-id="'+pse_id+'"][data-price-type="sale-price-with-tax"]').val(json.sale_price_with_tax);
$('input[data-pse-id="'+pse_id+'"][data-price-type="sale-price-without-tax"]').val(json.sale_price_without_tax);
},
error : function(jqXHR, textStatus, errorThrown) {
alert("{intl l='Failed to get converted prices. Please try again.'} (" +errorThrown+ ")");
}
});
}
else {
$('.price_field').prop('readonly', false)
}
});
function update_price(price, price_type, dest_field_id) {
var tax_rule_id = $('#tax_rule_field').val();
if (tax_rule_id != "") {
var operation;
if (price_type.indexOf('with-tax') != -1)
operation = 'from_tax';
else if (price_type.indexOf('without-tax') != -1)
operation = 'to_tax';
else
operation = '';
$.ajax({
url : '{url path="/admin/product/calculate-price"}',
data : {
price : price,
action : operation,
product_id : {$product_id}
},
type : 'get',
dataType : 'json',
success : function(json) {
$('#' + dest_field_id).val(json.result);
},
error : function(jqXHR, textStatus, errorThrown) {
alert("{intl l='Failed to get prices. Please try again.'} (" +errorThrown+ ")");
}
});
}
}
// -- Combination builder stuff --------------------------------------------
$('#open_combination_builder').click(function(ev) {
if (! confirm("{intl l='Existing combinations will be deleted. Do you want to continue ?'}'")) {
ev.preventDefault();
ev.stopPropagation();
}
});
{include
file = "includes/generic-js-dialog.html"
dialog_id = "combination_builder_dialog"
form_name = "thelia.admin.product_combination.build"
}
// Automatic update of price fields: any change in the taxed (resp. untaxed) price
// will update the untaxed (resp. taxed) one
$('.automatic_price_field').typeWatch({
captureLength: 1,
wait : 300,
callback : function () {
var price = $(this).val();
$(this).val(sanitizeFloat(price));
update_price($(this).val(), $(this).data('price-type'), $(this).data('rel-price'));
}
});
function sanitizeFloat(numVal) {
return numVal.replace(",", ".");
};
// Count generated combinations in real time
function countGeneratedCombinations() {
var total = 0;
var counter = {};
var list = $('.attribute_av_value:checked');
if (list.length > 0) {
list.each(function() {
var attr_id = $(this).data('attribute-id');
if (undefined != counter[attr_id])
counter[attr_id]++;
else
counter[attr_id] = 1;
});
total = 1;
for(var count in counter) {
total *= counter[count];
}
}
return total;
}
$('.attribute_av_value').change(function(ev) {
var total = countGeneratedCombinations();
$('#number_of_generated_combinations').text(total);
});
$(".pse-assoc-image-document").click(function() {
var $this = $(this);
var type = "none";
var toggle_event = "";
if ($this.hasClass("pse-assoc-image")) {
type = "image";
toggle_event = "click";
} else if ($this.hasClass("pse-assoc-document")) {
type = "document";
toggle_event = "switch-change";
} else {
if ($this.data("type")){
type = $this.data("type");
toggle_event = "switch-change";
}
}
var $modal_container = $("#pse-modal-container");
var pse_id = $(this).data("id");
$.ajax(
"{url path="/admin/product_sale_elements/ajax/"}"+ type + "/" + pse_id
).done(function(data) {
$modal_container.html(data);
$("#pse-image-document-assoc-modal").modal();
$(".do-associate").on(toggle_event, function(e, data) {
var $file = $(this);
var type_id = $file.data("id");
$.ajax(
"{url path='/admin/product_sale_elements'}/"+pse_id+"/"+type+"/"+type_id
).done(function() {
/**
* If the modal is for images, add some graphics
*/
if (type == "image") {
if ($file.hasClass("is-associated")) {
$file.removeClass("is-associated");
$(".product-pse-image-join-glyphicon", $file.parent()).remove();
} else {
$file.addClass("is-associated");
$file.parent().append("<span class='glyphicon glyphicon-ok product-pse-image-join-glyphicon'></span>");
}
} else if (type == "virtual") {
if ( $file.bootstrapSwitch('status') ) {
$(".do-associate").each(function(){
if (type_id != $(this).data("id") && $(this).bootstrapSwitch('status')) {
$(this).bootstrapSwitch('setState', false);
}
});
}
}
}).fail(function(data) {
var $body = $(".modal-body", $modal_container);
$errorMessage = $("<div class='alert alert-danger'>"+data["error"]+"</div>");
$body.html($errorMessage + $body.html());
});
});
}).fail(function(data) {
var $modal_title = $("#associate_images_documents_label");
var $body = $(".modal-body", $modal_container);
$modal_title.html("{intl l='Error'}");
var error_message = data["error"];
if (!error_message || error_message.length === 0) {
error_message = "{intl l='An unknown error occured, please try again.'}";
}
$body.html("<p>"+error_message+"</p>");
$("#pse-assoc-image-document-modal").modal();
});
});
});
//Product and category search
var $modalSearch;
$(function() {
var idDefaultCategorySelect = '#default_category_field';
$(idDefaultCategorySelect).after('<a class="js-btn-search-default-category btn btn-info" href="#"><span class="glyphicon glyphicon-search"></span></a>');
// Search categories and products
$modalSearch = $('.js-modal-search-category-product');
$modalSearch.initAndShow = function(title, searchUrl, selectSelector, searchPlaceholder, categoryIdToFilter){
categoryIdToFilter = (typeof categoryIdToFilter !== 'undefined') ? categoryIdToFilter : null;
$modalSearch.find('.modal-header h3').text(title);
$modalSearch.data('url', searchUrl);
$modalSearch.data('selectselector', selectSelector);
if(categoryIdToFilter != null){
$modalSearch.data('categoryid', categoryIdToFilter);
$modalSearch.data('filterbycategory', '1');
}else{
$modalSearch.data('filterbycategory', '0');
}
$modalSearch.find('.js-input-search').attr('placeholder',searchPlaceholder);
$modalSearch.modal('show');
};
$modalSearch.dismiss = function(){
$modalSearch.find('.js-block-search-result').addClass('hide');
$modalSearch.find('.js-alert-no-result').addClass('hide');
$modalSearch.find('.js-input-search').val('');
$modalSearch.modal('hide');
};
$modalSearch.on('click', '.js-modal-btn-select', function(e){
e.preventDefault();
var selectedVal = $modalSearch.find('.js-block-search-result select').val();
if(selectedVal != null) {
$($modalSearch.data('selectselector')).val(selectedVal).trigger('change');
$modalSearch.dismiss();
}
});
$modalSearch.on('click', '.js-btn-dismiss-modal', function(e) {
e.preventDefault();
$modalSearch.dismiss();
});
var searchTimer = null;
$modalSearch.on('keyup' ,'.js-input-search', function(){
var val = $(this).val();
if (searchTimer !== null) {
clearTimeout(searchTimer);
}
$modalSearch.find('.js-alert-no-result').addClass('hide');
var ajaxData = { q: val };
if($modalSearch.data('filterbycategory') == '1'){
ajaxData['category_id'] = $modalSearch.data('categoryid');
}
if (val.length > 2) {
$modalSearch.find('.js-loader').removeClass('hide');
searchTimer = setTimeout(function() {
$.ajax({
url: $modalSearch.data('url'),
data: ajaxData,
dataType: 'json',
method: 'GET',
success: function(data) {
$modalSearch.find('.js-loader').addClass('hide');
var options = [];
for (var id in data) {
options.push('<option value="' + id + '">' + data[id] + '</option>');
}
if (options.length > 0) {
$modalSearch.find(".js-block-search-result select").html(options.join(''));
$modalSearch.find('.js-block-search-result').removeClass('hide');
} else {
this.error();
}
},
error: function() {
$modalSearch.find('.js-loader').addClass('hide');
$modalSearch.find('.js-block-search-result').addClass('hide');
$modalSearch.find('.js-alert-no-result').removeClass('hide');
}
});
}, 350, this);
} else {
$modalSearch.find('.js-loader').addClass('hide');
$modalSearch.find('.js-block-search-result').addClass('hide');
}
});
$('.js-btn-search-default-category').on('click', function(event){
event.preventDefault();
$modalSearch.initAndShow(
'{intl l="Search category"}',
'{url path="/admin/products/related/tab/categories/search"}',
idDefaultCategorySelect,
"{intl l='Category title'}"
);
});
});
</script>
{/block}
{block name="javascript-last-call"}
{hook name="product.edit-js" location="product-edit-js" product_id={$product_id} }
{hook name="wysiwyg.js" location="wysiwyg-product-edit-js" }
{/block}