Recettes : BO, rajout de l'ajax
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
<hooks>
|
||||
<hook id="recettes.back.hook" class="Recettes\Hook\HookManager">
|
||||
<tag name="hook.event_listener" event="content.tab" type="back" method="onAddTab" />
|
||||
<tag name="hook.event_listener" event="content.edit-js" type="back" method="onAddJs" />
|
||||
</hook>
|
||||
<hook id="recettes.front.hook" class="Recettes\Hook\HookManager">
|
||||
<tag name="hook.event_listener" event="content.stylesheet" type="front" method="onAddCSS" />
|
||||
|
||||
@@ -4,12 +4,24 @@
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
|
||||
|
||||
<route id="recipe.save" path="/admin/module/Recettes/save" methods="post">
|
||||
<default key="_controller">Recettes\Controller\BackController::saveRecipe</default>
|
||||
</route>
|
||||
|
||||
<route id="recipe.addtocart" path="/admin/module/Recettes/addtocart" methods="post">
|
||||
<default key="_controller">Recettes\Controller\FrontController::addToCart</default>
|
||||
</route>
|
||||
|
||||
<route id="recipe.save" path="/admin/module/Recettes/save" methods="post">
|
||||
<default key="_controller">Recettes\Controller\BackController::saveRecipe</default>
|
||||
</route>
|
||||
<route id="recipe.delete_product" path="/admin/module/Recettes/remove-product/{recipeId}/{pseId}/{contentId}">
|
||||
<default key="_controller">Recettes\Controller\BackController::removeProduct</default>
|
||||
<requirement key="recipeId">\d+</requirement>
|
||||
<requirement key="pseId">\d+</requirement>
|
||||
<requirement key="contentId">\d+</requirement>
|
||||
</route>
|
||||
<route id="recipe.search_product" path="/admin/module/Recettes/search-product">
|
||||
<default key="_controller">Recettes\Controller\BackController::searchProduct</default>
|
||||
</route>
|
||||
<route id="recipe.search_combination" path="/admin/module/Recettes/search-combination">
|
||||
<default key="_controller">Recettes\Controller\BackController::searchCombination</default>
|
||||
</route>
|
||||
|
||||
</routes>
|
||||
|
||||
@@ -3,21 +3,28 @@
|
||||
namespace Recettes\Controller;
|
||||
|
||||
use Exception;
|
||||
use Propel\Runtime\ActiveQuery\Criteria;
|
||||
use Propel\Runtime\Exception\PropelException;
|
||||
use Propel\Runtime\Propel;
|
||||
use Recettes\Form\RecetteCreateForm;
|
||||
use Recettes\Model\Recipe;
|
||||
use Recettes\Model\RecipeProducts;
|
||||
use Recettes\Model\RecipeProductsQuery;
|
||||
use Recettes\Model\RecipeQuery;
|
||||
use Recettes\Model\RecipeSteps;
|
||||
use Recettes\Model\RecipeStepsQuery;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Thelia\Controller\Admin\BaseAdminController;
|
||||
use Thelia\Core\Event\Content\ContentUpdateEvent;
|
||||
use Thelia\Core\HttpFoundation\JsonResponse;
|
||||
use Thelia\Core\HttpFoundation\Request;
|
||||
use Thelia\Form\BaseForm;
|
||||
use Thelia\Model\AttributeCombinationQuery;
|
||||
use Thelia\Model\ContentI18nQuery;
|
||||
use Thelia\Model\ContentQuery;
|
||||
use Thelia\Model\Map\ProductI18nTableMap;
|
||||
use Thelia\Model\Map\ProductTableMap;
|
||||
use Thelia\Model\ProductQuery;
|
||||
use Thelia\Tools\URL;
|
||||
|
||||
|
||||
@@ -47,16 +54,12 @@ class BackController extends BaseAdminController
|
||||
$preparationTime = $data['preparation_time'];
|
||||
$cookingTime = $data['cooking_time'];
|
||||
$otherIngredients = $data['other_ingredients'];
|
||||
// $steps = $data['steps'];
|
||||
|
||||
if (null !== $title && null !== $contentId && null !== $difficulty && null !== $numberPeople && null !== $preparationTime) {
|
||||
|
||||
$recipe = RecipeQuery::create()->findOneByContentId($contentId);
|
||||
if (null === $recipe)
|
||||
{
|
||||
$nouvelleRecette = true;
|
||||
$recipe = new Recipe();
|
||||
}
|
||||
else
|
||||
$recipeId = $recipe->getId();
|
||||
|
||||
@@ -71,26 +74,7 @@ class BackController extends BaseAdminController
|
||||
$recipe->save($con);
|
||||
$con->commit();
|
||||
|
||||
if (!$nouvelleRecette)
|
||||
{
|
||||
// On supprime les étapes pour les recréer par la suite.
|
||||
// $steps = RecipeStepsQuery::create()->findByRecipeId($recipeId);
|
||||
// $steps->delete($con);
|
||||
// $con->commit();
|
||||
}
|
||||
/*
|
||||
foreach ($steps as $step) {
|
||||
$recipeSteps = new RecipeSteps();
|
||||
$recipeSteps->setRecipeId($recipeId);
|
||||
$recipeSteps->setStep($step['id']);
|
||||
$recipeSteps->setDescription($step['description']);
|
||||
$recipeSteps->save();
|
||||
$con->commit();
|
||||
}
|
||||
*/
|
||||
// A rajouter : les produits et les étapes
|
||||
|
||||
return new RedirectResponse(URL::getInstance()->absoluteUrl("/admin/content/update/" . $contentId));
|
||||
return new RedirectResponse(URL::getInstance()->absoluteUrl("/admin/content/update/" . $contentId . "#recipe"));
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
$error = $e->getMessage();
|
||||
@@ -99,4 +83,77 @@ class BackController extends BaseAdminController
|
||||
return new RedirectResponse(URL::getInstance()->absoluteUrl("/admin/content"));
|
||||
}
|
||||
|
||||
|
||||
public function removeProduct($recipeId, $pseId, $contentId)
|
||||
{
|
||||
RecipeProductsQuery::create()->filterByRecipeId($recipeId)->filterByPseId($pseId)->delete();
|
||||
|
||||
return new RedirectResponse(URL::getInstance()->absoluteUrl("/admin/content/update/" . $contentId . "#recipe"));
|
||||
}
|
||||
|
||||
|
||||
public function searchProduct()
|
||||
{
|
||||
$locale = $this->getCurrentEditionLocale();
|
||||
$ref = $this->getRequest()->get('query', null);
|
||||
$result = [];
|
||||
|
||||
if (! empty($ref)) {
|
||||
$data = ProductQuery::create()
|
||||
->filterByRef("%$ref%", Criteria::LIKE)
|
||||
->orderByRef()
|
||||
->useI18nQuery($locale)
|
||||
->withColumn(ProductI18nTableMap::COL_TITLE, 'title')
|
||||
->endUse()
|
||||
->limit(15)
|
||||
->select([
|
||||
ProductTableMap::COL_ID,
|
||||
ProductTableMap::COL_REF,
|
||||
'title'
|
||||
])
|
||||
->find();
|
||||
|
||||
foreach ($data as $item) {
|
||||
|
||||
$combinations = AttributeCombinationQuery::create()
|
||||
->filterByProductSaleElementsId($item->getId())
|
||||
|
||||
$item
|
||||
|
||||
|
||||
$result[] = [
|
||||
'id' => $item[ProductTableMap::COL_ID],
|
||||
'ref' => $item[ProductTableMap::COL_REF],
|
||||
'title' => $item['title'],
|
||||
'combinations' => []
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
$productId = (int) $this->getRequest()->get('product_id');
|
||||
|
||||
(new AgendaRelatedProduct())
|
||||
->setProductId($productId)
|
||||
->setContentId($contentId)
|
||||
->save();
|
||||
|
||||
return $this->render('ajax/related-products', [ 'content_id' => $contentId ]);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ use Thelia\Controller\Front\BaseFrontController;
|
||||
use Thelia\Core\Event\TheliaEvents;
|
||||
use Thelia\Core\HttpFoundation\Request;
|
||||
use Thelia\Core\Event\Cart\CartEvent;
|
||||
use Thelia\Exception\TheliaProcessException;
|
||||
use Thelia\Model\ProductSaleElementsQuery;
|
||||
use Thelia\Tools\URL;
|
||||
|
||||
@@ -51,4 +50,5 @@ class FrontController extends BaseFrontController
|
||||
return new RedirectResponse(URL::getInstance()->absoluteUrl('/cart'));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,9 +34,20 @@ class HookManager extends baseHook
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function onAddCss(HookRenderEvent $event)
|
||||
{
|
||||
$event->add($this->addCSS('assets/css/Recettes.css'));
|
||||
}
|
||||
|
||||
|
||||
public function onAddJs(HookRenderEvent $event)
|
||||
{
|
||||
$event->add(
|
||||
$this->render(
|
||||
"recette-tab-js.html"
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace Recettes\Loop;
|
||||
|
||||
use mysql_xdevapi\Exception;
|
||||
use Propel\Runtime\Exception\PropelException;
|
||||
use Recettes\Model\RecipeProductsQuery;
|
||||
use Thelia\Core\Template\Element\BaseLoop;
|
||||
use Thelia\Core\Template\Element\LoopResult;
|
||||
@@ -31,29 +33,35 @@ class ProductsLoop extends BaseLoop implements PropelSearchLoopInterface
|
||||
*/
|
||||
public function parseResults(LoopResult $loopResult)
|
||||
{
|
||||
$someProductsNotInStock = false;
|
||||
|
||||
foreach ($loopResult->getResultDataCollection() as $product) {
|
||||
|
||||
$pse = ProductSaleElementsQuery::create()->findOneById($product->getPseId());
|
||||
$productId = $pse->getProductId();
|
||||
$productLabel = ProductI18nQuery::create()->findOneById($pse->getProductId())->getTitle();
|
||||
$attributeCombination = AttributeCombinationQuery::create()->findOneByProductSaleElementsId($product->getPseId());
|
||||
$unity = AttributeAvI18nQuery::create()->findOneById($attributeCombination->getAttributeAvId())->getTitle();
|
||||
$inStock = $pse->getQuantity();
|
||||
try {
|
||||
$pse = ProductSaleElementsQuery::create()->findOneById($product->getPseId());
|
||||
$productId = $pse->getProductId();
|
||||
$productLabel = ProductI18nQuery::create()->findOneById($pse->getProductId())->getTitle();
|
||||
$attributeCombination = AttributeCombinationQuery::create()->findOneByProductSaleElementsId($product->getPseId());
|
||||
if ($attributeCombination)
|
||||
$unity = AttributeAvI18nQuery::create()->findOneById($attributeCombination->getAttributeAvId())->getTitle();
|
||||
else
|
||||
$unity = "Pas de déclinaison";
|
||||
$inStock = $pse->getQuantity();
|
||||
|
||||
$loopResultRow = new LoopResultRow($product);
|
||||
$loopResultRow
|
||||
->set("RECIPE_ID", $product->getRecipeId())
|
||||
->set("PSE_ID", $product->getPseId())
|
||||
->set("PRODUCT_ID", $productId)
|
||||
->set("IN_STOCK", $inStock > 0)
|
||||
->set("PRODUCT_LABEL", $productLabel)
|
||||
->set("QUANTITY_NEEDED", $product->getQuantity())
|
||||
->set("QUANTITY_PROPOSED", $product->getNbOfProducts())
|
||||
->set('UNITY', $unity)
|
||||
;
|
||||
$loopResult->addRow($loopResultRow);
|
||||
$loopResultRow = new LoopResultRow($product);
|
||||
$loopResultRow
|
||||
->set("RECIPE_ID", $product->getRecipeId())
|
||||
->set("PSE_ID", $product->getPseId())
|
||||
->set("PRODUCT_ID", $productId)
|
||||
->set("IN_STOCK", $inStock > 0)
|
||||
->set("PRODUCT_LABEL", $productLabel)
|
||||
->set("QUANTITY_NEEDED", $product->getQuantity())
|
||||
->set("QUANTITY_PROPOSED", $product->getNbOfProducts())
|
||||
->set('UNITY', $unity)
|
||||
;
|
||||
$loopResult->addRow($loopResultRow);
|
||||
}
|
||||
catch (PropelException $e) {
|
||||
throw new PropelException("Erreur dans l'alimentation de la ProductsLoop : " . $e);
|
||||
}
|
||||
}
|
||||
return $loopResult;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<td>{$UNITY}</td>
|
||||
<td>{$QUANTITY_PROPOSED}</td>
|
||||
<td class="text-center">
|
||||
<a href="{url path='/admin/module/Recettes/remove-product/%recipeId/%pseId' recipeId=$recipe_id pseId=$PSE_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>
|
||||
</tr>
|
||||
{/loop}
|
||||
@@ -26,9 +26,19 @@
|
||||
</tr>
|
||||
{/elseloop}
|
||||
|
||||
<tr>
|
||||
<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">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<input class="form-control" type="text" id="pse_id" autocomplete="off" data-content-id="{$pse_id}" placeholder="Choisissez une déclinaison">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<input class="form-control" type="text" id="product_ref" autocomplete="off" data-content-id="{$content_id}" placeholder="Indiquez une référence de produit">
|
||||
<input class="form-control" type="text" id="quantity" autocomplete="off" placeholder="Saisir une quantité">
|
||||
</td>
|
||||
<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>
|
||||
|
||||
1
local/modules/Recettes/templates/backOffice/default/js/bootstrap-typeahead.min.js
vendored
Normal file
1
local/modules/Recettes/templates/backOffice/default/js/bootstrap-typeahead.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,81 @@
|
||||
<script src="{javascript file="js/bootstrap-typeahead.min.js" source="Recettes"}"></script>
|
||||
|
||||
<script>
|
||||
{$langcode = {lang attr="code"}|substr:0:2}
|
||||
|
||||
$(function() {
|
||||
|
||||
function setupTypeAhead() {
|
||||
|
||||
$('#product_ref').typeahead({
|
||||
source: function (query, process) {
|
||||
return $.getJSON(
|
||||
'{url path="/admin/module/Recettes/search-product"}',
|
||||
{
|
||||
query: query
|
||||
},
|
||||
function (data) {
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
$('#pse_id').typeahead({
|
||||
source: function (query, process) {
|
||||
return $.getJSON(
|
||||
'{url path="/admin/module/Recettes/search-combination"}',
|
||||
{
|
||||
query: query
|
||||
},
|
||||
function (data) {
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$(document).on('click', '.add-product', function(event) {
|
||||
event.preventDefault();
|
||||
|
||||
$('#related-products-block').load(
|
||||
$(this).attr('href'),
|
||||
{
|
||||
product_id: $('#product_ref').data('product-id')
|
||||
},
|
||||
function() {
|
||||
setupTypeAhead();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
setupTypeAhead();
|
||||
$("#pse_id").attr('disabled', 'disabled');
|
||||
$("#quantity").attr('disabled', 'disabled');
|
||||
$(".add-product").attr('disabled', 'disabled');
|
||||
|
||||
});
|
||||
</script>
|
||||
@@ -115,12 +115,12 @@
|
||||
<div class="col-md-4 form-group">
|
||||
<label class="control-label">Produits attachés</label>
|
||||
<div id="related-products-block">
|
||||
{include file='ajax/related-products.html'}
|
||||
{include file="ajax/related-products.html" content_id=$content_id}
|
||||
</div>
|
||||
<br>
|
||||
<label class="control-label">Etapes de la recette</label>
|
||||
<div id="steps-block">
|
||||
{include file='ajax/steps.html'}
|
||||
{include file="ajax/steps.html"}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -110,12 +110,9 @@ div.entete span b {
|
||||
}
|
||||
.table-liste-recettes th {
|
||||
text-align: center !important;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.table-liste-recettes > tbody > tr > td:nth-child(1),
|
||||
.table-liste-recettes > tbody > tr > td:nth-child(2),
|
||||
.table-liste-recettes > tbody > tr > td:nth-child(4),
|
||||
.table-liste-recettes th:nth-child(1),
|
||||
.table-liste-recettes th:nth-child(3) {
|
||||
.table-liste-recettes th {
|
||||
background-color: rgba(128,189,138,0.12);
|
||||
}
|
||||
.table-liste-recettes > tbody > tr > td,
|
||||
|
||||
Reference in New Issue
Block a user