Added basic label generation dialog.

This commit is contained in:
Jan Böhmer 2020-04-16 19:56:30 +02:00
parent ea0d72bfbb
commit a4e1a17b4a
12 changed files with 230 additions and 5 deletions

View file

@ -21,12 +21,21 @@
namespace App\Controller;
use App\Entity\Base\AbstractDBElement;
use App\Entity\Contracts\NamedElementInterface;
use App\Entity\LabelSystem\LabelOptions;
use App\Entity\LabelSystem\LabelProfile;
use App\Entity\Parts\Part;
use App\Form\LabelOptionsType;
use App\Form\LabelSystem\LabelDialogType;
use App\Helpers\LabelResponse;
use App\Services\ElementTypeNameGenerator;
use App\Services\LabelSystem\LabelGenerator;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\SubmitButton;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\Routing\Annotation\Route;
@ -38,10 +47,14 @@ use Symfony\Component\Routing\Annotation\Route;
class LabelController extends AbstractController
{
protected $labelGenerator;
protected $em;
protected $elementTypeNameGenerator;
public function __construct(LabelGenerator $labelGenerator)
public function __construct(LabelGenerator $labelGenerator, EntityManagerInterface $em, ElementTypeNameGenerator $elementTypeNameGenerator)
{
$this->labelGenerator = $labelGenerator;
$this->em = $em;
$this->elementTypeNameGenerator = $elementTypeNameGenerator;
}
/**
@ -56,4 +69,68 @@ class LabelController extends AbstractController
return $response;
}
/**
* @Route("/dialog", name="label_dialog")
* @Route("/{profile}/dialog")
*/
public function generator(Request $request, ?LabelProfile $profile = null)
{
if ($profile) {
$label_options = $profile->getOptions();
} else {
$label_options = new LabelOptions();
}
$form = $this->createForm(LabelDialogType::class);
//Try to parse given target_type and target_id
$target_type = $request->query->get('target_type', null);
$target_id = $request->query->get('target_id', null);
if ($profile === null && is_string($target_type)) {
$label_options->setSupportedElement($target_type);
}
if (is_numeric($target_id)) {
$form['target_id']->setData((int) $target_id);
}
$form['options']->setData($label_options);
$form->handleRequest($request);
/** @var LabelOptions $form_options */
$form_options = $form['options']->getData();
$pdf_data = null;
$filename = 'invalid.pdf';
if ($form->isSubmitted() && $form->isValid()) {
$target_id = (int) $form->get('target_id')->getData();
$target = $this->findObject($form_options->getSupportedElement(), $target_id);
$pdf_data = $this->labelGenerator->generateLabel($form_options, $target);
$filename = $this->getLabelName($target, $profile);
}
return $this->render('LabelSystem/dialog.html.twig', [
'form' => $form->createView(),
'pdf_data' => $pdf_data,
'filename' => $filename,
]);
}
protected function getLabelName(AbstractDBElement $element, ?LabelProfile $profile = null): string
{
$ret = 'label_' . $this->elementTypeNameGenerator->getLocalizedTypeLabel($element);
$ret .= $element->getID();
return $ret . '.pdf';
}
protected function findObject(string $type, int $id): object
{
if(!isset(LabelGenerator::CLASS_SUPPORT_MAPPING[$type])) {
throw new \InvalidArgumentException('The given type is not known and can not be mapped to a class!');
}
return $this->em->find(LabelGenerator::CLASS_SUPPORT_MAPPING[$type], $id);
}
}

View file

@ -29,7 +29,7 @@ use Symfony\Component\Validator\Constraints as Assert;
class LabelOptions
{
public const BARCODE_TYPES = ['none', /*'ean8',*/ 'qr', 'code39'];
public const SUPPORTED_ELEMENTS = ['part'];
public const SUPPORTED_ELEMENTS = ['part', 'part_lot'];
public const PICTURE_TYPES = ['none', 'element_picture', 'main_attachment'];
public const POSITIONS = ['left', 'right', 'top', 'bottom'];
public const FONTS = ['default'];

View file

@ -52,6 +52,14 @@ class LabelOptionsType extends AbstractType
]
]);
$builder->add('supported_element', ChoiceType::class, [
'label' => 'label_options.supported_elements.label',
'choices' => [
'part.label' => 'part',
'part_lot.label' => 'part_lot'
]
]);
$builder->add('barcode_type', ChoiceType::class, [
'label' => 'label_options.barcode_type.label',
'empty_data' => 'none',

View file

@ -0,0 +1,56 @@
<?php
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2020 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace App\Form\LabelSystem;
use App\Form\LabelOptionsType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\NumberType;
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;
use Symfony\Component\Validator\Constraints\Type;
class LabelDialogType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('target_id', NumberType::class, [
'html5' => true,
'required' => true,
'label' => 'label_generator.target_id.label'
]);
$builder->add('options', LabelOptionsType::class, [
'label' => false,
]);
$builder->add('update', SubmitType::class, [
]);
}
public function configureOptions(OptionsResolver $resolver)
{
parent::configureOptions($resolver);
$resolver->setDefault('mapped', 'false');
}
}

View file

@ -24,14 +24,16 @@ namespace App\Services\LabelSystem;
use App\Entity\Contracts\NamedElementInterface;
use App\Entity\LabelSystem\LabelOptions;
use App\Entity\Parts\Part;
use App\Entity\Parts\PartLot;
use App\Services\ElementTypeNameGenerator;
use Dompdf\Dompdf;
use Twig\Environment;
class LabelGenerator
{
protected const CLASS_SUPPORT_MAPPING = [
public const CLASS_SUPPORT_MAPPING = [
'part' => Part::class,
'part_lot' => PartLot::class,
];
public const MM_TO_POINTS_FACTOR = 2.83465;

View file

@ -40,7 +40,7 @@ class LabelHTMLGenerator
public function getLabelHTML(LabelOptions $options, object $element): string
{
return $this->twig->render('labels/base_label.html.twig', [
return $this->twig->render('LabelSystem/labels/base_label.html.twig', [
'meta_title' => $this->getPDFTitle($options, $element),
'lines' => $this->replacer->replace($options->getLines(), $element),
]);

View file

@ -104,6 +104,7 @@ class ToolsTreeBuilder
$item->tag(['tree_tools', 'groups', $this->keyGenerator->generateKey()]);
$tree = [];
$tree[] = new TreeViewNode($this->translator->trans('tree.tools.tools'), null, $this->getToolsNode());
$tree[] = new TreeViewNode($this->translator->trans('tree.tools.edit'), null, $this->getEditNodes());
$tree[] = new TreeViewNode($this->translator->trans('tree.tools.show'), null, $this->getShowNodes());
$tree[] = new TreeViewNode($this->translator->trans('tree.tools.system'), null, $this->getSystemNodes());
@ -112,6 +113,18 @@ class ToolsTreeBuilder
});
}
protected function getToolsNode(): array
{
$nodes = [];
$nodes[] = new TreeViewNode(
$this->translator->trans('tree.tools.tools.label_dialog'),
$this->urlGenerator->generate('label_dialog')
);
return $nodes;
}
/**
* This functions creates a tree entries for the "edit" node of the tool's tree.
*

View file

@ -0,0 +1,40 @@
<?php
/**
* This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony).
*
* Copyright (C) 2019 - 2020 Jan Böhmer (https://github.com/jbtronics)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
namespace App\Twig;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
class DataInlinerExtension extends AbstractExtension
{
public function getFunctions()
{
return [
new TwigFunction('inlineData', [$this, 'inlineData'])
];
}
public function inlineData(string $data, string $mime_type)
{
return 'data:' . $mime_type . ';base64,' . base64_encode($data);
}
}

View file

@ -47,6 +47,7 @@
{% endblock %}
{% block label_options_widget %}
{{ form_row(form.supported_element) }}
<div class="form-group row">
{{ form_label(form.width) }}
<div class="input-group col-9">

View file

@ -0,0 +1,28 @@
{% extends 'main_card.html.twig' %}
{% block card_title %}<i class="fas fa-qrcode fa-fw"></i> {% trans %}label_generator.title{% endtrans %}{% endblock %}
{% block card_content %}
{{ form_start(form) }}
{{ form_row(form.target_id) }}
{{ form_widget(form.options) }}
{{ form_end(form) }}
{% if pdf_data %}
<div class="row">
<div class="col-sm-9 offset-sm-3">
<a data-no-ajax class="btn btn-secondary" href="#" onclick="this.href = document.getElementById('pdf_preview').data" download="{{ filename ?? '' }}">
{% trans %}label_generator.download{% endtrans %}
</a>
</div>
</div>
{% endif %}
{% endblock %}
{% block additional_content %}
{% if pdf_data %}
<div class="card mt-2 p-1 border-secondary" style="resize: vertical; overflow: scroll; height: 250px">
<object id="pdf_preview" data="{{ inlineData(pdf_data, 'application/pdf') | escape('html_attr') }}"style="height: inherit">
</object>
</div>
{% endif %}
{% endblock %}

View file

@ -7,7 +7,7 @@
<meta name="description" content="Label for {{ meta_title }}">
<meta name="keywords" content="Part-DB, Label, Barcode">
<style>
{% include("labels/label_style.css.twig") %}
{% include("LabelSystem/labels/label_style.css.twig") %}
</style>
</head>
<body>