<?php
namespace App\Controller\Admin;
use App\Entity\BlackList;
use App\Entity\ControllerUser;
use App\Entity\DictionaryImport;
use App\Entity\Eg\Admin\User;
use App\Entity\Eg\Admin\UserGroup;
use App\Entity\Eg\Osm\City;
use App\Entity\Eg\Osm\Device;
use App\Entity\Eg\Osm\Organization;
use App\Entity\Eg\Osm\ParkingType;
use App\Entity\Eg\Osm\Zone;
use App\Entity\EgFineExport;
use App\Entity\ElectricList;
use App\Entity\Fine;
use App\Entity\LapPair;
use App\Entity\RequestLog;
use App\Entity\Route as RouteEntity;
use App\Entity\RouteLap;
use App\Entity\VerificationStatus;
use Doctrine\ORM\EntityManagerInterface;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Assets;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Config\Dashboard;
use EasyCorp\Bundle\EasyAdminBundle\Config\MenuItem;
use EasyCorp\Bundle\EasyAdminBundle\Config\UserMenu;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
class AdminDashbordController extends AbstractDashboardController
{
/** @var Security */
protected $security;
/** @var ?Request */
protected $request;
/** @var EntityManagerInterface */
protected $manager;
public function __construct(Security $security, RequestStack $requestStack, EntityManagerInterface $entityManager)
{
$this->security = $security;
$this->request = $requestStack->getCurrentRequest();
$this->manager = $entityManager;
}
public function configureAssets(): Assets
{
return Assets::new()
->addWebpackEncoreEntry('app');
}
public function configureActions(): Actions
{
return Actions::new()
->add(Crud::PAGE_INDEX, Action::EDIT)
->add(Crud::PAGE_INDEX, Action::DETAIL)
->add(Crud::PAGE_DETAIL, Action::INDEX)
->add(Crud::PAGE_EDIT, Action::INDEX)
->add(Crud::PAGE_NEW, Action::INDEX)
->update(Crud::PAGE_INDEX, Action::DETAIL, fn (Action $action): Action => $action->setLabel('Pokaż')->setIcon('far fa-eye'))
->update(Crud::PAGE_INDEX, Action::EDIT, fn (Action $action): Action => $action->setLabel('Edytuj')->setIcon('fas fa-pencil-alt'))
->update(Crud::PAGE_DETAIL, Action::INDEX, fn (Action $action): Action => $action->setLabel('Wróć do listy')->setIcon('fas fa-list'))
->update(Crud::PAGE_EDIT, Action::INDEX, fn (Action $action): Action => $action->setLabel('Wróć do listy')->setIcon('fas fa-list'))
->update(Crud::PAGE_NEW, Action::INDEX, fn (Action $action): Action => $action->setLabel('Wróć do listy')->setIcon('fas fa-list'))
->add(Crud::PAGE_EDIT, Action::SAVE_AND_CONTINUE);
}
public function configureCrud(): Crud
{
$crud = Crud::new()
->setDefaultSort(['id' => 'DESC'])
->setDateTimeFormat('y-MM-dd HH:mm')
->overrideTemplate('crud/index', 'index.html.twig')
->overrideTemplate('crud/detail', 'detail.html.twig')
->overrideTemplate('crud/new', 'new.html.twig')
->overrideTemplate('crud/edit', 'edit.html.twig')
->overrideTemplate('crud/field/association', 'fields/association_edit.html.twig')
->overrideTemplate('layout', 'layout.html.twig')
->setPageTitle('detail', '%entity_label_singular% #%entity_id%')
->setFormThemes(['form.html.twig', '@EasyAdmin/crud/form_theme.html.twig'])
->setSearchFields(null)
->showEntityActionsInlined();
if ($this->request->query->has('indexPageTitle')) {
$crud->setPageTitle(Crud::PAGE_INDEX, $this->request->query->get('indexPageTitle'));
}
return $crud;
}
/**
* Funkcja odpowiadająca za elementy znajdujące się w wyświetlanym menu
*/
public function configureMenuItems(): iterable
{
$user = $this->security->getUser();
$menuItems = [MenuItem::linkToDashboard('Pulpit', 'fa fa-home')];
if ($this->isGranted('ROLE_LOGS')) {
$menuItems[] = MenuItem::section('Logi');
$requestLogLinks = [];
if ($user->isGranted('ROLE_REQUEST_LOGS_ALL')) {
$requestLogLinks[] = MenuItem::linkToCrud('Wszystkie', null, RequestLog::class);
}
if ($user->isGranted('ROLE_REQUEST_LOGS_UNVERIFIED')) {
$requestLogLinks[] = MenuItem::linkToCrud('Niezweryfikowane', null, RequestLog::class)
->setQueryParameter('isVerified', false)
->setQueryParameter('indexPageTitle', RequestLogCrudController::INDEX_PAGE_TITLES['unverified']);
}
if ($user->isGranted('ROLE_REQUEST_LOGS_VERIFIED')) {
$requestLogLinks[] = MenuItem::linkToCrud('Zweryfikowane', null, RequestLog::class)
->setQueryParameter('isVerified', true)
->setQueryParameter('indexPageTitle', RequestLogCrudController::INDEX_PAGE_TITLES['verified']);
}
if (\count($requestLogLinks) > 0) {
$menuItems[] = MenuItem::subMenu('Pojedyncze odczyty', 'fas fa-camera')->setSubItems($requestLogLinks);
}
$menuItems[] = MenuItem::linkToCrud('Przejazdy', 'fas fa-map-marker-alt', RouteLap::class);
$menuItems[] = MenuItem::linkToCrud('Pary przejazdów', 'fas fa-route', LapPair::class);
$fineLinks = [];
if ($user->isGranted('ROLE_SUPER_ADMIN')) {
$fineLinks[] = MenuItem::linkToCrud('Wszystkie', null, Fine::class);
}
if ($user->isGranted('ROLE_EXTENDED_FINES')) {
$fineLinks[] = MenuItem::linkToCrud('Wstępne', null, Fine::class)
->setQueryParameter('verificationStatus', VerificationStatus::PRELIMINARY)
->setQueryParameter('indexPageTitle', FineCrudController::INDEX_PAGE_TITLES[VerificationStatus::PRELIMINARY]);
}
$fineLinks[] = MenuItem::linkToCrud('Do weryfikacji', null, Fine::class)
->setQueryParameter('verificationStatus', VerificationStatus::TO_VERIFY)
->setQueryParameter('indexPageTitle', FineCrudController::INDEX_PAGE_TITLES[VerificationStatus::TO_VERIFY]);
$fineLinks[] = MenuItem::linkToCrud('Oczekujący na pozytywną weryfikację', null, Fine::class)
->setQueryParameter('verificationStatus', VerificationStatus::AWAITING_POSITIVE_VERIFICATION)
->setQueryParameter('indexPageTitle', FineCrudController::INDEX_PAGE_TITLES[VerificationStatus::AWAITING_POSITIVE_VERIFICATION]);
$fineLinks[] = MenuItem::linkToCrud('Oczekujący na negatywną weryfikację', null, Fine::class)
->setQueryParameter('verificationStatus', VerificationStatus::AWAITING_NEGATIVE_VERIFICATION)
->setQueryParameter('indexPageTitle', FineCrudController::INDEX_PAGE_TITLES[VerificationStatus::AWAITING_NEGATIVE_VERIFICATION]);
if ($user->isGranted('ROLE_EXTENDED_FINES')) {
$fineLinks[] = MenuItem::linkToCrud('Zweryfikowany pozytywnie', null, Fine::class)
->setQueryParameter('verificationStatus', VerificationStatus::POSITIVELY_VERIFIED)
->setQueryParameter('indexPageTitle', FineCrudController::INDEX_PAGE_TITLES[VerificationStatus::POSITIVELY_VERIFIED]);
$fineLinks[] = MenuItem::linkToCrud('Zweryfikowany negatywnie', null, Fine::class)
->setQueryParameter('verificationStatus', VerificationStatus::NEGATIVELY_VERIFIED)
->setQueryParameter('indexPageTitle', FineCrudController::INDEX_PAGE_TITLES[VerificationStatus::NEGATIVELY_VERIFIED]);
$fineLinks[] = MenuItem::linkToCrud('Wyeksportowany', null, Fine::class)
->setQueryParameter('verificationStatus', VerificationStatus::EXPORTED)
->setQueryParameter('indexPageTitle', FineCrudController::INDEX_PAGE_TITLES[VerificationStatus::EXPORTED]);
$fineLinks[] = MenuItem::linkToCrud('Automatycznie usunięte', null, Fine::class)
->setQueryParameter('verificationStatus', VerificationStatus::AUTOMATICALLY_DELETED)
->setQueryParameter('indexPageTitle', FineCrudController::INDEX_PAGE_TITLES[VerificationStatus::AUTOMATICALLY_DELETED]);
$fineLinks[] = MenuItem::linkToCrud('Ręcznie zanonimizowane', null, Fine::class)
->setQueryParameter('verificationStatus', VerificationStatus::MANUALLY_ANONYMIZED)
->setQueryParameter('indexPageTitle', FineCrudController::INDEX_PAGE_TITLES[VerificationStatus::MANUALLY_ANONYMIZED]);
$fineLinks[] = MenuItem::linkToCrud('Automatycznie zanonimizowane', null, Fine::class)
->setQueryParameter('verificationStatus', VerificationStatus::AUTOMATICALLY_ANONYMIZED)
->setQueryParameter('indexPageTitle', FineCrudController::INDEX_PAGE_TITLES[VerificationStatus::AUTOMATICALLY_ANONYMIZED]);
if ($user->isGranted('ROLE_SUPER_ADMIN')) {
$fineLinks[] = MenuItem::linkToCrud('Automatycznie zanonimizowane duplikaty (admin)', null, Fine::class)
->setQueryParameter('verificationStatus', VerificationStatus::AUTOMATICALLY_ANONYMIZED_DUPLICATE)
->setQueryParameter('indexPageTitle', FineCrudController::INDEX_PAGE_TITLES[VerificationStatus::AUTOMATICALLY_ANONYMIZED_DUPLICATE]);
}
}
$menuItems[] = MenuItem::subMenu('Zawiadomienia', 'fas fa-comment-dollar')->setSubItems($fineLinks);
// TODO: #28388 tymczasowe rozwiazanie az do ogarniecia tego widoku po stronie admina oraz WSow jak bedzie wiecej czasu
if ($_ENV['APP_ENV'] === 'dev' && $user->isGranted('ROLE_EG_EXPORTS')) {
$menuItems[] = MenuItem::linkToCrud('Grupowe eksporty', 'fas fa-file-export', EgFineExport::class);
}
}
// TODO: jeszcze pomyslec nad tą rolą, czy nie lepiej dać innej
if ($this->isGranted('ROLE_PARKING_LIST')) {
$menuItems[] = MenuItem::section('Strefy i Parkingi');
$menuItems[] = MenuItem::linkToCrud('Organizacje', 'fa fa-building', Organization::class);
$menuItems[] = MenuItem::linkToCrud('Miasta', 'fa fa-city', City::class);
$menuItems[] = MenuItem::linkToCrud('Strefy', 'fa fa-draw-polygon', Zone::class);
$menuItems[] = MenuItem::linkToCrud('Typy parkingów', 'fa fa-wheelchair', ParkingType::class);
}
if ($this->isGranted('ROLE_ROUTE_EDITOR')) {
$menuItems[] = MenuItem::section('Trasy');
$menuItems[] = MenuItem::linkToCrud('Zarządzanie trasami', 'fas fa-road', RouteEntity::class);
}
$menuItems[] = MenuItem::section('');
$menuItems[] = MenuItem::linkToRoute('Mapa', 'fa fa-map', 'map');
if ($this->isGranted('ROLE_STATISTICS')) {
$menuItems[] = MenuItem::section('Statystyki i zestawienia');
$menuItems[] = MenuItem::linktoRoute('Statystyki', 'fa fa-chart-bar', 'statistics');
$menuItems[] = MenuItem::linktoRoute('Zestawienia zawiadomień', 'fa fa-chart-bar', 'fine_statements');
$menuItems[] = MenuItem::linktoRoute('Zestawienia odczytów', 'fa fa-chart-bar', 'request_log_statements');
$menuItems[] = MenuItem::linktoRoute('Zestawienia eksportów', 'fa fa-chart-bar', 'log_exports_statements');
}
if ($this->isGranted('ROLE_USER_DISPLAY')) {
$menuItems[] = MenuItem::section('Administracja');
$menuItems[] = MenuItem::linkToCrud('Użytkownicy', 'fas fa-user', User::class);
}
if ($this->isGranted('ROLE_SUPER_ADMIN')) {
$menuItems[] = MenuItem::linkToCrud('Kontrolerzy', 'fas fa-mobile-alt', ControllerUser::class);
$menuItems[] = MenuItem::linkToCrud('Grupy Uprawnień', 'fas fa-users-cog', UserGroup::class);
$menuItems[] = MenuItem::linkToCrud('Import danych', 'fas fa-file-import', DictionaryImport::class)
->setPermission('ROLE_DATA_IMPORT');
$menuItems[] = MenuItem::linkToCrud('Czarna lista rejestracji', 'fas fa-ban', BlackList::class);
$menuItems[] = MenuItem::linkToCrud('Zestawy kontrolerskie', 'fa fa-video-camera', Device::class);
}
if ($this->isGranted('ROLE_ELECTRIC_LIST')) {
$menuItems[] = MenuItem::linkToCrud('Lista samochodów elektrycznych', 'fas fa-charging-station', ElectricList::class);
}
return $menuItems;
}
public function configureUserMenu(UserInterface $user): UserMenu
{
$url = $this->container->get(AdminUrlGenerator::class)
->setAction('changePassword')
->setController(UserCrudController::class)
->setEntityId($user->getId())
->set('referrer', urlencode($this->request->getRequestUri()))
->generateUrl();
return parent::configureUserMenu($user)
->addMenuItems([
MenuItem::linkToUrl('Zmień hasło', null, $url)
]);
}
/**
* Metoda do konfiguracji widoku pulpitu
*/
public function configureDashboard(): Dashboard
{
return Dashboard::new()
->disableUrlSignatures()
->setTitle('Admin kamery');
}
#[Route(path: '/admin', name: 'admin')]
public function index(): Response
{
$requestLogIndexes = $this->determineMenuIndex('Pojedyncze odczyty');
$routeLapIndexes = $this->determineMenuIndex('Przejazdy');
$lapPairIndexes = $this->determineMenuIndex('Pary przejazdów');
$fineIndexes = $this->determineMenuIndex('Zawiadomienia', 'Do weryfikacji');
$requestLogUrl = $this->container->get(AdminUrlGenerator::class)
->setAction('index')
->setController(RequestLogCrudController::class)
->set('menuIndex', $requestLogIndexes['menu'])
->set('submenuIndex', $requestLogIndexes['submenu'])
->generateUrl();
$routeLapUrl = $this->container->get(AdminUrlGenerator::class)
->setAction('index')
->setController(RouteLapCrudController::class)
->set('menuIndex', $routeLapIndexes['menu'])
->set('submenuIndex', $routeLapIndexes['submenu'])
->generateUrl();
$lapPairUrl = $this->container->get(AdminUrlGenerator::class)
->setAction('index')
->setController(LapPairCrudController::class)
->set('menuIndex', $lapPairIndexes['menu'])
->set('submenuIndex', $lapPairIndexes['submenu'])
->generateUrl();
$fineUrl = $this->container->get(AdminUrlGenerator::class)
->setAction('index')
->setController(FineCrudController::class)
->set('menuIndex', $fineIndexes['menu'])
->set('submenuIndex', $fineIndexes['submenu'])
->set('verificationStatus', VerificationStatus::TO_VERIFY)
->set('indexPageTitle', 'Zawiadomienia do weryfikacji')
->generateUrl();
$mapUrl = $this->redirectToRoute('map')->getTargetUrl();
return $this->render('start.html.twig', [
'requestLogUrl' => $requestLogUrl,
'routeLapUrl' => $routeLapUrl,
'lapPairUrl' => $lapPairUrl,
'fineUrl' => $fineUrl,
'mapUrl' => $mapUrl,
'serverData' => json_encode($_SERVER)
]);
}
#[Route(path: '/', name: 'blank')]
public function blank(): Response
{
return $this->redirectToRoute('admin');
}
#[Route(path: '/admin/map', name: 'map')]
public function showMap(): Response
{
// URL do edycji pojedynczych odczytów
// Aby podmienić wystarczy złapać parametr 'entityId=0' i podmienić go na odpowiednią wartość
$url = $this->container->get(AdminUrlGenerator::class)
->setAction(Crud::PAGE_EDIT)
->setController(RequestLogCrudController::class)
->setEntityId(0)
->set('referrer', '/admin/map')
->generateUrl();
return $this->render('map.html.twig', [
'requestLogURL' => $url
]);
}
#[Route(path: '/admin/statistics', name: 'statistics')]
public function renderStatistics(): Response
{
$this->denyAccessUnlessGranted('ROLE_STATISTICS');
return $this->render('stats/statistics.html.twig');
}
#[Route(path: '/admin/fine-statements', name: 'fine_statements')]
public function renderFineStatements(): Response
{
$this->denyAccessUnlessGranted('ROLE_STATISTICS');
return $this->render('stats/fine_statements.html.twig', [
'selectableUsers' => $this->manager->getRepository(User::class)->getAllUsernames(UserGroup::WORKERS_GROUP_NAMES)
]);
}
#[Route(path: '/admin/request-log-statements', name: 'request_log_statements')]
public function renderRequestLogStatements(): Response
{
$this->denyAccessUnlessGranted('ROLE_STATISTICS');
return $this->render('stats/request_log_statements.html.twig', [
'selectableUsers' => $this->manager->getRepository(User::class)->getAllUsernames(UserGroup::WORKERS_GROUP_NAMES)
]);
}
#[Route(path: '/admin/log-exports-statements', name: 'log_exports_statements')]
public function renderLogExportsStatements(): Response
{
$this->denyAccessUnlessGranted('ROLE_STATISTICS');
return $this->render('stats/log_exports_statements.html.twig');
}
/**
* Metoda służąca do obliczania indexu danej encji w menu
*/
private function determineMenuIndex(string $entityLabel, ?string $subEntityLabel = null)
{
$indexes = [
'menu' => -1,
'submenu' => -1
];
foreach ($this->configureMenuItems() as $index => $item) {
if ($item->getAsDto()->getLabel() == $entityLabel) {
$indexes['menu'] = $index;
if ($subEntityLabel) {
foreach ($item->getAsDto()->getSubItems() as $subIndex => $subItem) {
if ($subItem->getLabel() == $subEntityLabel) {
$indexes['submenu'] = $subIndex;
}
}
}
}
}
return $indexes;
}
}