mirror of
https://github.com/kevinveenbirkenbach/infinito.git
synced 2025-01-09 14:07:25 +01:00
Added source menu
This commit is contained in:
parent
9ae2290835
commit
3bf84d3ec8
@ -21,6 +21,11 @@ services:
|
|||||||
factory: ['@app.menu_builder', 'userTopbar']
|
factory: ['@app.menu_builder', 'userTopbar']
|
||||||
tags:
|
tags:
|
||||||
- { name: knp_menu.menu, alias: userTopbar }
|
- { name: knp_menu.menu, alias: userTopbar }
|
||||||
|
app.menu.source:
|
||||||
|
class: Knp\Menu\MenuItem
|
||||||
|
factory: ['@app.menu_builder', 'sourceNavbar']
|
||||||
|
tags:
|
||||||
|
- { name: knp_menu.menu, alias: sourceNavbar }
|
||||||
# makes classes in src/ available to be used as services
|
# makes classes in src/ available to be used as services
|
||||||
# this creates a service per class whose id is the fully-qualified class name
|
# this creates a service per class whose id is the fully-qualified class name
|
||||||
App\:
|
App\:
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Controller;
|
namespace App\Controller;
|
||||||
|
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
@ -7,19 +8,18 @@ use Symfony\Component\Routing\Annotation\Route;
|
|||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use App\Creator\Factory\Template\Source\SourceTemplateFactory;
|
use App\Creator\Factory\Template\Source\SourceTemplateFactory;
|
||||||
use FOS\RestBundle\Controller\FOSRestController;
|
use FOS\RestBundle\Controller\FOSRestController;
|
||||||
use App\Form\NameSourceType;
|
|
||||||
use App\Entity\SourceInterface;
|
use App\Entity\SourceInterface;
|
||||||
use App\Creator\Factory\Template\Source\SourceTemplateFormFactory;
|
use App\Creator\Factory\Template\Source\SourceTemplateFormFactory;
|
||||||
use App\Creator\Factory\Form\Source\SourceFormFactory;
|
use App\Creator\Factory\Form\Source\SourceFormFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @todo IMPLEMENT SECURITY!
|
* @todo IMPLEMENT SECURITY!
|
||||||
|
*
|
||||||
* @author kevinfrantz
|
* @author kevinfrantz
|
||||||
*/
|
*/
|
||||||
class SourceController extends FOSRestController
|
class SourceController extends FOSRestController
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @Route("/source/{id}.{_format}", defaults={"_format"="html"})
|
* @Route("/source/{id}.{_format}", defaults={"_format"="html"})
|
||||||
*/
|
*/
|
||||||
public function show(Request $request, int $id): Response
|
public function show(Request $request, int $id): Response
|
||||||
@ -28,11 +28,11 @@ class SourceController extends FOSRestController
|
|||||||
$view = $this->view($source, 200)
|
$view = $this->view($source, 200)
|
||||||
->setTemplate((new SourceTemplateFactory($source, $request))->getTemplatePath())
|
->setTemplate((new SourceTemplateFactory($source, $request))->getTemplatePath())
|
||||||
->setTemplateVar('source');
|
->setTemplateVar('source');
|
||||||
|
|
||||||
return $this->handleView($view);
|
return $this->handleView($view);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @Route("/source/{id}/edit.{_format}", defaults={"_format"="html"})
|
* @Route("/source/{id}/edit.{_format}", defaults={"_format"="html"})
|
||||||
*/
|
*/
|
||||||
public function edit(Request $request, int $id): Response
|
public function edit(Request $request, int $id): Response
|
||||||
@ -44,9 +44,10 @@ class SourceController extends FOSRestController
|
|||||||
$source = $form->getData();
|
$source = $form->getData();
|
||||||
$this->saveSource($source);
|
$this->saveSource($source);
|
||||||
}
|
}
|
||||||
return $this->render((new SourceTemplateFormFactory($source, $request))->getTemplatePath(), array(
|
|
||||||
|
return $this->render((new SourceTemplateFormFactory($source, $request))->getTemplatePath(), [
|
||||||
'form' => $form->createView(),
|
'form' => $form->createView(),
|
||||||
));
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function loadSource(Request $request, int $id): SourceInterface
|
private function loadSource(Request $request, int $id): SourceInterface
|
||||||
@ -54,9 +55,10 @@ class SourceController extends FOSRestController
|
|||||||
$source = $this->getDoctrine()
|
$source = $this->getDoctrine()
|
||||||
->getRepository(AbstractSource::class)
|
->getRepository(AbstractSource::class)
|
||||||
->find($id);
|
->find($id);
|
||||||
if (! $source) {
|
if (!$source) {
|
||||||
throw $this->createNotFoundException('No source found for id ' . $id);
|
throw $this->createNotFoundException('No source found for id '.$id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $source;
|
return $source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,34 +1,35 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Creator\Factory\Form\Source;
|
namespace App\Creator\Factory\Form\Source;
|
||||||
|
|
||||||
use App\Entity\SourceInterface;
|
use App\Entity\SourceInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author kevinfrantz
|
* @author kevinfrantz
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
class SourceFormFactory
|
class SourceFormFactory
|
||||||
{
|
{
|
||||||
const FORM_NAMESPACE = 'App\Form\\';
|
const FORM_NAMESPACE = 'App\Form\\';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var SourceInterface
|
* @var SourceInterface
|
||||||
*/
|
*/
|
||||||
private $source;
|
private $source;
|
||||||
|
|
||||||
public function __construct(SourceInterface $source){
|
public function __construct(SourceInterface $source)
|
||||||
|
{
|
||||||
$this->source = $source;
|
$this->source = $source;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getNamespace():string{
|
public function getNamespace(): string
|
||||||
|
{
|
||||||
return self::FORM_NAMESPACE.$this->getName();
|
return self::FORM_NAMESPACE.$this->getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getName(): string
|
protected function getName(): string
|
||||||
{
|
{
|
||||||
$reflectionClass = new \ReflectionClass($this->source);
|
$reflectionClass = new \ReflectionClass($this->source);
|
||||||
|
|
||||||
return $reflectionClass->getShortName().'Type';
|
return $reflectionClass->getShortName().'Type';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ class SourceTemplateFactory
|
|||||||
const SOURCE_TEMPLATE_ROOT = 'source';
|
const SOURCE_TEMPLATE_ROOT = 'source';
|
||||||
|
|
||||||
const VIEW_FOLDER = 'view';
|
const VIEW_FOLDER = 'view';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var SourceInterface
|
* @var SourceInterface
|
||||||
*/
|
*/
|
||||||
|
@ -1,18 +1,16 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Creator\Factory\Template\Source;
|
namespace App\Creator\Factory\Template\Source;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @author kevinfrantz
|
* @author kevinfrantz
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
class SourceTemplateFormFactory extends SourceTemplateFactory
|
class SourceTemplateFormFactory extends SourceTemplateFactory
|
||||||
{
|
{
|
||||||
const FORM_FOLDER = 'form';
|
const FORM_FOLDER = 'form';
|
||||||
|
|
||||||
public function getTemplatePath(): string
|
public function getTemplatePath(): string
|
||||||
{
|
{
|
||||||
return parent::SOURCE_TEMPLATE_ROOT.'/'.self::FORM_FOLDER.'/'.$this->generateName().'.'.$this->request->getRequestFormat().'.twig';
|
return parent::SOURCE_TEMPLATE_ROOT.'/'.self::FORM_FOLDER.'/'.$this->generateName().'.'.$this->request->getRequestFormat().'.twig';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ class NameSource extends AbstractSource implements NameSourceInterface
|
|||||||
/**
|
/**
|
||||||
* @ORM\Column(type="string",length=255)
|
* @ORM\Column(type="string",length=255)
|
||||||
* @Assert\NotBlank()
|
* @Assert\NotBlank()
|
||||||
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $name;
|
protected $name;
|
||||||
|
59
application/src/Event/Menu/Topbar/SourceMenuEvent.php
Normal file
59
application/src/Event/Menu/Topbar/SourceMenuEvent.php
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Event\Menu\Topbar;
|
||||||
|
|
||||||
|
use Knp\Menu\FactoryInterface;
|
||||||
|
use Knp\Menu\ItemInterface;
|
||||||
|
use Symfony\Component\EventDispatcher\Event;
|
||||||
|
use Symfony\Component\HttpFoundation\RequestStack;
|
||||||
|
|
||||||
|
class SourceMenuEvent extends Event
|
||||||
|
{
|
||||||
|
public const EVENT = 'app.menu.source.user';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var FactoryInterface
|
||||||
|
*/
|
||||||
|
private $factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ItemInterface
|
||||||
|
*/
|
||||||
|
private $item;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var RequestStack
|
||||||
|
*/
|
||||||
|
private $request;
|
||||||
|
|
||||||
|
public function __construct(FactoryInterface $factory, ItemInterface $item, RequestStack $request)
|
||||||
|
{
|
||||||
|
$this->factory = $factory;
|
||||||
|
$this->item = $item;
|
||||||
|
$this->request = $request;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return FactoryInterface
|
||||||
|
*/
|
||||||
|
public function getFactory(): FactoryInterface
|
||||||
|
{
|
||||||
|
return $this->factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ItemInterface
|
||||||
|
*/
|
||||||
|
public function getItem(): ItemInterface
|
||||||
|
{
|
||||||
|
return $this->item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return RequestStack
|
||||||
|
*/
|
||||||
|
public function getRequest(): RequestStack
|
||||||
|
{
|
||||||
|
return $this->request;
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
// src/Menu/Menu.php
|
|
||||||
|
|
||||||
namespace App\Menu;
|
namespace App\Menu;
|
||||||
|
|
||||||
use App\Event\Menu\Topbar\UserMenuEvent;
|
use App\Event\Menu\Topbar\UserMenuEvent;
|
||||||
@ -9,6 +7,7 @@ use Knp\Menu\FactoryInterface;
|
|||||||
use Knp\Menu\ItemInterface;
|
use Knp\Menu\ItemInterface;
|
||||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||||
use Symfony\Component\HttpFoundation\RequestStack;
|
use Symfony\Component\HttpFoundation\RequestStack;
|
||||||
|
use App\Event\Menu\Topbar\SourceMenuEvent;
|
||||||
|
|
||||||
class Menu
|
class Menu
|
||||||
{
|
{
|
||||||
@ -28,6 +27,19 @@ class Menu
|
|||||||
$this->factory = $factory;
|
$this->factory = $factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function SourceNavbar(RequestStack $request): ItemInterface
|
||||||
|
{
|
||||||
|
$menu = $this->factory->createItem('root', [
|
||||||
|
'childrenAttributes' => [
|
||||||
|
'class' => 'navbar-nav mr-auto',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$this->dispatcher->dispatch(SourceMenuEvent::EVENT, new SourceMenuEvent($this->factory, $menu, $request));
|
||||||
|
|
||||||
|
return $menu;
|
||||||
|
}
|
||||||
|
|
||||||
public function userTopbar(RequestStack $request): ItemInterface
|
public function userTopbar(RequestStack $request): ItemInterface
|
||||||
{
|
{
|
||||||
$menu = $this->factory->createItem('root', [
|
$menu = $this->factory->createItem('root', [
|
||||||
@ -36,10 +48,7 @@ class Menu
|
|||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->dispatcher->dispatch(
|
$this->dispatcher->dispatch(UserMenuEvent::EVENT, new UserMenuEvent($this->factory, $menu, $request));
|
||||||
UserMenuEvent::EVENT,
|
|
||||||
new UserMenuEvent($this->factory, $menu, $request)
|
|
||||||
);
|
|
||||||
|
|
||||||
return $menu;
|
return $menu;
|
||||||
}
|
}
|
||||||
|
53
application/src/Subscriber/SourceMenuSubscriber.php
Normal file
53
application/src/Subscriber/SourceMenuSubscriber.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Subscriber;
|
||||||
|
|
||||||
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
|
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||||
|
use Symfony\Component\Translation\TranslatorInterface;
|
||||||
|
use App\Event\Menu\Topbar\SourceMenuEvent;
|
||||||
|
|
||||||
|
class SourceMenuSubscriber implements EventSubscriberInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var TokenStorageInterface
|
||||||
|
*/
|
||||||
|
private $tokenStorage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var TranslatorInterface
|
||||||
|
*/
|
||||||
|
private $translator;
|
||||||
|
|
||||||
|
public function __construct(TokenStorageInterface $tokenStorage, TranslatorInterface $translator)
|
||||||
|
{
|
||||||
|
$this->tokenStorage = $tokenStorage;
|
||||||
|
$this->translator = $translator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onSourceMenuConfigure(SourceMenuEvent $event): void
|
||||||
|
{
|
||||||
|
$menu = $event->getItem();
|
||||||
|
$menu->addChild($this->translator->trans('edit'), [
|
||||||
|
'route' => 'app_source_edit',
|
||||||
|
'routeParameters' => ['id' => $event->getRequest()->getCurrentRequest()->attributes->get('id')],
|
||||||
|
'attributes' => [
|
||||||
|
'icon' => 'fas fa-edit',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
$menu->addChild($this->translator->trans('show'), [
|
||||||
|
'route' => 'app_source_show',
|
||||||
|
'routeParameters' => ['id' => $event->getRequest()->getCurrentRequest()->attributes->get('id')],
|
||||||
|
'attributes' => [
|
||||||
|
'icon' => 'fas fa-eye',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getSubscribedEvents(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
SourceMenuEvent::EVENT => 'onSourceMenuConfigure',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Subscriber;
|
namespace App\Subscriber;
|
||||||
|
|
||||||
use App\Event\Menu\Topbar\UserMenuEvent;
|
use App\Event\Menu\Topbar\UserMenuEvent;
|
||||||
@ -9,19 +10,16 @@ use Knp\Menu\ItemInterface;
|
|||||||
|
|
||||||
class UserMenuSubscriber implements EventSubscriberInterface
|
class UserMenuSubscriber implements EventSubscriberInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @var TokenStorageInterface
|
* @var TokenStorageInterface
|
||||||
*/
|
*/
|
||||||
private $tokenStorage;
|
private $tokenStorage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
|
||||||
* @var TranslatorInterface
|
* @var TranslatorInterface
|
||||||
*/
|
*/
|
||||||
private $translator;
|
private $translator;
|
||||||
|
|
||||||
public function __construct(TokenStorageInterface $tokenStorage, TranslatorInterface $translator)
|
public function __construct(TokenStorageInterface $tokenStorage, TranslatorInterface $translator)
|
||||||
{
|
{
|
||||||
$this->tokenStorage = $tokenStorage;
|
$this->tokenStorage = $tokenStorage;
|
||||||
@ -31,18 +29,18 @@ class UserMenuSubscriber implements EventSubscriberInterface
|
|||||||
public function onUserMenuConfigure(UserMenuEvent $event): void
|
public function onUserMenuConfigure(UserMenuEvent $event): void
|
||||||
{
|
{
|
||||||
$menu = $event->getItem();
|
$menu = $event->getItem();
|
||||||
$menu->addChild('start', [
|
$menu->addChild($this->translator->trans('start'), [
|
||||||
'route' => 'homepage',
|
'route' => 'homepage',
|
||||||
'attributes' => [
|
'attributes' => [
|
||||||
'icon' => 'fab fa-font-awesome-flag'
|
'icon' => 'fab fa-font-awesome-flag',
|
||||||
]
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$menu->addChild('imprint', [
|
$menu->addChild($this->translator->trans('imprint'), [
|
||||||
'route' => 'imprint',
|
'route' => 'imprint',
|
||||||
'attributes' => [
|
'attributes' => [
|
||||||
'icon' => 'fas fa-address-card'
|
'icon' => 'fas fa-address-card',
|
||||||
]
|
],
|
||||||
]);
|
]);
|
||||||
$this->generateUserDropdown($menu);
|
$this->generateUserDropdown($menu);
|
||||||
}
|
}
|
||||||
@ -53,45 +51,45 @@ class UserMenuSubscriber implements EventSubscriberInterface
|
|||||||
->getUsername() ?? 'user', [
|
->getUsername() ?? 'user', [
|
||||||
'attributes' => [
|
'attributes' => [
|
||||||
'dropdown' => true,
|
'dropdown' => true,
|
||||||
'icon' => 'fas fa-user'
|
'icon' => 'fas fa-user',
|
||||||
]
|
],
|
||||||
]);
|
]);
|
||||||
if ($this->tokenStorage->getToken()->getRoles()) {
|
if ($this->tokenStorage->getToken()->getRoles()) {
|
||||||
$dropdown->addChild('logout', [
|
$dropdown->addChild($this->translator->trans('logout'), [
|
||||||
'route' => 'logout',
|
'route' => 'logout',
|
||||||
'attributes' => [
|
'attributes' => [
|
||||||
'icon' => 'fas fa-sign-out-alt',
|
'icon' => 'fas fa-sign-out-alt',
|
||||||
'divider_append' => true
|
'divider_append' => true,
|
||||||
]
|
],
|
||||||
]);
|
]);
|
||||||
$dropdown->addChild('edit profile', [
|
$dropdown->addChild($this->translator->trans('edit profile'), [
|
||||||
'route' => 'fos_user_profile_edit',
|
'route' => 'fos_user_profile_edit',
|
||||||
'attributes' => [
|
'attributes' => [
|
||||||
'icon' => 'fas fa-user-edit',
|
'icon' => 'fas fa-user-edit',
|
||||||
'divider_append' => true
|
'divider_append' => true,
|
||||||
]
|
],
|
||||||
]);
|
]);
|
||||||
} else {
|
} else {
|
||||||
$dropdown->addChild('login', [
|
$dropdown->addChild($this->translator->trans('login'), [
|
||||||
'route' => 'fos_user_security_login',
|
'route' => 'fos_user_security_login',
|
||||||
'attributes' => [
|
'attributes' => [
|
||||||
'divider_append' => true,
|
'divider_append' => true,
|
||||||
'icon' => 'fas fa-sign-in-alt'
|
'icon' => 'fas fa-sign-in-alt',
|
||||||
]
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
$dropdown->addChild('register', [
|
$dropdown->addChild('register', [
|
||||||
'route' => 'fos_user_registration_register',
|
'route' => 'fos_user_registration_register',
|
||||||
'attributes' => [
|
'attributes' => [
|
||||||
'icon' => 'fas fa-file-signature'
|
'icon' => 'fas fa-file-signature',
|
||||||
]
|
],
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getSubscribedEvents(): array
|
public static function getSubscribedEvents(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
UserMenuEvent::EVENT => 'onUserMenuConfigure'
|
UserMenuEvent::EVENT => 'onUserMenuConfigure',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
<nav class="navbar navbar-expand-lg navbar-light bg-light">
|
||||||
|
<button class="navbar-toggler" type="button" data-toggle="collapse"
|
||||||
|
data-target="#navbarSupportedContent"
|
||||||
|
aria-controls="navbarSupportedContent" aria-expanded="false"
|
||||||
|
aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||||
|
{{ knp_menu_render('sourceNavbar', {'currentClass': 'active', 'template': 'frames/structure/navbar/knp_menu.html.twig'}) }}
|
||||||
|
</div>
|
||||||
|
</nav>
|
@ -1,6 +1,6 @@
|
|||||||
{% extends "frames/default.html.twig" %}
|
{% extends "source/source.html.twig" %}
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{% trans %}
|
{% trans %}
|
||||||
Source
|
Source edit
|
||||||
{% endtrans %}
|
{% endtrans %}
|
||||||
{% endblock %}
|
{% endblock %}
|
9
application/templates/source/source.html.twig
Normal file
9
application/templates/source/source.html.twig
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{% extends "frames/default.html.twig" %}
|
||||||
|
{% block title %}
|
||||||
|
{% trans %}
|
||||||
|
Source
|
||||||
|
{% endtrans %}
|
||||||
|
{% endblock %}
|
||||||
|
{% block sub_navigation %}
|
||||||
|
{% include 'frames/structure/navbar/source_sub.html.twig'%}
|
||||||
|
{% endblock %}
|
@ -1,4 +1,4 @@
|
|||||||
{% extends "frames/default.html.twig" %}
|
{% extends "source/source.html.twig" %}
|
||||||
{% block title %}
|
{% block title %}
|
||||||
{% trans %}
|
{% trans %}
|
||||||
Source
|
Source
|
||||||
|
Loading…
Reference in New Issue
Block a user