WIP: Implement CRUD, improve menu configuration
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
import { Controller } from '@hotwired/stimulus'
|
||||
import Sortable from 'sortablejs'
|
||||
|
||||
export default class extends Controller {
|
||||
|
||||
static values = { endpoint: String }
|
||||
static targets = ['item', 'handle']
|
||||
|
||||
connect() {
|
||||
new Sortable(this.element, {
|
||||
item: '[data-sortable-target="item"]',
|
||||
handle: '[data-sortable-target="handle"]',
|
||||
onEnd: e => {
|
||||
this.updateOrdering()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
updateOrdering() {
|
||||
let ordering = {}
|
||||
this.itemTargets.forEach((item, index) => {
|
||||
let projectId = parseInt(item.dataset.itemId)
|
||||
ordering[projectId] = index + 1
|
||||
})
|
||||
fetch(this.endpointValue, {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ ordering: ordering })
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { Controller } from '@hotwired/stimulus'
|
||||
|
||||
export default class extends Controller {
|
||||
|
||||
static classes = [ 'closed' ]
|
||||
static targets = [ 'toggle', 'icon' ]
|
||||
static values = { open: Boolean, iconClosed: String, iconOpen: String, spriteUrl: String }
|
||||
|
||||
connect() {
|
||||
this.target = this.hasToggleTarget ? this.toggleTarget : this.element
|
||||
this.openValue = !this.target.classList.contains(this.closedClass)
|
||||
}
|
||||
|
||||
toggle() {
|
||||
this.openValue ? this._close() : this._open()
|
||||
}
|
||||
|
||||
close() {
|
||||
this._close()
|
||||
}
|
||||
|
||||
_close() {
|
||||
this.openValue = false
|
||||
this.target.classList.add(this.closedClass)
|
||||
}
|
||||
|
||||
open() {
|
||||
this._open()
|
||||
}
|
||||
|
||||
_open() {
|
||||
this.openValue = true
|
||||
this.target.classList.remove(this.closedClass)
|
||||
}
|
||||
|
||||
openValueChanged() {
|
||||
if (false === this.hasIconTarget) {
|
||||
return
|
||||
}
|
||||
|
||||
this.iconTarget.classList.toggle('rotate-90', true === this.openValue)
|
||||
}
|
||||
}
|
||||
@@ -145,6 +145,14 @@
|
||||
<!-- Font Awesome Pro 5.15.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) -->
|
||||
<path d="M488 128h-8V80c0-44.8-99.2-80-224-80S32 35.2 32 80v48h-8c-13.25 0-24 10.74-24 24v80c0 13.25 10.75 24 24 24h8v160c0 17.67 14.33 32 32 32v32c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32v-32h192v32c0 17.67 14.33 32 32 32h32c17.67 0 32-14.33 32-32v-32h6.4c16 0 25.6-12.8 25.6-25.6V256h8c13.25 0 24-10.75 24-24v-80c0-13.26-10.75-24-24-24zM112 400c-17.67 0-32-14.33-32-32s14.33-32 32-32 32 14.33 32 32-14.33 32-32 32zm16-112c-17.67 0-32-14.33-32-32V128c0-17.67 14.33-32 32-32h256c17.67 0 32 14.33 32 32v128c0 17.67-14.33 32-32 32H128zm272 112c-17.67 0-32-14.33-32-32s14.33-32 32-32 32 14.33 32 32-14.33 32-32 32z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-ski" fill="currentColor" stroke="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
|
||||
<path d="M380.7 48a48 48 0 1 1 96 0 48 48 0 1 1 -96 0zM2.7 268.9c6.1-11.8 20.6-16.3 32.4-10.2L239.8 365l49.6-74.5-82.7-87.9c-9.5-10.1-14.4-22.4-15.1-34.9l87.7 42 49.4 52.5c12.8 13.6 14.5 34.1 4.2 49.6l-50.2 75.4 135.8 70.5c13.6 7.1 29.8 7.2 43.6 .3l15.2-7.6c11.9-5.9 26.3-1.1 32.2 10.7s1.1 26.3-10.7 32.2l-15.2 7.6c-27.5 13.7-59.9 13.5-87.2-.7L12.9 301.3C1.2 295.2-3.4 280.7 2.7 268.9zM118.9 65.6L137 74.2l8.7-17.4c4-7.9 13.6-11.1 21.5-7.2s11.1 13.6 7.2 21.5l-8.5 16.9 55.5 26.6c1.7-.9 3.5-1.7 5.4-2.5l80.9-32.4c32.4-13 68.6 6.5 75.6 40.7l12.3 59.7 62.9 30.1c12 5.7 17 20 11.3 32s-20 17-32 11.3l-54.2-25.9c-1-.3-1.9-.6-2.8-1l-229.1-110-9.2 18.4c-4 7.9-13.6 11.1-21.5 7.2s-11.1-13.6-7.2-21.5l9-18-17.6-8.4c-8-3.8-11.3-13.4-7.5-21.3s13.4-11.3 21.3-7.5zm217.3 64.7c-1-4.9-6.2-7.7-10.8-5.8l-45.7 18.3 65.5 31.5-9-43.9z"/>
|
||||
</symbol>
|
||||
<symbol id="icon-snowboard" fill="currentColor" stroke="nonw" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
|
||||
<!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
|
||||
<path d="M204.3 3c11.6-6.4 26.2-2.3 32.6 9.3l31.9 57.4c1.3 2.3 3.6 3.8 6.2 4.1l33.8 3.4c24.1 2.4 46.9 12 65.4 27.6L503.5 213.6c10.1 8.5 11.4 23.7 2.9 33.8s-23.7 11.4-33.8 2.9l-68.2-57.5-82.3 43.9 24.7 18.9c24.9 19 34.6 51.9 24.1 81.4l-28.2 79c-1.4 3.8-3.6 7-6.3 9.6l93.3 35.7c4.6 1.8 9.4 2.6 14.3 2.6H472c13.3 0 24 10.7 24 24s-10.7 24-24 24H443.8c-10.8 0-21.4-2-31.5-5.8L60.1 371.3c-11.5-4.4-22-11.2-30.8-20L7 329c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l22.4 22.4c4 4 8.7 7.1 14 9.1l19.4 7.4c-2.9-11.4 2.9-23.4 14-28.1L192 272l0-68.2c0-21.2 12-40.6 31-50.1L284.4 123l-14.1-1.4c-18.3-1.8-34.5-12.5-43.4-28.5L195 35.7c-6.4-11.6-2.3-26.2 9.3-32.6zm91.8 407.2c-.3-3.4 .1-6.9 1.3-10.3l28.2-79c3.5-9.8 .3-20.8-8-27.1L240 234.4l0 42.9c0 16.1-9.7 30.7-24.6 36.9L134 348.2l162.1 62.1zM259.6 189l20.5 15.7 84.6-45.1-17.2-14.5L259.6 189zM384 48a48 48 0 1 1 96 0 48 48 0 1 1 -96 0z"/>
|
||||
</symbol>
|
||||
<!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL -->
|
||||
<symbol id="icon-spinner" viewBox="0 0 44 44" xmlns="http://www.w3.org/2000/svg" stroke="currentColor">
|
||||
<g fill="none" fill-rule="evenodd" stroke-width="2">
|
||||
|
||||
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 27 KiB |
@@ -51,6 +51,7 @@
|
||||
"twig/extra-bundle": "^2.12|^3.0",
|
||||
"twig/html-extra": "^3.7",
|
||||
"twig/intl-extra": "^3.7",
|
||||
"twig/string-extra": "^3.7",
|
||||
"twig/twig": "^2.12|^3.0"
|
||||
},
|
||||
"config": {
|
||||
|
||||
Generated
+68
-1
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "55a86e3af41172ce63979c655a409640",
|
||||
"content-hash": "ffce78078f5185643c9ddfa6e2146e49",
|
||||
"packages": [
|
||||
{
|
||||
"name": "doctrine/cache",
|
||||
@@ -8256,6 +8256,73 @@
|
||||
],
|
||||
"time": "2023-07-29T15:34:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "twig/string-extra",
|
||||
"version": "v3.7.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twigphp/string-extra.git",
|
||||
"reference": "7230d630a25e91cd91a2bd8e2f0e872962507eab"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twigphp/string-extra/zipball/7230d630a25e91cd91a2bd8e2f0e872962507eab",
|
||||
"reference": "7230d630a25e91cd91a2bd8e2f0e872962507eab",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.5",
|
||||
"symfony/string": "^5.4|^6.0",
|
||||
"symfony/translation-contracts": "^1.1|^2|^3",
|
||||
"twig/twig": "^2.7|^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/phpunit-bridge": "^5.4|^6.3"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Twig\\Extra\\String\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "[email protected]",
|
||||
"homepage": "http://fabien.potencier.org",
|
||||
"role": "Lead Developer"
|
||||
}
|
||||
],
|
||||
"description": "A Twig extension for Symfony String",
|
||||
"homepage": "https://twig.symfony.com",
|
||||
"keywords": [
|
||||
"html",
|
||||
"string",
|
||||
"twig",
|
||||
"unicode"
|
||||
],
|
||||
"support": {
|
||||
"source": "https://github.com/twigphp/string-extra/tree/v3.7.1"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/twig/twig",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2023-07-29T15:34:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "twig/twig",
|
||||
"version": "v3.6.1",
|
||||
|
||||
Generated
+1126
-3260
File diff suppressed because it is too large
Load Diff
@@ -31,5 +31,8 @@
|
||||
"dev": "encore dev",
|
||||
"watch": "encore dev --watch",
|
||||
"build": "encore production --progress"
|
||||
},
|
||||
"dependencies": {
|
||||
"sortablejs": "^1.15.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\Application;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class IndexController extends AbstractController
|
||||
{
|
||||
#[Route('/admin/application', name: 'app_admin_application_index')]
|
||||
public function index(): Response
|
||||
{
|
||||
return $this->render('admin/application/index.html.twig');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\Assignment;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class IndexController extends AbstractController
|
||||
{
|
||||
#[Route('/admin/assignment', name: 'app_admin_assignment_index')]
|
||||
public function index(): Response
|
||||
{
|
||||
return $this->render('admin/assignment/index.html.twig');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\Document;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class IndexController extends AbstractController
|
||||
{
|
||||
#[Route('/admin/document', name: 'app_admin_document_index')]
|
||||
public function index(): Response
|
||||
{
|
||||
return $this->render('admin/document/index.html.twig');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\System\Faq;
|
||||
|
||||
use App\Entity\Faq;
|
||||
use App\Form\FaqType;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class CreateController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/system/faq/create', name: 'app_admin_system_faq_create')]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$faq = new Faq();
|
||||
$form = $this->createForm(FaqType::class, $faq);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$this->entityManager->persist($faq);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Der FAQ-Eintrag wurde angelegt');
|
||||
$this->logger->info('Create faq', [
|
||||
'faq' => $faq->getQuestion(),
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_admin_system_faq_index');
|
||||
}
|
||||
|
||||
return $this->render('admin/system/faq/create.html.twig', [
|
||||
'form' => $form
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\System\Faq;
|
||||
|
||||
use App\Entity\Faq;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class DeleteController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/system/faq/delete/{id}', name: 'app_admin_system_faq_delete', methods: ['POST'])]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function index(Faq $faq): Response
|
||||
{
|
||||
$this->entityManager->remove($faq);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Der FAQ-Eintrag wurde gelöscht');
|
||||
$this->logger->info('Delete faq', [
|
||||
'faq' => $faq->getQuestion(),
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_admin_system_faq_index');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\System\Faq;
|
||||
|
||||
use App\Entity\Faq;
|
||||
use App\Form\FaqType;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class EditController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/system/faq/edit/{id}', name: 'app_admin_system_faq_edit')]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function index(Faq $faq, Request $request): Response
|
||||
{
|
||||
$form = $this->createForm(FaqType::class, $faq);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Der FAQ-Eintrag wurde aktualisiert');
|
||||
$this->logger->info('Edit faq', [
|
||||
'faq' => $faq->getQuestion(),
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_admin_system_faq_index');
|
||||
}
|
||||
|
||||
return $this->render('admin/system/faq/edit.html.twig', [
|
||||
'form' => $form
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\System\Faq;
|
||||
|
||||
use App\Entity\Faq;
|
||||
use App\Repository\FaqRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class IndexController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly FaqRepository $faqRepository,
|
||||
private readonly EntityManagerInterface $entityManager
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/system/faq', name: 'app_admin_system_faq_index')]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function index(): Response
|
||||
{
|
||||
$faqs = $this->faqRepository->findBy([], ['sorting' => 'ASC']);
|
||||
|
||||
return $this->render('admin/system/faq/index.html.twig', [
|
||||
'faqs' => $faqs,
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/admin/system/faq/sort', name: 'app_admin_system_faq_sort', methods: ['POST'])]
|
||||
public function sort(Request $request): JsonResponse
|
||||
{
|
||||
$data = json_decode($request->getContent(), true);
|
||||
$ordering = $data['ordering'];
|
||||
$faqIds = array_keys($ordering);
|
||||
$faqs = $this
|
||||
->faqRepository
|
||||
->findBy(['id' => $faqIds])
|
||||
;
|
||||
foreach ($faqs as $faq) {
|
||||
/* @var Faq $faq */
|
||||
$faq->setSorting($ordering[$faq->getId()]);
|
||||
}
|
||||
$this->entityManager->flush();
|
||||
|
||||
return $this->json([
|
||||
'success' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ class EditController extends AbstractController
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Das Honorar wurde aktualisiert');
|
||||
$this->logger->info('Update fee', [
|
||||
$this->logger->info('Edit fee', [
|
||||
'fee' => $fee->getName(),
|
||||
]);
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\System\JobProfile;
|
||||
|
||||
use App\Entity\JobProfile;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class DeleteController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/system/job-profile/delete/{id}', name: 'app_admin_system_job_profile_delete', methods: ['POST'])]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function index(JobProfile $jobProfile): Response
|
||||
{
|
||||
$this->entityManager->remove($jobProfile);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Das Job-Profil wurde gelöscht');
|
||||
$this->logger->info('Delete job-profile', [
|
||||
'job_profile' => $jobProfile->getName(),
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_admin_system_job_profile_index');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\System\JobProfile;
|
||||
|
||||
use App\Entity\JobProfile;
|
||||
use App\Form\JobProfileType;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class EditController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/system/job-profile/edit/{id}', name: 'app_admin_system_job_profile_edit')]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function index(JobProfile $jobProfile, Request $request): Response
|
||||
{
|
||||
$form = $this->createForm(JobProfileType::class, $jobProfile);
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Das Job-Profil wurde aktualisiert');
|
||||
$this->logger->info('Edit Job profile', [
|
||||
'job_profile' => $jobProfile->getName(),
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_admin_system_job_profile_index');
|
||||
}
|
||||
|
||||
return $this->render('admin/system/job_profile/edit.html.twig', [
|
||||
'form' => $form
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Admin\System\Training;
|
||||
|
||||
use App\Entity\Training;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class DeleteController extends AbstractController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly EntityManagerInterface $entityManager,
|
||||
private readonly LoggerInterface $logger
|
||||
) {
|
||||
}
|
||||
|
||||
#[Route('/admin/system/training/delete/{id}', name: 'app_admin_system_training_delete', methods: ['POST'])]
|
||||
#[IsGranted('ROLE_ADMIN')]
|
||||
public function index(Training $training): Response
|
||||
{
|
||||
$this->entityManager->remove($training);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Die Fortbildung wurde gelöscht');
|
||||
$this->logger->info('Delete training', [
|
||||
'training' => $training->getName(),
|
||||
]);
|
||||
|
||||
return $this->redirectToRoute('app_admin_system_training_index');
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ class EditController extends AbstractController
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->addFlash('success', 'Die Fortbildung wurde aktualisiert');
|
||||
$this->logger->info('Update training', [
|
||||
$this->logger->info('Edit training', [
|
||||
'training' => $training->getName(),
|
||||
]);
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Common\Assignment;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class CreateController extends AbstractController
|
||||
{
|
||||
#[Route('/assignment/create', name: 'app_common_assignment_create')]
|
||||
#[IsGranted('ROLE_ADMINISTRATIVE')]
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller\Teamer;
|
||||
|
||||
use App\Repository\FaqRepository;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
class FaqController extends AbstractController
|
||||
{
|
||||
public function __construct(private readonly FaqRepository $faqRepository)
|
||||
{}
|
||||
|
||||
#[Route('/teamer/faq', name: 'app_teamer_faq')]
|
||||
#[IsGranted('ROLE_USER')]
|
||||
public function index(): Response
|
||||
{
|
||||
$faqs = $this->faqRepository->findBy([], ['sorting' => 'ASC']);
|
||||
|
||||
return $this->render('teamer/faq.html.twig', [
|
||||
'faqs' => $faqs,
|
||||
]);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -26,7 +26,7 @@ class Faq implements BlameableEntityInterface, TimestampableEntityInterface
|
||||
private ?string $answer = null;
|
||||
|
||||
#[ORM\Column]
|
||||
private ?int $sorting = null;
|
||||
private int $sorting = 0;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
@@ -57,7 +57,7 @@ class Faq implements BlameableEntityInterface, TimestampableEntityInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getSorting(): ?int
|
||||
public function getSorting(): int
|
||||
{
|
||||
return $this->sorting;
|
||||
}
|
||||
|
||||
@@ -94,6 +94,10 @@ class User implements UserInterface, TimestampableEntityInterface
|
||||
{
|
||||
$roles = ['ROLE_USER', ...$this->roles];
|
||||
|
||||
if (in_array('ROLE_ADMIN', $this->roles) || in_array('ROLE_MANAGER', $this->roles)) {
|
||||
$roles[] = 'ROLE_ADMINISTRATIVE';
|
||||
}
|
||||
|
||||
return array_unique($roles);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\Form;
|
||||
|
||||
use App\Entity\Faq;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\TextType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
class FaqType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||
{
|
||||
$builder
|
||||
->add('question', TextType::class, [
|
||||
'label' => 'Frage',
|
||||
])
|
||||
->add('answer', TextareaType::class, [
|
||||
'label' => 'Antwort',
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver): void
|
||||
{
|
||||
$resolver->setDefaults([
|
||||
'data_class' => Faq::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,52 @@ abstract class AbstractMenuBuilder
|
||||
return $this->factory->createItem('root');
|
||||
}
|
||||
|
||||
protected function createMenu(array $menuItems): ItemInterface
|
||||
{
|
||||
$menu = $this->createRootElement();
|
||||
|
||||
foreach ($menuItems as $menuItem) {
|
||||
$addedItem = $this->createMenuItem($menu, $menuItem);
|
||||
if (isset($menuItem['hideChildren'])&& true === $menuItem['hideChildren']) {
|
||||
$addedItem->setDisplayChildren(false);
|
||||
}
|
||||
if (isset($menuItem['children'])) {
|
||||
foreach ($menuItem['children'] as $subMenuItem) {
|
||||
$addedSubItem = $this->createMenuItem($addedItem, $subMenuItem);
|
||||
if (isset($subMenuItem['children'])) {
|
||||
$addedSubItem->setDisplayChildren(false);
|
||||
foreach ($subMenuItem['children'] as $hiddenItem) {
|
||||
$this->createMenuItem($addedSubItem, $hiddenItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $menu;
|
||||
}
|
||||
|
||||
protected function createMenuItem(ItemInterface $menu, array $options): ItemInterface
|
||||
{
|
||||
$itemOptions = [];
|
||||
if (false !== $options['route']) {
|
||||
$itemOptions['route'] = $options['route'];
|
||||
$itemOptions['linkAttributes'] = ['title' => $options['title']];
|
||||
}
|
||||
if (isset($options['routeParameters'])) {
|
||||
$itemOptions['routeParameters'] = $options['routeParameters'];
|
||||
}
|
||||
$addedItem = $menu
|
||||
->addChild($options['title'], $itemOptions)
|
||||
->setChildrenAttribute('title', $options['title'])
|
||||
;
|
||||
if (isset($options['icon'])) {
|
||||
$addedItem->setExtra('icon', $options['icon']);
|
||||
}
|
||||
|
||||
return $addedItem;
|
||||
}
|
||||
|
||||
protected function getDefaultRouteParameters(string $parameter = 'id', string $default = '0'): array
|
||||
{
|
||||
return [$parameter => $this->requestStack->getMainRequest()->get($parameter, $default)];
|
||||
@@ -74,18 +120,19 @@ abstract class AbstractMenuBuilder
|
||||
->addChild('Logout', [
|
||||
'route' => $originalUser->getDefaultRoute(),
|
||||
'routeParameters' => ['_switch_user' => '_exit'],
|
||||
])
|
||||
->setLinkAttributes([
|
||||
'title' => 'zurück',
|
||||
'class' => 'icon-link',
|
||||
'linkAttributes' => [
|
||||
'title' => 'zurück',
|
||||
],
|
||||
])
|
||||
->setExtra('icon', 'logout')
|
||||
;
|
||||
} else {
|
||||
$menu
|
||||
->addChild('Logout', ['route' => 'app_security_logout'])
|
||||
->setLinkAttributes([
|
||||
'title' => 'Logout',
|
||||
->addChild('Logout', [
|
||||
'route' => 'app_security_logout',
|
||||
'linkAttributes' => [
|
||||
'title' => 'Logout',
|
||||
],
|
||||
])
|
||||
->setExtra('icon', 'logout')
|
||||
;
|
||||
|
||||
@@ -8,96 +8,99 @@ class AdminMenuBuilder extends AbstractMenuBuilder
|
||||
{
|
||||
public function createMainMenu(array $options): ItemInterface
|
||||
{
|
||||
$menu = $this->createRootElement();
|
||||
|
||||
$menu
|
||||
->addChild('Dashboard', ['route' => 'app_admin_index'])
|
||||
->setChildrenAttribute('title', 'Dashboard')
|
||||
->setExtra('icon', 'lab')
|
||||
;
|
||||
|
||||
$menu
|
||||
->addChild('Einsatzübersicht', ['route' => 'app_admin_index'])
|
||||
->setChildrenAttribute('title', 'Einsatzübersicht')
|
||||
->setExtra('icon', 'calendar')
|
||||
;
|
||||
|
||||
$menu
|
||||
->addChild('Bewerbungsübersicht', ['route' => 'app_admin_index'])
|
||||
->setChildrenAttribute('title', 'Bewerbungsübersicht')
|
||||
->setExtra('icon', 'mail')
|
||||
;
|
||||
|
||||
$menu
|
||||
->addChild('Dokumentenübersicht', ['route' => 'app_admin_index'])
|
||||
->setChildrenAttribute('title', 'Dokumentenübersicht')
|
||||
->setExtra('icon', 'document')
|
||||
;
|
||||
|
||||
$menu
|
||||
->addChild('Teamerübersicht', ['route' => 'app_admin_teamer_index'])
|
||||
->setChildrenAttribute('title', 'Teamerübersicht')
|
||||
->setExtra('icon', 'users')
|
||||
;
|
||||
|
||||
$systemMenu = $menu
|
||||
->addChild('Einstellungen')
|
||||
->setExtra('icon', 'settings')
|
||||
;
|
||||
$feeMenu = $systemMenu
|
||||
->addChild('Honorare', [
|
||||
'route' => 'app_admin_system_fee_index',
|
||||
'linkAttributes' => [
|
||||
'title' => 'Honorare',
|
||||
$menuItems = [
|
||||
[
|
||||
'route' => 'app_admin_index',
|
||||
'title' => 'Dashboard',
|
||||
'icon' => 'lab',
|
||||
],
|
||||
[
|
||||
'route' => 'app_admin_assignment_index',
|
||||
'title' => 'Einsatzübersicht',
|
||||
'icon' => 'calendar',
|
||||
],
|
||||
[
|
||||
'route' => 'app_admin_application_index',
|
||||
'title' => 'Bewerbungsübersicht',
|
||||
'icon' => 'mail',
|
||||
],
|
||||
[
|
||||
'route' => 'app_admin_document_index',
|
||||
'title' => 'Dokumentenübersicht',
|
||||
'icon' => 'document',
|
||||
],
|
||||
[
|
||||
'route' => 'app_admin_teamer_index',
|
||||
'title' => 'Teamerübersicht',
|
||||
'icon' => 'users',
|
||||
'hideChildren' => true,
|
||||
'children' => [],
|
||||
],
|
||||
[
|
||||
'route' => false,
|
||||
'title' => 'Einstellungen',
|
||||
'icon' => 'settings',
|
||||
'children' => [
|
||||
[
|
||||
'route' => 'app_admin_system_fee_index',
|
||||
'title' => 'Honorare',
|
||||
'children' => [
|
||||
[
|
||||
'route' => 'app_admin_system_fee_create',
|
||||
'title' => 'Honorar anlegen',
|
||||
],
|
||||
[
|
||||
'route' => 'app_admin_system_fee_edit',
|
||||
'routeParameters' => $this->getDefaultRouteParameters(),
|
||||
'title' => 'Honorar bearbeiten',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'route' => 'app_admin_system_training_index',
|
||||
'title' => 'Fortbildungen',
|
||||
'children' => [
|
||||
[
|
||||
'route' => 'app_admin_system_training_create',
|
||||
'title' => 'Fortbildung anlegen',
|
||||
],
|
||||
[
|
||||
'route' => 'app_admin_system_training_edit',
|
||||
'routeParameters' => $this->getDefaultRouteParameters(),
|
||||
'title' => 'Fortbildung bearbeiten',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'route' => 'app_admin_system_job_profile_index',
|
||||
'title' => 'Job-Profile',
|
||||
'children' => [
|
||||
[
|
||||
'route' => 'app_admin_system_job_profile_create',
|
||||
'title' => 'Job-Profil anlegen',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'route' => 'app_admin_system_faq_index',
|
||||
'title' => 'FAQ',
|
||||
'children' => [
|
||||
[
|
||||
'route' => 'app_admin_system_faq_create',
|
||||
'title' => 'FAQ-Eintrag anlegen',
|
||||
],
|
||||
[
|
||||
'route' => 'app_admin_system_faq_edit',
|
||||
'routeParameters' => $this->getDefaultRouteParameters(),
|
||||
'title' => 'FAQ-Eintrag bearbeiten',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'displayChildren' => false,
|
||||
])
|
||||
;
|
||||
$feeMenu
|
||||
->addChild('Honorar anlegen', [
|
||||
'route' => 'app_admin_system_fee_create',
|
||||
])
|
||||
;
|
||||
$feeMenu
|
||||
->addChild('Honorar bearbeiten', [
|
||||
'route' => 'app_admin_system_fee_edit',
|
||||
'routeParameters' => $this->getDefaultRouteParameters(),
|
||||
])
|
||||
;
|
||||
$trainingMenu = $systemMenu
|
||||
->addChild('Fortbildungen', [
|
||||
'route' => 'app_admin_system_training_index',
|
||||
'linkAttributes' => [
|
||||
'title' => 'Fortbildungen',
|
||||
],
|
||||
'displayChildren' => false,
|
||||
])
|
||||
;
|
||||
$trainingMenu
|
||||
->addChild('Fortbildung anlegen', [
|
||||
'route' => 'app_admin_system_training_create',
|
||||
])
|
||||
;
|
||||
$trainingMenu
|
||||
->addChild('Fortbildung bearbeiten', [
|
||||
'route' => 'app_admin_system_training_edit',
|
||||
'routeParameters' => $this->getDefaultRouteParameters(),
|
||||
])
|
||||
;
|
||||
$jobProfileMenu = $systemMenu
|
||||
->addChild('Job-Profile', [
|
||||
'route' => 'app_admin_system_job_profile_index',
|
||||
'linkAttributes' => [
|
||||
'title' => 'Fortbildungen',
|
||||
],
|
||||
'displayChildren' => false,
|
||||
])
|
||||
;
|
||||
$jobProfileMenu
|
||||
->addChild('Job-Profil anlegen', [
|
||||
'route' => 'app_admin_system_job_profile_create',
|
||||
])
|
||||
;
|
||||
],
|
||||
];
|
||||
|
||||
$menu = $this->createMenu($menuItems);
|
||||
|
||||
$this->addDivider($menu);
|
||||
|
||||
|
||||
@@ -8,73 +8,80 @@ class TeamerMenuBuilder extends AbstractMenuBuilder
|
||||
{
|
||||
public function createMainMenu(array $options): ItemInterface
|
||||
{
|
||||
$menu = $this->createRootElement();
|
||||
$menuItems = [
|
||||
[
|
||||
'route' => 'app_teamer_index',
|
||||
'title' => 'Einsatzübersicht',
|
||||
'icon' => 'calendar',
|
||||
],
|
||||
[
|
||||
'route' => false,
|
||||
'title' => 'Mein Profil',
|
||||
'icon' => 'user',
|
||||
'children' => [
|
||||
[
|
||||
'route' => 'app_teamer_profile_index',
|
||||
'title' => 'Stammdaten und Foto',
|
||||
],
|
||||
[
|
||||
'route' => 'app_teamer_profile_skills',
|
||||
'title' => 'Jobprofile & Skills',
|
||||
],
|
||||
[
|
||||
'route' => 'app_teamer_profile_availabilities',
|
||||
'title' => 'Meine Verfügbarkeit',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'route' => false,
|
||||
'title' => 'Meine Einsätze',
|
||||
'icon' => 'bus',
|
||||
'children' => [
|
||||
[
|
||||
'route' => 'app_teamer_disposition_watchlist',
|
||||
'title' => 'Merkliste',
|
||||
],
|
||||
[
|
||||
'route' => 'app_teamer_disposition_watchlist',
|
||||
'title' => 'Offene Bewerbungen',
|
||||
],
|
||||
[
|
||||
'route' => 'app_teamer_disposition_watchlist',
|
||||
'title' => 'Nächste Einsätze',
|
||||
],
|
||||
[
|
||||
'route' => 'app_teamer_disposition_watchlist',
|
||||
'title' => 'Letzte Einsätze',
|
||||
],
|
||||
[
|
||||
'route' => 'app_teamer_disposition_watchlist',
|
||||
'title' => 'Meine Dokumente',
|
||||
],
|
||||
[
|
||||
'route' => 'app_teamer_disposition_watchlist',
|
||||
'title' => 'Mein Feedback',
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'route' => false,
|
||||
'title' => 'FAQ & Kontakt',
|
||||
'icon' => 'info',
|
||||
'children' => [
|
||||
[
|
||||
'route' => 'app_teamer_faq',
|
||||
'title' => 'FAQ',
|
||||
],
|
||||
[
|
||||
'route' => 'app_teamer_disposition_watchlist',
|
||||
'title' => 'Kontakt',
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$menu
|
||||
->addChild('Einsatzübersicht', ['route' => 'app_teamer_index'])
|
||||
->setChildrenAttribute('title', 'Einsatzübersicht')
|
||||
->setExtra('icon', 'calendar')
|
||||
;
|
||||
|
||||
$profileMenu = $menu
|
||||
->addChild('Mein Profil')
|
||||
->setExtra('icon', 'user')
|
||||
->setLinkAttribute('title', 'Mein Profil')
|
||||
;
|
||||
$profileMenu
|
||||
->addChild('Stammdaten und Foto', ['route' => 'app_teamer_profile_index'])
|
||||
->setLinkAttribute('title', 'Stammdaten und Foto')
|
||||
;
|
||||
$profileMenu
|
||||
->addChild('Jobprofile & Skills', ['route' => 'app_teamer_profile_skills'])
|
||||
->setLinkAttribute('title', 'Jobprofile & Skills')
|
||||
;
|
||||
$profileMenu
|
||||
->addChild('Meine Verfügbarkeit', ['route' => 'app_teamer_profile_availabilities'])
|
||||
->setLinkAttribute('title', 'Meine Verfügbarkeit')
|
||||
;
|
||||
|
||||
$dispositionMenu = $menu
|
||||
->addChild('Meine Einsätze')
|
||||
->setExtra('icon', 'bus')
|
||||
;
|
||||
$dispositionMenu
|
||||
->addChild('Merkliste', ['route' => 'app_teamer_disposition_watchlist'])
|
||||
->setLinkAttribute('title', 'Merkliste')
|
||||
;
|
||||
$dispositionMenu
|
||||
->addChild('Offene Bewerbungen', ['route' => 'app_teamer_disposition_watchlist'])
|
||||
->setLinkAttribute('title', 'Offene Bewerbungen')
|
||||
;
|
||||
$dispositionMenu
|
||||
->addChild('Nächste Einsätze', ['route' => 'app_teamer_disposition_watchlist'])
|
||||
->setLinkAttribute('title', 'Nächste Einsätze')
|
||||
;
|
||||
$dispositionMenu
|
||||
->addChild('Letzte Einsätze', ['route' => 'app_teamer_disposition_watchlist'])
|
||||
->setLinkAttribute('title', 'Letzte Einsätze')
|
||||
;
|
||||
$dispositionMenu
|
||||
->addChild('Meine Dokumente', ['route' => 'app_teamer_disposition_watchlist'])
|
||||
->setLinkAttribute('title', 'Meine Dokumente')
|
||||
;
|
||||
$dispositionMenu
|
||||
->addChild('Mein Feedback', ['route' => 'app_teamer_disposition_watchlist'])
|
||||
->setLinkAttribute('title', 'Mein Feedback')
|
||||
;
|
||||
|
||||
$faqMenu = $menu
|
||||
->addChild('FAQ & Kontakt')
|
||||
->setExtra('icon', 'info')
|
||||
;
|
||||
$faqMenu
|
||||
->addChild('FAQ', ['route' => 'app_teamer_disposition_watchlist'])
|
||||
->setLinkAttribute('title', 'FAQ')
|
||||
;
|
||||
$faqMenu
|
||||
->addChild('Kontakt', ['route' => 'app_teamer_disposition_watchlist'])
|
||||
->setLinkAttribute('title', 'Kontakt')
|
||||
;
|
||||
$menu = $this->createMenu($menuItems);
|
||||
|
||||
$this->addDivider($menu);
|
||||
|
||||
|
||||
@@ -20,47 +20,4 @@ class FaqRepository extends ServiceEntityRepository
|
||||
{
|
||||
parent::__construct($registry, Faq::class);
|
||||
}
|
||||
|
||||
public function save(Faq $entity, bool $flush = false): void
|
||||
{
|
||||
$this->getEntityManager()->persist($entity);
|
||||
|
||||
if ($flush) {
|
||||
$this->getEntityManager()->flush();
|
||||
}
|
||||
}
|
||||
|
||||
public function remove(Faq $entity, bool $flush = false): void
|
||||
{
|
||||
$this->getEntityManager()->remove($entity);
|
||||
|
||||
if ($flush) {
|
||||
$this->getEntityManager()->flush();
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return Faq[] Returns an array of Faq objects
|
||||
// */
|
||||
// public function findByExampleField($value): array
|
||||
// {
|
||||
// return $this->createQueryBuilder('f')
|
||||
// ->andWhere('f.exampleField = :val')
|
||||
// ->setParameter('val', $value)
|
||||
// ->orderBy('f.id', 'ASC')
|
||||
// ->setMaxResults(10)
|
||||
// ->getQuery()
|
||||
// ->getResult()
|
||||
// ;
|
||||
// }
|
||||
|
||||
// public function findOneBySomeField($value): ?Faq
|
||||
// {
|
||||
// return $this->createQueryBuilder('f')
|
||||
// ->andWhere('f.exampleField = :val')
|
||||
// ->setParameter('val', $value)
|
||||
// ->getQuery()
|
||||
// ->getOneOrNullResult()
|
||||
// ;
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ module.exports = {
|
||||
content: [
|
||||
'./templates/**/*.twig',
|
||||
],
|
||||
safelist: ['rotate-90'],
|
||||
theme: {
|
||||
container: {
|
||||
center: true,
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
{% extends 'admin/layout.html.twig' %}
|
||||
|
||||
{% block title %}Bewerbungsübersicht{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
Bewerbungsübersicht
|
||||
</h1>
|
||||
<div class="data-table-wrapper">
|
||||
<div class="data-table-wrapper__inner">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,21 @@
|
||||
{% extends 'admin/layout.html.twig' %}
|
||||
|
||||
{% block title %}Einsatzübersicht{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
Einsatzübersicht
|
||||
</h1>
|
||||
<div class="data-table-wrapper">
|
||||
<div class="data-table-wrapper__inner">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,21 @@
|
||||
{% extends 'admin/layout.html.twig' %}
|
||||
|
||||
{% block title %}Dokumentenübersicht{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
Dokumentenübersicht
|
||||
</h1>
|
||||
<div class="data-table-wrapper">
|
||||
<div class="data-table-wrapper__inner">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,15 @@
|
||||
{{ form_start(form) }}
|
||||
<div class="flex flex-col space-y-4 pb-8">
|
||||
{{ form_row(form.question) }}
|
||||
{{ form_row(form.answer) }}
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<button type="submit" class="btn">
|
||||
Speichern
|
||||
</button>
|
||||
<a href="{{ path('app_admin_system_faq_index') }}" class="btn btn--secondary">
|
||||
Abbrechen
|
||||
</a>
|
||||
</div>
|
||||
{{ form_rest(form) }}
|
||||
{{ form_end(form) }}
|
||||
@@ -0,0 +1,12 @@
|
||||
{% extends 'admin/layout.html.twig' %}
|
||||
|
||||
{% block title %}Einstellungen - FAQ anlegen{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="max-w-screen-sm">
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
FAQ anlegen
|
||||
</h1>
|
||||
{% include 'admin/system/faq/_form.html.twig' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,12 @@
|
||||
{% extends 'admin/layout.html.twig' %}
|
||||
|
||||
{% block title %}Einstellungen - FAQ bearbeiten{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="max-w-screen-sm">
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
FAQ bearbeiten
|
||||
</h1>
|
||||
{% include 'admin/system/faq/_form.html.twig' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,67 @@
|
||||
{% extends 'admin/layout.html.twig' %}
|
||||
|
||||
{% block title %}Einstellungen - FAQ{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
FAQ
|
||||
</h1>
|
||||
<div class="data-table-wrapper">
|
||||
<div class="data-table-wrapper__inner">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="w-2/5">
|
||||
Frage
|
||||
</th>
|
||||
<th class="w-2/5">
|
||||
Antwort
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody {{ stimulus_controller('sortable', { 'endpoint': path('app_admin_system_faq_sort') }) }}>
|
||||
{% for faq in faqs %}
|
||||
<tr {{ stimulus_target('sortable', 'item') }} data-item-id="{{ faq.id }}">
|
||||
<td>
|
||||
{{ faq.question }}
|
||||
</td>
|
||||
<td>
|
||||
{{ faq.answer|u.truncate(64, '...') }}
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex items-center space-x-2 justify-end">
|
||||
<button type="button"
|
||||
class="text-red-500"
|
||||
{{ stimulus_controller('modal-button', [], [], {'confirmation-modal': '#confirmation-modal'}) }}
|
||||
{{ stimulus_action('modal-button', 'confirmation', null, {
|
||||
'title': 'Bist du sicher?',
|
||||
'content': 'Möchtest du das Honorar wirklich löschen?',
|
||||
'target-url': path('app_admin_system_faq_delete', { 'id': faq.id })
|
||||
}) }}>
|
||||
{{ icon('delete') }}
|
||||
</button>
|
||||
<a href="{{ path('app_admin_system_faq_edit', { 'id': faq.id }) }}">
|
||||
{{ icon('edit') }}
|
||||
</a>
|
||||
<button type="button" class="cursor-move" {{ stimulus_target('sortable', 'handle') }}>
|
||||
{{ icon('sort') }}
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<div class="text-sm">Keine Daten...</div>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<a href="{{ path('app_admin_system_faq_create') }}" class="btn">
|
||||
Neu
|
||||
</a>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,12 @@
|
||||
{% extends 'admin/layout.html.twig' %}
|
||||
|
||||
{% block title %}Einstellungen - Job-Profil bearbeiten{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="max-w-screen-sm">
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
Job-Profil bearbeiten
|
||||
</h1>
|
||||
{% include 'admin/system/job_profile/_form.html.twig' %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -30,13 +30,30 @@
|
||||
{{ jobProfile.name }}
|
||||
</td>
|
||||
<td>
|
||||
{{ jobProfile.requiredTraining|default('-') }}
|
||||
{{ jobProfile.requiredTraining.name|default('-') }}
|
||||
</td>
|
||||
<td>
|
||||
{{ jobProfile.requiredLicenses|join(', ') }}
|
||||
<div class="flex items-center space-x-2">
|
||||
{% for license in jobProfile.requiredLicenses %}
|
||||
{{ icon(license, 'w-5 h-5') }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex items-center space-x-2 justify-end">
|
||||
<button type="button"
|
||||
class="text-red-500"
|
||||
{{ stimulus_controller('modal-button', [], [], {'confirmation-modal': '#confirmation-modal'}) }}
|
||||
{{ stimulus_action('modal-button', 'confirmation', null, {
|
||||
'title': 'Bist du sicher?',
|
||||
'content': 'Möchtest du das Job-Profil wirklich löschen?',
|
||||
'target-url': path('app_admin_system_job_profile_delete', { 'id': jobProfile.id })
|
||||
}) }}>
|
||||
{{ icon('delete') }}
|
||||
</button>
|
||||
<a href="{{ path('app_admin_system_job_profile_edit', { 'id': jobProfile.id }) }}">
|
||||
{{ icon('edit') }}
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -31,6 +31,19 @@
|
||||
</td>
|
||||
<td>
|
||||
<div class="flex items-center space-x-2 justify-end">
|
||||
<button type="button"
|
||||
class="text-red-500"
|
||||
{{ stimulus_controller('modal-button', [], [], {'confirmation-modal': '#confirmation-modal'}) }}
|
||||
{{ stimulus_action('modal-button', 'confirmation', null, {
|
||||
'title': 'Bist du sicher?',
|
||||
'content': 'Möchtest du die Fortbildung wirklich löschen?',
|
||||
'target-url': path('app_admin_system_training_delete', { 'id': training.id })
|
||||
}) }}>
|
||||
{{ icon('delete') }}
|
||||
</button>
|
||||
<a href="{{ path('app_admin_system_training_edit', { 'id': training.id }) }}">
|
||||
{{ icon('edit') }}
|
||||
</a>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
{% block body %}
|
||||
<div class="container grid lg:grid-cols-4 gap-8 py-8">
|
||||
<div class="lg:col-span-4 flex items-center justify-between">
|
||||
<img class="h-8 w-auto" src="{{ asset('build/images/logo.svg') }}" alt="My E&P Team">
|
||||
<a href="{{ path(app.user.defaultRoute) }}">
|
||||
<img class="h-8 w-auto" src="{{ asset('build/images/logo.svg') }}" alt="My E&P Team">
|
||||
</a>
|
||||
<a href="{{ path('app_security_logout') }}" class="hidden lg:block">
|
||||
{{ icon('logout', 'w-8 h-8 text-gray-700') }}
|
||||
</a>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="w-full h-screen flex flex-col items-center justify-center px-4">
|
||||
<div class="w-full max-w-sm">
|
||||
<h1 class="text-4xl font-bold text-gray-900 mb-6">
|
||||
MyE&P Teams
|
||||
MyE&P Team
|
||||
</h1>
|
||||
{% if error %}
|
||||
<div class="flex items-center space-x-1 bg-red-500 text-white p-2 rounded-md mb-6">
|
||||
@@ -32,6 +32,11 @@
|
||||
</button>
|
||||
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">
|
||||
</form>
|
||||
<div class="pt-4">
|
||||
<a href="{{ path('app_security_password_reset') }}" class="text-sm underline">
|
||||
Passwort vergessen?
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="w-full h-screen flex flex-col items-center justify-center px-4">
|
||||
<div class="w-full max-w-sm">
|
||||
<h1 class="text-4xl font-bold text-gray-900 mb-6">
|
||||
MyE&P Teams
|
||||
MyE&P Team
|
||||
</h1>
|
||||
{{ form_start(form) }}
|
||||
<div class="mb-6">
|
||||
@@ -19,6 +19,11 @@
|
||||
</button>
|
||||
{{ form_rest(form) }}
|
||||
{{ form_end(form) }}
|
||||
<div class="pt-4">
|
||||
<a href="{{ path('app_security_login') }}" class="text-sm underline">
|
||||
zurück zum Login
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
{% extends 'teamer/layout.html.twig' %}
|
||||
|
||||
{% block title %}FAQ{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1 class="text-2xl font-bold pb-8">
|
||||
FAQ
|
||||
</h1>
|
||||
<div class="flex flex-col space-y-4">
|
||||
{% for faq in faqs %}
|
||||
<div {{ stimulus_controller('toggle', [], {'closed': 'hidden'}) }}>
|
||||
<div {{ stimulus_action('toggle', 'toggle', 'click') }} role="button" class="flex items-center space-x-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-8 h-8" {{ stimulus_target('toggle', 'icon') }}>
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" />
|
||||
</svg>
|
||||
<span class="flex-1 text-xl">{{ faq.question }}</span>
|
||||
</div>
|
||||
<div class="hidden" {{ stimulus_target('toggle', 'toggle') }}>
|
||||
<div class="pl-10 pr-4 py-2">
|
||||
{{ faq.answer|nl2br }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user