From d88bc761e7ef988ec990c2430a1ddcae8eecf2d5 Mon Sep 17 00:00:00 2001 From: aina esokia Date: Thu, 29 Oct 2020 17:28:47 +0300 Subject: [PATCH 1/6] worker: validation reminder --- .../AdminConfigurationController.php | 25 ++- .../Provider/AlchemyWorkerServiceProvider.php | 5 + .../Provider/ControllerServiceProvider.php | 4 + .../WorkerManager/Queue/AMQPConnection.php | 19 +- .../WorkerManager/Queue/MessageHandler.php | 34 +-- .../WorkerManager/Queue/MessagePublisher.php | 13 +- .../Worker/ValidationReminderWorker.php | 193 ++++++++++++++++++ resources/locales/messages.de.xlf | 33 ++- resources/locales/messages.en.xlf | 33 ++- resources/locales/messages.fr.xlf | 33 ++- resources/locales/messages.nl.xlf | 33 ++- resources/locales/validators.de.xlf | 2 +- resources/locales/validators.en.xlf | 2 +- resources/locales/validators.fr.xlf | 2 +- resources/locales/validators.nl.xlf | 2 +- .../web/admin/worker-manager/index.html.twig | 6 + .../worker_validation_reminder.html.twig | 45 ++++ 17 files changed, 442 insertions(+), 42 deletions(-) create mode 100644 lib/Alchemy/Phrasea/WorkerManager/Worker/ValidationReminderWorker.php create mode 100644 templates/web/admin/worker-manager/worker_validation_reminder.html.twig diff --git a/lib/Alchemy/Phrasea/WorkerManager/Controller/AdminConfigurationController.php b/lib/Alchemy/Phrasea/WorkerManager/Controller/AdminConfigurationController.php index 9fad8d76de..af0840e6fb 100644 --- a/lib/Alchemy/Phrasea/WorkerManager/Controller/AdminConfigurationController.php +++ b/lib/Alchemy/Phrasea/WorkerManager/Controller/AdminConfigurationController.php @@ -210,6 +210,29 @@ class AdminConfigurationController extends Controller ]); } + public function validationReminderAction(PhraseaApplication $app, Request $request) + { + $interval = $app['conf']->get(['workers', 'validationReminder', 'interval'], 10); + + if ($request->getMethod() == 'POST') { + $reminderInterval = (int)$request->request->get('worker_reminder_interval'); + // save the period interval in second + $app['conf']->set(['workers', 'validationReminder', 'interval'], $reminderInterval); + + /** @var AMQPConnection $serverConnection */ + $serverConnection = $this->app['alchemy_worker.amqp.connection']; + // reinitialize the validation reminder queues + $serverConnection->reinitializeQueue([MessagePublisher::VALIDATION_REMINDER_QUEUE]); + $this->app['alchemy_worker.message.publisher']->initializeLoopQueue(MessagePublisher::VALIDATION_REMINDER_TYPE); + + return $app->redirectPath('worker_admin'); + } + + return $this->render('admin/worker-manager/worker_validation_reminder.html.twig', [ + 'interval' => $interval + ]); + } + public function populateStatusAction(PhraseaApplication $app, Request $request) { $databoxIds = $request->get('sbasIds'); @@ -236,7 +259,7 @@ class AdminConfigurationController extends Controller // reinitialize the pull queues $serverConnection->reinitializeQueue([MessagePublisher::PULL_QUEUE]); - $this->app['alchemy_worker.message.publisher']->initializePullAssets(); + $this->app['alchemy_worker.message.publisher']->initializeLoopQueue(MessagePublisher::PULL_ASSETS_TYPE); return $app->redirectPath('worker_admin'); } diff --git a/lib/Alchemy/Phrasea/WorkerManager/Provider/AlchemyWorkerServiceProvider.php b/lib/Alchemy/Phrasea/WorkerManager/Provider/AlchemyWorkerServiceProvider.php index d45858c855..c9593023e0 100644 --- a/lib/Alchemy/Phrasea/WorkerManager/Provider/AlchemyWorkerServiceProvider.php +++ b/lib/Alchemy/Phrasea/WorkerManager/Provider/AlchemyWorkerServiceProvider.php @@ -18,6 +18,7 @@ use Alchemy\Phrasea\WorkerManager\Worker\PullAssetsWorker; use Alchemy\Phrasea\WorkerManager\Worker\Resolver\TypeBasedWorkerResolver; use Alchemy\Phrasea\WorkerManager\Worker\SubdefCreationWorker; use Alchemy\Phrasea\WorkerManager\Worker\SubtitleWorker; +use Alchemy\Phrasea\WorkerManager\Worker\ValidationReminderWorker; use Alchemy\Phrasea\WorkerManager\Worker\WebhookWorker; use Alchemy\Phrasea\WorkerManager\Worker\WorkerInvoker; use Alchemy\Phrasea\WorkerManager\Worker\WriteMetadatasWorker; @@ -140,6 +141,10 @@ class AlchemyWorkerServiceProvider implements PluginProviderInterface $app['alchemy_worker.type_based_worker_resolver']->addFactory(MessagePublisher::MAIN_QUEUE_TYPE, new CallableWorkerFactory(function () use ($app) { return new MainQueueWorker($app['alchemy_worker.message.publisher'], $app['repo.worker-job']); })); + + $app['alchemy_worker.type_based_worker_resolver']->addFactory(MessagePublisher::VALIDATION_REMINDER_TYPE, new CallableWorkerFactory(function () use ($app) { + return new ValidationReminderWorker($app); + })); } /** diff --git a/lib/Alchemy/Phrasea/WorkerManager/Provider/ControllerServiceProvider.php b/lib/Alchemy/Phrasea/WorkerManager/Provider/ControllerServiceProvider.php index aca995c046..2ba171ceed 100644 --- a/lib/Alchemy/Phrasea/WorkerManager/Provider/ControllerServiceProvider.php +++ b/lib/Alchemy/Phrasea/WorkerManager/Provider/ControllerServiceProvider.php @@ -84,6 +84,10 @@ class ControllerServiceProvider implements ControllerProviderInterface, ServiceP ->method('GET|POST') ->bind('worker_admin_pullAssets'); + $controllers->match('/validation-reminder', 'controller.worker.admin.configuration:validationReminderAction') + ->method('GET|POST') + ->bind('worker_admin_validationReminder'); + $controllers->match('/queue-monitor', 'controller.worker.admin.configuration:queueMonitorAction') ->method('GET') ->bind('worker_admin_queue_monitor'); diff --git a/lib/Alchemy/Phrasea/WorkerManager/Queue/AMQPConnection.php b/lib/Alchemy/Phrasea/WorkerManager/Queue/AMQPConnection.php index 4508741ca7..6997ff872c 100644 --- a/lib/Alchemy/Phrasea/WorkerManager/Queue/AMQPConnection.php +++ b/lib/Alchemy/Phrasea/WorkerManager/Queue/AMQPConnection.php @@ -27,11 +27,12 @@ class AMQPConnection MessagePublisher::WEBHOOK_TYPE => MessagePublisher::WEBHOOK_QUEUE, MessagePublisher::ASSETS_INGEST_TYPE => MessagePublisher::ASSETS_INGEST_QUEUE, MessagePublisher::CREATE_RECORD_TYPE => MessagePublisher::CREATE_RECORD_QUEUE, - MessagePublisher::PULL_QUEUE => MessagePublisher::PULL_QUEUE, + MessagePublisher::PULL_ASSETS_TYPE => MessagePublisher::PULL_QUEUE, MessagePublisher::POPULATE_INDEX_TYPE => MessagePublisher::POPULATE_INDEX_QUEUE, MessagePublisher::DELETE_RECORD_TYPE => MessagePublisher::DELETE_RECORD_QUEUE, MessagePublisher::MAIN_QUEUE_TYPE => MessagePublisher::MAIN_QUEUE, - MessagePublisher::SUBTITLE_TYPE => MessagePublisher::SUBTITLE_QUEUE + MessagePublisher::SUBTITLE_TYPE => MessagePublisher::SUBTITLE_QUEUE, + MessagePublisher::VALIDATION_REMINDER_TYPE => MessagePublisher::VALIDATION_REMINDER_QUEUE ]; // the corresponding worker queues and retry queues, loop queue @@ -43,7 +44,8 @@ class AMQPConnection MessagePublisher::ASSETS_INGEST_QUEUE => MessagePublisher::RETRY_ASSETS_INGEST_QUEUE, MessagePublisher::CREATE_RECORD_QUEUE => MessagePublisher::RETRY_CREATE_RECORD_QUEUE, MessagePublisher::POPULATE_INDEX_QUEUE => MessagePublisher::RETRY_POPULATE_INDEX_QUEUE, - MessagePublisher::PULL_QUEUE => MessagePublisher::LOOP_PULL_QUEUE + MessagePublisher::PULL_QUEUE => MessagePublisher::LOOP_PULL_QUEUE, + MessagePublisher::VALIDATION_REMINDER_QUEUE => MessagePublisher::LOOP_VALIDATION_REMINDER_QUEUE ]; public static $defaultFailedQueues = [ @@ -61,6 +63,11 @@ class AMQPConnection MessagePublisher::SUBDEF_QUEUE => MessagePublisher::DELAYED_SUBDEF_QUEUE ]; + public static $defaultLoopTypes = [ + MessagePublisher::PULL_ASSETS_TYPE, + MessagePublisher::VALIDATION_REMINDER_TYPE + ]; + // default message TTL in retry queue in millisecond const RETRY_DELAY = 10000; @@ -264,6 +271,12 @@ class AMQPConnection isset($config['pull_assets']['pullInterval']) ) { // convert in milli second return (int)($config['pull_assets']['pullInterval']) * 1000; + } elseif ($routing == MessagePublisher::VALIDATION_REMINDER_QUEUE && + isset($config['validationReminder']) && + isset($config['validationReminder']['interval'])) { + + // convert in milli second + return (int)($config['validationReminder']['interval']) * 1000; } elseif (isset($config['retry_queue']) && isset($config['retry_queue'][array_search($routing, AMQPConnection::$defaultQueues)])) { diff --git a/lib/Alchemy/Phrasea/WorkerManager/Queue/MessageHandler.php b/lib/Alchemy/Phrasea/WorkerManager/Queue/MessageHandler.php index b06bbab265..7f13668903 100644 --- a/lib/Alchemy/Phrasea/WorkerManager/Queue/MessageHandler.php +++ b/lib/Alchemy/Phrasea/WorkerManager/Queue/MessageHandler.php @@ -4,6 +4,7 @@ namespace Alchemy\Phrasea\WorkerManager\Queue; use Alchemy\Phrasea\WorkerManager\Worker\ProcessPool; use Alchemy\Phrasea\WorkerManager\Worker\WorkerInvoker; +use PhpAmqpLib\Channel\AMQPChannel; use PhpAmqpLib\Message\AMQPMessage; use PhpAmqpLib\Wire\AMQPTable; use Ramsey\Uuid\Uuid; @@ -61,7 +62,7 @@ class MessageHandler } // if message is yet executed 3 times, save the unprocessed message in the corresponding failed queues - if ($count > self::MAX_OF_TRY && $data['message_type'] != MessagePublisher::PULL_ASSETS_TYPE) { + if ($count > self::MAX_OF_TRY && !in_array($data['message_type'], AMQPConnection::$defaultLoopTypes)) { $this->messagePublisher->publishFailedMessage($data['payload'], $headers, AMQPConnection::$defaultFailedQueues[$data['message_type']]); $logMessage = sprintf("Rabbit message executed 3 times, it's to be saved in %s , payload >>> %s", @@ -75,8 +76,8 @@ class MessageHandler try { $workerInvoker->invokeWorker($data['message_type'], json_encode($data['payload'])); - if ($data['message_type'] == MessagePublisher::PULL_ASSETS_TYPE) { - // make a loop for the pull assets + if (in_array($data['message_type'], AMQPConnection::$defaultLoopTypes)) { + // make a loop for the loop type $channel->basic_nack($message->delivery_info['delivery_tag']); } else { $channel->basic_ack($message->delivery_info['delivery_tag']); @@ -101,19 +102,26 @@ class MessageHandler foreach (AMQPConnection::$defaultQueues as $queueName) { if ($argQueueName ) { if (in_array($queueName, $argQueueName)) { - $serverConnection->setQueue($queueName); - - // give prefetch message to a worker consumer at a time - $channel->basic_qos(null, $prefetchCount, null); - $channel->basic_consume($queueName, Uuid::uuid4(), false, false, false, false, $callback); + $this->runConsumer($queueName, $serverConnection, $channel, $prefetchCount, $callback); } } else { - $serverConnection->setQueue($queueName); - - // give prefetch message to a worker consumer at a time - $channel->basic_qos(null, $prefetchCount, null); - $channel->basic_consume($queueName, Uuid::uuid4(), false, false, false, false, $callback); + $this->runConsumer($queueName, $serverConnection, $channel, $prefetchCount, $callback); } } } + + private function runConsumer($queueName, AMQPConnection $serverConnection, AMQPChannel $channel, $prefetchCount, $callback) + { + // initialize validation reminder when starting consumer + if ($queueName == MessagePublisher::VALIDATION_REMINDER_QUEUE) { + $serverConnection->reinitializeQueue([MessagePublisher::VALIDATION_REMINDER_QUEUE]); + $this->messagePublisher->initializeLoopQueue(MessagePublisher::VALIDATION_REMINDER_TYPE); + } + + $serverConnection->setQueue($queueName); + + // give prefetch message to a worker consumer at a time + $channel->basic_qos(null, $prefetchCount, null); + $channel->basic_consume($queueName, Uuid::uuid4(), false, false, false, false, $callback); + } } diff --git a/lib/Alchemy/Phrasea/WorkerManager/Queue/MessagePublisher.php b/lib/Alchemy/Phrasea/WorkerManager/Queue/MessagePublisher.php index 1a236e2a08..7191220d33 100644 --- a/lib/Alchemy/Phrasea/WorkerManager/Queue/MessagePublisher.php +++ b/lib/Alchemy/Phrasea/WorkerManager/Queue/MessagePublisher.php @@ -18,6 +18,7 @@ class MessagePublisher const WEBHOOK_TYPE = 'webhook'; const POPULATE_INDEX_TYPE = 'populateIndex'; const PULL_ASSETS_TYPE = 'pullAssets'; + const VALIDATION_REMINDER_TYPE = 'validationReminder'; const SUBTITLE_TYPE = 'subtitle'; const MAIN_QUEUE_TYPE = 'mainQueue'; @@ -35,6 +36,7 @@ class MessagePublisher const DELETE_RECORD_QUEUE = 'deleterecord-queue'; const POPULATE_INDEX_QUEUE = 'populateindex-queue'; const PULL_QUEUE = 'pull-queue'; + const VALIDATION_REMINDER_QUEUE = 'validationReminder-queue'; // retry queue // we can use these retry queue with TTL, so when message expires it is requeued to the corresponding worker queue @@ -45,8 +47,9 @@ class MessagePublisher const RETRY_ASSETS_INGEST_QUEUE = 'retry-ingest-queue'; const RETRY_CREATE_RECORD_QUEUE = 'retry-createrecord-queue'; const RETRY_POPULATE_INDEX_QUEUE = 'retry-populateindex-queue'; - // use this queue to make a loop on a consumer - const LOOP_PULL_QUEUE = 'loop-pull-queue'; + // use those queue to make a loop on a consumer + const LOOP_PULL_QUEUE = 'loop-pull-queue'; + const LOOP_VALIDATION_REMINDER_QUEUE = 'loop-validationReminder-queue'; // all failed queue, if message is treated over 3 times it goes to the failed queue const FAILED_EXPORT_QUEUE = 'failed-export-queue'; @@ -116,16 +119,16 @@ class MessagePublisher return true; } - public function initializePullAssets() + public function initializeLoopQueue($type) { $payload = [ - 'message_type' => self::PULL_ASSETS_TYPE, + 'message_type' => $type, 'payload' => [ 'initTimestamp' => new \DateTime('now', new \DateTimeZone('UTC')) ] ]; - $this->publishMessage($payload, self::PULL_QUEUE); + $this->publishMessage($payload, AMQPConnection::$defaultQueues[$type]); } public function connectionClose() diff --git a/lib/Alchemy/Phrasea/WorkerManager/Worker/ValidationReminderWorker.php b/lib/Alchemy/Phrasea/WorkerManager/Worker/ValidationReminderWorker.php new file mode 100644 index 0000000000..4801d209d2 --- /dev/null +++ b/lib/Alchemy/Phrasea/WorkerManager/Worker/ValidationReminderWorker.php @@ -0,0 +1,193 @@ +app = $app; + $this->messagePublisher = $this->app['alchemy_worker.message.publisher']; + $this->logger = $this->app['alchemy_worker.logger']; + } + + public function process(array $payload) + { + $this->setDelivererLocator(new LazyLocator($this->app, 'notification.deliverer')); + + $days = (int)$this->getConf()->get(['registry', 'actions', 'validation-reminder-days']); + + $interval = sprintf('P%dD', $days); + $now = new DateTime(); + + $dateTo = clone($now); + try { + $dateTo->add(new DateInterval($interval)); + } catch(\Exception $e) { + $this->logger->error(sprintf('Bad interval "%s" ?', $interval)); + return ; + } + + foreach ($this->getValidationParticipantRepository()->findNotConfirmedAndNotRemindedParticipantsByExpireDate($dateTo, $now) as $participant) { + $validationSession = $participant->getSession(); + $basket = $validationSession->getBasket(); + + $canSend = true; + + $user = $participant->getUser(); // always ok ! + try { + $str_email = $user->getEmail(); // force to hydrate + } catch (\Exception $e) { + $this->logger->error('user not found!'); + $canSend = false; + } + + $emails[] = + + // find the token if exists + // nb : a validation may have not generated tokens if forcing auth was required upon creation + $token = null; + try { + $token = $this->getTokenRepository()->findValidationToken($basket, $user); + } + catch (\Exception $e) { + // not unique token ? should not happen + $canSend = false; + } + + if(!$canSend) { + continue; + } + + if(!is_null($token)) { + $url = $this->app->url('lightbox_validation', ['basket' => $basket->getId(), 'LOG' => $token->getValue()]); + } else { + $url = $this->app->url('lightbox_validation', ['basket' => $basket->getId()]); + } + + $this->doRemind($participant, $basket, $url); + } + + $this->getEntityManager()->flush(); + } + + private function doRemind(ValidationParticipant $participant, Basket $basket, $url) + { + $params = [ + 'from' => $basket->getValidation()->getInitiator()->getId(), + 'to' => $participant->getUser()->getId(), + 'ssel_id' => $basket->getId(), + 'url' => $url, + ]; + + $datas = json_encode($params); + + $mailed = false; + + $userFrom = $basket->getValidation()->getInitiator(); + $userTo = $participant->getUser(); + + if ($this->shouldSendNotificationFor($participant->getUser(), 'eventsmanager_notify_validationreminder')) { + $readyToSend = false; + $title = $receiver = $emitter = null; + try { + $title = $basket->getName(); + + $receiver = Receiver::fromUser($userTo); + $emitter = Emitter::fromUser($userFrom); + + $readyToSend = true; + } + catch (\Exception $e) { + // no-op + } + + if ($readyToSend) { + $this->logger->info(sprintf(' -> remind "%s" from "%s" to "%s"', $title, $emitter->getEmail(), $receiver->getEmail())); + + $mail = MailInfoValidationReminder::create($this->app, $receiver, $emitter); + $mail->setButtonUrl($params['url']); + $mail->setTitle($title); + + $this->deliver($mail); + $mailed = true; + + $participant->setReminded(new DateTime('now')); + $this->getEntityManager()->persist($participant); + } + } + + return $this->app['events-manager']->notify($params['to'], 'eventsmanager_notify_validationreminder', $datas, $mailed); + } + + /** + * @param User $user + * @param $type + * @return mixed + */ + private function shouldSendNotificationFor(User $user, $type) + { + return $this->app['settings']->getUserNotificationSetting($user, $type); + } + + /** + * @return PropertyAccess + */ + private function getConf() + { + return $this->app['conf']; + } + + /** + * @return EntityManagerInterface + */ + private function getEntityManager() + { + return $this->app['orm.em']; + } + + /** + * @return ValidationParticipantRepository + */ + private function getValidationParticipantRepository() + { + return $this->app['repo.validation-participants']; + } + + /** + * @return TokenRepository + */ + private function getTokenRepository() + { + return $this->app['repo.tokens']; + } +} diff --git a/resources/locales/messages.de.xlf b/resources/locales/messages.de.xlf index 132e8d0047..f4143e8fac 100644 --- a/resources/locales/messages.de.xlf +++ b/resources/locales/messages.de.xlf @@ -1,6 +1,6 @@ - +
The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. @@ -9114,7 +9114,27 @@ admin::workermanager: Rabbit config error Konfigurationsfehler des Nachrichten Managers - admin/worker-manager/index.html.twig + admin/worker-manager/index.html.twig + + + admin::workermanager:tab:Reminder: Interval in second + admin::workermanager:tab:Reminder: Interval in second + admin/worker-manager/worker_validation_reminder.html.twig + + + admin::workermanager:tab:Reminder: Start + admin::workermanager:tab:Reminder: Start + admin/worker-manager/worker_validation_reminder.html.twig + + + admin::workermanager:tab:Reminder: Stop + admin::workermanager:tab:Reminder: Stop + admin/worker-manager/worker_validation_reminder.html.twig + + + admin::workermanager:tab:Reminder: description + admin::workermanager:tab:Reminder: description + admin/worker-manager/worker_validation_reminder.html.twig admin::workermanager:tab:configuration: title @@ -9199,6 +9219,11 @@ admin::workermanager:tab:queueMonitor: title Warteschlange + admin/worker-manager/index.html.twig + + + admin::workermanager:tab:reminder: title + admin::workermanager:tab:reminder: title admin/worker-manager/index.html.twig @@ -9359,7 +9384,7 @@ admin::workermanager:tab:workerinfo: Manually interrupt Unterbrechen - admin/worker-manager/worker_info.html.twig + admin/worker-manager/worker_info.html.twig admin::workermanager:tab:workerinfo: Refresh list @@ -9439,7 +9464,7 @@ admin:worker Retrieve configuration error Worker Abruf Konfigurationsfehler - admin/worker-manager/index.html.twig + admin/worker-manager/index.html.twig alert diff --git a/resources/locales/messages.en.xlf b/resources/locales/messages.en.xlf index 0bca5e4f91..10a64d45f4 100644 --- a/resources/locales/messages.en.xlf +++ b/resources/locales/messages.en.xlf @@ -1,6 +1,6 @@ - +
The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. @@ -9117,7 +9117,27 @@ admin::workermanager: Rabbit config error Message Queue configuration error - admin/worker-manager/index.html.twig + admin/worker-manager/index.html.twig + + + admin::workermanager:tab:Reminder: Interval in second + admin::workermanager:tab:Reminder: Interval in second + admin/worker-manager/worker_validation_reminder.html.twig + + + admin::workermanager:tab:Reminder: Start + admin::workermanager:tab:Reminder: Start + admin/worker-manager/worker_validation_reminder.html.twig + + + admin::workermanager:tab:Reminder: Stop + admin::workermanager:tab:Reminder: Stop + admin/worker-manager/worker_validation_reminder.html.twig + + + admin::workermanager:tab:Reminder: description + admin::workermanager:tab:Reminder: description + admin/worker-manager/worker_validation_reminder.html.twig admin::workermanager:tab:configuration: title @@ -9202,6 +9222,11 @@ admin::workermanager:tab:queueMonitor: title Queues + admin/worker-manager/index.html.twig + + + admin::workermanager:tab:reminder: title + admin::workermanager:tab:reminder: title admin/worker-manager/index.html.twig @@ -9362,7 +9387,7 @@ admin::workermanager:tab:workerinfo: Manually interrupt interrupt - admin/worker-manager/worker_info.html.twig + admin/worker-manager/worker_info.html.twig admin::workermanager:tab:workerinfo: Refresh list @@ -9442,7 +9467,7 @@ admin:worker Retrieve configuration error Worker Retrieve configuration error - admin/worker-manager/index.html.twig + admin/worker-manager/index.html.twig alert diff --git a/resources/locales/messages.fr.xlf b/resources/locales/messages.fr.xlf index 460c5c5304..85d52a5c4c 100644 --- a/resources/locales/messages.fr.xlf +++ b/resources/locales/messages.fr.xlf @@ -1,6 +1,6 @@ - +
The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. @@ -9117,7 +9117,27 @@ Si vous recevez cet e-mail sans l'avoir sollicité, merci de l'ignorer ou de le admin::workermanager: Rabbit config error Erreur dans la configuration du gestionnaire de messages - admin/worker-manager/index.html.twig + admin/worker-manager/index.html.twig + + + admin::workermanager:tab:Reminder: Interval in second + admin::workermanager:tab:Reminder: Interval in second + admin/worker-manager/worker_validation_reminder.html.twig + + + admin::workermanager:tab:Reminder: Start + admin::workermanager:tab:Reminder: Start + admin/worker-manager/worker_validation_reminder.html.twig + + + admin::workermanager:tab:Reminder: Stop + admin::workermanager:tab:Reminder: Stop + admin/worker-manager/worker_validation_reminder.html.twig + + + admin::workermanager:tab:Reminder: description + admin::workermanager:tab:Reminder: description + admin/worker-manager/worker_validation_reminder.html.twig admin::workermanager:tab:configuration: title @@ -9202,6 +9222,11 @@ Si vous recevez cet e-mail sans l'avoir sollicité, merci de l'ignorer ou de le admin::workermanager:tab:queueMonitor: title Files de message + admin/worker-manager/index.html.twig + + + admin::workermanager:tab:reminder: title + admin::workermanager:tab:reminder: title admin/worker-manager/index.html.twig @@ -9362,7 +9387,7 @@ Si vous recevez cet e-mail sans l'avoir sollicité, merci de l'ignorer ou de le admin::workermanager:tab:workerinfo: Manually interrupt interrompre - admin/worker-manager/worker_info.html.twig + admin/worker-manager/worker_info.html.twig admin::workermanager:tab:workerinfo: Refresh list @@ -9442,7 +9467,7 @@ Si vous recevez cet e-mail sans l'avoir sollicité, merci de l'ignorer ou de le admin:worker Retrieve configuration error Erreur lors de la récupération de la configuration des workers - admin/worker-manager/index.html.twig + admin/worker-manager/index.html.twig alert diff --git a/resources/locales/messages.nl.xlf b/resources/locales/messages.nl.xlf index 2874b8e3d6..30f7a5e403 100644 --- a/resources/locales/messages.nl.xlf +++ b/resources/locales/messages.nl.xlf @@ -1,6 +1,6 @@ - +
The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. @@ -9124,7 +9124,27 @@ admin::workermanager: Rabbit config error admin::workermanager: Rabbit config error - admin/worker-manager/index.html.twig + admin/worker-manager/index.html.twig + + + admin::workermanager:tab:Reminder: Interval in second + admin::workermanager:tab:Reminder: Interval in second + admin/worker-manager/worker_validation_reminder.html.twig + + + admin::workermanager:tab:Reminder: Start + admin::workermanager:tab:Reminder: Start + admin/worker-manager/worker_validation_reminder.html.twig + + + admin::workermanager:tab:Reminder: Stop + admin::workermanager:tab:Reminder: Stop + admin/worker-manager/worker_validation_reminder.html.twig + + + admin::workermanager:tab:Reminder: description + admin::workermanager:tab:Reminder: description + admin/worker-manager/worker_validation_reminder.html.twig admin::workermanager:tab:configuration: title @@ -9209,6 +9229,11 @@ admin::workermanager:tab:queueMonitor: title admin::workermanager:tab:queueMonitor: title + admin/worker-manager/index.html.twig + + + admin::workermanager:tab:reminder: title + admin::workermanager:tab:reminder: title admin/worker-manager/index.html.twig @@ -9369,7 +9394,7 @@ admin::workermanager:tab:workerinfo: Manually interrupt admin::workermanager:tab:workerinfo: Manually interrupt - admin/worker-manager/worker_info.html.twig + admin/worker-manager/worker_info.html.twig admin::workermanager:tab:workerinfo: Refresh list @@ -9449,7 +9474,7 @@ admin:worker Retrieve configuration error admin:worker Retrieve configuration error - admin/worker-manager/index.html.twig + admin/worker-manager/index.html.twig alert diff --git a/resources/locales/validators.de.xlf b/resources/locales/validators.de.xlf index 620eaf460e..e13abdc3b7 100644 --- a/resources/locales/validators.de.xlf +++ b/resources/locales/validators.de.xlf @@ -1,6 +1,6 @@ - +
The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. diff --git a/resources/locales/validators.en.xlf b/resources/locales/validators.en.xlf index 9ad24dae56..21b2e0507a 100644 --- a/resources/locales/validators.en.xlf +++ b/resources/locales/validators.en.xlf @@ -1,6 +1,6 @@ - +
The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. diff --git a/resources/locales/validators.fr.xlf b/resources/locales/validators.fr.xlf index 2952bd16e4..296a7eb92e 100644 --- a/resources/locales/validators.fr.xlf +++ b/resources/locales/validators.fr.xlf @@ -1,6 +1,6 @@ - +
The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. diff --git a/resources/locales/validators.nl.xlf b/resources/locales/validators.nl.xlf index 013bdc7130..8df9fda145 100644 --- a/resources/locales/validators.nl.xlf +++ b/resources/locales/validators.nl.xlf @@ -1,6 +1,6 @@ - +
The source node in most cases contains the sample message as written by the developer. If it looks like a dot-delimitted string such as "form.label.firstname", then the developer has not provided a default message. diff --git a/templates/web/admin/worker-manager/index.html.twig b/templates/web/admin/worker-manager/index.html.twig index 50d27d9b6e..f50d30bbf0 100644 --- a/templates/web/admin/worker-manager/index.html.twig +++ b/templates/web/admin/worker-manager/index.html.twig @@ -35,6 +35,11 @@ {{ 'admin::workermanager:tab:metadata: title' |trans }} +