added section name for meta-fields positioning (#5747)

This commit is contained in:
Kevin Papst
2025-12-26 12:54:15 +01:00
committed by GitHub
parent 26361da873
commit 5a0c783a76
10 changed files with 101 additions and 52 deletions

View File

@@ -12,8 +12,8 @@ namespace App\Entity;
use Doctrine\Common\Collections\Collection; use Doctrine\Common\Collections\Collection;
/** /**
* @method getTags() array * @method array<Tag> getTags()
* @method getBreak() int * @method int getBreak()
*/ */
interface ExportableItem interface ExportableItem
{ {

View File

@@ -11,6 +11,10 @@ namespace App\Entity;
use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Constraint;
/**
* @method null|string getSection()
* @method void setSection(?string $name)
*/
interface MetaTableTypeInterface interface MetaTableTypeInterface
{ {
/** /**
@@ -43,6 +47,8 @@ interface MetaTableTypeInterface
/** /**
* This will merge the current object with the values from the given $meta instance. * This will merge the current object with the values from the given $meta instance.
* It should NOT update the name or value, but only the form settings. * It should NOT update the name or value, but only the form settings.
*
* Settings from the given $meta object will win over the current ones.
*/ */
public function merge(MetaTableTypeInterface $meta): MetaTableTypeInterface; public function merge(MetaTableTypeInterface $meta): MetaTableTypeInterface;
@@ -132,6 +138,16 @@ interface MetaTableTypeInterface
*/ */
public function getOrder(): int; public function getOrder(): int;
/**
* FIXME activate with 3.0
*/
//public function setSection(?string $section): void;
/**
* FIXME activate with 3.0
*/
//public function getSection(): ?string;
/** /**
* Whether true if this field is defined by a plugin, or false if it is a value stored in the database. * Whether true if this field is defined by a plugin, or false if it is a value stored in the database.
*/ */

View File

@@ -67,6 +67,7 @@ trait MetaTableTypeTrait
*/ */
private mixed $data = null; private mixed $data = null;
private bool $updated = false; private bool $updated = false;
private ?string $section = null;
public function getName(): ?string public function getName(): ?string
{ {
@@ -193,13 +194,11 @@ trait MetaTableTypeTrait
public function merge(MetaTableTypeInterface $meta): MetaTableTypeInterface public function merge(MetaTableTypeInterface $meta): MetaTableTypeInterface
{ {
$this $this->setConstraints($meta->getConstraints());
->setConstraints($meta->getConstraints()) $this->setIsRequired($meta->isRequired());
->setIsRequired($meta->isRequired()) $this->setIsVisible($meta->isVisible());
->setIsVisible($meta->isVisible()) $this->setOptions($meta->getOptions());
->setOptions($meta->getOptions()) $this->setOrder($meta->getOrder());
->setOrder($meta->getOrder())
;
if ($meta->getLabel() !== null) { if ($meta->getLabel() !== null) {
$this->setLabel($meta->getLabel()); $this->setLabel($meta->getLabel());
@@ -209,6 +208,10 @@ trait MetaTableTypeTrait
$this->setType($meta->getType()); $this->setType($meta->getType());
} }
if ($meta->getSection() !== null) {
$this->setSection($meta->getSection());
}
return $this; return $this;
} }
@@ -266,6 +269,16 @@ trait MetaTableTypeTrait
} }
} }
public function setSection(?string $section): void
{
$this->section = $section;
}
public function getSection(): ?string
{
return $this->section;
}
/** /**
* Whether this field is defined by a plugin or just a value stored in the database. * Whether this field is defined by a plugin or just a value stored in the database.
*/ */

View File

@@ -14,9 +14,9 @@ use App\Repository\Query\TimesheetQuery;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
/** /**
* TODO change interface for 3.0 * FIXME change interface for 3.0
* @method getType() string * @method string getType()
* @method isInternal() bool * @method bool isInternal()
*/ */
interface ExportRendererInterface interface ExportRendererInterface
{ {

View File

@@ -8,6 +8,7 @@
'back': path('admin_activity') 'back': path('admin_activity')
} %} } %}
{% embed formEditTemplate with formOptions %} {% embed formEditTemplate with formOptions %}
{% import "macros/form_helper.html.twig" as form_helper %}
{% block form_body %} {% block form_body %}
<div class="row"> <div class="row">
<div class="col-md-9"> <div class="col-md-9">
@@ -49,6 +50,18 @@
</div> </div>
</div> </div>
{% endif %} {% endif %}
{{ form_helper.metafields(form, null) }}
{% embed '@theme/embeds/collapsible.html.twig' with {id: 'activity_invoice_settings'} %}
{% import "macros/widgets.html.twig" as widgets %}
{% import "macros/form_helper.html.twig" as form_helper %}
{% block title %}{{ 'invoices'|trans }}{% endblock %}
{% block body %}
{% if form.invoiceText is defined %}
{{ form_row(form.invoiceText) }}
{% endif %}
{{ form_helper.metafields(form, 'invoice') }}
{% endblock %}
{% endembed %}
<div class="row"> <div class="row">
<div class="col-md-6"> <div class="col-md-6">
{{ form_row(form.visible) }} {{ form_row(form.visible) }}
@@ -57,18 +70,6 @@
{{ form_row(form.billable) }} {{ form_row(form.billable) }}
</div> </div>
</div> </div>
{% if form.metaFields is defined and form.metaFields is not empty %}
{{ form_row(form.metaFields) }}
{% endif %}
{% embed '@theme/embeds/collapsible.html.twig' with {id: 'activity_invoice_settings'} %}
{% import "macros/widgets.html.twig" as widgets %}
{% block title %}{{ 'invoices'|trans }}{% endblock %}
{% block body %}
{% if form.invoiceText is defined %}
{{ form_row(form.invoiceText) }}
{% endif %}
{% endblock %}
{% endembed %}
{{ form_rest(form) }} {{ form_rest(form) }}
{% endblock %} {% endblock %}
{% endembed %} {% endembed %}

View File

@@ -8,6 +8,7 @@
'back': path('admin_customer') 'back': path('admin_customer')
} %} } %}
{% embed formEditTemplate with formOptions %} {% embed formEditTemplate with formOptions %}
{% import "macros/form_helper.html.twig" as form_helper %}
{% block form_body %} {% block form_body %}
<div class="row"> <div class="row">
<div class="col-md-9"> <div class="col-md-9">
@@ -75,11 +76,10 @@
</div> </div>
</div> </div>
{% endif %} {% endif %}
{% if form.metaFields is defined and form.metaFields is not empty %} {{ form_helper.metafields(form, null) }}
{{ form_row(form.metaFields) }}
{% endif %}
{% embed '@theme/embeds/collapsible.html.twig' with {id: 'customer_address_settings'} %} {% embed '@theme/embeds/collapsible.html.twig' with {id: 'customer_address_settings'} %}
{% import "macros/widgets.html.twig" as widgets %} {% import "macros/widgets.html.twig" as widgets %}
{% import "macros/form_helper.html.twig" as form_helper %}
{% block title %}{{ 'address'|trans }}{% endblock %} {% block title %}{{ 'address'|trans }}{% endblock %}
{% block body %} {% block body %}
<div class="row"> <div class="row">
@@ -125,11 +125,12 @@
{{ form_row(form.timezone) }} {{ form_row(form.timezone) }}
</div> </div>
</div> </div>
{{ form_helper.metafields(form, 'address') }}
{% endblock %} {% endblock %}
{% endembed %} {% endembed %}
{% embed '@theme/embeds/collapsible.html.twig' with {id: 'customer_invoice_settings'} %} {% embed '@theme/embeds/collapsible.html.twig' with {id: 'customer_invoice_settings'} %}
{% import "macros/widgets.html.twig" as widgets %} {% import "macros/widgets.html.twig" as widgets %}
{% import "macros/form_helper.html.twig" as form_helper %}
{% block title %}{{ 'invoices'|trans }}{% endblock %} {% block title %}{{ 'invoices'|trans }}{% endblock %}
{% block body %} {% block body %}
{% if form.buyerReference is defined %} {% if form.buyerReference is defined %}
@@ -141,6 +142,7 @@
{% if form.invoiceText is defined %} {% if form.invoiceText is defined %}
{{ form_row(form.invoiceText) }} {{ form_row(form.invoiceText) }}
{% endif %} {% endif %}
{{ form_helper.metafields(form, 'invoice') }}
{% endblock %} {% endblock %}
{% endembed %} {% endembed %}
<div class="row"> <div class="row">

View File

@@ -474,7 +474,9 @@
{%- block meta_fields_collection_widget -%} {%- block meta_fields_collection_widget -%}
{% for meta in form|sort((a, b) => a.vars.data.order <=> b.vars.data.order) %} {% for meta in form|sort((a, b) => a.vars.data.order <=> b.vars.data.order) %}
{{ form_row(meta.value, {'row_attr': {'class': 'mb-3 ' ~ form.parent.vars.name ~ '_row_' ~ form.vars.name ~ '_' ~ meta.vars.name}}) }} {% if not meta.rendered %}
{{ form_row(meta.value, {'row_attr': {'class': 'mb-3 ' ~ form.parent.vars.name ~ '_row_' ~ form.vars.name ~ '_' ~ meta.vars.name}}) }}
{% endif %}
{% endfor %} {% endfor %}
{%- endblock meta_fields_collection_widget %} {%- endblock meta_fields_collection_widget %}

View File

@@ -0,0 +1,7 @@
{% macro metafields(form, section) %}
{% for meta in form.metaFields|sort((a, b) => a.vars.data.order <=> b.vars.data.order) %}
{% if meta.vars.data.section is same as (section) %}
{{ form_row(meta.value, {'row_attr': {'class': 'mb-3 ' ~ form.vars.name ~ '_row_' ~ form.metaFields.vars.name ~ '_' ~ meta.vars.name}}) }}
{% endif %}
{% endfor %}
{% endmacro %}

View File

@@ -8,6 +8,7 @@
'back': path('admin_project') 'back': path('admin_project')
} %} } %}
{% embed formEditTemplate with formOptions %} {% embed formEditTemplate with formOptions %}
{% import "macros/form_helper.html.twig" as form_helper %}
{% block form_body %} {% block form_body %}
<div class="row"> <div class="row">
<div class="col-md-9"> <div class="col-md-9">
@@ -58,11 +59,10 @@
</div> </div>
</div> </div>
{% endif %} {% endif %}
{% if form.metaFields is defined and form.metaFields is not empty %} {{ form_helper.metafields(form, null) }}
{{ form_row(form.metaFields) }}
{% endif %}
{% embed '@theme/embeds/collapsible.html.twig' with {id: 'project_invoice_settings'} %} {% embed '@theme/embeds/collapsible.html.twig' with {id: 'project_invoice_settings'} %}
{% import "macros/widgets.html.twig" as widgets %} {% import "macros/widgets.html.twig" as widgets %}
{% import "macros/form_helper.html.twig" as form_helper %}
{% block title %}{{ 'invoices'|trans }}{% endblock %} {% block title %}{{ 'invoices'|trans }}{% endblock %}
{% block body %} {% block body %}
<div class="row"> <div class="row">
@@ -76,6 +76,7 @@
{% if form.invoiceText is defined %} {% if form.invoiceText is defined %}
{{ form_row(form.invoiceText) }} {{ form_row(form.invoiceText) }}
{% endif %} {% endif %}
{{ form_helper.metafields(form, 'invoice') }}
{% endblock %} {% endblock %}
{% endembed %} {% endembed %}
<div class="row"> <div class="row">

View File

@@ -38,6 +38,7 @@ abstract class AbstractMetaEntityTestCase extends TestCase
self::assertFalse($sut->isVisible()); self::assertFalse($sut->isVisible());
self::assertFalse($sut->isRequired()); self::assertFalse($sut->isRequired());
self::assertEquals(0, $sut->getOrder()); self::assertEquals(0, $sut->getOrder());
self::assertNull($sut->getSection());
} }
public function testSetterAndGetter(): void public function testSetterAndGetter(): void
@@ -83,6 +84,11 @@ abstract class AbstractMetaEntityTestCase extends TestCase
$entity = $this->getEntity(); $entity = $this->getEntity();
self::assertInstanceOf(MetaTableTypeInterface::class, $sut->setEntity($entity)); self::assertInstanceOf(MetaTableTypeInterface::class, $sut->setEntity($entity));
self::assertSame($entity, $sut->getEntity()); self::assertSame($entity, $sut->getEntity());
$sut->setSection('foo');
self::assertEquals('foo', $sut->getSection());
$sut->setSection(null);
self::assertNull($sut->getSection());
} }
public function testMerge(): void public function testMerge(): void
@@ -90,18 +96,19 @@ abstract class AbstractMetaEntityTestCase extends TestCase
$entity1 = $this->getEntity(); $entity1 = $this->getEntity();
$entity2 = $this->getEntity(); $entity2 = $this->getEntity();
$meta1 = $this->getMetaEntity(); $meta1 = $this->getMetaEntity();
$meta1 $meta1->setName('foo');
->setName('foo') $meta1->setValue('bar');
->setValue('bar') $meta1->setType('blub');
->setType('blub') $meta1->setEntity($entity1);
->setEntity($entity1) $meta1->setConstraints([new NotNull()]);
->setConstraints([new NotNull()]) $meta1->setOptions(['foo' => 'bar', 'bar' => 'foo']);
->setOptions(['foo' => 'bar', 'bar' => 'foo']) $meta1->setSection('hello');
;
self::assertEquals('foo', $meta1->getName()); self::assertEquals('foo', $meta1->getName());
self::assertEquals('bar', $meta1->getValue()); self::assertEquals('bar', $meta1->getValue());
self::assertEquals('blub', $meta1->getType()); self::assertEquals('blub', $meta1->getType());
self::assertEquals('foo', $meta1->getLabel()); self::assertEquals('foo', $meta1->getLabel());
self::assertEquals('hello', $meta1->getSection());
self::assertFalse($meta1->isRequired()); self::assertFalse($meta1->isRequired());
self::assertFalse($meta1->isVisible()); self::assertFalse($meta1->isVisible());
self::assertSame($entity1, $meta1->getEntity()); self::assertSame($entity1, $meta1->getEntity());
@@ -109,18 +116,17 @@ abstract class AbstractMetaEntityTestCase extends TestCase
self::assertCount(2, $meta1->getOptions()); self::assertCount(2, $meta1->getOptions());
$meta2 = $this->getMetaEntity(); $meta2 = $this->getMetaEntity();
$meta2 $meta2->setName('foo2');
->setName('foo2') $meta2->setLabel('TRALALA');
->setLabel('TRALALA') $meta2->setValue('bar2');
->setValue('bar2') $meta2->setType('blub2');
->setType('blub2') $meta2->setSection('world');
->setEntity($entity2) $meta2->setEntity($entity2);
->setIsRequired(true) $meta2->setIsRequired(true);
->setIsVisible(true) $meta2->setIsVisible(true);
->setOrder(93) $meta2->setOrder(93);
->setConstraints([new NotBlank(), new Length(['min' => 1])]) $meta2->setConstraints([new NotBlank(), new Length(['min' => 1])]);
->setOptions(['foo1' => 'bar1']) $meta2->setOptions(['foo1' => 'bar1']);
;
self::assertInstanceOf(MetaTableTypeInterface::class, $meta1->merge($meta2)); self::assertInstanceOf(MetaTableTypeInterface::class, $meta1->merge($meta2));
@@ -128,6 +134,7 @@ abstract class AbstractMetaEntityTestCase extends TestCase
self::assertEquals('bar', $meta1->getValue()); self::assertEquals('bar', $meta1->getValue());
self::assertEquals('blub2', $meta1->getType()); self::assertEquals('blub2', $meta1->getType());
self::assertEquals('TRALALA', $meta1->getLabel()); self::assertEquals('TRALALA', $meta1->getLabel());
self::assertEquals('world', $meta1->getSection());
self::assertEquals(93, $meta1->getOrder()); self::assertEquals(93, $meta1->getOrder());
self::assertTrue($meta1->isRequired()); self::assertTrue($meta1->isRequired());
self::assertTrue($meta1->isVisible()); self::assertTrue($meta1->isVisible());