Compare commits
6 Commits
8ccba31bf4
...
81bf848698
Author | SHA1 | Date |
---|---|---|
![]() |
81bf848698 | 1 month ago |
![]() |
a278133eeb | 1 month ago |
![]() |
eb9844fe70 | 1 month ago |
![]() |
c30a8735b8 | 2 months ago |
![]() |
625f9fceb8 | 2 months ago |
![]() |
0198efa503 | 2 months ago |
@ -0,0 +1,31 @@
|
|||||||
|
import 'jqueryLocal';
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
const machineExtraInfo1 = $('#recipe_edit_form_machineExtraInfo1');
|
||||||
|
const machineExtraInfo1_div = machineExtraInfo1.parents('div.row').first();
|
||||||
|
const machineExtraInfo1_label = machineExtraInfo1_div.find('label[for="' + machineExtraInfo1.attr('id') + '"]')
|
||||||
|
|
||||||
|
const machineExtraInfo2 = $('#recipe_edit_form_machineExtraInfo2');
|
||||||
|
const machineExtraInfo2_div = machineExtraInfo2.parents('div.row').first();
|
||||||
|
const machineExtraInfo2_label = machineExtraInfo2_div.find('label[for="' + machineExtraInfo2.attr('id') + '"]')
|
||||||
|
|
||||||
|
$('#recipe_edit_form_machine')
|
||||||
|
.on('change', function () {
|
||||||
|
const machine = $(this)
|
||||||
|
.find(':selected')
|
||||||
|
.dataDefault(
|
||||||
|
'machine',
|
||||||
|
{
|
||||||
|
labelExtraInfo1: null,
|
||||||
|
labelExtraInfo2: null,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
machineExtraInfo1_div.toggleClass('d-none', machine.labelExtraInfo1 === null);
|
||||||
|
machineExtraInfo1_label.text(machine.labelExtraInfo1);
|
||||||
|
|
||||||
|
machineExtraInfo2_div.toggleClass('d-none', machine.labelExtraInfo2 === null);
|
||||||
|
machineExtraInfo2_label.text(machine.labelExtraInfo2);
|
||||||
|
})
|
||||||
|
.trigger('change');
|
||||||
|
});
|
@ -0,0 +1,40 @@
|
|||||||
|
import 'jqueryLocal';
|
||||||
|
import {Tooltip} from 'bootstrap';
|
||||||
|
|
||||||
|
$(function () {
|
||||||
|
$(document).on('click', '.collection-add', function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const button = $(this);
|
||||||
|
//region Ajoute la ligne
|
||||||
|
const collectionId = button.data('collection');
|
||||||
|
const collection = $('#' + collectionId);
|
||||||
|
|
||||||
|
const deleteButton = $(`#${collectionId}__collection_entry_add-delete_button > *`);
|
||||||
|
|
||||||
|
const rowPrototypePlaceholder = collection.data('prototypePlaceholder');
|
||||||
|
const rowPrototypeIndex = collection.data('prototypeIndex');
|
||||||
|
const rowPrototypeRaw = collection.data('prototypeCode').replaceAll(new RegExp(rowPrototypePlaceholder, 'g'), rowPrototypeIndex);
|
||||||
|
const rowPrototype = $(rowPrototypeRaw);
|
||||||
|
const rowPrototypeDiv = rowPrototype.find('#' + collectionId + '_' + rowPrototypeIndex);
|
||||||
|
rowPrototypeDiv.append(deleteButton.clone());
|
||||||
|
|
||||||
|
rowPrototype.insertBefore(button.parents('.row').first());
|
||||||
|
collection.data('prototypeIndex', rowPrototypeIndex + 1);
|
||||||
|
//endregion
|
||||||
|
});
|
||||||
|
$(document).on('click', '.collection-row-delete', function (event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const button = $(this);
|
||||||
|
//region Masque le tooltip (si existant) du bouton, car celui-ci va être supprimé en même temps que sa ligne
|
||||||
|
const buttonTooltip = Tooltip.getInstance(button);
|
||||||
|
if (buttonTooltip !== null) {
|
||||||
|
buttonTooltip.hide();
|
||||||
|
}
|
||||||
|
//endregion
|
||||||
|
//region Supprime la ligne
|
||||||
|
button.parents('.collection-row').parent().parent().remove();
|
||||||
|
//endregion
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20250603101350 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
DROP INDEX UNIQ_DA88B1375E237E06 ON recipe
|
||||||
|
SQL);
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
ALTER TABLE recipe DROP name
|
||||||
|
SQL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
ALTER TABLE recipe ADD name VARCHAR(50) NOT NULL
|
||||||
|
SQL);
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
CREATE UNIQUE INDEX UNIQ_DA88B1375E237E06 ON recipe (name)
|
||||||
|
SQL);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Schema\Schema;
|
||||||
|
use Doctrine\Migrations\AbstractMigration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-generated Migration: Please modify to your needs!
|
||||||
|
*/
|
||||||
|
final class Version20250606142337 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function getDescription(): string
|
||||||
|
{
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function up(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this up() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
CREATE UNIQUE INDEX UNIQ_77575DA759D8A214E308AC6F ON input_recipe_material (recipe_id, material_id)
|
||||||
|
SQL);
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
CREATE UNIQUE INDEX UNIQ_CB0D94B259D8A214E308AC6F ON output_recipe_material (recipe_id, material_id)
|
||||||
|
SQL);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
DROP INDEX UNIQ_77575DA759D8A214E308AC6F ON input_recipe_material
|
||||||
|
SQL);
|
||||||
|
$this->addSql(<<<'SQL'
|
||||||
|
DROP INDEX UNIQ_CB0D94B259D8A214E308AC6F ON output_recipe_material
|
||||||
|
SQL);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,101 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controller\Config;
|
||||||
|
|
||||||
|
use App\Entity\Recipe;
|
||||||
|
use App\Form\Config\RecipeEditForm;
|
||||||
|
use App\Misc\FlashType;
|
||||||
|
use App\Repository\RecipeRepository;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
|
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller for the configuration pages of material
|
||||||
|
*/
|
||||||
|
#[Route('/Config/Recipe')]
|
||||||
|
#[IsGranted('IS_AUTHENTICATED')]
|
||||||
|
class RecipeController extends AbstractController {
|
||||||
|
/**
|
||||||
|
* @var EntityManagerInterface The entity manager
|
||||||
|
*/
|
||||||
|
private readonly EntityManagerInterface $entityManager;
|
||||||
|
/**
|
||||||
|
* @var RecipeRepository The recipe repository
|
||||||
|
*/
|
||||||
|
private readonly RecipeRepository $recipeRepository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialization
|
||||||
|
*
|
||||||
|
* @param EntityManagerInterface $entityManager The entity manager
|
||||||
|
* @param RecipeRepository $recipeRepository The material repository
|
||||||
|
*/
|
||||||
|
public function __construct (EntityManagerInterface $entityManager, RecipeRepository $recipeRepository) {
|
||||||
|
$this->entityManager = $entityManager;
|
||||||
|
$this->recipeRepository = $recipeRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of materials
|
||||||
|
*
|
||||||
|
* @return Response The response
|
||||||
|
*/
|
||||||
|
#[Route('/', name: 'config_recipe_list', alias: 'config_recipe')]
|
||||||
|
public function list (): Response {
|
||||||
|
return $this->render(
|
||||||
|
'Config/Recipe/List.html.twig',
|
||||||
|
[
|
||||||
|
'recipes' => $this->recipeRepository->findAll(),
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edit/Create a recipe
|
||||||
|
*
|
||||||
|
* @param Request $request The request
|
||||||
|
* @param Recipe|null $recipe The recipe to edit
|
||||||
|
*
|
||||||
|
* @return Response The response
|
||||||
|
*/
|
||||||
|
#[Route('/Create', name: 'config_recipe_create')]
|
||||||
|
#[Route('/Edit-{id}', name: 'config_recipe_edit')]
|
||||||
|
public function edit (Request $request, ?Recipe $recipe = null): Response {
|
||||||
|
$recipe ??= new Recipe();
|
||||||
|
|
||||||
|
$form = $this->createForm(RecipeEditForm::class, $recipe);
|
||||||
|
$form->handleRequest($request);
|
||||||
|
if ($form->isSubmitted() && $form->isValid()) {
|
||||||
|
$this->entityManager->persist($recipe);
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
$this->addFlash(FlashType::SUCCESS, 'La recette a bien été enregistré.');
|
||||||
|
return $this->redirectToRoute('config_recipe_list');
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->render('Config/Recipe/Edit.html.twig', [
|
||||||
|
'recipe' => $recipe,
|
||||||
|
'form' => $form->createView(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a recipe
|
||||||
|
*
|
||||||
|
* @param Recipe $recipe The recipe to delete
|
||||||
|
*
|
||||||
|
* @return Response The response
|
||||||
|
*/
|
||||||
|
#[Route('/Delete-{id}', name: 'config_recipe_delete')]
|
||||||
|
public function delete (Recipe $recipe): Response {
|
||||||
|
$this->entityManager->remove($recipe);
|
||||||
|
$this->entityManager->flush();
|
||||||
|
|
||||||
|
$this->addFlash(FlashType::SUCCESS, 'La recette a bien été supprimée.');
|
||||||
|
return $this->redirectToRoute('config_recipe_list');
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Form\Config;
|
||||||
|
|
||||||
|
use App\Entity\InputRecipeMaterial;
|
||||||
|
use App\Repository\MaterialRepository;
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\ButtonType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The form for an input material of a recipe
|
||||||
|
*/
|
||||||
|
class InputRecipeMaterialForm extends AbstractType {
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function configureOptions (OptionsResolver $resolver): void {
|
||||||
|
$resolver->setDefaults(
|
||||||
|
[
|
||||||
|
'data_class' => InputRecipeMaterial::class,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function buildForm (FormBuilderInterface $builder, array $options): void {
|
||||||
|
$builder
|
||||||
|
->add('material', null, [
|
||||||
|
'label' => 'Matériau',
|
||||||
|
//'query_builder' => function (MaterialRepository $materialRepository): QueryBuilder {
|
||||||
|
// return $materialRepository->createQueryBuilder('m')
|
||||||
|
// ->orderBy('m.name');
|
||||||
|
//},
|
||||||
|
])
|
||||||
|
->add('consumedQuantity', null, [
|
||||||
|
'label' => 'Quantité consommée',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Form\Config;
|
||||||
|
|
||||||
|
use App\Entity\OutputRecipeMaterial;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The form for an output material of a recipe
|
||||||
|
*/
|
||||||
|
class OutputRecipeMaterialForm extends AbstractType {
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function configureOptions (OptionsResolver $resolver): void {
|
||||||
|
$resolver->setDefaults(
|
||||||
|
[
|
||||||
|
'data_class' => OutputRecipeMaterial::class,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function buildForm (FormBuilderInterface $builder, array $options): void {
|
||||||
|
$builder
|
||||||
|
->add('material', null, [
|
||||||
|
'label' => 'Matériau',
|
||||||
|
])
|
||||||
|
->add('producedQuantity', null, [
|
||||||
|
'label' => 'Quantité produite',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Form\Config;
|
||||||
|
|
||||||
|
use App\Entity\Machine;
|
||||||
|
use App\Entity\Recipe;
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\CollectionType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The form for editing a recipe
|
||||||
|
*/
|
||||||
|
class RecipeEditForm extends AbstractType {
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function configureOptions (OptionsResolver $resolver): void {
|
||||||
|
$resolver->setDefaults(
|
||||||
|
[
|
||||||
|
'data_class' => Recipe::class,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritDoc
|
||||||
|
*/
|
||||||
|
public function buildForm (FormBuilderInterface $builder, array $options): void {
|
||||||
|
$builder
|
||||||
|
->add('machine', null, [
|
||||||
|
'label' => 'Machine',
|
||||||
|
'choice_attr' => function (Machine $machine, string $index, string $machineId): array {
|
||||||
|
return [
|
||||||
|
'data-machine' => json_encode([
|
||||||
|
'labelExtraInfo1' => $machine->getLabelExtraInfo1(),
|
||||||
|
'labelExtraInfo2' => $machine->getLabelExtraInfo2(),
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
},
|
||||||
|
])
|
||||||
|
->add('machineExtraInfo1', TextType::class, [
|
||||||
|
'label' => 'Information complémentaire n° 1',
|
||||||
|
'required' => false,
|
||||||
|
'row_attr' => [
|
||||||
|
'class' => 'd-none mb-3',
|
||||||
|
],
|
||||||
|
])
|
||||||
|
->add('machineExtraInfo2', null, [
|
||||||
|
'label' => 'Information complémentaire n° 2',
|
||||||
|
'required' => false,
|
||||||
|
'row_attr' => [
|
||||||
|
'class' => 'd-none mb-3',
|
||||||
|
],
|
||||||
|
])
|
||||||
|
->add('craftingTime', null, [
|
||||||
|
'label' => 'Temps de production',
|
||||||
|
])
|
||||||
|
->add('consumedMaterials', CollectionType::class, [
|
||||||
|
'label' => 'Matériaux consommés',
|
||||||
|
'entry_type' => InputRecipeMaterialForm::class,
|
||||||
|
'entry_options' => [
|
||||||
|
'label' => false,
|
||||||
|
],
|
||||||
|
'allow_add' => true,
|
||||||
|
'allow_delete' => true,
|
||||||
|
'by_reference' => false,
|
||||||
|
])
|
||||||
|
->add('producedMaterials', CollectionType::class, [
|
||||||
|
'label' => 'Matériaux produits',
|
||||||
|
'entry_type' => OutputRecipeMaterialForm::class,
|
||||||
|
'entry_options' => [
|
||||||
|
'label' => false,
|
||||||
|
],
|
||||||
|
'allow_add' => true,
|
||||||
|
'allow_delete' => true,
|
||||||
|
'by_reference' => false,
|
||||||
|
])
|
||||||
|
->add('submit', SubmitType::class, [
|
||||||
|
'label' => 'Enregistrer',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
|
{% block title %}{% if recipe.id is null %}Création {% else %}Modification{% endif %} recette - {{ parent() }}{% endblock %}
|
||||||
|
|
||||||
|
{% block mainContent %}
|
||||||
|
<h1>
|
||||||
|
{% if recipe.id is null %}
|
||||||
|
Création nouvelle recette
|
||||||
|
{% else %}
|
||||||
|
Modification d'une recette
|
||||||
|
{% endif %}
|
||||||
|
</h1>
|
||||||
|
{{ form(form) }}
|
||||||
|
<a href="{{ path('config_recipe_list') }}" class="btn btn-danger">Annuler</a>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block importmap %}
|
||||||
|
{{ importmap(['app', 'config_recipe_edit']) }}
|
||||||
|
{% endblock %}
|
||||||
|
|
@ -0,0 +1,95 @@
|
|||||||
|
{% extends '/base.html.twig' %}
|
||||||
|
|
||||||
|
{% block title %}Liste des recettes - {{ parent() }}{% endblock %}
|
||||||
|
{% block importmap %}{{ importmap(['app', 'datatables2']) }}{% endblock %}
|
||||||
|
|
||||||
|
{% block mainContent %}
|
||||||
|
<h1>Liste des recettes</h1>
|
||||||
|
<div class="d-flex">
|
||||||
|
<div class="table-responsive mnw-25">
|
||||||
|
<table class="table table-sm table-striped table-hover table-bordered table-datatable2 align-middle">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col" data-sort-onLoad="1" class="align-middle">Matériaux produits</th>
|
||||||
|
<th scope="col" class="align-middle">Machine</th>
|
||||||
|
<th scope="col" class="align-middle">Matériaux consommés</th>
|
||||||
|
<th scope="col" data-sort="false" class="fit-content align-middle">
|
||||||
|
<a href="{{ path('config_recipe_create') }}" class="btn btn-primary" data-bs-toggle="tooltip" data-bs-title="Ajouter">
|
||||||
|
<i class="fa-solid fa-square-plus"></i>
|
||||||
|
</a>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for recipe in recipes %}
|
||||||
|
{% set machine = recipe.machine %}
|
||||||
|
{% set firstExtraInfo = true %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{% for producedMaterial in recipe.producedMaterials %}
|
||||||
|
{% if not loop.first %}<br>{% endif %}{{ producedMaterial }}
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
{% if machine.labelExtraInfo1 is not null or machine.labelExtraInfo2 is not null %}
|
||||||
|
data-bs-toggle="tooltip"
|
||||||
|
data-bs-html="true"
|
||||||
|
data-bs-title="
|
||||||
|
{% for extraInfo in 1..2 %}
|
||||||
|
{% if machine.('labelExtraInfo' ~ extraInfo) is not null %}
|
||||||
|
{% if firstExtraInfo %}
|
||||||
|
{% set firstExtraInfo = false %}
|
||||||
|
{% else %}
|
||||||
|
<br>
|
||||||
|
{% endif %}
|
||||||
|
{{ machine.('labelExtraInfo' ~ extraInfo) }} = {{ recipe.('machineExtraInfo' ~ extraInfo) }}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
"
|
||||||
|
{% endif %}
|
||||||
|
>
|
||||||
|
{{ machine }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{% for consumedMaterial in recipe.consumedMaterials %}
|
||||||
|
{% if not loop.first %}<br>{% endif %}{{ consumedMaterial }}
|
||||||
|
{% endfor %}
|
||||||
|
</td>
|
||||||
|
<td class="fit-content">
|
||||||
|
<a href="{{ path('config_recipe_edit', {id: recipe.id}) }}"
|
||||||
|
class="text-primary me-2"
|
||||||
|
data-bs-toggle="tooltip"
|
||||||
|
data-bs-title="Éditer"
|
||||||
|
><i class="fa-solid fa-pen"></i></a>
|
||||||
|
<a href="#" class="text-danger" id="btDelete" data-bs-toggle="tooltip" data-bs-title="Supprimer">
|
||||||
|
<span data-bs-toggle="modal"
|
||||||
|
data-bs-target="#deleteConfirmation"
|
||||||
|
data-modal-dynamic-link-url="{{ path('config_recipe_delete', {id: recipe.id}) }}"
|
||||||
|
><i class="fa-solid fa-xmark"></i></span>
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal modal-dynamic fade" id="deleteConfirmation" tabindex="-1" aria-label="btDelete" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h1 class="modal-title fs-5">Suppression</h1>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
Êtes-vous sûr de vouloir supprimer ce matériau ?
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Non</button>
|
||||||
|
<a href="#" class="modal-confirm-link btn btn-danger">Oui</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
@ -0,0 +1,227 @@
|
|||||||
|
{% use "bootstrap_5_horizontal_layout.html.twig" %}
|
||||||
|
|
||||||
|
{% block collection_widget %}
|
||||||
|
{% if prototype is defined and not prototype.rendered %}
|
||||||
|
{% set attr = attr|merge({
|
||||||
|
'data-prototype-code': form_row(prototype),
|
||||||
|
'data-prototype-placeholder': prototype.vars.name,
|
||||||
|
'data-prototype-index': prototype.parent.children|length > 0 ? prototype.parent.children|last.vars.name + 1 : 0,
|
||||||
|
}) %}
|
||||||
|
{% endif %}
|
||||||
|
{{ block('form_widget') }}
|
||||||
|
{% endblock collection_widget %}
|
||||||
|
|
||||||
|
{% block collection_entry_row %}
|
||||||
|
{% if expanded is defined and expanded %}
|
||||||
|
{{ block('fieldset_form_row') }}
|
||||||
|
{% else %}
|
||||||
|
{% set widget_attr = {context_collection_entry: true} %}
|
||||||
|
{% if help is not empty %}
|
||||||
|
{% set widget_attr = {attr: {'aria-describedby': id ~"_help"}} %}
|
||||||
|
{% endif %}
|
||||||
|
{% set row_class = row_class|default(row_attr.class|default('mb-3')) %}
|
||||||
|
{% set is_form_floating = is_form_floating|default('form-floating' in row_class) %}
|
||||||
|
{% set is_input_group = is_input_group|default('input-group' in row_class) %}
|
||||||
|
{#- Remove behavior class from the main container -#}
|
||||||
|
{% set row_class = row_class|replace({'form-floating': '', 'input-group': ''}) %}
|
||||||
|
<div{% with {attr: row_attr|merge({class: (row_class ~ ' row' ~ ((not compound or force_error|default(false)) and not valid ? ' is-invalid'))|trim})} %}{{ block('attributes') }}{% endwith %}>
|
||||||
|
{% if is_form_floating or is_input_group %}
|
||||||
|
<div class="{{ block('form_label_class') }}"></div>
|
||||||
|
<div class="{{ block('form_group_class') }}">
|
||||||
|
{% if is_form_floating %}
|
||||||
|
<div class="form-floating">
|
||||||
|
{{ form_widget(form, widget_attr) }}
|
||||||
|
{{ form_label(form) }}
|
||||||
|
</div>
|
||||||
|
{% elseif is_input_group %}
|
||||||
|
<div class="input-group">
|
||||||
|
{{ form_label(form) }}
|
||||||
|
{{ form_widget(form, widget_attr) }}
|
||||||
|
{#- Hack to properly display help with input group -#}
|
||||||
|
{{ form_help(form) }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if not is_input_group %}
|
||||||
|
{{ form_help(form) }}
|
||||||
|
{% endif %}
|
||||||
|
{{ form_errors(form) }}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form_label(form) }}
|
||||||
|
<div class="{% if label is same as false %}col-sm-12{% else %}col-sm-10{% endif %}">
|
||||||
|
{{ form_widget(form, widget_attr) }}
|
||||||
|
{{ form_help(form) }}
|
||||||
|
{{ form_errors(form) }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
{% block collection_entry_label %}
|
||||||
|
{% if label is same as false %}
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
{{ block('form_label') }}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
{% block collection_entry_widget %}
|
||||||
|
{% set attr = {'class': 'row row-cols-lg-auto g-3 align-items-center collection-row'} %}
|
||||||
|
{{ block('form_widget') }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block collection_entry_add %}
|
||||||
|
<div class="mb-3 row">
|
||||||
|
<div class="col-12 column-gap-2">
|
||||||
|
<button type="button"
|
||||||
|
class="btn btn-primary collection-add"
|
||||||
|
data-bs-toggle="tooltip"
|
||||||
|
data-bs-title="Ajouter"
|
||||||
|
data-collection="{{ id }}"
|
||||||
|
>
|
||||||
|
<i class="fa-solid fa-square-plus"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
{% block collection_entry_delete %}
|
||||||
|
<div class="col-12 column-gap-2">
|
||||||
|
<button type="button"
|
||||||
|
class="btn btn-danger collection-row-delete"
|
||||||
|
data-bs-toggle="tooltip"
|
||||||
|
data-bs-title="Supprimer"
|
||||||
|
>
|
||||||
|
<i class="fa-solid fa-trash"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block form_rows %}
|
||||||
|
{% set child_vars = {} %}
|
||||||
|
{% if not context_collection_entry|default(false) %}
|
||||||
|
{% if allow_add is defined %}
|
||||||
|
{% set child_vars = child_vars|merge({'allow_add': allow_add}) %}
|
||||||
|
{% endif %}
|
||||||
|
{% if allow_delete is defined %}
|
||||||
|
{% set child_vars = child_vars|merge({'allow_delete': allow_delete}) %}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% if context_collection_entry is defined %}
|
||||||
|
{% set child_vars = child_vars|merge({'context_collection_entry': context_collection_entry}) %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% for child in form|filter(child => not child.rendered) %}
|
||||||
|
{{ form_row(child, child_vars) }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% if context_collection_entry|default(false) %}
|
||||||
|
{% if allow_delete|default(false) %}
|
||||||
|
{{ block('collection_entry_delete') }}
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
{% if allow_add|default(false) %}
|
||||||
|
{{ block('collection_entry_add') }}
|
||||||
|
<div id="{{ id }}__collection_entry_add-delete_button" class="d-none">
|
||||||
|
{{ block('collection_entry_delete') }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock form_rows %}
|
||||||
|
{% block form_row %}
|
||||||
|
{% set context_collection_entry = context_collection_entry|default(false) %}
|
||||||
|
{% if expanded is defined and expanded %}
|
||||||
|
{{ block('fieldset_form_row') }}
|
||||||
|
{% else %}
|
||||||
|
{% set widget_attr = {} %}
|
||||||
|
{% if help is not empty %}
|
||||||
|
{% set widget_attr = {attr: {'aria-describedby': id ~"_help"}} %}
|
||||||
|
{% endif %}
|
||||||
|
{% set row_class = row_class|default(row_attr.class|default(context_collection_entry ? '' : 'mb-3')) %}
|
||||||
|
{% set is_form_floating = is_form_floating|default('form-floating' in row_class) %}
|
||||||
|
{% set is_input_group = is_input_group|default('input-group' in row_class) %}
|
||||||
|
{#- Remove behavior class from the main container -#}
|
||||||
|
{% set row_class = row_class|replace({'form-floating': '', 'input-group': ''}) %}
|
||||||
|
<div
|
||||||
|
{% with {
|
||||||
|
attr: row_attr|merge({
|
||||||
|
class: (
|
||||||
|
row_class
|
||||||
|
~ (not context_collection_entry ? ' row' : ' col-12 d-flex column-gap-2')
|
||||||
|
~ ((not compound or force_error|default(false)) and not valid ? ' is-invalid')
|
||||||
|
)|trim
|
||||||
|
})
|
||||||
|
} %}
|
||||||
|
{{ block('attributes') }}
|
||||||
|
{% endwith %}
|
||||||
|
>
|
||||||
|
{% if is_form_floating or is_input_group %}
|
||||||
|
<div class="{{ block('form_label_class') }}"></div>
|
||||||
|
<div class="{{ block('form_group_class') }}">
|
||||||
|
{% if is_form_floating %}
|
||||||
|
<div class="form-floating">
|
||||||
|
{{ form_widget(form, widget_attr) }}
|
||||||
|
{{ form_label(form) }}
|
||||||
|
</div>
|
||||||
|
{% elseif is_input_group %}
|
||||||
|
<div class="input-group">
|
||||||
|
{{ form_label(form) }}
|
||||||
|
{{ form_widget(form, widget_attr) }}
|
||||||
|
{#- Hack to properly display help with input group -#}
|
||||||
|
{{ form_help(form) }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% if not is_input_group %}
|
||||||
|
{{ form_help(form) }}
|
||||||
|
{% endif %}
|
||||||
|
{{ form_errors(form) }}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{{ form_label(form) }}
|
||||||
|
<div class="{{ not context_collection_entry ? block('form_group_class') }}">
|
||||||
|
{{ form_widget(form, widget_attr) }}
|
||||||
|
{{ form_help(form) }}
|
||||||
|
{{ form_errors(form) }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock form_row %}
|
||||||
|
{% block form_label -%}
|
||||||
|
{% set context_collection_entry = context_collection_entry|default(false) %}
|
||||||
|
{%- if label is same as(false) -%}
|
||||||
|
<div class="{{ block('form_label_class') }}"></div>
|
||||||
|
{%- else -%}
|
||||||
|
{%- set row_class = row_class|default(row_attr.class|default('')) -%}
|
||||||
|
{%- if 'form-floating' not in row_class and 'input-group' not in row_class -%}
|
||||||
|
{%- if expanded is not defined or not expanded -%}
|
||||||
|
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' col-form-label')|trim}) -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ (not context_collection_entry ? block('form_label_class')))|trim}) -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{% if label is not same as(false) -%}
|
||||||
|
{%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%}
|
||||||
|
{%- if compound is defined and compound -%}
|
||||||
|
{%- set element = 'legend' -%}
|
||||||
|
{%- if 'col-form-label' not in parent_label_class -%}
|
||||||
|
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' col-form-label' )|trim}) -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- else -%}
|
||||||
|
{%- set row_class = row_class|default(row_attr.class|default('')) -%}
|
||||||
|
{%- set label_attr = label_attr|merge({for: id}) -%}
|
||||||
|
{%- if 'col-form-label' not in parent_label_class -%}
|
||||||
|
{%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ('input-group' in row_class ? ' input-group-text' : ' form-label') )|trim}) -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{% if label is not same as(false) -%}
|
||||||
|
{% if not compound -%}
|
||||||
|
{% set label_attr = label_attr|merge({'for': id}) %}
|
||||||
|
{%- endif -%}
|
||||||
|
{% if required -%}
|
||||||
|
{% set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' required')|trim}) %}
|
||||||
|
{%- endif -%}
|
||||||
|
<{{ element|default('label') }}{% if label_attr %}{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}{% endif %}>
|
||||||
|
{{- block('form_label_content') -}}
|
||||||
|
</{{ element|default('label') }}>
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endblock form_label %}
|
Loading…
Reference in New Issue