Recettes : c'est bon sur l'ajout des produits, on ataque la liste des étapes
@@ -20,8 +20,9 @@
|
|||||||
<route id="recipe.search_product" path="/admin/module/Recettes/search-product">
|
<route id="recipe.search_product" path="/admin/module/Recettes/search-product">
|
||||||
<default key="_controller">Recettes\Controller\BackController::searchProduct</default>
|
<default key="_controller">Recettes\Controller\BackController::searchProduct</default>
|
||||||
</route>
|
</route>
|
||||||
<route id="recipe.search_combination" path="/admin/module/Recettes/search-combination">
|
<route id="recipe.add_product" path="/admin/module/Recettes/add-product/{contentId}">
|
||||||
<default key="_controller">Recettes\Controller\BackController::searchCombination</default>
|
<default key="_controller">Recettes\Controller\BackController::addProduct</default>
|
||||||
|
<requirement key="contentId">\d+</requirement>
|
||||||
</route>
|
</route>
|
||||||
|
|
||||||
</routes>
|
</routes>
|
||||||
|
|||||||
@@ -19,12 +19,18 @@ use Thelia\Core\Event\Content\ContentUpdateEvent;
|
|||||||
use Thelia\Core\HttpFoundation\JsonResponse;
|
use Thelia\Core\HttpFoundation\JsonResponse;
|
||||||
use Thelia\Core\HttpFoundation\Request;
|
use Thelia\Core\HttpFoundation\Request;
|
||||||
use Thelia\Form\BaseForm;
|
use Thelia\Form\BaseForm;
|
||||||
|
use Thelia\Model\AttributeAvI18n;
|
||||||
|
use Thelia\Model\AttributeAvI18nQuery;
|
||||||
use Thelia\Model\AttributeCombinationQuery;
|
use Thelia\Model\AttributeCombinationQuery;
|
||||||
|
use Thelia\Model\AttributeI18n;
|
||||||
|
use Thelia\Model\AttributeI18nQuery;
|
||||||
|
use Thelia\Model\AttributeQuery;
|
||||||
use Thelia\Model\ContentI18nQuery;
|
use Thelia\Model\ContentI18nQuery;
|
||||||
use Thelia\Model\ContentQuery;
|
use Thelia\Model\ContentQuery;
|
||||||
use Thelia\Model\Map\ProductI18nTableMap;
|
use Thelia\Model\Map\ProductI18nTableMap;
|
||||||
use Thelia\Model\Map\ProductTableMap;
|
use Thelia\Model\Map\ProductTableMap;
|
||||||
use Thelia\Model\ProductQuery;
|
use Thelia\Model\ProductQuery;
|
||||||
|
use Thelia\Model\ProductSaleElementsQuery;
|
||||||
use Thelia\Tools\URL;
|
use Thelia\Tools\URL;
|
||||||
|
|
||||||
|
|
||||||
@@ -37,9 +43,7 @@ class BackController extends BaseAdminController
|
|||||||
|
|
||||||
public function saveRecipe(Request $request)
|
public function saveRecipe(Request $request)
|
||||||
{
|
{
|
||||||
$error = "";
|
|
||||||
$con = Propel::getConnection();
|
$con = Propel::getConnection();
|
||||||
$nouvelleRecette = false;
|
|
||||||
|
|
||||||
$form = new RecetteCreateForm($request);
|
$form = new RecetteCreateForm($request);
|
||||||
try {
|
try {
|
||||||
@@ -88,10 +92,40 @@ class BackController extends BaseAdminController
|
|||||||
{
|
{
|
||||||
RecipeProductsQuery::create()->filterByRecipeId($recipeId)->filterByPseId($pseId)->delete();
|
RecipeProductsQuery::create()->filterByRecipeId($recipeId)->filterByPseId($pseId)->delete();
|
||||||
|
|
||||||
return new RedirectResponse(URL::getInstance()->absoluteUrl("/admin/content/update/" . $contentId . "#recipe"));
|
return new RedirectResponse(URL::getInstance()->absoluteUrl("/admin/content/update/" . $contentId . "?current_tab=recipe"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function getData($product_id)
|
||||||
|
{
|
||||||
|
$locale = $this->getCurrentEditionLocale();
|
||||||
|
$combinations = [];
|
||||||
|
|
||||||
|
$con = Propel::getConnection();
|
||||||
|
$pse = ProductSaleElementsQuery::create()
|
||||||
|
->filterByProductId($product_id)
|
||||||
|
->find($con);
|
||||||
|
|
||||||
|
foreach ($pse as $pseItem)
|
||||||
|
{
|
||||||
|
$combinationsArray = AttributeCombinationQuery::create()
|
||||||
|
->filterByProductSaleElements($pseItem)
|
||||||
|
->find($con);
|
||||||
|
|
||||||
|
foreach ($combinationsArray as $combination) {
|
||||||
|
$pseId = $pseItem->getId();
|
||||||
|
$label = AttributeAvI18nQuery::create()
|
||||||
|
->filterByLocale($locale)
|
||||||
|
->findOneById($combination->getAttributeAvId())
|
||||||
|
->getTitle();
|
||||||
|
|
||||||
|
array_push($combinations, [$pseId => $label]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $combinations;
|
||||||
|
}
|
||||||
|
|
||||||
public function searchProduct()
|
public function searchProduct()
|
||||||
{
|
{
|
||||||
$locale = $this->getCurrentEditionLocale();
|
$locale = $this->getCurrentEditionLocale();
|
||||||
@@ -115,17 +149,13 @@ class BackController extends BaseAdminController
|
|||||||
|
|
||||||
foreach ($data as $item) {
|
foreach ($data as $item) {
|
||||||
|
|
||||||
$combinations = AttributeCombinationQuery::create()
|
$combinations = self::getData($item['product.id']);
|
||||||
->filterByProductSaleElementsId($item->getId())
|
|
||||||
|
|
||||||
$item
|
|
||||||
|
|
||||||
|
|
||||||
$result[] = [
|
$result[] = [
|
||||||
'id' => $item[ProductTableMap::COL_ID],
|
'id' => $item[ProductTableMap::COL_ID],
|
||||||
'ref' => $item[ProductTableMap::COL_REF],
|
'ref' => $item[ProductTableMap::COL_REF],
|
||||||
'title' => $item['title'],
|
'title' => $item['title'],
|
||||||
'combinations' => []
|
'combinations' => $combinations,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -133,27 +163,22 @@ class BackController extends BaseAdminController
|
|||||||
return JsonResponse::create($result);
|
return JsonResponse::create($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function searchCombination()
|
|
||||||
{
|
|
||||||
$locale = $this->getCurrentEditionLocale();
|
|
||||||
$ref = $this->getRequest()->get('query', null);
|
|
||||||
$result = [];
|
|
||||||
|
|
||||||
return JsonResponse::create($result);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
public function addProduct($contentId)
|
public function addProduct($contentId)
|
||||||
{
|
{
|
||||||
$productId = (int) $this->getRequest()->get('product_id');
|
$pseId = (int) $this->getRequest()->get('pse_id');
|
||||||
|
$quantityNeeded = (string) $this->getRequest()->get('quantity_needed');
|
||||||
|
$recipeId = (int) $this->getRequest()->get('recipe_id');
|
||||||
|
$quantityProposed = (int) $this->getRequest()->get('quantity_proposed');
|
||||||
|
|
||||||
(new AgendaRelatedProduct())
|
(new RecipeProducts())
|
||||||
->setProductId($productId)
|
->setRecipeId($recipeId)
|
||||||
->setContentId($contentId)
|
->setPseId($pseId)
|
||||||
|
->setQuantity($quantityNeeded)
|
||||||
|
->setNbOfProducts($quantityProposed)
|
||||||
->save();
|
->save();
|
||||||
|
|
||||||
return $this->render('ajax/related-products', [ 'content_id' => $contentId ]);
|
return $this->render('ajax/related-products', [ 'content_id' => $contentId ]);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ return array(
|
|||||||
'Number of people' => 'Nombre de couverts',
|
'Number of people' => 'Nombre de couverts',
|
||||||
'Product' => 'Produit',
|
'Product' => 'Produit',
|
||||||
'Quantity' => 'Quantité',
|
'Quantity' => 'Quantité',
|
||||||
'Summary' => 'Détail',
|
'Summary' => 'Petit résumé de la recette',
|
||||||
'Other ingredients' => 'Ingrédients supplémentaires',
|
'Other ingredients' => 'Ingrédients supplémentaires',
|
||||||
'Ingredients' => 'Ingrédients',
|
'Ingredients' => 'Ingrédients',
|
||||||
'Ingredient' => 'Nos produits',
|
'Ingredient' => 'Nos produits',
|
||||||
@@ -22,4 +22,5 @@ return array(
|
|||||||
'Some products may not be in stock' => '* ce produit n\'est plus en stock, désolé',
|
'Some products may not be in stock' => '* ce produit n\'est plus en stock, désolé',
|
||||||
'Name' => 'Notre recette',
|
'Name' => 'Notre recette',
|
||||||
'Created on' => 'Rédigée le',
|
'Created on' => 'Rédigée le',
|
||||||
|
'Save recipe' => 'Sauvegarder la recette',
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,15 +1,22 @@
|
|||||||
<table class="table table-condensed">
|
{loop type="recipe" name="recipe-loop" content_id=$content_id limit="1"}
|
||||||
|
|
||||||
{loop type="recipe" name="recipe-loop" content_id=$content_id limit="1"}
|
|
||||||
{assign var="recipe_id" value="$ID"}
|
{assign var="recipe_id" value="$ID"}
|
||||||
{/loop}
|
<input type="hidden" id="recipe_id" value="{$ID}">
|
||||||
|
{/loop}
|
||||||
|
|
||||||
|
<table class="table table-condensed">
|
||||||
|
<thead>
|
||||||
|
<th>{intl l="Product" d="recettes"}</th>
|
||||||
|
<th>{intl l="Quantity needed" d="recettes"}</th>
|
||||||
|
<th colspan="2">{intl l="Quantity proposed" d="recettes"}</th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
{loop type="recipe_products" name="products-loop" recipe_id=$recipe_id}
|
{loop type="recipe_products" name="products-loop" recipe_id=$recipe_id}
|
||||||
{loop type="product" visible='*' name="related-product" id=$PRODUCT_ID}
|
{loop type="product" visible="*" name="related-product" id=$PRODUCT_ID}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{$TITLE}<input type="hidden" value="{$PSE_ID}"</input></td>
|
<td>{$TITLE}<input type="hidden" value="{$PSE_ID}"</input></td>
|
||||||
<td>{$UNITY}</td>
|
<td>{$QUANTITY_NEEDED}</td>
|
||||||
<td>{$QUANTITY_PROPOSED}</td>
|
<td>{$QUANTITY_PROPOSED}</td>
|
||||||
|
<td>{$UNITY}</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<a href="{url path='/admin/module/Recettes/remove-product/%recipeId/%pseId/%contentId' recipeId=$recipe_id pseId=$PSE_ID contentId=$content_id}" class="delete-product"><i class="glyphicon glyphicon-trash"></i></a>
|
<a href="{url path='/admin/module/Recettes/remove-product/%recipeId/%pseId/%contentId' recipeId=$recipe_id pseId=$PSE_ID contentId=$content_id}" class="delete-product"><i class="glyphicon glyphicon-trash"></i></a>
|
||||||
</td>
|
</td>
|
||||||
@@ -28,20 +35,29 @@
|
|||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3">
|
<td colspan="3">
|
||||||
<input class="form-control" type="text" id="product_ref" autocomplete="off" data-content-id="{$recipe_id}" placeholder="Indiquez une référence de produit">
|
<input class="form-control" type="text" id="product_ref" autocomplete="off" data-content-id="{$recipe_id}" placeholder="Saisir une référence de produit">
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3">
|
<td colspan="3">
|
||||||
<input class="form-control" type="text" id="pse_id" autocomplete="off" data-content-id="{$pse_id}" placeholder="Choisissez une déclinaison">
|
<input class="form-control" type="text" id="quantity_needed" autocomplete="off" placeholder="Quantité nécessaire (texte libre)">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="3">
|
||||||
|
<label class="control-label">Choix de la déclinaison</label>
|
||||||
|
<input type="hidden" id="combinations" name="combinations" value="---">
|
||||||
|
<select id="select-combination" name="select-combination" class="form-control input-sm pse-option">
|
||||||
|
</select>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2">
|
<td colspan="2">
|
||||||
<input class="form-control" type="text" id="quantity" autocomplete="off" placeholder="Saisir une quantité">
|
<input class="form-control" type="text" id="quantity_proposed" autocomplete="off" placeholder="Quantité proposée, en fonction de la déclinaison">
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<a href="{url path='/admin/module/Recettes/add-product/%recipeId' recipeId=$recipe_id}" class="btn btn-sm btn-primary add-product"><i class="glyphicon glyphicon-plus-sign"></i></a>
|
<a href="{url path='/admin/module/Recettes/add-product/%contentId' contentId=$content_id}" class="btn btn-sm btn-primary add-product"><i class="glyphicon glyphicon-plus-sign"></i></a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<input type="hidden" id="recipe_id" value="{$recipe_id}">
|
||||||
|
|
||||||
|
<table class="table table-condensed">
|
||||||
|
<thead>
|
||||||
|
<th>{intl l="Step" d="recettes"}</th>
|
||||||
|
<th colspan="2">{intl l="Detail" d="recettes"}</th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{loop name="steps-loop" type="recipe_steps" recipe_id=$recipe_id}
|
||||||
|
<tr>
|
||||||
|
<td>{$STEP}</td>
|
||||||
|
<td>{$DESCRIPTION}</td>
|
||||||
|
</tr>
|
||||||
|
{/loop}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
@@ -24,38 +24,42 @@
|
|||||||
},
|
},
|
||||||
afterSelect: function (item) {
|
afterSelect: function (item) {
|
||||||
this.$element[0].value = item.title
|
this.$element[0].value = item.title
|
||||||
$('#product_ref').data('product-id', item.id);
|
$("#select-combination").attr('disabled', null);
|
||||||
$("#pse_id").attr('disabled', null);
|
$("#quantity_needed").attr('disabled', null);
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#pse_id').typeahead({
|
$('#select-combination')
|
||||||
source: function (query, process) {
|
.empty()
|
||||||
return $.getJSON(
|
.append($('<option>').val("").text("Choisissez une déclinaison"));
|
||||||
'{url path="/admin/module/Recettes/search-combination"}',
|
|
||||||
{
|
item.combinations.forEach(function(key, value) {
|
||||||
query: query
|
for (var id in key) {
|
||||||
},
|
$('#select-combination')
|
||||||
function (data) {
|
.append($('<option>').val(id).text(key[id]));
|
||||||
process(data)
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
displayText: function (item) {
|
|
||||||
return item.title
|
|
||||||
},
|
|
||||||
afterSelect: function (item) {
|
|
||||||
this.$element[0].value = item.title
|
|
||||||
$('#product_ref').data('product-id', item.id);
|
|
||||||
$("#pse_id").attr('disabled', null);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#select-combination').change(function() {
|
||||||
|
var option = $("#select-combination option:selected").val();
|
||||||
|
if (option != "") {
|
||||||
|
$("#quantity_proposed").attr('disabled', null);
|
||||||
|
$('#product_ref').data('pse-id', option);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$("#quantity_proposed").attr('disabled', 'disabled');
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#quantity_proposed').change(function() {
|
||||||
|
if ($('#quantity_proposed').val() <= 0) {
|
||||||
|
alert("Veuillez saisir une quantité positive.");
|
||||||
|
$("#quantity_proposed").attr('disabled', null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$(".add-product").attr('disabled', null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
$(document).on('click', '.add-product', function(event) {
|
$(document).on('click', '.add-product', function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@@ -63,7 +67,10 @@
|
|||||||
$('#related-products-block').load(
|
$('#related-products-block').load(
|
||||||
$(this).attr('href'),
|
$(this).attr('href'),
|
||||||
{
|
{
|
||||||
product_id: $('#product_ref').data('product-id')
|
quantity_needed: $('#quantity_needed').val(),
|
||||||
|
pse_id: $('#product_ref').data('pse-id'),
|
||||||
|
quantity_proposed: $('#quantity_proposed').val(),
|
||||||
|
recipe_id : $("#recipe_id").val()
|
||||||
},
|
},
|
||||||
function() {
|
function() {
|
||||||
setupTypeAhead();
|
setupTypeAhead();
|
||||||
@@ -73,8 +80,11 @@
|
|||||||
|
|
||||||
|
|
||||||
setupTypeAhead();
|
setupTypeAhead();
|
||||||
$("#pse_id").attr('disabled', 'disabled');
|
|
||||||
$("#quantity").attr('disabled', 'disabled');
|
// Par défaut, les champs de saisie du produit sont désactivés.
|
||||||
|
$("#quantity_needed").attr('disabled', 'disabled');
|
||||||
|
$("#select-combination").attr('disabled', 'disabled');
|
||||||
|
$("#quantity_proposed").attr('disabled', 'disabled');
|
||||||
$(".add-product").attr('disabled', 'disabled');
|
$(".add-product").attr('disabled', 'disabled');
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -8,10 +8,9 @@
|
|||||||
{assign var="other_ingredients" value=$OTHER_INGREDIENTS}
|
{assign var="other_ingredients" value=$OTHER_INGREDIENTS}
|
||||||
{/loop}
|
{/loop}
|
||||||
|
|
||||||
<div id="wrapper" class="container">
|
<div class="form-container">
|
||||||
<div class="row">
|
|
||||||
{form name="recette_create_form"}
|
{form name="recette_create_form"}
|
||||||
<form id="admin-comment-form" method="post" action="{url path='/admin/module/Recettes/save'}" {form_enctype form=$form}>
|
<form id="admin-comment-form" method="post" action="{url path='/admin/module/Recettes/save'}" {form_enctype form=$form} class="clearfix">
|
||||||
|
|
||||||
{form_hidden_fields form=$form}
|
{form_hidden_fields form=$form}
|
||||||
|
|
||||||
@@ -120,14 +119,13 @@
|
|||||||
<br>
|
<br>
|
||||||
<label class="control-label">Etapes de la recette</label>
|
<label class="control-label">Etapes de la recette</label>
|
||||||
<div id="steps-block">
|
<div id="steps-block">
|
||||||
{include file="ajax/steps.html"}
|
{include file="ajax/steps.html" content_id=$content_id}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<button type="submit" class="btn btn-primary">{intl l="Save" d="recettes"}</button>
|
<button type="submit" class="btn btn-primary">{intl l="Save recipe" d="recettes"}</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{/form}
|
{/form}
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
@@ -132,6 +132,7 @@ td.table-liste-recettes-image {
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
width: auto;
|
width: auto;
|
||||||
vertical-align: middle !important;
|
vertical-align: middle !important;
|
||||||
|
margin: auto;
|
||||||
}
|
}
|
||||||
.table-liste-recettes-image img {
|
.table-liste-recettes-image img {
|
||||||
width: 65px;
|
width: 65px;
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 355 B After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 86 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.6 KiB |