Merge branch 'feature/ws' into develop

This commit is contained in:
Simon Vieille 2021-05-24 18:42:49 +02:00
commit 07ab45ce29
13 changed files with 304 additions and 12 deletions

View File

@ -6,19 +6,25 @@ module.exports = function() {
e.stopPropagation();
let container = $('#modal-container');
const body = $('body')
if (!container.length) {
container = $('<div id="modal-container" class="modal">');
$('body').append(container);
body.append(container);
}
container.html('');
const loader = $('<div style="position: absolute; top: 25vh; left: 50vw; z-index: 2000">')
loader.html('<div class="spinner-border text-primary" role="status"><span class="sr-only">Loading...</span></div>')
body.append(loader)
container.html();
const url = $(e.target).attr('data-modal');
$(container).modal('show');
container.load(url, function() {
$(container).modal('show');
loader.remove()
});
});

View File

@ -10,6 +10,7 @@ use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\HttpClient\Exception\ClientException;
use Symfony\Component\Console\Output\OutputInterface;
/**
* class SymfonyCacheManager.
@ -51,11 +52,14 @@ class SymfonyCacheManager
}
}
public function cleanAll()
public function cleanAll(OutputInterface $output = null)
{
$application = new Application($this->kernel);
$application->setAutoExit(false);
$output = new BufferedOutput();
if (null === $output) {
$output = new BufferedOutput();
}
$input = new ArrayInput([
'command' => 'cache:clear',

View File

@ -0,0 +1,59 @@
<?php
namespace App\Core\Controller\Task;
use App\Core\Controller\Admin\AdminController;
use App\Core\Event\Task\TaskInitEvent;
use App\Core\Event\Task\TaskRunRequestedEvent;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* @Route("/admin/task")
*/
class TaskAdminController extends AdminController
{
/**
* @Route("/", name="admin_task_index")
*/
public function index(EventDispatcherInterface $eventDispatcher): Response
{
$event = new TaskInitEvent();
$eventDispatcher->dispatch($event, TaskInitEvent::INIT_EVENT);
return $this->render('@Core/task/task_admin/index.html.twig', [
'pager' => $event->getTasks(),
]);
}
/**
* @Route("/run/{task}", name="admin_task_run", methods={"GET"})
*/
public function run(
string $task,
Request $request,
EventDispatcherInterface $eventDispatcher
): Response {
if (!$this->isCsrfTokenValid('task_run', $request->query->get('_token'))) {
throw $this->createAccessDeniedException();
}
$output = new BufferedOutput();
$event = new TaskRunRequestedEvent($task, $request->query, $output);
$eventDispatcher->dispatch($event, TaskRunRequestedEvent::RUN_REQUEST_EVENT);
$content = $output->fetch();
return $this->render('@Core/task/task_admin/run.html.twig', [
'output' => $content,
]);
}
public function getSection(): string
{
return 'task';
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace App\Core\Event\Task;
use Symfony\Contracts\EventDispatcher\Event;
/**
* class TaskInitEvent.
*
* @author Simon Vieille <simon@deblan.fr>
*/
class TaskInitEvent extends Event
{
const INIT_EVENT = 'task_event.init';
protected array $tasks = [];
public function getTasks(): array
{
usort($this->tasks, function ($t1, $t2) {
return $t1['section'] != $t2['section'];
});
return $this->tasks;
}
public function addTask(string $task, string $label, string $section): self
{
$this->tasks[$task] = [
'label' => $label,
'section' => $section,
'task' => $task,
];
return $this;
}
}

View File

@ -0,0 +1,44 @@
<?php
namespace App\Core\Event\Task;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
use Symfony\Component\HttpFoundation\InputBag;
use Symfony\Contracts\EventDispatcher\Event;
/**
* class TaskRunRequestedEvent.
*
* @author Simon Vieille <simon@deblan.fr>
*/
class TaskRunRequestedEvent extends Event
{
const RUN_REQUEST_EVENT = 'task_event.run_request';
protected string $task;
protected InputBag $parameters;
protected BufferedOutput $output;
public function __construct(string $task, InputBag $parameters, BufferedOutput $output)
{
$this->task = $task;
$this->parameters = $parameters;
$this->output = $output;
}
public function getTask(): string
{
return $this->task;
}
public function getParameters(): ParameterBagInterface
{
return $this->parameters;
}
public function getOutput(): BufferedOutput
{
return $this->output;
}
}

View File

@ -10,7 +10,7 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
*
* @author Simon Vieille <simon@deblan.fr>
*/
class SettingEventSubscriber implements EventSubscriberInterface
abstract class SettingEventSubscriber implements EventSubscriberInterface
{
protected static int $priority = 0;

View File

@ -0,0 +1,36 @@
<?php
namespace App\Core\EventSuscriber\Task;
use App\Core\Cache\SymfonyCacheManager;
use App\Core\Event\Task\TaskInitEvent;
use App\Core\Event\Task\TaskRunRequestedEvent;
/**
* class CacheCleanTaskEventSubscriber.
*
* @author Simon Vieille <simon@deblan.fr>
*/
class CacheCleanTaskEventSubscriber extends TaskEventSubscriber
{
protected SymfonyCacheManager $cacheManager;
public function __construct(SymfonyCacheManager $cacheManager)
{
$this->cacheManager = $cacheManager;
}
public function onInit(TaskInitEvent $event)
{
$event->addTask('cache:clear', 'Clean all cache', '♻️ Cache');
}
public function onRunRequest(TaskRunRequestedEvent $event)
{
if ('cache:clear' !== $event->getTask()) {
return;
}
$this->cacheManager->cleanAll($event->getOutput());
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace App\Core\EventSuscriber\Task;
use App\Core\Event\Task\TaskInitEvent;
use App\Core\Event\Task\TaskRunRequestedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* class TaskEventSubscriber.
*
* @author Simon Vieille <simon@deblan.fr>
*/
abstract class TaskEventSubscriber implements EventSubscriberInterface
{
protected static int $priority = 0;
public static function getSubscribedEvents()
{
return [
TaskInitEvent::INIT_EVENT => ['onInit', self::$priority],
TaskRunRequestedEvent::RUN_REQUEST_EVENT => ['onRunRequest', self::$priority],
];
}
public function onInit(TaskInitEvent $event)
{
}
public function onRunRequest(TaskRunRequestedEvent $event)
{
}
}

View File

@ -153,3 +153,7 @@
"Regular expression: do not add the delimiter": "Expréssion régulière : ne pas ajouter de délimiteur"
"Content type": "Type de contenu"
'Leave blank equals "text/html"': 'Laissez vide équivaut à "text/html"'
"Close": "Fermer"
"Tasks": "Tâches"
"Results": "Résultats"
"Clean all cache": "Nettoyer tout le cache"

View File

@ -68,6 +68,16 @@
</a>
</li>
<li class="nav-item">
<a class="nav-link {{ macros_menu.active_class('task', section) }}" href="{{ path('admin_task_index') }}">
<span class="fa fa-play"></span>
<span class="nav-item-label">
{{ 'Tasks'|trans }}
</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link {{ macros_menu.active_class('setting', section) }}" href="{{ path('admin_setting_index') }}">
<span class="fa fa-sliders-h"></span>

View File

@ -0,0 +1,5 @@
<div class="row">
<div class="col-md-12">
{{ form_widget(form) }}
</div>
</div>

View File

@ -0,0 +1,56 @@
{% extends '@Core/admin/layout.html.twig' %}
{% block title %}{{ 'Tasks'|trans }} - {{ parent() }}{% endblock %}
{% block body %}
<div class="bg-light pl-5 pr-4 pt-5 pb-5">
<div class="crud-header">
<h1 class="crud-header-title">{{ 'Tasks'|trans }}</h1>
</div>
</div>
<div class="table-responsive">
<table class="table">
<thead class="thead-light">
<tr>
<th class="col-5">{{ 'Label'|trans }}</th>
<th class="col-5">{{ 'Section'|trans }}</th>
<th class="col-2 miw-100 text-right">{{ 'Actions'|trans }}</th>
</tr>
</thead>
<tbody>
{% for item in pager %}
{% set run = path('admin_task_run', {
task: item.task,
_token: csrf_token('task_run')
}) %}
<tr>
<td class="col-5">
{{ item.label|trans }}
</td>
<td class="col-5">
<span class="btn btn-light">{{ item.section|trans }}</span>
</td>
<td class="col-2 miw-100 text-right">
<span data-modal="{{ run }}" class="btn btn-sm btn-primary mr-1">
<span data-modal="{{ run }}" class="fa fa-play"></span>
</span>
</td>
</tr>
{% else %}
<tr>
<td class="col-12 text-center p-4 text-black-50" colspan="3">
<div class="display-1">
<span class="fa fa-search"></span>
</div>
<div class="display-5 mt-3">
{{ 'No result'|trans }}
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

View File

@ -2,20 +2,18 @@
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">
{{ 'Filter'|trans }}
{{ 'Results'|trans }}
</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form action="{{ path('admin_site_page_index') }}" id="form-filters" method="GET">
{{ form_widget(form) }}
</form>
<pre>{{ output|trim }}</pre>
</div>
<div class="modal-footer">
<a href="{{ path('admin_site_page_index', {page_filter: 0}) }}" class="btn btn-secondary">{{ 'Vider'|trans }}</a>
<button type="submit" form="form-filters" class="btn btn-primary">{{ 'Filter'|trans }}</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{ 'Close'|trans }}</button>
</div>
</div>
</div>