Fixes
This commit is contained in:
parent
d598a9214f
commit
a2187a48b8
@ -474,7 +474,7 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator;
|
|||||||
* datetime?: array{
|
* datetime?: array{
|
||||||
* default_format?: scalar|null, // Default: "Y-m-d\\TH:i:sP"
|
* default_format?: scalar|null, // Default: "Y-m-d\\TH:i:sP"
|
||||||
* default_deserialization_formats?: list<scalar|null>,
|
* default_deserialization_formats?: list<scalar|null>,
|
||||||
* default_timezone?: scalar|null, // Default: "Europe/Berlin"
|
* default_timezone?: scalar|null, // Default: "UTC"
|
||||||
* cdata?: scalar|null, // Default: true
|
* cdata?: scalar|null, // Default: true
|
||||||
* },
|
* },
|
||||||
* array_collection?: array{
|
* array_collection?: array{
|
||||||
@ -574,7 +574,7 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator;
|
|||||||
* datetime?: array{
|
* datetime?: array{
|
||||||
* default_format?: scalar|null, // Default: "Y-m-d\\TH:i:sP"
|
* default_format?: scalar|null, // Default: "Y-m-d\\TH:i:sP"
|
||||||
* default_deserialization_formats?: list<scalar|null>,
|
* default_deserialization_formats?: list<scalar|null>,
|
||||||
* default_timezone?: scalar|null, // Default: "Europe/Berlin"
|
* default_timezone?: scalar|null, // Default: "UTC"
|
||||||
* cdata?: scalar|null, // Default: true
|
* cdata?: scalar|null, // Default: true
|
||||||
* },
|
* },
|
||||||
* array_collection?: array{
|
* array_collection?: array{
|
||||||
|
|||||||
@ -25,11 +25,11 @@
|
|||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="flex flex-col gap-6">
|
<div class="flex flex-col gap-6">
|
||||||
<div class="rounded-sm border bg-white px-7.5 py-6 shadow-lg dark:border-strokedark dark:bg-boxdark">
|
<div class="rounded-md border bg-white px-7.5 py-6 shadow-lg dark:border-strokedark dark:bg-boxdark">
|
||||||
<div class="mb-6 px-4">
|
<div class="mb-6 px-4">
|
||||||
{{ form_start(form, { 'attr': {'class': ''}}) }}
|
{{ form_start(form, { 'attr': {'class': ''}}) }}
|
||||||
<div class="flex items-center gap-6">
|
<div class="flex items-center gap-6">
|
||||||
<label class="font-medium text-gray-700 text-sm min-w-fit">
|
<label class="font-medium text-gray-700 text-sm min-w-fit dark:text-gray-300">
|
||||||
Suche:
|
Suche:
|
||||||
</label>
|
</label>
|
||||||
<div class="flex-1 max-w-xl">
|
<div class="flex-1 max-w-xl">
|
||||||
@ -61,58 +61,67 @@
|
|||||||
|
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<table class="min-w-full text-sm">
|
<table class="min-w-full text-sm">
|
||||||
<thead class="bg-slate-100 border-t border-stroke">
|
<thead class="bg-slate-50 dark:bg-gray-800">
|
||||||
<tr>
|
<tr class="border-b-2 border-gray-200 dark:border-gray-700">
|
||||||
<th class="px-2 py-3 text-left font-medium text-gray-700">{{ knp_pagination_sortable(pagination, 'Uid', 'contact.uid') }}</th>
|
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">{{ knp_pagination_sortable(pagination, 'Uid', 'contact.uid') }}</th>
|
||||||
<th class="px-2 py-3 text-left font-medium text-gray-700">{{ knp_pagination_sortable(pagination, 'Loginname'|trans, 'contact.username') }}</th>
|
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">{{ knp_pagination_sortable(pagination, 'Loginname'|trans, 'contact.username') }}</th>
|
||||||
<th class="px-2 py-3 text-left font-medium text-gray-700">{{ knp_pagination_sortable(pagination, 'generated'|trans, 'contact.createdAt') }}</th>
|
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">{{ knp_pagination_sortable(pagination, 'generated'|trans, 'contact.createdAt') }}</th>
|
||||||
<th class="px-2 py-3 text-left font-medium text-gray-700">{{ knp_pagination_sortable(pagination, 'changed'|trans, 'contact.updatedAt') }}</th>
|
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">{{ knp_pagination_sortable(pagination, 'changed'|trans, 'contact.updatedAt') }}</th>
|
||||||
<th class="px-2 py-3 text-left font-medium text-gray-700">{{ knp_pagination_sortable(pagination, 'firstname'|trans, 'contact.selffirstname') }}</th>
|
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">{{ knp_pagination_sortable(pagination, 'firstname'|trans, 'contact.selffirstname') }}</th>
|
||||||
<th class="px-2 py-3 text-left font-medium text-gray-700">{{ knp_pagination_sortable(pagination, 'lastname'|trans, 'contact.lastname') }}</th>
|
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">{{ knp_pagination_sortable(pagination, 'lastname'|trans, 'contact.lastname') }}</th>
|
||||||
<th class="px-2 py-3 text-left font-medium text-gray-700">{{ knp_pagination_sortable(pagination, 'street'|trans, 'contact.street') }}/{{ knp_pagination_sortable(pagination, 'housenumber'|trans, 'contact.houseNumber') }}</th>
|
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">{{ knp_pagination_sortable(pagination, 'street'|trans, 'contact.street') }}/{{ knp_pagination_sortable(pagination, 'housenumber'|trans, 'contact.houseNumber') }}</th>
|
||||||
<th class="px-2 py-3 text-left font-medium text-gray-700">{{ knp_pagination_sortable(pagination, 'zip'|trans, 'contact.zip') }}</th>
|
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">{{ knp_pagination_sortable(pagination, 'zip'|trans, 'contact.zip') }}</th>
|
||||||
<th class="px-2 py-3 text-left font-medium text-gray-700">{{ knp_pagination_sortable(pagination, 'city'|trans, 'contact.city') }}</th>
|
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">{{ knp_pagination_sortable(pagination, 'city'|trans, 'contact.city') }}</th>
|
||||||
<th class="px-2 py-3 text-left font-medium text-gray-700">{{ 'virtual'|trans }}</th>
|
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">{{ 'virtual'|trans }}</th>
|
||||||
<th class="px-2 py-3 text-left font-medium text-gray-700">{{ 'shops'|trans }}</th>
|
<th class="px-4 py-4 text-left text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">{{ 'shops'|trans }}</th>
|
||||||
<th class="px-2 py-3 text-right font-medium text-gray-700">Aktionen</th>
|
<th class="px-4 py-4 text-right text-xs font-semibold text-gray-600 uppercase tracking-wider dark:text-gray-300">Aktionen</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody class="bg-white dark:bg-boxdark">
|
||||||
{% for contact in pagination %}
|
{% for contact in pagination %}
|
||||||
<tr class="border-t border-stroke hover:bg-gray-50">
|
<tr class="border-t border-gray-100 hover:bg-gray-50 dark:border-gray-700 dark:hover:bg-gray-800/50 transition-colors">
|
||||||
<td class="px-2 py-3 font-medium">{{ contact.id }}</td>
|
<td class="px-4 py-3">
|
||||||
<td class="px-2 py-3">
|
<a href="{{ path("psc_shop_contact_backend_edit", {uuid: contact.uuid}) }}"
|
||||||
<a href="mailto:{{ contact.username }}" class="text-psc-500 hover:underline">{{ contact.username }}</a>
|
class="inline-flex items-center px-2.5 py-1 rounded-md text-xs font-mono font-medium bg-gray-100 text-gray-800 border border-gray-200 hover:bg-psc-50 hover:text-psc-700 hover:border-psc-300 transition-colors dark:bg-gray-700 dark:text-gray-300 dark:border-gray-600 dark:hover:bg-psc-900 dark:hover:text-psc-300">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-3.5 h-3.5 mr-1.5 text-gray-500 dark:text-gray-400">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M5.25 8.25h15m-16.5 7.5h15m-1.8-13.5l-3.9 19.5m-2.1-19.5l-3.9 19.5" />
|
||||||
|
</svg>
|
||||||
|
{{ contact.id }}
|
||||||
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-2 py-3 whitespace-nowrap">{{ contact.createdAt|date('d.m.Y') }}</td>
|
<td class="px-4 py-3">
|
||||||
<td class="px-2 py-3 whitespace-nowrap">{{ contact.updatedAt|date('d.m.Y') }}</td>
|
<a href="mailto:{{ contact.username }}" class="text-psc-500 hover:underline dark:text-psc-400">{{ contact.username }}</a>
|
||||||
<td class="px-2 py-3">{{ contact.firstname }}</td>
|
</td>
|
||||||
<td class="px-2 py-3">{{ contact.lastname }}</td>
|
<td class="px-4 py-3 text-gray-900 dark:text-gray-100 whitespace-nowrap">{{ contact.createdAt|date('d.m.Y') }}</td>
|
||||||
<td class="px-2 py-3">{{ contact.street }} {{ contact.houseNumber }}</td>
|
<td class="px-4 py-3 text-gray-900 dark:text-gray-100 whitespace-nowrap">{{ contact.updatedAt|date('d.m.Y') }}</td>
|
||||||
<td class="px-2 py-3">{{ contact.zip }}</td>
|
<td class="px-4 py-3 text-gray-900 dark:text-gray-100">{{ contact.firstname }}</td>
|
||||||
<td class="px-2 py-3">{{ contact.city }}</td>
|
<td class="px-4 py-3 font-medium text-gray-900 dark:text-gray-100">{{ contact.lastname }}</td>
|
||||||
<td class="px-2 py-3">
|
<td class="px-4 py-3 text-gray-900 dark:text-gray-100">{{ contact.street }} {{ contact.houseNumber }}</td>
|
||||||
|
<td class="px-4 py-3 text-gray-900 dark:text-gray-100">{{ contact.zip }}</td>
|
||||||
|
<td class="px-4 py-3 text-gray-900 dark:text-gray-100">{{ contact.city }}</td>
|
||||||
|
<td class="px-4 py-3">
|
||||||
{% if contact.virtual == 1 %}
|
{% if contact.virtual == 1 %}
|
||||||
<div class="badge-yes">{{ 'yes'|trans }}</div>
|
<span class="badge-yes">{{ 'yes'|trans }}</span>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="badge-no">{{ 'no'|trans }}</div>
|
<span class="badge-no">{{ 'no'|trans }}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-2 py-3">
|
<td class="px-4 py-3">
|
||||||
{% if contact.shops|length > 1 %}
|
{% if contact.shops|length > 1 %}
|
||||||
<div class="flex flex-wrap gap-1">
|
<div class="flex flex-wrap gap-1">
|
||||||
{% for shop in contact.shops %}
|
{% for shop in contact.shops %}
|
||||||
<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800">{{ shop.title }}</span>
|
<span class="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200">{{ shop.title }}</span>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="badge-no">{{ 'no'|trans }}</div>
|
<span class="badge-no">{{ 'no'|trans }}</span>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-2 py-3 text-right">
|
<td class="px-4 py-3 text-right">
|
||||||
<div class="flex flex-row gap-2 justify-end">
|
<div class="flex flex-row gap-2 justify-end">
|
||||||
<a href="{{ path("psc_shop_contact_backend_edit", {uuid: contact.uuid}) }}" class="">
|
{# Bearbeiten - GRÜN #}
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="table-icon">
|
<a href="{{ path("psc_shop_contact_backend_edit", {uuid: contact.uuid}) }}" title="{{'edit'|trans}}">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="table-icon text-green-600 hover:text-green-700 dark:text-green-500 dark:hover:text-green-400">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10" />
|
<path stroke-linecap="round" stroke-linejoin="round" d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L10.582 16.07a4.5 4.5 0 01-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 011.13-1.897l8.932-8.931zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0115.75 21H5.25A2.25 2.25 0 013 18.75V8.25A2.25 2.25 0 015.25 6H10" />
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@ -63,6 +63,32 @@ class GetSettings
|
|||||||
$setting->setTabPositions($tabPositions);
|
$setting->setTabPositions($tabPositions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure OCR markers are initialized
|
||||||
|
if (empty($setting->getOcrMarkers())) {
|
||||||
|
$ocrMarkers = [];
|
||||||
|
for ($i = 1; $i <= 4; $i++) {
|
||||||
|
$marker = new \Plugin\Custom\PSC\LaufkartenLayouter\Model\OcrMarker();
|
||||||
|
$marker->setType('dot');
|
||||||
|
$marker->setLabel("Dot {$i}");
|
||||||
|
$marker->setX(0.0);
|
||||||
|
$marker->setY(0.0);
|
||||||
|
$ocrMarkers[] = $marker;
|
||||||
|
}
|
||||||
|
$textMarker = new \Plugin\Custom\PSC\LaufkartenLayouter\Model\OcrMarker();
|
||||||
|
$textMarker->setType('text');
|
||||||
|
$textMarker->setLabel('Text Position');
|
||||||
|
$textMarker->setX(0.0);
|
||||||
|
$textMarker->setY(0.0);
|
||||||
|
$ocrMarkers[] = $textMarker;
|
||||||
|
$triangleMarker = new \Plugin\Custom\PSC\LaufkartenLayouter\Model\OcrMarker();
|
||||||
|
$triangleMarker->setType('triangle');
|
||||||
|
$triangleMarker->setLabel('Triangle (Pfeil nach oben)');
|
||||||
|
$triangleMarker->setX(0.0);
|
||||||
|
$triangleMarker->setY(0.0);
|
||||||
|
$ocrMarkers[] = $triangleMarker;
|
||||||
|
$setting->setOcrMarkers($ocrMarkers);
|
||||||
|
}
|
||||||
|
|
||||||
// Serialize settings to JSON
|
// Serialize settings to JSON
|
||||||
$settingsJson = $serializer->serialize($setting, 'json');
|
$settingsJson = $serializer->serialize($setting, 'json');
|
||||||
|
|
||||||
|
|||||||
@ -56,6 +56,63 @@ class IndexController extends AbstractController
|
|||||||
$tabPositions[] = $tabPosition;
|
$tabPositions[] = $tabPosition;
|
||||||
}
|
}
|
||||||
$setting->setTabPositions($tabPositions);
|
$setting->setTabPositions($tabPositions);
|
||||||
|
|
||||||
|
// Initialize OCR markers (4 dots, 1 text, 1 triangle)
|
||||||
|
$ocrMarkers = [];
|
||||||
|
|
||||||
|
// 4 Dots
|
||||||
|
for ($i = 1; $i <= 4; $i++) {
|
||||||
|
$marker = new \Plugin\Custom\PSC\LaufkartenLayouter\Model\OcrMarker();
|
||||||
|
$marker->setType('dot');
|
||||||
|
$marker->setLabel("Dot {$i}");
|
||||||
|
$marker->setX(0.0);
|
||||||
|
$marker->setY(0.0);
|
||||||
|
$ocrMarkers[] = $marker;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1 Text
|
||||||
|
$textMarker = new \Plugin\Custom\PSC\LaufkartenLayouter\Model\OcrMarker();
|
||||||
|
$textMarker->setType('text');
|
||||||
|
$textMarker->setLabel('Text Position');
|
||||||
|
$textMarker->setX(0.0);
|
||||||
|
$textMarker->setY(0.0);
|
||||||
|
$ocrMarkers[] = $textMarker;
|
||||||
|
|
||||||
|
// 1 Triangle
|
||||||
|
$triangleMarker = new \Plugin\Custom\PSC\LaufkartenLayouter\Model\OcrMarker();
|
||||||
|
$triangleMarker->setType('triangle');
|
||||||
|
$triangleMarker->setLabel('Triangle (Pfeil nach oben)');
|
||||||
|
$triangleMarker->setX(0.0);
|
||||||
|
$triangleMarker->setY(0.0);
|
||||||
|
$ocrMarkers[] = $triangleMarker;
|
||||||
|
|
||||||
|
$setting->setOcrMarkers($ocrMarkers);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure OCR markers are initialized even when loading from DB
|
||||||
|
if (empty($setting->getOcrMarkers())) {
|
||||||
|
$ocrMarkers = [];
|
||||||
|
for ($i = 1; $i <= 4; $i++) {
|
||||||
|
$marker = new \Plugin\Custom\PSC\LaufkartenLayouter\Model\OcrMarker();
|
||||||
|
$marker->setType('dot');
|
||||||
|
$marker->setLabel("Dot {$i}");
|
||||||
|
$marker->setX(0.0);
|
||||||
|
$marker->setY(0.0);
|
||||||
|
$ocrMarkers[] = $marker;
|
||||||
|
}
|
||||||
|
$textMarker = new \Plugin\Custom\PSC\LaufkartenLayouter\Model\OcrMarker();
|
||||||
|
$textMarker->setType('text');
|
||||||
|
$textMarker->setLabel('Text Position');
|
||||||
|
$textMarker->setX(0.0);
|
||||||
|
$textMarker->setY(0.0);
|
||||||
|
$ocrMarkers[] = $textMarker;
|
||||||
|
$triangleMarker = new \Plugin\Custom\PSC\LaufkartenLayouter\Model\OcrMarker();
|
||||||
|
$triangleMarker->setType('triangle');
|
||||||
|
$triangleMarker->setLabel('Triangle (Pfeil nach oben)');
|
||||||
|
$triangleMarker->setX(0.0);
|
||||||
|
$triangleMarker->setY(0.0);
|
||||||
|
$ocrMarkers[] = $triangleMarker;
|
||||||
|
$setting->setOcrMarkers($ocrMarkers);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create tab positions form
|
// Create tab positions form
|
||||||
|
|||||||
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Plugin\Custom\PSC\LaufkartenLayouter\Form;
|
||||||
|
|
||||||
|
use Symfony\Component\Form\AbstractType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\NumberType;
|
||||||
|
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||||
|
use Symfony\Component\Form\FormBuilderInterface;
|
||||||
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||||
|
|
||||||
|
class OcrMarker extends AbstractType
|
||||||
|
{
|
||||||
|
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||||
|
{
|
||||||
|
$builder
|
||||||
|
->add('type', ChoiceType::class, [
|
||||||
|
'label' => 'Type',
|
||||||
|
'choices' => [
|
||||||
|
'Dot (Punkt)' => 'dot',
|
||||||
|
'Text' => 'text',
|
||||||
|
'Triangle (Dreieck)' => 'triangle',
|
||||||
|
],
|
||||||
|
'attr' => ['readonly' => true],
|
||||||
|
])
|
||||||
|
->add('label', TextType::class, [
|
||||||
|
'label' => 'Label',
|
||||||
|
'attr' => ['readonly' => true],
|
||||||
|
])
|
||||||
|
->add('x', NumberType::class, [
|
||||||
|
'label' => 'X Position',
|
||||||
|
'scale' => 1,
|
||||||
|
'html5' => true,
|
||||||
|
'attr' => ['step' => '0.1'],
|
||||||
|
])
|
||||||
|
->add('y', NumberType::class, [
|
||||||
|
'label' => 'Y Position',
|
||||||
|
'scale' => 1,
|
||||||
|
'html5' => true,
|
||||||
|
'attr' => ['step' => '0.1'],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function configureOptions(OptionsResolver $resolver): void
|
||||||
|
{
|
||||||
|
$resolver->setDefaults([
|
||||||
|
'data_class' => \Plugin\Custom\PSC\LaufkartenLayouter\Model\OcrMarker::class,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -101,6 +101,13 @@ class TabPositions extends AbstractType
|
|||||||
'allow_delete' => true,
|
'allow_delete' => true,
|
||||||
'by_reference' => false,
|
'by_reference' => false,
|
||||||
'label' => 'Tab Positions',
|
'label' => 'Tab Positions',
|
||||||
|
])
|
||||||
|
->add('ocrMarkers', CollectionType::class, [
|
||||||
|
'entry_type' => OcrMarker::class,
|
||||||
|
'allow_add' => false,
|
||||||
|
'allow_delete' => false,
|
||||||
|
'by_reference' => false,
|
||||||
|
'label' => 'OCR Markers',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Plugin\Custom\PSC\LaufkartenLayouter\Model;
|
||||||
|
|
||||||
|
class OcrMarker
|
||||||
|
{
|
||||||
|
private string $type; // 'dot', 'text', 'triangle'
|
||||||
|
private string $label;
|
||||||
|
private float $x = 0.0;
|
||||||
|
private float $y = 0.0;
|
||||||
|
|
||||||
|
public function getType(): string
|
||||||
|
{
|
||||||
|
return $this->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setType(string $type): self
|
||||||
|
{
|
||||||
|
$this->type = $type;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLabel(): string
|
||||||
|
{
|
||||||
|
return $this->label;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setLabel(string $label): self
|
||||||
|
{
|
||||||
|
$this->label = $label;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getX(): float
|
||||||
|
{
|
||||||
|
return $this->x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setX(float $x): self
|
||||||
|
{
|
||||||
|
$this->x = $x;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getY(): float
|
||||||
|
{
|
||||||
|
return $this->y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setY(float $y): self
|
||||||
|
{
|
||||||
|
$this->y = $y;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -22,6 +22,11 @@ class Setting
|
|||||||
*/
|
*/
|
||||||
private array $tabPositions = [];
|
private array $tabPositions = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var OcrMarker[]
|
||||||
|
*/
|
||||||
|
private array $ocrMarkers = [];
|
||||||
|
|
||||||
public function getOrientation(): string
|
public function getOrientation(): string
|
||||||
{
|
{
|
||||||
return $this->orientation;
|
return $this->orientation;
|
||||||
@ -175,4 +180,15 @@ class Setting
|
|||||||
$this->tabPositions = $tabPositions;
|
$this->tabPositions = $tabPositions;
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getOcrMarkers(): array
|
||||||
|
{
|
||||||
|
return $this->ocrMarkers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setOcrMarkers(array $ocrMarkers): self
|
||||||
|
{
|
||||||
|
$this->ocrMarkers = $ocrMarkers;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,6 +38,16 @@
|
|||||||
aria-controls="positions"
|
aria-controls="positions"
|
||||||
aria-selected="false">Tab Positionen</button>
|
aria-selected="false">Tab Positionen</button>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item" role="presentation">
|
||||||
|
<button class="nav-link"
|
||||||
|
id="ocr-markers-tab"
|
||||||
|
data-bs-toggle="tab"
|
||||||
|
data-bs-target="#ocr-markers"
|
||||||
|
type="button"
|
||||||
|
role="tab"
|
||||||
|
aria-controls="ocr-markers"
|
||||||
|
aria-selected="false">OCR Marker</button>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
{{ form_start(tabPositionsForm) }}
|
{{ form_start(tabPositionsForm) }}
|
||||||
@ -222,6 +232,75 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="tab-pane"
|
||||||
|
id="ocr-markers"
|
||||||
|
role="tabpanel"
|
||||||
|
aria-labelledby="ocr-markers-tab">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="card d-flex">
|
||||||
|
<div class="card-header">
|
||||||
|
OCR Marker Positionen
|
||||||
|
<span class="badge bg-info float-end">4 Dots + 1 Text + 1 Dreieck</span>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="text-muted mb-3">
|
||||||
|
<i class="fas fa-info-circle"></i>
|
||||||
|
Definieren Sie die Positionen für OCR-Erkennung: 4 Punkte (Dots), 1 Text-Position und 1 Dreieck (Pfeil nach oben).
|
||||||
|
Diese Marker werden für die automatische Erkennung der Meldegruppe verwendet.
|
||||||
|
</p>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-striped table-bordered">
|
||||||
|
<thead class="table-dark">
|
||||||
|
<tr>
|
||||||
|
<th style="width: 15%">Type</th>
|
||||||
|
<th style="width: 25%">Label</th>
|
||||||
|
<th style="width: 30%">X Position ({{ setting.unit }})</th>
|
||||||
|
<th style="width: 30%">Y Position ({{ setting.unit }})</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for ocrMarker in tabPositionsForm.ocrMarkers %}
|
||||||
|
<tr>
|
||||||
|
<td class="align-middle">
|
||||||
|
{% if ocrMarker.vars.data.type == 'dot' %}
|
||||||
|
<span class="badge bg-primary"><i class="fas fa-circle"></i> Dot</span>
|
||||||
|
{% elseif ocrMarker.vars.data.type == 'text' %}
|
||||||
|
<span class="badge bg-success"><i class="fas fa-font"></i> Text</span>
|
||||||
|
{% elseif ocrMarker.vars.data.type == 'triangle' %}
|
||||||
|
<span class="badge bg-warning"><i class="fas fa-caret-up"></i> Dreieck</span>
|
||||||
|
{% endif %}
|
||||||
|
{{ form_widget(ocrMarker.type, {'attr': {'class': 'd-none'}}) }}
|
||||||
|
</td>
|
||||||
|
<td class="align-middle">
|
||||||
|
<strong>{{ ocrMarker.vars.data.label }}</strong>
|
||||||
|
{{ form_widget(ocrMarker.label, {'attr': {'class': 'd-none'}}) }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ form_widget(ocrMarker.x, {'attr': {'class': 'form-control', 'placeholder': '0.0'}}) }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ form_widget(ocrMarker.y, {'attr': {'class': 'form-control', 'placeholder': '0.0'}}) }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div class="col-12 text-end">
|
||||||
|
<button type="submit" class="btn btn-success">
|
||||||
|
<i class="fas fa-save"></i> OCR Marker speichern
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{ form_end(tabPositionsForm) }}
|
{{ form_end(tabPositionsForm) }}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user