Added a basic dialog for editing/creating attachmentType elements.

This commit is contained in:
Jan Böhmer 2019-03-28 19:24:34 +01:00
parent 4652339879
commit 3e7150735d
12 changed files with 568 additions and 146 deletions

View file

@ -68,8 +68,12 @@ class AjaxUI {
* Starts the ajax ui und execute handlers registered in addStartAction(). * Starts the ajax ui und execute handlers registered in addStartAction().
* Should be called in a document.ready, after handlers are set. * Should be called in a document.ready, after handlers are set.
*/ */
public start() public start(disabled : boolean = false)
{ {
if(disabled) {
return;
}
console.info("AjaxUI started!"); console.info("AjaxUI started!");
this.BASE = $("body").data("base-url") + "/"; this.BASE = $("body").data("base-url") + "/";
@ -227,6 +231,19 @@ class AjaxUI {
{ {
let options : JQueryFormOptions = { let options : JQueryFormOptions = {
success: this.onAjaxComplete, success: this.onAjaxComplete,
beforeSerialize: function() : boolean {
//Update the content of textarea fields using CKEDITOR before submitting.
//@ts-ignore
for(let name in CKEDITOR.instances)
{
//@ts-ignore
CKEDITOR.instances[name].updateElement();
}
return true;
},
beforeSubmit: function (arr, $form, options) : boolean { beforeSubmit: function (arr, $form, options) : boolean {
//When data-with-progbar is specified, then show progressbar. //When data-with-progbar is specified, then show progressbar.
if($form.data("with-progbar") != undefined) { if($form.data("with-progbar") != undefined) {

View file

@ -0,0 +1,97 @@
<?php
/**
*
* part-db version 0.1
* Copyright (C) 2005 Christoph Lechner
* http://www.cl-projects.de/
*
* part-db version 0.2+
* Copyright (C) 2009 K. Jacobs and others (see authors.php)
* http://code.google.com/p/part-db/
*
* Part-DB Version 0.4+
* Copyright (C) 2016 - 2019 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 General Public License
* as published by the Free Software Foundation; either version 2
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
namespace App\Controller;
use App\Entity\AttachmentType;
use App\Form\BaseEntityAdminForm;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
/**
* @Route("/attachment_type")
* @package App\Controller
*/
class AttachmentTypeController extends AbstractController
{
/**
* @Route("/{id}/edit", requirements={"id"="\d+"}, name="attachment_type_edit")
* @Route("/{id}/", requirements={"id"="\d+"})
*/
public function edit(AttachmentType $entity, Request $request, EntityManagerInterface $em)
{
$form = $this->createForm(BaseEntityAdminForm::class, $entity);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em->persist($entity);
$em->flush();
}
return $this->render('AdminPages/AttachmentTypeAdmin.html.twig', [
'entity' => $entity,
'form' => $form->createView()
]);
}
/**
* @Route("/new")
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function new(Request $request, EntityManagerInterface $em)
{
$new_entity = new AttachmentType();
$this->denyAccessUnlessGranted('create', $new_entity);
$form = $this->createForm(BaseEntityAdminForm::class, $new_entity);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em->persist($new_entity);
$em->flush();
//$this->addFlash('success', $translator->trans('part.created_flash'));
return $this->redirectToRoute('attachment_type_edit', ['id' => $new_entity->getID()]);
}
return $this->render('AdminPages/AttachmentTypeAdmin.html.twig', [
'entity' => $new_entity,
'form' => $form->createView()
]);
}
}

View file

@ -23,6 +23,7 @@ declare(strict_types=1);
namespace App\Entity; namespace App\Entity;
use App\Validator\Constraints\NoneOfItsChildren;
use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;

View file

@ -50,9 +50,11 @@ abstract class DBElement
* Get the ID. The ID can be zero, or even negative (for virtual elements). If an elemenent is virtual, can be * Get the ID. The ID can be zero, or even negative (for virtual elements). If an elemenent is virtual, can be
* checked with isVirtualElement(). * checked with isVirtualElement().
* *
* @return int the ID of this element * Returns null, if the element is not saved to the DB yet.
*
* @return int|null the ID of this element
*/ */
final public function getID(): int final public function getID(): ?int
{ {
return (int) $this->id; return (int) $this->id;
} }

View file

@ -74,20 +74,22 @@ abstract class NamedDBElement extends DBElement
/** /**
* Returns the last time when the element was modified. * Returns the last time when the element was modified.
* Returns null if the element was not yet saved to DB yet.
* *
* @return \DateTime The time of the last edit. * @return \DateTime|null The time of the last edit.
*/ */
public function getLastModified(): \DateTime public function getLastModified(): ?\DateTime
{ {
return $this->lastModified; return $this->lastModified;
} }
/** /**
* Returns the date/time when the element was created. * Returns the date/time when the element was created.
* Returns null if the element was not yet saved to DB yet.
* *
* @return \DateTime The creation time of the part. * @return \DateTime|null The creation time of the part.
*/ */
public function getAddedDate(): \DateTime public function getAddedDate(): ?\DateTime
{ {
return $this->addedDate; return $this->addedDate;
} }

View file

@ -23,9 +23,9 @@ declare(strict_types=1);
namespace App\Entity; namespace App\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping as ORM;
use Doctrine\ORM\PersistentCollection; use Doctrine\ORM\PersistentCollection;
use App\Validator\Constraints\NoneOfItsChildren;
/** /**
* All elements with the fields "id", "name" and "parent_id" (at least). * All elements with the fields "id", "name" and "parent_id" (at least).
@ -53,6 +53,7 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement
protected $children; protected $children;
/** /**
* @var StructuralDBElement * @var StructuralDBElement
* @NoneOfItsChildren()
*/ */
protected $parent; protected $parent;
@ -97,10 +98,10 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement
//Check if both elements compared, are from the same type: //Check if both elements compared, are from the same type:
if ($class_name != \get_class($another_element)) { if ($class_name != \get_class($another_element)) {
throw new \InvalidArgumentException('isChildOf() funktioniert nur mit Elementen des gleichen Typs!'); throw new \InvalidArgumentException('isChildOf() only works for objects of the same type!');
} }
if (null == $this->getID()) { // this is the root node if (null == $this->getParent()) { // this is the root node
return false; return false;
} }
@ -116,13 +117,13 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement
******************************************************************************/ ******************************************************************************/
/** /**
* @brief Get the parent-ID * Get the parent-ID
* *
* @retval integer * the ID of the parent element * @return integer * the ID of the parent element
* * NULL means, the parent is the root node * * NULL means, the parent is the root node
* * the parent ID of the root node is -1 * * the parent ID of the root node is -1
*/ */
public function getParentID(): int protected function getParentID(): int
{ {
return $this->parent_id ?? self::ID_ROOT_ELEMENT; //Null means root element return $this->parent_id ?? self::ID_ROOT_ELEMENT; //Null means root element
} }
@ -139,14 +140,12 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement
/** /**
* Get the comment of the element. * Get the comment of the element.
*
* @param bool $parse_bbcode Should BBCode converted to HTML, before returning
*
* @return string the comment * @return string the comment
*/ */
public function getComment(bool $parse_bbcode = true): string public function getComment(): ?string
{ {
return htmlspecialchars($this->comment ?? ''); return $this->comment;
} }
/** /**
@ -179,8 +178,6 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement
* @param string $delimeter the delimeter of the returned string * @param string $delimeter the delimeter of the returned string
* *
* @return string the full path (incl. the name of this element), delimeted by $delimeter * @return string the full path (incl. the name of this element), delimeted by $delimeter
*
* @throws Exception if there was an error
*/ */
public function getFullPath(string $delimeter = self::PATH_DELIMITER_ARROW): string public function getFullPath(string $delimeter = self::PATH_DELIMITER_ARROW): string
{ {
@ -189,9 +186,13 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement
$this->full_path_strings[] = $this->getName(); $this->full_path_strings[] = $this->getName();
$element = $this; $element = $this;
while (null != $element->parent) { $overflow = 20; //We only allow 20 levels depth
while (null != $element->parent && $overflow >= 0) {
$element = $element->parent; $element = $element->parent;
$this->full_path_strings[] = $element->getName(); $this->full_path_strings[] = $element->getName();
//Decrement to prevent mem overflow.
$overflow--;
} }
$this->full_path_strings = array_reverse($this->full_path_strings); $this->full_path_strings = array_reverse($this->full_path_strings);
@ -219,143 +220,31 @@ abstract class StructuralDBElement extends AttachmentContainingDBElement
******************************************************************************/ ******************************************************************************/
/** /**
* Change the parent ID of this element. * Sets the new parent object
* * @param self $new_parent The new parent object
* @param int|null $new_parent_id * the ID of the new parent element * @return StructuralDBElement
* * NULL if the parent should be the root node
*/ */
public function setParentID($new_parent_id): self public function setParent(?self $new_parent) : self
{ {
$this->parent_id = $new_parent_id; /*
if ($new_parent->isChildOf($this)) {
throw new \InvalidArgumentException('You can not use one of the element childs as parent!');
} */
$this->parent = $new_parent;
return $this; return $this;
} }
/** /**
* Set the comment. * Set the comment.
*
* @param string $new_comment the new comment * @param string $new_comment the new comment
* * @return StructuralDBElement
* @throws Exception if there was an error
*/ */
public function setComment(string $new_comment): self public function setComment(?string $new_comment): self
{ {
$this->comment = $new_comment; $this->comment = $new_comment;
return $this; return $this;
} }
/********************************************************************************
*
* Tree / Table Builders
*
*********************************************************************************/
/**
* Build a HTML tree with all subcategories of this element.
*
* This method prints a <option>-Line for every item.
* <b>The <select>-tags are not printed here, you have to print them yourself!</b>
* Deeper levels have more spaces in front.
*
* @param int $selected_id the ID of the selected item
* @param bool $recursive if true, the tree will be recursive
* @param bool $show_root if true, the root node will be displayed
* @param string $root_name if the root node is the very root element, you can set its name here
* @param string $value_prefix This string is used as a prefix before the id in the value part of the option.
*
* @return string HTML string if success
*
* @throws Exception if there was an error
*/
public function buildHtmlTree(
$selected_id = null,
bool $recursive = true,
bool $show_root = true,
string $root_name = '$$',
string $value_prefix = ''
): string {
if ('$$' == $root_name) {
$root_name = _('Oberste Ebene');
}
$html = array();
if ($show_root) {
$root_level = $this->getLevel();
if ($this->getID() > 0) {
$root_name = htmlspecialchars($this->getName());
}
$html[] = '<option value="'.$value_prefix.$this->getID().'">'.$root_name.'</option>';
} else {
$root_level = $this->getLevel() + 1;
}
// get all subelements
$subelements = $this->getSubelements($recursive);
foreach ($subelements as $element) {
$level = $element->getLevel() - $root_level;
$selected = ($element->getID() == $selected_id) ? 'selected' : '';
$html[] = '<option '.$selected.' value="'.$value_prefix.$element->getID().'">';
for ($i = 0; $i < $level; ++$i) {
$html[] = '&nbsp;&nbsp;&nbsp;';
}
$html[] = htmlspecialchars($element->getName()).'</option>';
}
return implode("\n", $html);
}
/**
* Creates a template loop for a Breadcrumb bar, representing the structural DB element.
*
* @param $page string The base page, to which the breadcrumb links should be directing to.
* @param $parameter string The parameter, which selects the ID of the StructuralDBElement.
* @param bool $show_root Show the root as its own breadcrumb.
* @param string $root_name The label which should be used for the root breadcrumb.
*
* @return array An Loop containing multiple arrays, which contains href and caption for the breadcrumb.
*/
public function buildBreadcrumbLoop(string $page, string $parameter, bool $show_root = false, $root_name = '$$', bool $element_is_link = false): array
{
$breadcrumb = array();
if ('$$' == $root_name) {
$root_name = _('Oberste Ebene');
}
if ($show_root) {
$breadcrumb[] = array('label' => $root_name,
'disabled' => true, );
}
if (!$this->current_user->canDo(static::getPermissionName(), StructuralPermission::READ)) {
return array('label' => '???',
'disabled' => true, );
}
$tmp = array();
if ($element_is_link) {
$tmp[] = array('label' => $this->getName(), 'href' => $page.'?'.$parameter.'='.$this->getID(), 'selected' => true);
} else {
$tmp[] = array('label' => $this->getName(), 'selected' => true);
}
$parent_id = $this->getParentID();
while ($parent_id > 0) {
/** @var StructuralDBElement $element */
$element = static::getInstance($this->database, $this->current_user, $this->log, $parent_id);
$parent_id = $element->getParentID();
$tmp[] = array('label' => $element->getName(), 'href' => $page.'?'.$parameter.'='.$element->getID());
}
$tmp = array_reverse($tmp);
$breadcrumb = array_merge($breadcrumb, $tmp);
return $breadcrumb;
}
} }

View file

@ -0,0 +1,76 @@
<?php
/**
*
* part-db version 0.1
* Copyright (C) 2005 Christoph Lechner
* http://www.cl-projects.de/
*
* part-db version 0.2+
* Copyright (C) 2009 K. Jacobs and others (see authors.php)
* http://code.google.com/p/part-db/
*
* Part-DB Version 0.4+
* Copyright (C) 2016 - 2019 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 General Public License
* as published by the Free Software Foundation; either version 2
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
namespace App\Form;
use FOS\CKEditorBundle\Form\Type\CKEditorType;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\ResetType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Security\Core\Security;
class BaseEntityAdminForm extends AbstractType
{
protected $security;
public function __construct(Security $security)
{
$this->security = $security;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
$entity = $options['data'];
$builder
->add('name', TextType::class, ['empty_data' => '', 'label' => 'name.label',
'attr' => ['placeholder' => 'part.name.placeholder'],
'disabled' => !$this->security->isGranted('edit', $entity), ])
->add('parent', EntityType::class, ['class' => get_class($entity), 'choice_label' => 'full_path',
'attr' => ['class' => 'selectpicker', 'data-live-search' => true], 'required' => false, 'label' => 'parent.label',
'disabled' => !$this->security->isGranted('move', $entity), ])
->add('comment', CKEditorType::class, ['required' => false,
'label' => 'comment.label', 'attr' => ['rows' => 4], 'help' => 'bbcode.hint',
'disabled' => !$this->security->isGranted('edit', $entity)])
//Buttons
->add('save', SubmitType::class, ['label' => 'part.edit.save'])
->add('reset', ResetType::class, ['label' => 'part.edit.reset']);
}
}

View file

@ -0,0 +1,109 @@
<?php
/**
*
* part-db version 0.1
* Copyright (C) 2005 Christoph Lechner
* http://www.cl-projects.de/
*
* part-db version 0.2+
* Copyright (C) 2009 K. Jacobs and others (see authors.php)
* http://code.google.com/p/part-db/
*
* Part-DB Version 0.4+
* Copyright (C) 2016 - 2019 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 General Public License
* as published by the Free Software Foundation; either version 2
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
namespace App\Security\Voter;
use App\Entity\AttachmentType;
use App\Entity\Category;
use App\Entity\Device;
use App\Entity\Footprint;
use App\Entity\Manufacturer;
use App\Entity\Storelocation;
use App\Entity\Supplier;
use App\Entity\User;
class StructureVoter extends ExtendedVoter
{
/**
* Determines if the attribute and subject are supported by this voter.
*
* @param string $attribute An attribute
* @param mixed $subject The subject to secure, e.g. an object the user wants to access or any other PHP type
*
* @return bool True if the attribute and subject are supported, false otherwise
*/
protected function supports($attribute, $subject)
{
$permission_name = $this->instanceToPermissionName($subject);
//If permission name is null, then the subject is not supported
return ($permission_name !== null) && $this->resolver->isValidOperation($permission_name, $attribute);
}
/**
* Maps a instance type to the permission name.
* @param $subject mixed The subject for which the permission name should be generated.
* @return string|null The name of the permission for the subject's type or null, if the subject is not supported.
*/
protected function instanceToPermissionName($subject) : ?string
{
$class_name = get_class($subject);
switch ($class_name) {
case AttachmentType::class:
return 'attachment_types';
case Category::class:
return 'categories';
case Device::class:
return 'devices';
case Footprint::class:
return 'footprints';
case Manufacturer::class:
return 'manufacturers';
case Storelocation::class:
return 'storelocations';
case Supplier::class:
return 'suppliers';
}
//When the class is not supported by this class return null
return null;
}
/**
* Similar to voteOnAttribute, but checking for the anonymous user is already done.
* The current user (or the anonymous user) is passed by $user.
*
* @param $attribute
* @param $subject
* @param User $user
*
* @return bool
*/
protected function voteOnUser($attribute, $subject, User $user): bool
{
$permission_name = $this->instanceToPermissionName($subject);
//Just resolve the permission
return $this->resolver->inherit($user, $permission_name, $attribute) ?? false;
}
}

View file

@ -0,0 +1,54 @@
<?php
/**
*
* part-db version 0.1
* Copyright (C) 2005 Christoph Lechner
* http://www.cl-projects.de/
*
* part-db version 0.2+
* Copyright (C) 2009 K. Jacobs and others (see authors.php)
* http://code.google.com/p/part-db/
*
* Part-DB Version 0.4+
* Copyright (C) 2016 - 2019 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 General Public License
* as published by the Free Software Foundation; either version 2
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
namespace App\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
/**
* Constraints the parent property on StructuralDBElement objects in the way, that neither the object self or any
* of its children can be assigned.
*
* @Annotation
* @package App\Validator\Constraints
*/
class NoneOfItsChildren extends Constraint
{
/** @var string The message used if it is tried to assign a object as its own parent */
public $self_message = 'validator.noneofitschild.self';
/** @var string The message used if it is tried to use one of the children for as parent */
public $children_message = 'validator.noneofitschild.children';
public function validatedBy()
{
return parent::validatedBy(); // TODO: Change the autogenerated stub
}
}

View file

@ -0,0 +1,88 @@
<?php
/**
*
* part-db version 0.1
* Copyright (C) 2005 Christoph Lechner
* http://www.cl-projects.de/
*
* part-db version 0.2+
* Copyright (C) 2009 K. Jacobs and others (see authors.php)
* http://code.google.com/p/part-db/
*
* Part-DB Version 0.4+
* Copyright (C) 2016 - 2019 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 General Public License
* as published by the Free Software Foundation; either version 2
* 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
namespace App\Validator\Constraints;
use App\Entity\StructuralDBElement;
use Symfony\Bundle\MakerBundle\Str;
use Symfony\Component\Form\Exception\UnexpectedTypeException;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
/**
* The validator for the NoneOfItsChildren annotation.
* @package App\Validator\Constraints
*/
class NoneOfItsChildrenValidator extends ConstraintValidator
{
/**
* Checks if the passed value is valid.
*
* @param mixed $value The value that should be validated
* @param Constraint $constraint The constraint for the validation
*/
public function validate($value, Constraint $constraint)
{
if (!$constraint instanceof NoneOfItsChildren) {
throw new UnexpectedTypeException($constraint, NoneOfItsChildren::class);
}
// custom constraints should ignore null and empty values to allow
// other constraints (NotBlank, NotNull, etc.) take care of that
if (null === $value || '' === $value) {
return;
}
//Check if the object is assigned to itself
/** @var StructuralDBElement $entity */
$entity = $this->context->getObject();
/** @var StructuralDBElement $value */
// Check if the targeted parent is the object itself:
$entity_id = $entity->getID();
if ($entity_id !== null && $entity_id === $value->getID()) {
//Set the entity to a valid state
$entity->setParent(null);
$this->context->buildViolation($constraint->self_message)->addViolation();
//The other things can not happen.
return;
}
// Check if the targeted parent is a child object
if ($value->isChildOf($entity)) {
//Set the entity to a valid state
$entity->setParent(null);
$this->context->buildViolation($constraint->children_message)->addViolation();
return;
}
}
}

View file

@ -0,0 +1,5 @@
{% extends "AdminPages/EntityAdminBase.html.twig" %}
{% block card_title %}
<i class="fas fa-file-alt fa-fw"></i> {% trans %}attachment_type.caption{% endtrans %}
{% endblock %}

View file

@ -0,0 +1,82 @@
{% extends "main_card.html.twig" %}
{% block card_content %}
<div class="row">
<div class="col-4">
</div>
<div class="col-8">
{{ form_start(form) }}
<fieldset>
<legend>
{% if entity.ID %}
<strong>{% trans with {'%name': entity.name} %}edit.caption{% endtrans %}</strong>
{% else %}
<strong>{% trans %}new.caption{% endtrans %}</strong>
{% endif %}
</legend>
<ul class="nav nav-tabs mt-2">
<li class="nav-item"><a class="link-anchor active nav-link" data-toggle="tab" href="#home">standard.label</a></li>
<li class="nav-item"><a data-toggle="tab" class="link-anchor nav-link" href="#info">infos.label</a></li>
</ul>
<div class="tab-content mb-3 mt-3">
<div id="home" class="tab-pane fade show active">
{{ form_row(form.name) }}
{{ form_row(form.parent) }}
{% block additional_controls %}{% endblock %}
{{ form_row(form.comment) }}
</div>
<div id="info" class="tab-pane fade">
<div class="form-group row">
<label class="col-form-label col-md-3">{% trans %}id.label{% endtrans %}</label>
<div class="col-md-9">
<p class="form-control-plaintext">{% if entity.iD %}{{ entity.id }}{% else %}-{% endif %}</p>
</div>
</div>
<div class="form-group row">
<label class="col-form-label col-md-3">{% trans %}createdAt{% endtrans %}</label>
<div class="col-md-9">
<p class="form-control-plaintext">
{% if entity.addedDate %}
{{ entity.addedDate | localizeddate("long") }}
{% else %}
-
{% endif %}
</p>
</div>
</div>
<div class="form-group row">
<label class="col-form-label col-md-3">{% trans %}lastModified{% endtrans %}</label>
<div class="col-md-9">
<p class="form-control-plaintext">
{% if entity.lastModified %}
{{ entity.lastModified | localizeddate("long") }}
{% else %}
-
{% endif %}
</p>
</div>
</div>
</div>
</div>
{{ form_row(form.save) }}
{{ form_row(form.reset) }}
</fieldset>
{{ form_end(form) }}
</div>
</div>
{% endblock %}