- Refactors and renames code
- Adds Queue menu option and displays status
This commit is contained in:
56
assets/js/src/queue.jsx
Normal file
56
assets/js/src/queue.jsx
Normal file
@@ -0,0 +1,56 @@
|
||||
define(
|
||||
[
|
||||
'react',
|
||||
'react-dom',
|
||||
'mailpoet',
|
||||
'classnames'
|
||||
],
|
||||
function (
|
||||
React,
|
||||
ReactDOM,
|
||||
MailPoet,
|
||||
classNames
|
||||
) {
|
||||
var QueueDaemonControl = React.createClass({
|
||||
getInitialState: function () {
|
||||
return (queueDaemon) ? {status: queueDaemon.status} : null;
|
||||
},
|
||||
getDaemonData: function () {
|
||||
MailPoet.Ajax.post({
|
||||
endpoint: 'queue',
|
||||
action: 'getQueueStatus'
|
||||
}).done(function (response) {
|
||||
this.setState({status: response.status});
|
||||
}.bind(this));
|
||||
},
|
||||
componentDidMount: function () {
|
||||
this.getDaemonData;
|
||||
setInterval(this.getDaemonData, 2000);
|
||||
},
|
||||
render: function () {
|
||||
if (!this.state) {
|
||||
return (
|
||||
<div className="QueueControl">
|
||||
If you're seeing this message, queue daemon has not even been created!
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div>
|
||||
Queue is currently <b>{this.state.status}</b>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
let container = document.getElementById('queue_container');
|
||||
|
||||
if (container) {
|
||||
ReactDOM.render(
|
||||
<QueueDaemonControl />,
|
||||
container
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
);
|
@@ -8,7 +8,9 @@
|
||||
"tburry/pquery": "*",
|
||||
"j4mie/paris": "1.5.4",
|
||||
"swiftmailer/swiftmailer": "^5.4",
|
||||
"phpseclib/phpseclib": "*"
|
||||
"phpseclib/phpseclib": "*",
|
||||
"mtdowling/cron-expression": "^1.0",
|
||||
"nesbot/carbon": "^1.21"
|
||||
},
|
||||
"require-dev": {
|
||||
"codeception/codeception": "*",
|
||||
|
@@ -137,7 +137,7 @@ class Initializer {
|
||||
function runQueueSupervisor() {
|
||||
try {
|
||||
$supervisor = new Supervisor();
|
||||
$supervisor->checkQueue();
|
||||
$supervisor->checkDaemon();
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
}
|
||||
|
@@ -2,16 +2,17 @@
|
||||
namespace MailPoet\Config;
|
||||
|
||||
use MailPoet\Subscribers\ImportExport\BootStrapMenu;
|
||||
use \MailPoet\Models\Segment;
|
||||
use \MailPoet\Models\Setting;
|
||||
use \MailPoet\Models\Form;
|
||||
use \MailPoet\Form\Block;
|
||||
use \MailPoet\Form\Renderer as FormRenderer;
|
||||
use \MailPoet\Settings\Hosts;
|
||||
use \MailPoet\Settings\Pages;
|
||||
use \MailPoet\Settings\Charsets;
|
||||
use \MailPoet\Util\Permissions;
|
||||
use \MailPoet\Util\DKIM;
|
||||
use MailPoet\Form\Block;
|
||||
use MailPoet\Form\Renderer as FormRenderer;
|
||||
use MailPoet\Models\Form;
|
||||
use MailPoet\Models\Segment;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Settings\Charsets;
|
||||
use MailPoet\Settings\Hosts;
|
||||
use MailPoet\Settings\Pages;
|
||||
use MailPoet\Subscribers\ImportExport\BootStrapMenu;
|
||||
use MailPoet\Util\DKIM;
|
||||
use MailPoet\Util\Permissions;
|
||||
|
||||
if(!defined('ABSPATH')) exit;
|
||||
|
||||
@@ -24,7 +25,10 @@ class Menu {
|
||||
function init() {
|
||||
add_action(
|
||||
'admin_menu',
|
||||
array($this, 'setup')
|
||||
array(
|
||||
$this,
|
||||
'setup'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -34,7 +38,10 @@ class Menu {
|
||||
'MailPoet',
|
||||
'manage_options',
|
||||
'mailpoet',
|
||||
array($this, 'home'),
|
||||
array(
|
||||
$this,
|
||||
'home'
|
||||
),
|
||||
$this->assets_url . '/img/menu_icon.png',
|
||||
30
|
||||
);
|
||||
@@ -44,7 +51,10 @@ class Menu {
|
||||
__('Newsletters'),
|
||||
'manage_options',
|
||||
'mailpoet-newsletters',
|
||||
array($this, 'newsletters')
|
||||
array(
|
||||
$this,
|
||||
'newsletters'
|
||||
)
|
||||
);
|
||||
add_submenu_page(
|
||||
'mailpoet',
|
||||
@@ -52,7 +62,10 @@ class Menu {
|
||||
__('Forms'),
|
||||
'manage_options',
|
||||
'mailpoet-forms',
|
||||
array($this, 'forms')
|
||||
array(
|
||||
$this,
|
||||
'forms'
|
||||
)
|
||||
);
|
||||
add_submenu_page(
|
||||
'mailpoet',
|
||||
@@ -60,7 +73,10 @@ class Menu {
|
||||
__('Subscribers'),
|
||||
'manage_options',
|
||||
'mailpoet-subscribers',
|
||||
array($this, 'subscribers')
|
||||
array(
|
||||
$this,
|
||||
'subscribers'
|
||||
)
|
||||
);
|
||||
add_submenu_page(
|
||||
'mailpoet',
|
||||
@@ -68,7 +84,10 @@ class Menu {
|
||||
__('Segments'),
|
||||
'manage_options',
|
||||
'mailpoet-segments',
|
||||
array($this, 'segments')
|
||||
array(
|
||||
$this,
|
||||
'segments'
|
||||
)
|
||||
);
|
||||
add_submenu_page(
|
||||
'mailpoet',
|
||||
@@ -76,7 +95,10 @@ class Menu {
|
||||
__('Settings'),
|
||||
'manage_options',
|
||||
'mailpoet-settings',
|
||||
array($this, 'settings')
|
||||
array(
|
||||
$this,
|
||||
'settings'
|
||||
)
|
||||
);
|
||||
add_submenu_page(
|
||||
null,
|
||||
@@ -84,7 +106,10 @@ class Menu {
|
||||
__('Import'),
|
||||
'manage_options',
|
||||
'mailpoet-import',
|
||||
array($this, 'import')
|
||||
array(
|
||||
$this,
|
||||
'import'
|
||||
)
|
||||
);
|
||||
add_submenu_page(
|
||||
null,
|
||||
@@ -92,7 +117,10 @@ class Menu {
|
||||
__('Export'),
|
||||
'manage_options',
|
||||
'mailpoet-export',
|
||||
array($this, 'export')
|
||||
array(
|
||||
$this,
|
||||
'export'
|
||||
)
|
||||
);
|
||||
|
||||
add_submenu_page(
|
||||
@@ -101,7 +129,10 @@ class Menu {
|
||||
__('Welcome'),
|
||||
'manage_options',
|
||||
'mailpoet-welcome',
|
||||
array($this, 'welcome')
|
||||
array(
|
||||
$this,
|
||||
'welcome'
|
||||
)
|
||||
);
|
||||
|
||||
add_submenu_page(
|
||||
@@ -110,7 +141,10 @@ class Menu {
|
||||
__('Update'),
|
||||
'manage_options',
|
||||
'mailpoet-update',
|
||||
array($this, 'update')
|
||||
array(
|
||||
$this,
|
||||
'update'
|
||||
)
|
||||
);
|
||||
|
||||
add_submenu_page(
|
||||
@@ -119,7 +153,10 @@ class Menu {
|
||||
__('Form editor'),
|
||||
'manage_options',
|
||||
'mailpoet-form-editor',
|
||||
array($this, 'formEditor')
|
||||
array(
|
||||
$this,
|
||||
'formEditor'
|
||||
)
|
||||
);
|
||||
|
||||
add_submenu_page(
|
||||
@@ -128,7 +165,22 @@ class Menu {
|
||||
__('Newsletter editor'),
|
||||
'manage_options',
|
||||
'mailpoet-newsletter-editor',
|
||||
array($this, 'newletterEditor')
|
||||
array(
|
||||
$this,
|
||||
'newletterEditor'
|
||||
)
|
||||
);
|
||||
|
||||
add_submenu_page(
|
||||
'mailpoet',
|
||||
__('Queue'),
|
||||
__('Queue'),
|
||||
'manage_options',
|
||||
'mailpoet-queue',
|
||||
array(
|
||||
$this,
|
||||
'queue'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -142,8 +194,8 @@ class Menu {
|
||||
$current_url = home_url(add_query_arg($wp->query_string, $wp->request));
|
||||
$redirect_url =
|
||||
(!empty($_GET['mailpoet_redirect']))
|
||||
? urldecode($_GET['mailpoet_redirect'])
|
||||
: wp_get_referer();
|
||||
? urldecode($_GET['mailpoet_redirect'])
|
||||
: wp_get_referer();
|
||||
|
||||
if(
|
||||
$redirect_url === $current_url
|
||||
@@ -166,8 +218,8 @@ class Menu {
|
||||
$current_url = home_url(add_query_arg($wp->query_string, $wp->request));
|
||||
$redirect_url =
|
||||
(!empty($_GET['mailpoet_redirect']))
|
||||
? urldecode($_GET['mailpoet_redirect'])
|
||||
: wp_get_referer();
|
||||
? urldecode($_GET['mailpoet_redirect'])
|
||||
: wp_get_referer();
|
||||
|
||||
if(
|
||||
$redirect_url === $current_url
|
||||
@@ -206,7 +258,8 @@ class Menu {
|
||||
|
||||
$data = array(
|
||||
'settings' => $settings,
|
||||
'segments' => Segment::getPublic()->findArray(),
|
||||
'segments' => Segment::getPublished()
|
||||
->findArray(),
|
||||
'pages' => Pages::getAll(),
|
||||
'flags' => $this->_getFlags(),
|
||||
'charsets' => Charsets::getAll(),
|
||||
@@ -234,11 +287,14 @@ class Menu {
|
||||
|
||||
// check if users can register
|
||||
$flags['registration_enabled'] =
|
||||
!(in_array($registration, array('none', 'blog')));
|
||||
!(in_array($registration, array(
|
||||
'none',
|
||||
'blog'
|
||||
)));
|
||||
} else {
|
||||
// check if users can register
|
||||
$flags['registration_enabled'] =
|
||||
(bool)get_option('users_can_register', false);
|
||||
(bool) get_option('users_can_register', false);
|
||||
}
|
||||
|
||||
return $flags;
|
||||
@@ -272,7 +328,7 @@ class Menu {
|
||||
$data['segments'] = Segment::findArray();
|
||||
$settings = Setting::findArray();
|
||||
$data['settings'] = array();
|
||||
foreach($settings as $setting) {
|
||||
foreach ($settings as $setting) {
|
||||
$data['settings'][$setting['name']] = $setting['value'];
|
||||
}
|
||||
$data['roles'] = $wp_roles->get_names();
|
||||
@@ -300,7 +356,7 @@ class Menu {
|
||||
}
|
||||
|
||||
function formEditor() {
|
||||
$id = (isset($_GET['id']) ? (int)$_GET['id'] : 0);
|
||||
$id = (isset($_GET['id']) ? (int) $_GET['id'] : 0);
|
||||
$form = Form::findOne($id);
|
||||
if($form !== false) {
|
||||
$form = $form->asArray();
|
||||
@@ -309,7 +365,8 @@ class Menu {
|
||||
$data = array(
|
||||
'form' => $form,
|
||||
'pages' => Pages::getAll(),
|
||||
'segments' => Segment::getPublic()->findArray(),
|
||||
'segments' => Segment::getPublished()
|
||||
->findArray(),
|
||||
'styles' => FormRenderer::getStyles($form),
|
||||
'date_types' => Block\Date::getDateTypes(),
|
||||
'date_formats' => Block\Date::getDateFormats()
|
||||
@@ -317,4 +374,10 @@ class Menu {
|
||||
|
||||
echo $this->renderer->render('form/editor.html', $data);
|
||||
}
|
||||
|
||||
function queue() {
|
||||
$daemon = new \MailPoet\Queue\BootStrapMenu();
|
||||
$data['daemon'] = json_encode($daemon->bootstrap());
|
||||
echo $this->renderer->render('queue.html', $data);
|
||||
}
|
||||
}
|
24
lib/Queue/BootStrapMenu.php
Normal file
24
lib/Queue/BootStrapMenu.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
namespace MailPoet\Queue;
|
||||
|
||||
use MailPoet\Models\Setting;
|
||||
|
||||
class BootStrapMenu {
|
||||
function __construct() {
|
||||
$this->daemon = Setting::where('name', 'daemon')
|
||||
->findOne()
|
||||
->asArray();
|
||||
}
|
||||
|
||||
function bootStrap() {
|
||||
return ($this->daemon) ?
|
||||
array_merge(
|
||||
array(
|
||||
'started_at' => $this->daemon['created_at'],
|
||||
'updated_at' => $this->daemon['updated_at']
|
||||
),
|
||||
json_decode($this->daemon['value'], true)
|
||||
) :
|
||||
"false";
|
||||
}
|
||||
}
|
@@ -12,7 +12,7 @@ class Daemon {
|
||||
function __construct($payload = array()) {
|
||||
set_time_limit(0);
|
||||
ignore_user_abort();
|
||||
list ($this->queue, $this->queueData) = $this->getQueue();
|
||||
list ($this->daemon, $this->daemonData) = $this->getDaemon();
|
||||
$this->refreshedToken = $this->refreshToken();
|
||||
$this->payload = $payload;
|
||||
$this->timer = microtime(true);
|
||||
@@ -23,30 +23,30 @@ class Daemon {
|
||||
$this->abortWithError('missing session ID');
|
||||
}
|
||||
$this->manageSession('start');
|
||||
$queue = $this->queue;
|
||||
$queueData = $this->queueData;
|
||||
if(!$queue) {
|
||||
$queue = Setting::create();
|
||||
$queue->name = 'queue';
|
||||
$queue->value = json_encode(array('status' => 'stopped'));
|
||||
$queue->save();
|
||||
$daemon = $this->daemon;
|
||||
$daemonData = $this->daemonData;
|
||||
if(!$daemon) {
|
||||
$daemon = Setting::create();
|
||||
$daemon->name = 'daemon';
|
||||
$daemon->value = json_encode(array('status' => 'stopped'));
|
||||
$daemon->save();
|
||||
}
|
||||
if($queueData['status'] !== 'started') {
|
||||
$_SESSION['queue'] = 'started';
|
||||
$queueData = array(
|
||||
if($daemonData['status'] !== 'started') {
|
||||
$_SESSION['daemon'] = 'started';
|
||||
$daemonData = array(
|
||||
'status' => 'started',
|
||||
'token' => $this->refreshedToken,
|
||||
'counter' => ($queueData['status'] === 'paused') ?
|
||||
$queueData['counter'] :
|
||||
'counter' => ($daemonData['status'] === 'paused') ?
|
||||
$daemonData['counter'] :
|
||||
0
|
||||
);
|
||||
$_SESSION['queue'] = array('result' => true);
|
||||
$_SESSION['daemon'] = array('result' => true);
|
||||
$this->manageSession('end');
|
||||
$queue->value = json_encode($queueData);
|
||||
$queue->save();
|
||||
$daemon->value = json_encode($daemonData);
|
||||
$daemon->save();
|
||||
$this->callSelf();
|
||||
} else {
|
||||
$_SESSION['queue'] = array(
|
||||
$_SESSION['daemon'] = array(
|
||||
'result' => false,
|
||||
'error' => 'already started'
|
||||
);
|
||||
@@ -55,33 +55,37 @@ class Daemon {
|
||||
}
|
||||
|
||||
function run() {
|
||||
if(!$this->queue || $this->queueData['status'] !== 'started') {
|
||||
if(!$this->daemon || $this->daemonData['status'] !== 'started') {
|
||||
$this->abortWithError('not running');
|
||||
}
|
||||
if(!isset($this->payload['token']) ||
|
||||
$this->payload['token'] !== $this->queueData['token']
|
||||
$this->payload['token'] !== $this->daemonData['token']
|
||||
) {
|
||||
$this->abortWithError('invalid token');
|
||||
}
|
||||
|
||||
$worker = new Worker();
|
||||
$worker->process();
|
||||
|
||||
// after each execution, read queue in case it's status was modified
|
||||
list($queue, $queueData) = $this->getQueue();
|
||||
$queueData['counter']++;
|
||||
$queueData['token'] = $this->refreshedToken;
|
||||
$queue->value = json_encode($queueData);
|
||||
$queue->save();
|
||||
$elapsedTime = microtime(true) - $this->timer;
|
||||
if ($elapsedTime < 30) {
|
||||
sleep(30 - $elapsedTime);
|
||||
}
|
||||
|
||||
// after each execution, read daemon in case it's status was modified
|
||||
list($daemon, $daemonData) = $this->getDaemon();
|
||||
$daemonData['counter']++;
|
||||
$daemonData['token'] = $this->refreshedToken;
|
||||
$daemon->value = json_encode($daemonData);
|
||||
$daemon->save();
|
||||
$this->callSelf();
|
||||
}
|
||||
|
||||
function getQueue() {
|
||||
$queue = Setting::where('name', 'queue')
|
||||
function getDaemon() {
|
||||
$daemon = Setting::where('name', 'daemon')
|
||||
->findOne();
|
||||
return array(
|
||||
($queue) ? $queue : null,
|
||||
($queue) ? json_decode($queue->value, true) : null
|
||||
($daemon) ? $daemon : null,
|
||||
($daemon) ? json_decode($daemon->value, true) : null
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -13,15 +13,16 @@ class Supervisor {
|
||||
if(!Env::isPluginActivated()) {
|
||||
throw new \Exception('Database has not been configured.');
|
||||
}
|
||||
list ($this->queue, $this->queueData) = $this->getQueue();
|
||||
list ($this->daemon, $this->daemonData) = $this->getDaemon();
|
||||
}
|
||||
|
||||
function checkQueue() {
|
||||
if(!$this->queue) {
|
||||
return $this->startQueue();
|
||||
function checkDaemon() {
|
||||
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH'])) return;
|
||||
if(!$this->daemon) {
|
||||
return $this->startDaemon();
|
||||
} else {
|
||||
if(!$this->forceStart && ($this->queueData['status'] === 'paused' ||
|
||||
$this->queueData['status'] === 'stopped'
|
||||
if(!$this->forceStart && ($this->daemonData['status'] === 'paused' ||
|
||||
$this->daemonData['status'] === 'stopped'
|
||||
)
|
||||
) {
|
||||
return;
|
||||
@@ -29,40 +30,40 @@ class Supervisor {
|
||||
$currentTime = Carbon::now('UTC');
|
||||
$lastUpdateTime = Carbon::createFromFormat(
|
||||
'Y-m-d H:i:s',
|
||||
$this->queue->updated_at, 'UTC'
|
||||
$this->daemon->updated_at, 'UTC'
|
||||
);
|
||||
$timeSinceLastStart = $currentTime->diffInSeconds($lastUpdateTime);
|
||||
if($timeSinceLastStart < 5) return;
|
||||
$this->queueData['status'] = 'paused';
|
||||
$this->queue->value = json_encode($this->queueData);
|
||||
$this->queue->save();
|
||||
return $this->startQueue();
|
||||
$this->daemonData['status'] = 'paused';
|
||||
$this->daemon->value = json_encode($this->daemonData);
|
||||
$this->daemon->save();
|
||||
return $this->startDaemon();
|
||||
}
|
||||
}
|
||||
|
||||
function startQueue() {
|
||||
function startDaemon() {
|
||||
if(!session_id()) session_start();
|
||||
$sessionId = session_id();
|
||||
session_write_close();
|
||||
$_SESSION['queue'] = null;
|
||||
$_SESSION['daemon'] = null;
|
||||
$payload = json_encode(array('session' => $sessionId));
|
||||
self::getRemoteUrl(
|
||||
'/?mailpoet-api§ion=queue&action=start&payload=' . urlencode($payload)
|
||||
);
|
||||
session_start();
|
||||
$queueStatus = $_SESSION['queue'];
|
||||
unset($_SESSION['queue']);
|
||||
$daemonStatus = $_SESSION['daemon'];
|
||||
unset($_SESSION['daemon']);
|
||||
session_write_close();
|
||||
return $queueStatus;
|
||||
return $daemonStatus;
|
||||
}
|
||||
|
||||
function getQueue() {
|
||||
$queue = Setting::where('name', 'queue')
|
||||
function getDaemon() {
|
||||
$daemon = Setting::where('name', 'daemon')
|
||||
->findOne();
|
||||
$queueData = ($queue) ? json_decode($queue->value, true) : false;
|
||||
$daemonData = ($daemon) ? json_decode($daemon->value, true) : false;
|
||||
return array(
|
||||
$queue,
|
||||
$queueData
|
||||
$daemon,
|
||||
$daemonData
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -28,8 +28,9 @@ class Worker {
|
||||
if(!isset($subscribers['processed'])) $subscribers['processed'] = array();
|
||||
$subscribersToProcess = $subscribers['to_process'];
|
||||
foreach ($subscribersToProcess as $subscriber) {
|
||||
if(microtime(true) - $this->timer >= 28) break;
|
||||
// TODO: remove
|
||||
$elapsedTime = microtime(true) - $this->timer;
|
||||
if($elapsedTime >= 28) break;
|
||||
// TODO: hook up to mailer
|
||||
sleep(1);
|
||||
$newsletterStatistics = NewsletterStatistics::create();
|
||||
$newsletterStatistics->subscriber_id = $subscriber;
|
||||
|
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace MailPoet\Router;
|
||||
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Queue\Daemon;
|
||||
use MailPoet\Queue\Supervisor;
|
||||
|
||||
@@ -11,7 +12,7 @@ class Queue {
|
||||
$supervisor = new Supervisor();
|
||||
wp_send_json(
|
||||
array(
|
||||
'result' => ($supervisor->checkQueue($forceStart = true)) ?
|
||||
'result' => ($supervisor->checkDaemon($forceStart = true)) ?
|
||||
true :
|
||||
false
|
||||
)
|
||||
@@ -27,13 +28,13 @@ class Queue {
|
||||
$status = 'paused';
|
||||
break;
|
||||
}
|
||||
$queue = new Daemon();
|
||||
if(!$queue->queue || $queue->queueData['status'] !== 'started') {
|
||||
$daemon = new Daemon();
|
||||
if(!$daemon->daemon || $daemon->daemonData['status'] !== 'started') {
|
||||
$result = false;
|
||||
} else {
|
||||
$queue->queueData['status'] = $status;
|
||||
$queue->queue->value = json_encode($queue->queueData);
|
||||
$result = $queue->queue->save();
|
||||
$daemon->daemonData['status'] = $status;
|
||||
$daemon->daemon->value = json_encode($daemon->daemonData);
|
||||
$result = $daemon->daemon->save();
|
||||
}
|
||||
wp_send_json(
|
||||
array(
|
||||
@@ -41,4 +42,10 @@ class Queue {
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function getQueueStatus() {
|
||||
$daemon = new \MailPoet\Queue\BootStrapMenu();
|
||||
wp_send_json($daemon->bootStrap());
|
||||
|
||||
}
|
||||
}
|
10
views/queue.html
Normal file
10
views/queue.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<% extends 'layout.html' %>
|
||||
|
||||
<% block content %>
|
||||
<div id="queue_container"></div>
|
||||
<script type="text/javascript">
|
||||
</script>
|
||||
<script>
|
||||
var queueDaemon = <%= daemon|raw %>
|
||||
</script>
|
||||
<% endblock %>
|
@@ -102,7 +102,8 @@ config.push(_.extend({}, baseConfig, {
|
||||
'settings/tabs.js',
|
||||
'subscribers/importExport/import.js',
|
||||
'subscribers/importExport/export.js',
|
||||
'helpscout'
|
||||
'helpscout',
|
||||
'queue.jsx'
|
||||
],
|
||||
form_editor: [
|
||||
'form_editor/form_editor.js',
|
||||
|
Reference in New Issue
Block a user