Compare commits
243 Commits
3.0.0-beta
...
3.0.0-beta
Author | SHA1 | Date | |
---|---|---|---|
f5b152cdfa | |||
90b93bd76e | |||
08bbfcb5e8 | |||
9dd326e7db | |||
cf00813c7f | |||
4c898b76b2 | |||
81a2ba8e03 | |||
7e6d900b53 | |||
1a522794d6 | |||
197537d6ca | |||
b212ca801b | |||
db8f3216d7 | |||
78f9945296 | |||
0cebcd3965 | |||
4062e0662d | |||
20b7e82d3c | |||
9ab8a80567 | |||
f98d02121b | |||
e68e212ad0 | |||
cb1a1e51ba | |||
b42d8e68d9 | |||
e88d130ebb | |||
c924778d50 | |||
a9051c6d09 | |||
f6243b5d79 | |||
68c0b93586 | |||
0e8be8040c | |||
f3ea548d65 | |||
1ab6be8acd | |||
c413acd93d | |||
7614a4d8dc | |||
4a94c29b85 | |||
b5b9531ff3 | |||
e2a048a65f | |||
c28726f118 | |||
7c74885669 | |||
5f74f34cba | |||
d6ef526a9d | |||
0da0507e0a | |||
3f03c985bf | |||
77f6e13aa3 | |||
213d0e8627 | |||
1d019bc11e | |||
ca12487416 | |||
c5d42a5033 | |||
3b079440b5 | |||
419697991f | |||
d119a1e5fa | |||
1bd4264dd5 | |||
21ee60b7d7 | |||
849ca27d1f | |||
a4dad46fb7 | |||
fac4c8fb41 | |||
cdc87c23ea | |||
34d09ce0c9 | |||
fe9ae392f2 | |||
9501640f4f | |||
ad028ab55d | |||
74cb8d9735 | |||
381608df22 | |||
6aca598dc3 | |||
acbe2e383a | |||
55d3b67a2a | |||
c02394b576 | |||
6a9b8d88c2 | |||
b24c51d800 | |||
d3a3d3b277 | |||
3dcff8eb8a | |||
401339244c | |||
653ecdc4d0 | |||
88d5952684 | |||
c4d6c19c67 | |||
0554a84f77 | |||
c01b57a383 | |||
65f4f493f1 | |||
8a7ea791b0 | |||
1823985172 | |||
e735b5f3e0 | |||
cd5c57b7e9 | |||
fbf59723d8 | |||
2e166a233b | |||
1608ba5893 | |||
9d7eb8038d | |||
c9c78a7160 | |||
53df10dc2b | |||
a746c124a3 | |||
ca5a5301a8 | |||
7a2aaa86cf | |||
b626c7ea3c | |||
695152e947 | |||
a36fe400ed | |||
22bb971db5 | |||
b88452c5a2 | |||
4a2f9ad1f9 | |||
593a7de9fe | |||
e5ecf870c7 | |||
11cc97b201 | |||
e352b5bfad | |||
334448c964 | |||
7d8d535cb3 | |||
68988edd7e | |||
f164e9bb95 | |||
fe83435d14 | |||
453b7683bc | |||
25625b1ce1 | |||
048d71164a | |||
24e682e92e | |||
23d90c9f73 | |||
a9f190661f | |||
c1e56e5fa1 | |||
e2bb2679e4 | |||
d49530da0f | |||
0bc28ef3c7 | |||
563b7eccb0 | |||
94a9b63136 | |||
91ff008485 | |||
cb8fa23c3f | |||
3499de05e8 | |||
77ed4d34e8 | |||
cfc5f5a88d | |||
2514d87a00 | |||
23c6750ccc | |||
bb2af5176b | |||
95b5206e8b | |||
394118f113 | |||
b691fb5a48 | |||
1ba2492929 | |||
d08243b0ce | |||
189656fdc8 | |||
0be872eea9 | |||
22c39c0092 | |||
1b54e356b2 | |||
9079d7d4db | |||
160b28a632 | |||
03ebb30ac2 | |||
56eac1ae86 | |||
89da4c9aae | |||
b510071857 | |||
4bbec4700d | |||
29a2af2555 | |||
94d57b5287 | |||
6b7bc8a731 | |||
3dd0f00b7f | |||
b58f6cc4e0 | |||
7c942147ec | |||
6fca2061e6 | |||
0acc41c887 | |||
20d1ac81e2 | |||
cdb7b99728 | |||
54cb838d71 | |||
0b9ea23f0b | |||
3e40f768b4 | |||
6e929dcf79 | |||
7be01f0e4e | |||
9cb08734a3 | |||
55fda047f6 | |||
4706c5fc25 | |||
3ba857d03f | |||
f39cbe6b55 | |||
6dc1bf4e95 | |||
5b65a8f0ac | |||
583adf86da | |||
3b4a1b686d | |||
5390dd8421 | |||
fe8452711f | |||
f7cb53de2c | |||
1ac6dd8ccb | |||
b1425198b6 | |||
00a45f3214 | |||
8e46451337 | |||
b0d0cc09c8 | |||
af559a6fac | |||
67acceb968 | |||
703ee7ff71 | |||
29491dfd3e | |||
a49a230983 | |||
b8d285a1d9 | |||
d5227a9f2c | |||
693117eb40 | |||
f3aab6095e | |||
d70587a550 | |||
82226f2c36 | |||
2774101380 | |||
ee0e3ff95e | |||
17584dde43 | |||
3ac416de56 | |||
1e4c00169f | |||
11bbf54aad | |||
688e78560e | |||
5ca577a718 | |||
605df7dff1 | |||
fb1a3a80ff | |||
d3db755489 | |||
a4282b6a3e | |||
bc17984030 | |||
b823991867 | |||
04e238634d | |||
eba482cc67 | |||
e6663f0f3e | |||
7fa94a67c9 | |||
b4be9e1d28 | |||
a7504136a2 | |||
43fa12ec08 | |||
6723a563ed | |||
15e3e93c99 | |||
cbce789ac8 | |||
97607993fb | |||
334b119bb3 | |||
ed0b2e6231 | |||
ad7ad05ec7 | |||
bfba6d459c | |||
344eecbf11 | |||
14dc022d2d | |||
eff75cce94 | |||
51084fc57d | |||
298270f86c | |||
fe6d5d1523 | |||
3cceb32ec1 | |||
c8251a3bcd | |||
58888505b5 | |||
558c493dd7 | |||
8cdb7d77f6 | |||
539e6d3ee1 | |||
c9a0939ddd | |||
2add301b9f | |||
2d217e416a | |||
77e0ace951 | |||
933749f8f0 | |||
7b13babf3f | |||
8c673f78d7 | |||
2285c08c01 | |||
836b7179e9 | |||
f89a728c38 | |||
58f2c32362 | |||
5bd6c6533a | |||
f539860922 | |||
536267c8f5 | |||
5b905a60e8 | |||
5e152ebaa1 | |||
2c35c7061e | |||
2515dcf4ce | |||
9458bf7418 | |||
44bf4b98b8 |
@ -1,8 +0,0 @@
|
||||
#!/usr/bin/ruby
|
||||
path = "/tmp"
|
||||
Dir.mkdir(path) if !File.exists?(path)
|
||||
File.open("#{path}/mailpoet-#{Time.now.to_f}.txt", "w") do |f|
|
||||
sleep 5
|
||||
f.puts ARGV.inspect
|
||||
$stdin.each_line { |line| f.puts line }
|
||||
end
|
@ -1,3 +0,0 @@
|
||||
; For Unix only. You may supply arguments as well (default: "sendmail -t -i").
|
||||
; http://php.net/sendmail-path
|
||||
sendmail_path = /home/ubuntu/mailpoet/.circle_ci/fake-sendmail.rb
|
@ -3,11 +3,11 @@ Listen 8080
|
||||
<VirtualHost *:8080>
|
||||
UseCanonicalName Off
|
||||
ServerName mailpoet.loc
|
||||
DocumentRoot /home/ubuntu/mailpoet/wordpress
|
||||
DocumentRoot /home/circleci/mailpoet/wordpress
|
||||
DirectoryIndex index.php
|
||||
LogLevel notice
|
||||
|
||||
<Directory /home/ubuntu/mailpoet/wordpress>
|
||||
<Directory /home/circleci/mailpoet/wordpress>
|
||||
Require all granted
|
||||
</Directory>
|
||||
</VirtualHost>
|
94
.circleci/config.yml
Normal file
@ -0,0 +1,94 @@
|
||||
version: 2
|
||||
jobs:
|
||||
qa_js_php5:
|
||||
working_directory: /home/circleci/mailpoet
|
||||
docker:
|
||||
- image: circleci/php:5.6.30-apache-browsers
|
||||
- image: circleci/mysql:5.7
|
||||
environment:
|
||||
TZ: /usr/share/zoneinfo/Etc/UTC
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Set up virtual host"
|
||||
command: echo 127.0.0.1 mailpoet.loc | sudo tee -a /etc/hosts
|
||||
- restore_cache:
|
||||
key: composer-{{ checksum "composer.json" }}-{{ checksum "composer.lock" }}
|
||||
- restore_cache:
|
||||
key: npm-{{ checksum "package.json" }}
|
||||
- run:
|
||||
name: "Set up test environment"
|
||||
command: source ./.circleci/setup.bash && setup php5
|
||||
- save_cache:
|
||||
key: composer-{{ checksum "composer.json" }}-{{ checksum "composer.lock" }}
|
||||
paths:
|
||||
- vendor
|
||||
- save_cache:
|
||||
key: npm-{{ checksum "package.json" }}
|
||||
paths:
|
||||
- node_modules
|
||||
- run:
|
||||
name: "QA Scripts"
|
||||
command: ./do qa
|
||||
- run:
|
||||
name: "Preparing test results folder"
|
||||
command: mkdir test-results
|
||||
- run:
|
||||
name: "JS tests"
|
||||
command: |
|
||||
mkdir test-results/mocha
|
||||
./do t:j test-results/mocha/junit.xml
|
||||
- run:
|
||||
name: "PHP Unit tests"
|
||||
command: |
|
||||
WP_TEST_PATH="/home/circleci/mailpoet/wordpress" ./do t:u --xml
|
||||
- store_test_results:
|
||||
path: test-results/mocha
|
||||
- store_artifacts:
|
||||
path: test-results/mocha
|
||||
destination: mocha
|
||||
- store_test_results:
|
||||
path: tests/_output
|
||||
- store_artifacts:
|
||||
path: tests/_output
|
||||
destination: codeception
|
||||
- store_artifacts:
|
||||
path: /tmp/fake-mailer/
|
||||
destination: fake-mailer
|
||||
php7:
|
||||
working_directory: /home/circleci/mailpoet
|
||||
docker:
|
||||
- image: circleci/php:7.1-apache-browsers
|
||||
- image: circleci/mysql:5.7
|
||||
environment:
|
||||
TZ: /usr/share/zoneinfo/Etc/UTC
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: "Set up virtual host"
|
||||
command: echo 127.0.0.1 mailpoet.loc | sudo tee -a /etc/hosts
|
||||
- restore_cache:
|
||||
key: composer-{{ checksum "composer.json" }}-{{ checksum "composer.lock" }}
|
||||
- restore_cache:
|
||||
key: npm-{{ checksum "package.json" }}
|
||||
- run:
|
||||
name: "Set up test environment"
|
||||
command: source ./.circleci/setup.bash && setup php7
|
||||
- run:
|
||||
name: "PHP Unit tests"
|
||||
command: |
|
||||
WP_TEST_PATH="/home/circleci/mailpoet/wordpress" ./do t:u --xml
|
||||
- store_test_results:
|
||||
path: tests/_output
|
||||
- store_artifacts:
|
||||
path: tests/_output
|
||||
destination: codeception
|
||||
- store_artifacts:
|
||||
path: /tmp/fake-mailer/
|
||||
destination: fake-mailer
|
||||
workflows:
|
||||
version: 2
|
||||
build_and_test:
|
||||
jobs:
|
||||
- qa_js_php5
|
||||
- php7
|
17
.circleci/fake-sendmail.php
Executable file
@ -0,0 +1,17 @@
|
||||
#!/usr/local/bin/php
|
||||
<?php
|
||||
$path = "/tmp/fake-mailer";
|
||||
if(!file_exists($path)) {
|
||||
mkdir($path);
|
||||
}
|
||||
$filename = $path . '/mailpoet-' . microtime(true) . '.txt';
|
||||
$file_handle = fopen($filename, "w");
|
||||
|
||||
$call_arguments = print_r($argv, true) . "\n";
|
||||
fwrite($file_handle, $call_arguments);
|
||||
|
||||
while($line = fgets(STDIN)) {
|
||||
fwrite($file_handle, $line);
|
||||
}
|
||||
|
||||
fclose($file_handle);
|
9
.circleci/mailpoet_php.ini
Normal file
@ -0,0 +1,9 @@
|
||||
; For Unix only. You may supply arguments as well (default: "sendmail -t -i").
|
||||
; http://php.net/sendmail-path
|
||||
sendmail_path = /usr/local/bin/fake-sendmail.php
|
||||
|
||||
[Date]
|
||||
; Defines the default timezone used by the date functions
|
||||
; http://php.net/date.timezone
|
||||
date.timezone = UTC
|
||||
|
48
.circleci/setup.bash
Normal file
@ -0,0 +1,48 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
function setup {
|
||||
local version=$1
|
||||
# install PHP dependencies for WordPress
|
||||
if [[ $version == "php7" ]]; then
|
||||
echo "deb http://packages.dotdeb.org jessie all" | sudo tee -a /etc/apt/sources.list.d/dotdeb.list
|
||||
echo "deb-src http://packages.dotdeb.org jessie all" | sudo tee -a /etc/apt/sources.list.d/dotdeb.list
|
||||
wget -qO - http://www.dotdeb.org/dotdeb.gpg | sudo apt-key add -
|
||||
sudo apt-get update
|
||||
sudo apt-get install mysql-client php7.0-mysql zlib1g-dev
|
||||
sudo docker-php-ext-install mysqli pdo pdo_mysql zip
|
||||
else
|
||||
sudo apt-get update
|
||||
sudo apt-get install mysql-client php5-mysql zlib1g-dev
|
||||
sudo docker-php-ext-install mysql mysqli pdo pdo_mysql zip
|
||||
fi
|
||||
# Add a fake sendmail mailer
|
||||
sudo cp ./.circleci/fake-sendmail.php /usr/local/bin/
|
||||
# configure Apache
|
||||
sudo cp ./.circleci/mailpoet_php.ini /usr/local/etc/php/conf.d/
|
||||
sudo cp ./.circleci/apache/mailpoet.loc.conf /etc/apache2/sites-available
|
||||
sudo a2ensite mailpoet.loc
|
||||
sudo a2enmod rewrite
|
||||
sudo service apache2 restart
|
||||
# Install NodeJS+NPM
|
||||
curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
|
||||
sudo apt-get install nodejs build-essential
|
||||
# install plugin dependencies
|
||||
curl -sS https://getcomposer.org/installer | php
|
||||
./composer.phar install
|
||||
./do install
|
||||
# Set up Wordpress
|
||||
mysql -h 127.0.0.1 -u root -e "create database wordpress"
|
||||
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
|
||||
chmod +x wp-cli.phar
|
||||
./wp-cli.phar core download --allow-root --path=wordpress
|
||||
# Generate `wp-config.php` file with debugging enabled
|
||||
echo "define(\"WP_DEBUG\", true);" | ./wp-cli.phar core config --allow-root --dbname=wordpress --dbuser=root --dbhost=127.0.0.1 --path=wordpress --extra-php
|
||||
# Install WordPress
|
||||
./wp-cli.phar core install --allow-root --admin_name=admin --admin_password=admin --admin_email=admin@mailpoet.loc --url=http://mailpoet.loc:8080 --title=WordPress --path=wordpress
|
||||
# Softlink plugin to plugin path
|
||||
ln -s ../../.. wordpress/wp-content/plugins/mailpoet
|
||||
./wp-cli.phar plugin activate mailpoet --path=wordpress
|
||||
# Create .env file with correct path to WP installation
|
||||
# TODO: Remove this line after PR gets merged and CircleCI env variables change
|
||||
echo "WP_TEST_PATH=\"/home/circleci/mailpoet/wordpress\"" > .env
|
||||
}
|
@ -40,23 +40,14 @@
|
||||
"jsx-a11y/alt-text": 0,
|
||||
|
||||
"comma-dangle": 0,
|
||||
"prefer-arrow-callback": 0,
|
||||
"func-names": 0,
|
||||
"space-before-function-paren": 0,
|
||||
"object-shorthand": 0,
|
||||
"no-bitwise": 0,
|
||||
"arrow-body-style": 0,
|
||||
"prefer-template": 0,
|
||||
"eol-last": 0,
|
||||
"no-unused-vars": 0,
|
||||
"no-plusplus": 0,
|
||||
"semi": 0,
|
||||
"keyword-spacing": 0,
|
||||
"default-case": 0,
|
||||
"quote-props": 0,
|
||||
"indent": 0,
|
||||
"prefer-const": 0,
|
||||
"arrow-parens": 0,
|
||||
"array-callback-return": 0,
|
||||
"consistent-return": 0,
|
||||
"no-unreachable": 0,
|
||||
@ -67,7 +58,6 @@
|
||||
"camelcase": 0,
|
||||
"template-curly-spacing": 0,
|
||||
"quotes": 0,
|
||||
"radix": 0,
|
||||
"eqeqeq": 0,
|
||||
"no-lonely-if": 0,
|
||||
"space-unary-ops": 0,
|
||||
@ -96,13 +86,11 @@
|
||||
"one-var-declaration-per-line": 0,
|
||||
"no-script-url": 0,
|
||||
"wrap-iife": 0,
|
||||
"no-var": 0,
|
||||
"vars-on-top": 0,
|
||||
"space-infix-ops": 0,
|
||||
"no-irregular-whitespace": 0,
|
||||
"padded-blocks": 0,
|
||||
"no-underscore-dangle": 0,
|
||||
"object-curly-spacing": 0,
|
||||
"no-undef": 0
|
||||
}
|
||||
}
|
||||
|
25
RoboFile.php
@ -235,14 +235,23 @@ class RoboFile extends \Robo\Tasks {
|
||||
} else {
|
||||
$severityFlag = '-n';
|
||||
}
|
||||
return $this->_exec(
|
||||
'./vendor/bin/phpcs '.
|
||||
'--standard=./tasks/code_sniffer/MailPoet '.
|
||||
'--ignore=./lib/Util/Sudzy/*,./lib/Util/CSS.php,./lib/Util/XLSXWriter.php,'.
|
||||
'./lib/Util/pQuery/*,./lib/Config/PopulatorData/Templates/* '.
|
||||
'lib/ '.
|
||||
$severityFlag
|
||||
);
|
||||
return $this->collectionBuilder()
|
||||
->taskExec(
|
||||
'./vendor/bin/phpcs '.
|
||||
'--standard=./tasks/code_sniffer/MailPoet '.
|
||||
'--ignore=./lib/Util/Sudzy/*,./lib/Util/CSS.php,./lib/Util/XLSXWriter.php,'.
|
||||
'./lib/Util/pQuery/*,./lib/Config/PopulatorData/Templates/* '.
|
||||
'lib/ '.
|
||||
$severityFlag
|
||||
)
|
||||
->taskExec(
|
||||
'./vendor/bin/phpcs '.
|
||||
'--standard=./tasks/code_sniffer/MailPoetTests '.
|
||||
'--ignore=./tests/unit/_bootstrap.php '.
|
||||
'tests/unit/ '.
|
||||
$severityFlag
|
||||
)
|
||||
->run();
|
||||
}
|
||||
|
||||
function svnCheckout() {
|
||||
|
@ -24,5 +24,6 @@
|
||||
@require 'subscribers'
|
||||
|
||||
@require 'pages'
|
||||
@require 'pages_custom'
|
||||
|
||||
@require 'mp2migrator'
|
||||
|
@ -21,6 +21,9 @@ a:focus
|
||||
.mailpoet_spaced_block
|
||||
margin: 1em 0
|
||||
|
||||
.mailpoet_centered
|
||||
text-align: center
|
||||
|
||||
// select 2
|
||||
.select2-container
|
||||
width: 25em !important
|
||||
|
@ -62,3 +62,9 @@ $draggable-widget-z-index = 2
|
||||
background-color: $primary-active-color
|
||||
box-shadow(inset 1px 2px 1px $primary-inset-shadow-color)
|
||||
color: $white-color
|
||||
|
||||
.mailpoet_droppable_block
|
||||
cursor: move
|
||||
|
||||
&.mailpoet_ignore_drag
|
||||
cursor: auto
|
||||
|
@ -18,6 +18,7 @@
|
||||
.mailpoet_settings_posts_display_options
|
||||
.mailpoet_settings_posts_selection
|
||||
animation-slide-open-downwards()
|
||||
overflow-x: hidden
|
||||
|
||||
.mailpoet_settings_posts_show_display_options,
|
||||
.mailpoet_settings_posts_show_post_selection
|
||||
@ -26,7 +27,12 @@
|
||||
|
||||
.mailpoet_post_selection_container
|
||||
margin-top: 20px
|
||||
margin-bottom: 20px
|
||||
margin-bottom: 0
|
||||
|
||||
.mailpoet_post_scroll_container
|
||||
overflow-y: scroll
|
||||
overflow-x: hidden
|
||||
max-height: 400px
|
||||
|
||||
.mailpoet_settings_posts_single_post
|
||||
border-radius(1px)
|
||||
@ -45,3 +51,6 @@
|
||||
.mailpoet_select_post_checkbox
|
||||
margin-left: 10px
|
||||
margin-right: 8px
|
||||
|
||||
.mailpoet_post_selection_loading
|
||||
color: #999
|
||||
|
@ -2,6 +2,7 @@
|
||||
Based on /wp-admin/css/about.css of WP 4.7.
|
||||
This is to make MailPoet pages independent of the WordPress
|
||||
About page styles that may differ across WP versions.
|
||||
Please add custom styles to pages_custom.styl
|
||||
*/
|
||||
|
||||
.mailpoet-about-wrap
|
||||
|
35
assets/css/src/pages_custom.styl
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
Custom styles for MailPoet pages.
|
||||
*/
|
||||
|
||||
.mailpoet-about-wrap
|
||||
|
||||
.videoWrapper
|
||||
position: relative
|
||||
padding-bottom: 56.25% /* 16:9 */
|
||||
/*padding-top: 25px*/
|
||||
height: 0
|
||||
|
||||
iframe
|
||||
position: absolute
|
||||
top: 0
|
||||
left: 0
|
||||
width: 100%
|
||||
height: 100%
|
||||
|
||||
|
||||
.mailpoet_video
|
||||
border: 1px solid rgba(0, 0, 0, 0.1)
|
||||
|
||||
#mailpoet-changelog ul
|
||||
list-style: disc
|
||||
padding-left: 20px
|
||||
|
||||
h2.mailpoet-feature-top
|
||||
margin: 50px auto
|
||||
|
||||
a.button.go-to-plugin
|
||||
margin-top: 2em
|
||||
|
||||
p.top-space-triple
|
||||
margin-top: 3em
|
@ -9,15 +9,25 @@
|
||||
// sending methods
|
||||
.mailpoet_sending_methods
|
||||
margin 25px 0 0 0
|
||||
li
|
||||
float left
|
||||
position relative
|
||||
padding 15px 15px 0 15px
|
||||
display flex
|
||||
flex-direction row
|
||||
justify-content flex-start
|
||||
> li
|
||||
flex-grow 1
|
||||
flex-shrink 1
|
||||
display flex
|
||||
flex-direction column
|
||||
flex-basis 0
|
||||
margin 0 25px 25px 0
|
||||
width 300px
|
||||
height 300px
|
||||
border 1px solid #dedede
|
||||
background-color #fff
|
||||
max-width 500px
|
||||
.mailpoet_sending_method_description
|
||||
padding: 25px
|
||||
flex-grow 1
|
||||
flex-shrink 0
|
||||
> li:last-child
|
||||
margin-right 0
|
||||
h3
|
||||
text-align center
|
||||
height 54px
|
||||
@ -25,12 +35,12 @@
|
||||
.mailpoet_description
|
||||
font-size 14px
|
||||
.mailpoet_status
|
||||
display flex
|
||||
flex-direction row
|
||||
justify-content space-between
|
||||
align-items center
|
||||
background-color #2f2f2f
|
||||
color #fff
|
||||
position absolute
|
||||
bottom 0
|
||||
left 0
|
||||
right 0
|
||||
text-overflow ellipsis
|
||||
padding 15px
|
||||
span
|
||||
@ -43,23 +53,17 @@
|
||||
visibility visible
|
||||
#mailpoet_mta_activate
|
||||
visibility hidden
|
||||
.mailpoet_actions
|
||||
bottom 15px
|
||||
color #fff
|
||||
padding 0
|
||||
position absolute
|
||||
right 15px
|
||||
.button-secondary
|
||||
margin 0 -6px -4px 0
|
||||
|
||||
// premium key
|
||||
.mailpoet_key
|
||||
&_valid
|
||||
&::before
|
||||
content '✔ '
|
||||
&_invalid
|
||||
&::before
|
||||
content: '✗ '
|
||||
ul.sending-method-benefits
|
||||
list-style-type: none
|
||||
margin-bottom: 2em
|
||||
margin-top: 2em
|
||||
|
||||
.mailpoet_success_item::before
|
||||
content '✔ '
|
||||
|
||||
.mailpoet_error_item::before
|
||||
content '✗ '
|
||||
|
||||
// responsive
|
||||
@media screen and (max-width: 782px)
|
||||
@ -67,8 +71,10 @@
|
||||
width auto
|
||||
|
||||
.mailpoet_sending_methods
|
||||
li
|
||||
float none
|
||||
width auto
|
||||
flex-flow: row wrap
|
||||
justify-content: space-around
|
||||
> li
|
||||
margin-right 0
|
||||
flex-basis auto
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 143 KiB |
Before Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 124 KiB |
Before Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 75 KiB |
Before Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 262 KiB |
Before Width: | Height: | Size: 276 KiB |
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 441 KiB |
Before Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 79 KiB |
Before Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 122 KiB |
Before Width: | Height: | Size: 119 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 106 KiB |
Before Width: | Height: | Size: 73 KiB |
@ -1,5 +1,19 @@
|
||||
function requestFailed(errorMessage, xhr) {
|
||||
if (xhr.responseJSON) {
|
||||
return xhr.responseJSON;
|
||||
}
|
||||
var message = errorMessage.replace("%d", xhr.status);
|
||||
return {
|
||||
errors: [
|
||||
{
|
||||
message: message
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
define('ajax', ['mailpoet', 'jquery', 'underscore'], function(MailPoet, jQuery, _) {
|
||||
'use strict';
|
||||
|
||||
MailPoet.Ajax = {
|
||||
version: 0.5,
|
||||
options: {},
|
||||
@ -36,7 +50,7 @@ define('ajax', ['mailpoet', 'jquery', 'underscore'], function(MailPoet, jQuery,
|
||||
endpoint: this.options.endpoint,
|
||||
method: this.options.action,
|
||||
data: this.options.data || {}
|
||||
}
|
||||
};
|
||||
},
|
||||
request: function(method, options) {
|
||||
// set options
|
||||
@ -44,26 +58,23 @@ define('ajax', ['mailpoet', 'jquery', 'underscore'], function(MailPoet, jQuery,
|
||||
|
||||
// set request params
|
||||
var params = this.getParams();
|
||||
var deferred = jQuery.Deferred();
|
||||
|
||||
// remove null values from the data object
|
||||
if (_.isObject(params.data)) {
|
||||
params.data = _.pick(params.data, function(value) {
|
||||
return (value !== null)
|
||||
})
|
||||
return (value !== null);
|
||||
});
|
||||
}
|
||||
|
||||
// ajax request
|
||||
deferred = jQuery.post(
|
||||
var deferred = jQuery.post(
|
||||
this.options.url,
|
||||
params,
|
||||
null,
|
||||
'json'
|
||||
).then(function(data) {
|
||||
return data;
|
||||
}, function(xhr) {
|
||||
return xhr.responseJSON;
|
||||
});
|
||||
}, _.partial(requestFailed, MailPoet.I18n.t('ajaxFailedErrorMessage')));
|
||||
|
||||
// clear options
|
||||
this.options = {};
|
||||
|
@ -1,15 +1,15 @@
|
||||
define([
|
||||
'react'
|
||||
],
|
||||
function(
|
||||
(
|
||||
React
|
||||
) {
|
||||
) => {
|
||||
const FormFieldCheckbox = React.createClass({
|
||||
onValueChange: function(e) {
|
||||
onValueChange: function (e) {
|
||||
e.target.value = this.refs.checkbox.checked ? '1' : '0';
|
||||
return this.props.onValueChange(e);
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
if (this.props.field.values === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
define([
|
||||
'react',
|
||||
'moment',
|
||||
], function(
|
||||
], (
|
||||
React,
|
||||
Moment
|
||||
) {
|
||||
) => {
|
||||
class FormFieldDateYear extends React.Component {
|
||||
render() {
|
||||
const yearsRange = 100;
|
||||
@ -17,7 +17,7 @@ define([
|
||||
}
|
||||
|
||||
const currentYear = Moment().year();
|
||||
for (let i = currentYear; i >= currentYear - yearsRange; i--) {
|
||||
for (let i = currentYear; i >= currentYear - yearsRange; i -= 1) {
|
||||
years.push((
|
||||
<option
|
||||
key={ i }
|
||||
@ -47,7 +47,7 @@ define([
|
||||
));
|
||||
}
|
||||
|
||||
for (let i = 1; i <= 12; i++) {
|
||||
for (let i = 1; i <= 12; i += 1) {
|
||||
months.push((
|
||||
<option
|
||||
key={ i }
|
||||
@ -77,7 +77,7 @@ define([
|
||||
));
|
||||
}
|
||||
|
||||
for (let i = 1; i <= 31; i++) {
|
||||
for (let i = 1; i <= 31; i += 1) {
|
||||
days.push((
|
||||
<option
|
||||
key={ i }
|
||||
@ -105,12 +105,12 @@ define([
|
||||
year: '',
|
||||
month: '',
|
||||
day: ''
|
||||
}
|
||||
};
|
||||
}
|
||||
componentDidMount() {
|
||||
this.extractDateParts();
|
||||
}
|
||||
componentDidUpdate(prevProps, prevState) {
|
||||
componentDidUpdate(prevProps) {
|
||||
if (
|
||||
(this.props.item !== undefined && prevProps.item !== undefined)
|
||||
&& (this.props.item.id !== prevProps.item.id)
|
||||
@ -147,26 +147,26 @@ define([
|
||||
'month': this.state.month,
|
||||
'day': this.state.day
|
||||
};
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'year_month':
|
||||
value = {
|
||||
'year': this.state.year,
|
||||
'month': this.state.month
|
||||
};
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'month':
|
||||
value = {
|
||||
'month': this.state.month
|
||||
};
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'year':
|
||||
value = {
|
||||
'year': this.state.year
|
||||
};
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
@ -181,7 +181,7 @@ define([
|
||||
field = matches[1];
|
||||
property = matches[2];
|
||||
|
||||
let value = ~~(e.target.value);
|
||||
const value = ~~(e.target.value);
|
||||
|
||||
this.setState({
|
||||
[`${property}`]: value
|
||||
@ -201,7 +201,7 @@ define([
|
||||
const dateType = this.props.field.params.date_type;
|
||||
const dateSelects = dateFormats[dateType][0].split('/');
|
||||
|
||||
const fields = dateSelects.map(type => {
|
||||
const fields = dateSelects.map((type) => {
|
||||
switch(type) {
|
||||
case 'YYYY':
|
||||
return (<FormFieldDateYear
|
||||
@ -212,7 +212,7 @@ define([
|
||||
year={ this.state.year }
|
||||
placeholder={ this.props.field.year_placeholder }
|
||||
/>);
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'MM':
|
||||
return (<FormFieldDateMonth
|
||||
@ -224,7 +224,7 @@ define([
|
||||
monthNames={ monthNames }
|
||||
placeholder={ this.props.field.month_placeholder }
|
||||
/>);
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'DD':
|
||||
return (<FormFieldDateDay
|
||||
@ -235,9 +235,9 @@ define([
|
||||
day={ this.state.day }
|
||||
placeholder={ this.props.field.day_placeholder }
|
||||
/>);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
@ -8,7 +8,7 @@ define([
|
||||
'form/fields/selection.jsx',
|
||||
'form/fields/date.jsx',
|
||||
],
|
||||
function(
|
||||
(
|
||||
React,
|
||||
FormFieldText,
|
||||
FormFieldTextarea,
|
||||
@ -17,17 +17,17 @@ function(
|
||||
FormFieldCheckbox,
|
||||
FormFieldSelection,
|
||||
FormFieldDate
|
||||
) {
|
||||
var FormField = React.createClass({
|
||||
renderField: function(data, inline = false) {
|
||||
var description = false;
|
||||
) => {
|
||||
const FormField = React.createClass({
|
||||
renderField: function (data, inline = false) {
|
||||
let description = false;
|
||||
if(data.field.description) {
|
||||
description = (
|
||||
<p className="description">{ data.field.description }</p>
|
||||
);
|
||||
}
|
||||
|
||||
var field = false;
|
||||
let field = false;
|
||||
|
||||
if(data.field['field'] !== undefined) {
|
||||
data.field = jQuery.merge(data.field, data.field.field);
|
||||
@ -36,35 +36,35 @@ function(
|
||||
switch(data.field.type) {
|
||||
case 'text':
|
||||
field = (<FormFieldText {...data} />);
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'textarea':
|
||||
field = (<FormFieldTextarea {...data} />);
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'select':
|
||||
field = (<FormFieldSelect {...data} />);
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'radio':
|
||||
field = (<FormFieldRadio {...data} />);
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'checkbox':
|
||||
field = (<FormFieldCheckbox {...data} />);
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'selection':
|
||||
field = (<FormFieldSelection {...data} />);
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'date':
|
||||
field = (<FormFieldDate {...data} />);
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'reactComponent':
|
||||
field = (<data.field.component {...data} />);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
if(inline === true) {
|
||||
@ -83,23 +83,23 @@ function(
|
||||
);
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
var field = false;
|
||||
render: function () {
|
||||
let field = false;
|
||||
|
||||
if(this.props.field['fields'] !== undefined) {
|
||||
field = this.props.field.fields.map(function(subfield, index) {
|
||||
field = this.props.field.fields.map((subfield, index) => {
|
||||
return this.renderField({
|
||||
index: index,
|
||||
field: subfield,
|
||||
item: this.props.item,
|
||||
onValueChange: this.props.onValueChange || false
|
||||
});
|
||||
}.bind(this));
|
||||
});
|
||||
} else {
|
||||
field = this.renderField(this.props);
|
||||
}
|
||||
|
||||
var tip = false;
|
||||
let tip = false;
|
||||
if(this.props.field.tip) {
|
||||
tip = (
|
||||
<p className="description">{ this.props.field.tip }</p>
|
||||
|
@ -1,11 +1,11 @@
|
||||
define([
|
||||
'react'
|
||||
],
|
||||
function(
|
||||
(
|
||||
React
|
||||
) {
|
||||
) => {
|
||||
const FormFieldRadio = React.createClass({
|
||||
render: function() {
|
||||
render: function () {
|
||||
if (this.props.field.values === undefined) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React from 'react'
|
||||
import _ from 'underscore'
|
||||
import React from 'react';
|
||||
import _ from 'underscore';
|
||||
|
||||
const FormFieldSelect = React.createClass({
|
||||
render() {
|
||||
@ -33,12 +33,12 @@ const FormFieldSelect = React.createClass({
|
||||
_.map(
|
||||
_.sortBy(
|
||||
_.pairs(this.props.field.values),
|
||||
(item) => sortBy(item[0], item[1])
|
||||
item => sortBy(item[0], item[1])
|
||||
),
|
||||
(item) => item[0]
|
||||
item => item[0]
|
||||
);
|
||||
} else {
|
||||
keys = Object.keys(this.props.field.values)
|
||||
keys = Object.keys(this.props.field.values);
|
||||
}
|
||||
|
||||
const options = keys.map(
|
||||
|
@ -4,33 +4,33 @@ define([
|
||||
'jquery',
|
||||
'select2'
|
||||
],
|
||||
function(
|
||||
(
|
||||
React,
|
||||
ReactDOM,
|
||||
jQuery
|
||||
) {
|
||||
var Selection = React.createClass({
|
||||
getInitialState: function() {
|
||||
) => {
|
||||
const Selection = React.createClass({
|
||||
getInitialState: function () {
|
||||
return {
|
||||
items: [],
|
||||
select2: false
|
||||
};
|
||||
},
|
||||
componentWillMount: function() {
|
||||
componentWillMount: function () {
|
||||
this.loadCachedItems();
|
||||
},
|
||||
allowMultipleValues: function() {
|
||||
allowMultipleValues: function () {
|
||||
return (this.props.field.multiple === true);
|
||||
},
|
||||
isSelect2Initialized: function() {
|
||||
isSelect2Initialized: function () {
|
||||
return (this.state.select2 === true);
|
||||
},
|
||||
componentDidMount: function() {
|
||||
componentDidMount: function () {
|
||||
if(this.allowMultipleValues()) {
|
||||
this.setupSelect2();
|
||||
}
|
||||
},
|
||||
componentDidUpdate: function(prevProps, prevState) {
|
||||
componentDidUpdate: function (prevProps) {
|
||||
if(
|
||||
(this.props.item !== undefined && prevProps.item !== undefined)
|
||||
&& (this.props.item.id !== prevProps.item.id)
|
||||
@ -40,24 +40,24 @@ function(
|
||||
.trigger('change');
|
||||
}
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
componentWillUnmount: function () {
|
||||
if(this.allowMultipleValues()) {
|
||||
this.destroySelect2();
|
||||
}
|
||||
},
|
||||
destroySelect2: function() {
|
||||
destroySelect2: function () {
|
||||
if(this.isSelect2Initialized()) {
|
||||
jQuery('#'+this.refs.select.id).select2('destroy');
|
||||
}
|
||||
},
|
||||
setupSelect2: function() {
|
||||
setupSelect2: function () {
|
||||
if(this.isSelect2Initialized()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var select2 = jQuery('#'+this.refs.select.id).select2({
|
||||
const select2 = jQuery('#'+this.refs.select.id).select2({
|
||||
width: (this.props.width || ''),
|
||||
templateResult: function(item) {
|
||||
templateResult: function (item) {
|
||||
if(item.element && item.element.selected) {
|
||||
return null;
|
||||
} else {
|
||||
@ -70,11 +70,11 @@ function(
|
||||
}
|
||||
});
|
||||
|
||||
var hasRemoved = false;
|
||||
select2.on('select2:unselecting', function(e) {
|
||||
let hasRemoved = false;
|
||||
select2.on('select2:unselecting', () => {
|
||||
hasRemoved = true;
|
||||
});
|
||||
select2.on('select2:opening', function(e) {
|
||||
select2.on('select2:opening', (e) => {
|
||||
if(hasRemoved === true) {
|
||||
hasRemoved = false;
|
||||
e.preventDefault();
|
||||
@ -85,13 +85,13 @@ function(
|
||||
|
||||
this.setState({ select2: true });
|
||||
},
|
||||
getSelectedValues: function() {
|
||||
getSelectedValues: function () {
|
||||
if(this.props.field['selected'] !== undefined) {
|
||||
return this.props.field['selected'](this.props.item);
|
||||
} else if(this.props.item !== undefined && this.props.field.name !== undefined) {
|
||||
if (this.allowMultipleValues()) {
|
||||
if (Array.isArray(this.props.item[this.props.field.name])) {
|
||||
return this.props.item[this.props.field.name].map(function(item) {
|
||||
return this.props.item[this.props.field.name].map((item) => {
|
||||
return item.id;
|
||||
});
|
||||
}
|
||||
@ -101,9 +101,9 @@ function(
|
||||
}
|
||||
return null;
|
||||
},
|
||||
loadCachedItems: function() {
|
||||
loadCachedItems: function () {
|
||||
if(typeof(window['mailpoet_'+this.props.field.endpoint]) !== 'undefined') {
|
||||
var items = window['mailpoet_'+this.props.field.endpoint];
|
||||
let items = window['mailpoet_'+this.props.field.endpoint];
|
||||
|
||||
|
||||
if(this.props.field['filter'] !== undefined) {
|
||||
@ -115,35 +115,35 @@ function(
|
||||
});
|
||||
}
|
||||
},
|
||||
handleChange: function(e) {
|
||||
handleChange: function (e) {
|
||||
if(this.props.onValueChange !== undefined) {
|
||||
if(this.props.field.multiple) {
|
||||
value = jQuery('#'+this.refs.select.id).val();
|
||||
} else {
|
||||
value = e.target.value;
|
||||
}
|
||||
var transformedValue = this.transformChangedValue(value);
|
||||
const transformedValue = this.transformChangedValue(value);
|
||||
this.props.onValueChange({
|
||||
target: {
|
||||
target: {
|
||||
value: transformedValue,
|
||||
name: this.props.field.name
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
getLabel: function(item) {
|
||||
getLabel: function (item) {
|
||||
if(this.props.field['getLabel'] !== undefined) {
|
||||
return this.props.field.getLabel(item, this.props.item);
|
||||
}
|
||||
return item.name;
|
||||
},
|
||||
getSearchLabel: function(item) {
|
||||
getSearchLabel: function (item) {
|
||||
if(this.props.field['getSearchLabel'] !== undefined) {
|
||||
return this.props.field.getSearchLabel(item, this.props.item);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
getValue: function(item) {
|
||||
getValue: function (item) {
|
||||
if(this.props.field['getValue'] !== undefined) {
|
||||
return this.props.field.getValue(item, this.props.item);
|
||||
}
|
||||
@ -152,18 +152,18 @@ function(
|
||||
// When it's impossible to represent the desired value in DOM,
|
||||
// this function may be used to transform the placeholder value into
|
||||
// desired value.
|
||||
transformChangedValue: function(value) {
|
||||
transformChangedValue: function (value) {
|
||||
if(typeof this.props.field['transformChangedValue'] === 'function') {
|
||||
return this.props.field.transformChangedValue.call(this, value);
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
const options = this.state.items.map((item, index) => {
|
||||
let label = this.getLabel(item);
|
||||
let searchLabel = this.getSearchLabel(item);
|
||||
let value = this.getValue(item);
|
||||
const label = this.getLabel(item);
|
||||
const searchLabel = this.getSearchLabel(item);
|
||||
const value = this.getValue(item);
|
||||
|
||||
return (
|
||||
<option
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React from 'react'
|
||||
import React from 'react';
|
||||
|
||||
const FormFieldText = React.createClass({
|
||||
render() {
|
||||
|
@ -1,11 +1,11 @@
|
||||
define([
|
||||
'react'
|
||||
],
|
||||
function(
|
||||
(
|
||||
React
|
||||
) {
|
||||
var FormFieldTextarea = React.createClass({
|
||||
render: function() {
|
||||
) => {
|
||||
const FormFieldTextarea = React.createClass({
|
||||
render: function () {
|
||||
return (
|
||||
<textarea
|
||||
type="text"
|
||||
|
@ -6,37 +6,37 @@ define(
|
||||
'react-router',
|
||||
'form/fields/field.jsx'
|
||||
],
|
||||
function(
|
||||
(
|
||||
React,
|
||||
MailPoet,
|
||||
classNames,
|
||||
Router,
|
||||
FormField
|
||||
) {
|
||||
) => {
|
||||
|
||||
var Form = React.createClass({
|
||||
const Form = React.createClass({
|
||||
contextTypes: {
|
||||
router: React.PropTypes.object.isRequired
|
||||
},
|
||||
getDefaultProps: function() {
|
||||
getDefaultProps: function () {
|
||||
return {
|
||||
params: {},
|
||||
};
|
||||
},
|
||||
getInitialState: function() {
|
||||
getInitialState: function () {
|
||||
return {
|
||||
loading: false,
|
||||
errors: [],
|
||||
item: {}
|
||||
};
|
||||
},
|
||||
getValues: function() {
|
||||
getValues: function () {
|
||||
return this.props.item ? this.props.item : this.state.item;
|
||||
},
|
||||
getErrors: function() {
|
||||
getErrors: function () {
|
||||
return this.props.errors ? this.props.errors : this.state.errors;
|
||||
},
|
||||
componentDidMount: function() {
|
||||
componentDidMount: function () {
|
||||
if(this.isMounted()) {
|
||||
if(this.props.params.id !== undefined) {
|
||||
this.loadItem(this.props.params.id);
|
||||
@ -47,7 +47,7 @@ define(
|
||||
}
|
||||
}
|
||||
},
|
||||
componentWillReceiveProps: function(props) {
|
||||
componentWillReceiveProps: function (props) {
|
||||
if(props.params.id === undefined) {
|
||||
this.setState({
|
||||
loading: false,
|
||||
@ -60,7 +60,7 @@ define(
|
||||
this.loadItem(props.params.id);
|
||||
}
|
||||
},
|
||||
loadItem: function(id) {
|
||||
loadItem: function (id) {
|
||||
this.setState({ loading: true });
|
||||
|
||||
MailPoet.Ajax.post({
|
||||
@ -75,16 +75,16 @@ define(
|
||||
loading: false,
|
||||
item: response.data
|
||||
});
|
||||
}).fail((response) => {
|
||||
}).fail(() => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
item: {}
|
||||
}, function() {
|
||||
}, function () {
|
||||
this.context.router.push('/new');
|
||||
});
|
||||
});
|
||||
},
|
||||
handleSubmit: function(e) {
|
||||
handleSubmit: function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
// handle validation
|
||||
@ -97,16 +97,16 @@ define(
|
||||
this.setState({ loading: true });
|
||||
|
||||
// only get values from displayed fields
|
||||
var item = {};
|
||||
this.props.fields.map(function(field) {
|
||||
const item = {};
|
||||
this.props.fields.map((field) => {
|
||||
if(field['fields'] !== undefined) {
|
||||
field.fields.map(function(subfield) {
|
||||
field.fields.map((subfield) => {
|
||||
item[subfield.name] = this.state.item[subfield.name];
|
||||
}.bind(this));
|
||||
});
|
||||
} else {
|
||||
item[field.name] = this.state.item[field.name];
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
// set id if specified
|
||||
if(this.props.params.id !== undefined) {
|
||||
item.id = this.props.params.id;
|
||||
@ -119,7 +119,7 @@ define(
|
||||
data: item
|
||||
}).always(() => {
|
||||
this.setState({ loading: false });
|
||||
}).done((response) => {
|
||||
}).done(() => {
|
||||
if(this.props.onSuccess !== undefined) {
|
||||
this.props.onSuccess();
|
||||
} else {
|
||||
@ -137,12 +137,12 @@ define(
|
||||
}
|
||||
});
|
||||
},
|
||||
handleValueChange: function(e) {
|
||||
handleValueChange: function (e) {
|
||||
if (this.props.onChange) {
|
||||
return this.props.onChange(e);
|
||||
} else {
|
||||
var item = this.state.item,
|
||||
field = e.target.name;
|
||||
const item = this.state.item;
|
||||
const field = e.target.name;
|
||||
|
||||
item[field] = e.target.value;
|
||||
|
||||
@ -152,9 +152,10 @@ define(
|
||||
return true;
|
||||
}
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
let errors;
|
||||
if(this.getErrors() !== undefined) {
|
||||
var errors = this.getErrors().map(function(error, index) {
|
||||
errors = this.getErrors().map((error, index) => {
|
||||
return (
|
||||
<p key={ 'error-'+index } className="mailpoet_error">
|
||||
{ error.message }
|
||||
@ -163,13 +164,13 @@ define(
|
||||
});
|
||||
}
|
||||
|
||||
var formClasses = classNames(
|
||||
const formClasses = classNames(
|
||||
'mailpoet_form',
|
||||
{ 'mailpoet_form_loading': this.state.loading || this.props.loading }
|
||||
);
|
||||
|
||||
var beforeFormContent = false;
|
||||
var afterFormContent = false;
|
||||
let beforeFormContent = false;
|
||||
let afterFormContent = false;
|
||||
|
||||
if (this.props.beforeFormContent !== undefined) {
|
||||
beforeFormContent = this.props.beforeFormContent(this.getValues());
|
||||
@ -179,17 +180,26 @@ define(
|
||||
afterFormContent = this.props.afterFormContent(this.getValues());
|
||||
}
|
||||
|
||||
var fields = this.props.fields.map(function(field, i) {
|
||||
const fields = this.props.fields.map((field, i) => {
|
||||
// Compose an onChange handler from the default and custom one
|
||||
let onValueChange = this.handleValueChange;
|
||||
if (field.onBeforeChange) {
|
||||
onValueChange = (e) => {
|
||||
field.onBeforeChange(e);
|
||||
return this.handleValueChange(e);
|
||||
};
|
||||
}
|
||||
|
||||
return (
|
||||
<FormField
|
||||
field={ field }
|
||||
item={ this.getValues() }
|
||||
onValueChange={ this.handleValueChange }
|
||||
onValueChange={ onValueChange }
|
||||
key={ 'field-'+i } />
|
||||
);
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
var actions = false;
|
||||
let actions = false;
|
||||
if(this.props.children) {
|
||||
actions = this.props.children;
|
||||
} else {
|
||||
|
@ -1,14 +1,14 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { Router, Route, IndexRoute, Link, useRouterHistory } from 'react-router'
|
||||
import { createHashHistory } from 'history'
|
||||
import FormList from 'forms/list.jsx'
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Router, Route, IndexRoute, useRouterHistory } from 'react-router';
|
||||
import { createHashHistory } from 'history';
|
||||
import FormList from 'forms/list.jsx';
|
||||
|
||||
const history = useRouterHistory(createHashHistory)({ queryKey: false });
|
||||
|
||||
const App = React.createClass({
|
||||
render() {
|
||||
return this.props.children
|
||||
return this.props.children;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,9 +1,7 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { Router, Link } from 'react-router'
|
||||
import Listing from 'listing/listing.jsx'
|
||||
import classNames from 'classnames'
|
||||
import MailPoet from 'mailpoet'
|
||||
import React from 'react';
|
||||
import Listing from 'listing/listing.jsx';
|
||||
import classNames from 'classnames';
|
||||
import MailPoet from 'mailpoet';
|
||||
|
||||
const columns = [
|
||||
{
|
||||
@ -86,7 +84,7 @@ const item_actions = [
|
||||
{
|
||||
name: 'edit',
|
||||
label: MailPoet.I18n.t('edit'),
|
||||
link: function(item) {
|
||||
link: function (item) {
|
||||
return (
|
||||
<a href={ `admin.php?page=mailpoet-form-editor&id=${item.id}` }>{MailPoet.I18n.t('edit')}</a>
|
||||
);
|
||||
@ -95,7 +93,7 @@ const item_actions = [
|
||||
{
|
||||
name: 'duplicate',
|
||||
label: MailPoet.I18n.t('duplicate'),
|
||||
onClick: function(item, refresh) {
|
||||
onClick: function (item, refresh) {
|
||||
return MailPoet.Ajax.post({
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'forms',
|
||||
@ -111,7 +109,7 @@ const item_actions = [
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
@ -134,22 +132,22 @@ const FormList = React.createClass({
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
renderItem(form, actions) {
|
||||
let row_classes = classNames(
|
||||
const row_classes = classNames(
|
||||
'manage-column',
|
||||
'column-primary',
|
||||
'has-row-actions'
|
||||
);
|
||||
|
||||
let segments = mailpoet_segments.filter(function(segment) {
|
||||
let segments = mailpoet_segments.filter((segment) => {
|
||||
return (jQuery.inArray(segment.id, form.segments) !== -1);
|
||||
}).map(function(segment) {
|
||||
}).map((segment) => {
|
||||
return segment.name;
|
||||
}).join(', ');
|
||||
|
||||
|
32
assets/js/src/help/help.jsx
Normal file
@ -0,0 +1,32 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Router, Route, IndexRedirect, useRouterHistory } from 'react-router';
|
||||
import { createHashHistory } from 'history';
|
||||
|
||||
import KnowledgeBase from 'help/knowledge_base.jsx';
|
||||
import SystemInfo from 'help/system_info.jsx';
|
||||
|
||||
const history = useRouterHistory(createHashHistory)({ queryKey: false });
|
||||
|
||||
const App = React.createClass({
|
||||
render() {
|
||||
return this.props.children;
|
||||
}
|
||||
});
|
||||
|
||||
const container = document.getElementById('help_container');
|
||||
|
||||
if(container) {
|
||||
|
||||
ReactDOM.render((
|
||||
<Router history={ history }>
|
||||
<Route path="/" component={ App }>
|
||||
<IndexRedirect to="knowledgeBase" />
|
||||
{/* Pages */}
|
||||
<Route path="knowledgeBase(/)**" params={{ tab: 'knowledgeBase' }} component={ KnowledgeBase } />
|
||||
<Route path="systemInfo(/)**" params={{ tab: 'systemInfo' }} component={ SystemInfo } />
|
||||
</Route>
|
||||
</Router>
|
||||
), container);
|
||||
|
||||
}
|
29
assets/js/src/help/knowledge_base.jsx
Normal file
@ -0,0 +1,29 @@
|
||||
import React from 'react';
|
||||
import MailPoet from 'mailpoet';
|
||||
|
||||
import Tabs from './tabs.jsx';
|
||||
|
||||
function KnowledgeBase() {
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
||||
<Tabs tab="knowledgeBase" />
|
||||
|
||||
<p>{MailPoet.I18n.t('knowledgeBaseIntro')}</p>
|
||||
<ul>
|
||||
<li><a target="_blank" href="http://beta.docs.mailpoet.com/category/116-common-problems">Common Problems</a></li>
|
||||
<li><a target="_blank" href="http://beta.docs.mailpoet.com/category/165-newsletters">Newsletters</a></li>
|
||||
<li><a target="_blank" href="http://beta.docs.mailpoet.com/category/156-migration-questions">Migration Questions</a></li>
|
||||
<li><a target="_blank" href="http://beta.docs.mailpoet.com/category/149-sending-methods">Sending Methods</a></li>
|
||||
<li><a target="_blank" href="http://beta.docs.mailpoet.com/category/139-subscription-forms">Subscription Forms</a></li>
|
||||
<li><a target="_blank" href="http://beta.docs.mailpoet.com/category/114-getting-started">Getting Started</a></li>
|
||||
<li><a target="_blank" href="http://beta.docs.mailpoet.com/category/123-newsletter-designer">Newsletter Designer</a></li>
|
||||
<li><a target="_blank" href="http://beta.docs.mailpoet.com/category/121-subscribers-and-lists">Subscribers and Lists</a></li>
|
||||
</ul>
|
||||
<a target="_blank" href="http://beta.docs.mailpoet.com/" className="button button-primary">{MailPoet.I18n.t('knowledgeBaseButton')}</a>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = KnowledgeBase;
|
47
assets/js/src/help/system_info.jsx
Normal file
@ -0,0 +1,47 @@
|
||||
import React from 'react';
|
||||
import MailPoet from 'mailpoet';
|
||||
import _ from 'underscore';
|
||||
|
||||
import Tabs from './tabs.jsx';
|
||||
|
||||
function handleFocus(event) {
|
||||
event.target.select();
|
||||
}
|
||||
|
||||
function printData(data) {
|
||||
if (_.isObject(data)) {
|
||||
const printableData = Object.keys(data).map((key) => {
|
||||
return `${key}: ${data[key]}`;
|
||||
});
|
||||
|
||||
return (<textarea
|
||||
readOnly={true}
|
||||
onFocus={handleFocus}
|
||||
value={printableData.join("\n")}
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "400px",
|
||||
}}
|
||||
/>);
|
||||
} else {
|
||||
return (<p>{MailPoet.I18n.t('systemInfoDataError')}</p>);
|
||||
}
|
||||
}
|
||||
|
||||
function KnowledgeBase() {
|
||||
const data = window.help_scout_data;
|
||||
return (
|
||||
<div>
|
||||
|
||||
<Tabs tab="systemInfo" />
|
||||
|
||||
<div className="mailpoet_notice notice inline notice-success" style={{ marginTop: "1em" }}>
|
||||
<p>{MailPoet.I18n.t('systemInfoIntro')}</p>
|
||||
</div>
|
||||
|
||||
{printData(data)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = KnowledgeBase;
|
46
assets/js/src/help/tabs.jsx
Normal file
@ -0,0 +1,46 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import classNames from 'classnames';
|
||||
import MailPoet from 'mailpoet';
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
name: 'knowledgeBase',
|
||||
label: MailPoet.I18n.t('tabKnowledgeBaseTitle'),
|
||||
link: '/knowledgeBase'
|
||||
},
|
||||
{
|
||||
name: 'systemInfo',
|
||||
label: MailPoet.I18n.t('tabSystemInfoTitle'),
|
||||
link: '/systemInfo'
|
||||
},
|
||||
];
|
||||
|
||||
function Tabs(props) {
|
||||
|
||||
const tabLinks = tabs.map((tab, index) => {
|
||||
const tabClasses = classNames(
|
||||
'nav-tab',
|
||||
{ 'nav-tab-active': (props.tab === tab.name) }
|
||||
);
|
||||
|
||||
return (
|
||||
<Link
|
||||
key={ 'tab-'+index }
|
||||
className={ tabClasses }
|
||||
to={ tab.link }
|
||||
>{ tab.label }</Link>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<h2 className="nav-tab-wrapper">
|
||||
{ tabLinks }
|
||||
</h2>
|
||||
);
|
||||
};
|
||||
|
||||
Tabs.propTypes = { tab: React.PropTypes.string };
|
||||
Tabs.defaultProps = { tab: "knowledgeBase" };
|
||||
|
||||
module.exports = Tabs;
|
@ -2,23 +2,23 @@ define([
|
||||
'react',
|
||||
'mailpoet'
|
||||
],
|
||||
function(
|
||||
(
|
||||
React,
|
||||
MailPoet
|
||||
) {
|
||||
var ListingBulkActions = React.createClass({
|
||||
getInitialState: function() {
|
||||
) => {
|
||||
const ListingBulkActions = React.createClass({
|
||||
getInitialState: function () {
|
||||
return {
|
||||
action: false,
|
||||
extra: false
|
||||
}
|
||||
};
|
||||
},
|
||||
handleChangeAction: function(e) {
|
||||
handleChangeAction: function (e) {
|
||||
this.setState({
|
||||
action: e.target.value,
|
||||
extra: false
|
||||
}, function() {
|
||||
var action = this.getSelectedAction();
|
||||
}, () => {
|
||||
const action = this.getSelectedAction();
|
||||
|
||||
// action on select callback
|
||||
if(action !== null && action['onSelect'] !== undefined) {
|
||||
@ -26,28 +26,28 @@ function(
|
||||
extra: action.onSelect(e)
|
||||
});
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
handleApplyAction: function(e) {
|
||||
handleApplyAction: function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
var action = this.getSelectedAction();
|
||||
const action = this.getSelectedAction();
|
||||
|
||||
if(action === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var selected_ids = (this.props.selection !== 'all')
|
||||
const selected_ids = (this.props.selection !== 'all')
|
||||
? this.props.selected_ids
|
||||
: [];
|
||||
|
||||
var data = (action['getData'] !== undefined)
|
||||
const data = (action['getData'] !== undefined)
|
||||
? action.getData()
|
||||
: {};
|
||||
|
||||
data.action = this.state.action;
|
||||
|
||||
var onSuccess = function() {};
|
||||
let onSuccess = function () {};
|
||||
if(action['onSuccess'] !== undefined) {
|
||||
onSuccess = action.onSuccess;
|
||||
}
|
||||
@ -64,10 +64,10 @@ function(
|
||||
extra: false
|
||||
});
|
||||
},
|
||||
getSelectedAction: function() {
|
||||
var selected_action = this.refs.action.value;
|
||||
getSelectedAction: function () {
|
||||
const selected_action = this.refs.action.value;
|
||||
if(selected_action.length > 0) {
|
||||
var action = this.props.bulk_actions.filter(function(action) {
|
||||
const action = this.props.bulk_actions.filter((action) => {
|
||||
return (action.name === selected_action);
|
||||
});
|
||||
|
||||
@ -77,7 +77,7 @@ function(
|
||||
}
|
||||
return null;
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
if(this.props.bulk_actions.length === 0) {
|
||||
return null;
|
||||
}
|
||||
@ -97,14 +97,14 @@ function(
|
||||
onChange={this.handleChangeAction}
|
||||
>
|
||||
<option value="">{MailPoet.I18n.t('bulkActions')}</option>
|
||||
{ this.props.bulk_actions.map(function(action, index) {
|
||||
{ this.props.bulk_actions.map((action, index) => {
|
||||
return (
|
||||
<option
|
||||
value={ action.name }
|
||||
key={ 'action-' + index }
|
||||
>{ action.label }</option>
|
||||
);
|
||||
}.bind(this)) }
|
||||
}) }
|
||||
</select>
|
||||
<input
|
||||
onClick={ this.handleApplyAction }
|
||||
|
@ -3,25 +3,28 @@ define([
|
||||
'jquery',
|
||||
'mailpoet'
|
||||
],
|
||||
function(
|
||||
(
|
||||
React,
|
||||
jQuery,
|
||||
MailPoet
|
||||
) {
|
||||
var ListingFilters = React.createClass({
|
||||
handleFilterAction: function() {
|
||||
let filters = {};
|
||||
) => {
|
||||
const ListingFilters = React.createClass({
|
||||
handleFilterAction: function () {
|
||||
const filters = {};
|
||||
this.getAvailableFilters().map((filter, i) => {
|
||||
filters[this.refs['filter-'+i].name] = this.refs['filter-'+i].value
|
||||
filters[this.refs['filter-'+i].name] = this.refs['filter-'+i].value;
|
||||
});
|
||||
if (this.props.onBeforeSelectFilter) {
|
||||
this.props.onBeforeSelectFilter(filters);
|
||||
}
|
||||
return this.props.onSelectFilter(filters);
|
||||
},
|
||||
handleEmptyTrash: function() {
|
||||
handleEmptyTrash: function () {
|
||||
return this.props.onEmptyTrash();
|
||||
},
|
||||
getAvailableFilters: function() {
|
||||
let filters = this.props.filters;
|
||||
return Object.keys(filters).filter(function(filter) {
|
||||
getAvailableFilters: function () {
|
||||
const filters = this.props.filters;
|
||||
return Object.keys(filters).filter((filter) => {
|
||||
return !(
|
||||
filters[filter].length === 0
|
||||
|| (
|
||||
@ -31,39 +34,39 @@ function(
|
||||
);
|
||||
});
|
||||
},
|
||||
componentDidUpdate: function() {
|
||||
componentDidUpdate: function () {
|
||||
const selected_filters = this.props.filter;
|
||||
const available_filters = this.getAvailableFilters().map(
|
||||
function(filter, i) {
|
||||
this.getAvailableFilters().map(
|
||||
(filter, i) => {
|
||||
if (selected_filters[filter] !== undefined && selected_filters[filter]) {
|
||||
jQuery(this.refs['filter-'+i])
|
||||
.val(selected_filters[filter])
|
||||
.trigger('change');
|
||||
}
|
||||
}.bind(this)
|
||||
);
|
||||
}
|
||||
);
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
const filters = this.props.filters;
|
||||
const available_filters = this.getAvailableFilters()
|
||||
.map(function(filter, i) {
|
||||
.map((filter, i) => {
|
||||
return (
|
||||
<select
|
||||
ref={ `filter-${i}` }
|
||||
key={ `filter-${i}` }
|
||||
name={ filter }
|
||||
>
|
||||
{ filters[filter].map(function(option, j) {
|
||||
{ filters[filter].map((option, j) => {
|
||||
return (
|
||||
<option
|
||||
value={ option.value }
|
||||
key={ 'filter-option-' + j }
|
||||
>{ option.label }</option>
|
||||
);
|
||||
}.bind(this)) }
|
||||
}) }
|
||||
</select>
|
||||
);
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
let button;
|
||||
|
||||
|
@ -1,20 +1,20 @@
|
||||
define(['react', 'classnames'], function(React, classNames) {
|
||||
define(['react', 'classnames'], (React, classNames) => {
|
||||
|
||||
var ListingGroups = React.createClass({
|
||||
handleSelect: function(group) {
|
||||
return this.props.onSelectGroup(group);
|
||||
},
|
||||
render: function() {
|
||||
var groups = this.props.groups.map(function(group, index) {
|
||||
if(group.name === 'trash' && group.count === 0) {
|
||||
return false;
|
||||
}
|
||||
const ListingGroups = React.createClass({
|
||||
handleSelect: function (group) {
|
||||
return this.props.onSelectGroup(group);
|
||||
},
|
||||
render: function () {
|
||||
const groups = this.props.groups.map((group, index) => {
|
||||
if(group.name === 'trash' && group.count === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var classes = classNames(
|
||||
const classes = classNames(
|
||||
{ 'current' : (group.name === this.props.group) }
|
||||
);
|
||||
|
||||
return (
|
||||
return (
|
||||
<li key={index}>
|
||||
{(index > 0) ? ' |' : ''}
|
||||
<a
|
||||
@ -24,17 +24,17 @@ define(['react', 'classnames'], function(React, classNames) {
|
||||
{group.label} <span className="count">({ group.count.toLocaleString() })</span>
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
}.bind(this));
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
return (
|
||||
<ul className="subsubsub">
|
||||
{ groups }
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
});
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return ListingGroups;
|
||||
}
|
||||
return ListingGroups;
|
||||
}
|
||||
);
|
@ -1,15 +1,15 @@
|
||||
import MailPoet from 'mailpoet'
|
||||
import React from 'react'
|
||||
import classNames from 'classnames'
|
||||
import MailPoet from 'mailpoet';
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
const ListingHeader = React.createClass({
|
||||
handleSelectItems: function() {
|
||||
handleSelectItems: function () {
|
||||
return this.props.onSelectItems(
|
||||
this.refs.toggle.checked
|
||||
);
|
||||
},
|
||||
render: function() {
|
||||
const columns = this.props.columns.map(function(column, index) {
|
||||
render: function () {
|
||||
const columns = this.props.columns.map((column, index) => {
|
||||
column.is_primary = (index === 0);
|
||||
column.sorted = (this.props.sort_by === column.name)
|
||||
? this.props.sort_order
|
||||
@ -21,7 +21,7 @@ const ListingHeader = React.createClass({
|
||||
key={ 'column-' + index }
|
||||
column={column} />
|
||||
);
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
let checkbox;
|
||||
|
||||
@ -52,12 +52,12 @@ const ListingHeader = React.createClass({
|
||||
});
|
||||
|
||||
const ListingColumn = React.createClass({
|
||||
handleSort: function() {
|
||||
handleSort: function () {
|
||||
const sort_by = this.props.column.name;
|
||||
const sort_order = (this.props.column.sorted === 'asc') ? 'desc' : 'asc';
|
||||
this.props.onSort(sort_by, sort_order);
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
const classes = classNames(
|
||||
'manage-column',
|
||||
{ 'column-primary': this.props.column.is_primary },
|
||||
|
@ -1,23 +1,23 @@
|
||||
import MailPoet from 'mailpoet'
|
||||
import jQuery from 'jquery'
|
||||
import React from 'react'
|
||||
import _ from 'underscore'
|
||||
import { Router, Link } from 'react-router'
|
||||
import classNames from 'classnames'
|
||||
import ListingBulkActions from 'listing/bulk_actions.jsx'
|
||||
import ListingHeader from 'listing/header.jsx'
|
||||
import ListingPages from 'listing/pages.jsx'
|
||||
import ListingSearch from 'listing/search.jsx'
|
||||
import ListingGroups from 'listing/groups.jsx'
|
||||
import ListingFilters from 'listing/filters.jsx'
|
||||
import MailPoet from 'mailpoet';
|
||||
import jQuery from 'jquery';
|
||||
import React from 'react';
|
||||
import _ from 'underscore';
|
||||
import { Link } from 'react-router';
|
||||
import classNames from 'classnames';
|
||||
import ListingBulkActions from 'listing/bulk_actions.jsx';
|
||||
import ListingHeader from 'listing/header.jsx';
|
||||
import ListingPages from 'listing/pages.jsx';
|
||||
import ListingSearch from 'listing/search.jsx';
|
||||
import ListingGroups from 'listing/groups.jsx';
|
||||
import ListingFilters from 'listing/filters.jsx';
|
||||
|
||||
const ListingItem = React.createClass({
|
||||
getInitialState: function() {
|
||||
getInitialState: function () {
|
||||
return {
|
||||
expanded: false
|
||||
};
|
||||
},
|
||||
handleSelectItem: function(e) {
|
||||
handleSelectItem: function (e) {
|
||||
this.props.onSelectItem(
|
||||
parseInt(e.target.value, 10),
|
||||
e.target.checked
|
||||
@ -25,20 +25,20 @@ const ListingItem = React.createClass({
|
||||
|
||||
return !e.target.checked;
|
||||
},
|
||||
handleRestoreItem: function(id) {
|
||||
handleRestoreItem: function (id) {
|
||||
this.props.onRestoreItem(id);
|
||||
},
|
||||
handleTrashItem: function(id) {
|
||||
handleTrashItem: function (id) {
|
||||
this.props.onTrashItem(id);
|
||||
},
|
||||
handleDeleteItem: function(id) {
|
||||
handleDeleteItem: function (id) {
|
||||
this.props.onDeleteItem(id);
|
||||
},
|
||||
handleToggleItem: function(id) {
|
||||
handleToggleItem: function () {
|
||||
this.setState({ expanded: !this.state.expanded });
|
||||
},
|
||||
render: function() {
|
||||
var checkbox = false;
|
||||
render: function () {
|
||||
let checkbox = false;
|
||||
|
||||
if (this.props.is_selectable === true) {
|
||||
checkbox = (
|
||||
@ -63,7 +63,7 @@ const ListingItem = React.createClass({
|
||||
|
||||
if (custom_actions.length > 0) {
|
||||
let is_first = true;
|
||||
item_actions = custom_actions.map(function(action, index) {
|
||||
item_actions = custom_actions.map((action, index) => {
|
||||
if (action.display !== undefined) {
|
||||
if (action.display(this.props.item) === false) {
|
||||
return;
|
||||
@ -125,7 +125,7 @@ const ListingItem = React.createClass({
|
||||
}
|
||||
|
||||
return custom_action;
|
||||
}.bind(this));
|
||||
});
|
||||
} else {
|
||||
item_actions = (
|
||||
<span className="edit">
|
||||
@ -137,7 +137,7 @@ const ListingItem = React.createClass({
|
||||
let actions;
|
||||
|
||||
if (this.props.group === 'trash') {
|
||||
actions = (
|
||||
actions = (
|
||||
<div>
|
||||
<div className="row-actions">
|
||||
<span>
|
||||
@ -196,7 +196,7 @@ const ListingItem = React.createClass({
|
||||
|
||||
|
||||
const ListingItems = React.createClass({
|
||||
render: function() {
|
||||
render: function () {
|
||||
if (this.props.items.length === 0) {
|
||||
let message;
|
||||
if (this.props.loading === true) {
|
||||
@ -259,7 +259,7 @@ const ListingItems = React.createClass({
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{this.props.items.map(function(item, index) {
|
||||
{this.props.items.map((item, index) => {
|
||||
item.id = parseInt(item.id, 10);
|
||||
item.selected = (this.props.selected_ids.indexOf(item.id) !== -1);
|
||||
|
||||
@ -279,7 +279,7 @@ const ListingItems = React.createClass({
|
||||
key={ `item-${item.id}-${index}` }
|
||||
item={ item } />
|
||||
);
|
||||
}.bind(this))}
|
||||
})}
|
||||
</tbody>
|
||||
);
|
||||
}
|
||||
@ -290,7 +290,7 @@ const Listing = React.createClass({
|
||||
contextTypes: {
|
||||
router: React.PropTypes.object.isRequired
|
||||
},
|
||||
getInitialState: function() {
|
||||
getInitialState: function () {
|
||||
return {
|
||||
loading: false,
|
||||
search: '',
|
||||
@ -309,28 +309,28 @@ const Listing = React.createClass({
|
||||
meta: {}
|
||||
};
|
||||
},
|
||||
getParam: function(param) {
|
||||
getParam: function (param) {
|
||||
const regex = /(.*)\[(.*)\]/;
|
||||
const matches = regex.exec(param);
|
||||
return [matches[1], matches[2]];
|
||||
},
|
||||
initWithParams: function(params) {
|
||||
let state = this.getInitialState();
|
||||
initWithParams: function (params) {
|
||||
const state = this.getInitialState();
|
||||
// check for url params
|
||||
if (params.splat) {
|
||||
params.splat.split('/').map(param => {
|
||||
let [key, value] = this.getParam(param);
|
||||
params.splat.split('/').map((param) => {
|
||||
const [key, value] = this.getParam(param);
|
||||
switch(key) {
|
||||
case 'filter':
|
||||
let filters = {};
|
||||
value.split('&').map(function(pair) {
|
||||
let [k, v] = pair.split('=')
|
||||
filters[k] = v
|
||||
}
|
||||
const filters = {};
|
||||
value.split('&').map((pair) => {
|
||||
const [k, v] = pair.split('=');
|
||||
filters[k] = v;
|
||||
}
|
||||
);
|
||||
|
||||
state.filter = filters;
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
state[key] = value;
|
||||
}
|
||||
@ -352,13 +352,13 @@ const Listing = React.createClass({
|
||||
state.sort_order = this.props.sort_order;
|
||||
}
|
||||
|
||||
this.setState(state, function() {
|
||||
this.setState(state, () => {
|
||||
this.getItems();
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
getParams: function() {
|
||||
getParams: function () {
|
||||
// get all route parameters (without the "splat")
|
||||
let params = _.omit(this.props.params, 'splat');
|
||||
const params = _.omit(this.props.params, 'splat');
|
||||
// TODO:
|
||||
// find a way to set the "type" in the routes definition
|
||||
// so that it appears in `this.props.params`
|
||||
@ -367,10 +367,10 @@ const Listing = React.createClass({
|
||||
}
|
||||
return params;
|
||||
},
|
||||
setParams: function() {
|
||||
setParams: function () {
|
||||
if (this.props.location) {
|
||||
let params = Object.keys(this.state)
|
||||
.filter(key => {
|
||||
const params = Object.keys(this.state)
|
||||
.filter((key) => {
|
||||
return (
|
||||
[
|
||||
'group',
|
||||
@ -380,32 +380,32 @@ const Listing = React.createClass({
|
||||
'sort_by',
|
||||
'sort_order'
|
||||
].indexOf(key) !== -1
|
||||
)
|
||||
);
|
||||
})
|
||||
.map(key => {
|
||||
.map((key) => {
|
||||
let value = this.state[key];
|
||||
if (value === Object(value)) {
|
||||
value = jQuery.param(value)
|
||||
value = jQuery.param(value);
|
||||
} else if (value === Boolean(value)) {
|
||||
value = value.toString()
|
||||
value = value.toString();
|
||||
}
|
||||
|
||||
if (value !== '' && value !== null) {
|
||||
return `${key}[${value}]`
|
||||
return `${key}[${value}]`;
|
||||
}
|
||||
})
|
||||
.filter(key => { return (key !== undefined) })
|
||||
.filter((key) => { return (key !== undefined); })
|
||||
.join('/');
|
||||
|
||||
// set url
|
||||
let url = this.getUrlWithParams(params);
|
||||
const url = this.getUrlWithParams(params);
|
||||
|
||||
if (this.props.location.pathname !== url) {
|
||||
this.context.router.push(`${url}`);
|
||||
}
|
||||
}
|
||||
},
|
||||
getUrlWithParams: function(params) {
|
||||
getUrlWithParams: function (params) {
|
||||
let base_url = (this.props.base_url !== undefined)
|
||||
? this.props.base_url
|
||||
: null;
|
||||
@ -417,7 +417,7 @@ const Listing = React.createClass({
|
||||
return `/${ params }`;
|
||||
}
|
||||
},
|
||||
setBaseUrlParams: function(base_url) {
|
||||
setBaseUrlParams: function (base_url) {
|
||||
if (base_url.indexOf(':') !== -1) {
|
||||
const params = this.getParams();
|
||||
Object.keys(params).map((key) => {
|
||||
@ -429,23 +429,23 @@ const Listing = React.createClass({
|
||||
|
||||
return base_url;
|
||||
},
|
||||
componentDidMount: function() {
|
||||
componentDidMount: function () {
|
||||
if (this.isMounted()) {
|
||||
const params = this.props.params || {};
|
||||
this.initWithParams(params);
|
||||
|
||||
if (this.props.auto_refresh) {
|
||||
jQuery(document).on('heartbeat-tick.mailpoet', function(e, data) {
|
||||
jQuery(document).on('heartbeat-tick.mailpoet', () => {
|
||||
this.getItems();
|
||||
}.bind(this));
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
componentWillReceiveProps: function (nextProps) {
|
||||
const params = nextProps.params || {};
|
||||
this.initWithParams(params);
|
||||
},
|
||||
getItems: function() {
|
||||
getItems: function () {
|
||||
if (this.isMounted()) {
|
||||
this.setState({ loading: true });
|
||||
|
||||
@ -487,16 +487,16 @@ const Listing = React.createClass({
|
||||
}
|
||||
});
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
if(response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
handleRestoreItem: function(id) {
|
||||
handleRestoreItem: function (id) {
|
||||
this.setState({
|
||||
loading: true,
|
||||
page: 1
|
||||
@ -519,12 +519,12 @@ const Listing = React.createClass({
|
||||
this.getItems();
|
||||
}).fail((response) => {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
});
|
||||
},
|
||||
handleTrashItem: function(id) {
|
||||
handleTrashItem: function (id) {
|
||||
this.setState({
|
||||
loading: true,
|
||||
page: 1
|
||||
@ -547,12 +547,12 @@ const Listing = React.createClass({
|
||||
this.getItems();
|
||||
}).fail((response) => {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
});
|
||||
},
|
||||
handleDeleteItem: function(id) {
|
||||
handleDeleteItem: function (id) {
|
||||
this.setState({
|
||||
loading: true,
|
||||
page: 1
|
||||
@ -575,12 +575,12 @@ const Listing = React.createClass({
|
||||
this.getItems();
|
||||
}).fail((response) => {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
});
|
||||
},
|
||||
handleEmptyTrash: function() {
|
||||
handleEmptyTrash: function () {
|
||||
return this.handleBulkAction('all', {
|
||||
action: 'delete',
|
||||
group: 'trash'
|
||||
@ -592,12 +592,12 @@ const Listing = React.createClass({
|
||||
this.handleGroup('all');
|
||||
}).fail((response) => {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
});
|
||||
},
|
||||
handleBulkAction: function(selected_ids, params) {
|
||||
handleBulkAction: function (selected_ids, params) {
|
||||
if (
|
||||
this.state.selection === false
|
||||
&& this.state.selected_ids.length === 0
|
||||
@ -608,7 +608,7 @@ const Listing = React.createClass({
|
||||
|
||||
this.setState({ loading: true });
|
||||
|
||||
var data = params || {};
|
||||
const data = params || {};
|
||||
data.listing = {
|
||||
params: this.getParams(),
|
||||
offset: 0,
|
||||
@ -616,7 +616,7 @@ const Listing = React.createClass({
|
||||
filter: this.state.filter,
|
||||
group: this.state.group,
|
||||
search: this.state.search
|
||||
}
|
||||
};
|
||||
if (selected_ids !== 'all') {
|
||||
data.listing.selection = selected_ids;
|
||||
}
|
||||
@ -628,29 +628,36 @@ const Listing = React.createClass({
|
||||
data: data
|
||||
}).done(() => {
|
||||
this.getItems();
|
||||
}).fail((response) => {
|
||||
if(response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
handleSearch: function(search) {
|
||||
handleSearch: function (search) {
|
||||
this.setState({
|
||||
search: search,
|
||||
page: 1,
|
||||
selection: false,
|
||||
selected_ids: []
|
||||
}, function() {
|
||||
}, () => {
|
||||
this.setParams();
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
handleSort: function(sort_by, sort_order = 'asc') {
|
||||
handleSort: function (sort_by, sort_order = 'asc') {
|
||||
this.setState({
|
||||
sort_by: sort_by,
|
||||
sort_order: (sort_order === 'asc') ? 'asc' : 'desc',
|
||||
}, function() {
|
||||
}, () => {
|
||||
this.setParams();
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
handleSelectItem: function(id, is_checked) {
|
||||
var selected_ids = this.state.selected_ids,
|
||||
selection = false;
|
||||
handleSelectItem: function (id, is_checked) {
|
||||
let selected_ids = this.state.selected_ids,
|
||||
selection = false;
|
||||
|
||||
if (is_checked) {
|
||||
selected_ids = jQuery.merge(selected_ids, [ id ]);
|
||||
@ -669,11 +676,11 @@ const Listing = React.createClass({
|
||||
selected_ids: selected_ids
|
||||
});
|
||||
},
|
||||
handleSelectItems: function(is_checked) {
|
||||
handleSelectItems: function (is_checked) {
|
||||
if (is_checked === false) {
|
||||
this.clearSelection();
|
||||
} else {
|
||||
var selected_ids = this.state.items.map(function(item) {
|
||||
const selected_ids = this.state.items.map((item) => {
|
||||
return ~~item.id;
|
||||
});
|
||||
|
||||
@ -683,7 +690,7 @@ const Listing = React.createClass({
|
||||
});
|
||||
}
|
||||
},
|
||||
handleSelectAll: function() {
|
||||
handleSelectAll: function () {
|
||||
if (this.state.selection === 'all') {
|
||||
this.clearSelection();
|
||||
} else {
|
||||
@ -693,21 +700,21 @@ const Listing = React.createClass({
|
||||
});
|
||||
}
|
||||
},
|
||||
clearSelection: function() {
|
||||
clearSelection: function () {
|
||||
this.setState({
|
||||
selection: false,
|
||||
selected_ids: []
|
||||
});
|
||||
},
|
||||
handleFilter: function(filters) {
|
||||
handleFilter: function (filters) {
|
||||
this.setState({
|
||||
filter: filters,
|
||||
page: 1
|
||||
}, function() {
|
||||
}, () => {
|
||||
this.setParams();
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
handleGroup: function(group) {
|
||||
handleGroup: function (group) {
|
||||
// reset search
|
||||
jQuery('#search_input').val('');
|
||||
|
||||
@ -716,34 +723,34 @@ const Listing = React.createClass({
|
||||
filter: {},
|
||||
search: '',
|
||||
page: 1
|
||||
}, function() {
|
||||
}, () => {
|
||||
this.setParams();
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
handleSetPage: function(page) {
|
||||
handleSetPage: function (page) {
|
||||
this.setState({
|
||||
page: page,
|
||||
selection: false,
|
||||
selected_ids: []
|
||||
}, function() {
|
||||
}, () => {
|
||||
this.setParams();
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
handleRenderItem: function(item, actions) {
|
||||
handleRenderItem: function (item, actions) {
|
||||
const render = this.props.onRenderItem(item, actions, this.state.meta);
|
||||
return render.props.children;
|
||||
},
|
||||
handleRefreshItems: function() {
|
||||
handleRefreshItems: function () {
|
||||
this.getItems();
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
const items = this.state.items;
|
||||
const sort_by = this.state.sort_by;
|
||||
const sort_order = this.state.sort_order;
|
||||
|
||||
// columns
|
||||
let columns = this.props.columns || [];
|
||||
columns = columns.filter(function(column) {
|
||||
columns = columns.filter((column) => {
|
||||
return (column.display === undefined || !!(column.display) === true);
|
||||
});
|
||||
|
||||
@ -821,6 +828,7 @@ const Listing = React.createClass({
|
||||
filters={ this.state.filters }
|
||||
filter={ this.state.filter }
|
||||
group={ this.state.group }
|
||||
onBeforeSelectFilter={ this.props.onBeforeSelectFilter || null }
|
||||
onSelectFilter={ this.handleFilter }
|
||||
onEmptyTrash={ this.handleEmptyTrash }
|
||||
/>
|
||||
|
@ -1,76 +1,76 @@
|
||||
define([
|
||||
'react',
|
||||
'classnames',
|
||||
'mailpoet'
|
||||
], function(
|
||||
'react',
|
||||
'classnames',
|
||||
'mailpoet'
|
||||
], (
|
||||
React,
|
||||
classNames,
|
||||
MailPoet
|
||||
) {
|
||||
) => {
|
||||
|
||||
var ListingPages = React.createClass({
|
||||
getInitialState: function() {
|
||||
const ListingPages = React.createClass({
|
||||
getInitialState: function () {
|
||||
return {
|
||||
page: null
|
||||
}
|
||||
};
|
||||
},
|
||||
setPage: function(page) {
|
||||
setPage: function (page) {
|
||||
this.setState({
|
||||
page: null
|
||||
}, function () {
|
||||
}, () => {
|
||||
this.props.onSetPage(this.constrainPage(page));
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
setFirstPage: function() {
|
||||
setFirstPage: function () {
|
||||
this.setPage(1);
|
||||
},
|
||||
setLastPage: function() {
|
||||
setLastPage: function () {
|
||||
this.setPage(this.getLastPage());
|
||||
},
|
||||
setPreviousPage: function() {
|
||||
setPreviousPage: function () {
|
||||
this.setPage(this.constrainPage(
|
||||
parseInt(this.props.page, 10) - 1)
|
||||
);
|
||||
},
|
||||
setNextPage: function() {
|
||||
setNextPage: function () {
|
||||
this.setPage(this.constrainPage(
|
||||
parseInt(this.props.page, 10) + 1)
|
||||
);
|
||||
},
|
||||
constrainPage: function(page) {
|
||||
constrainPage: function (page) {
|
||||
return Math.min(Math.max(1, Math.abs(~~page)), this.getLastPage());
|
||||
},
|
||||
handleSetManualPage: function(e) {
|
||||
handleSetManualPage: function (e) {
|
||||
if(e.which === 13) {
|
||||
this.setPage(this.state.page);
|
||||
}
|
||||
},
|
||||
handleChangeManualPage: function(e) {
|
||||
handleChangeManualPage: function (e) {
|
||||
this.setState({
|
||||
page: e.target.value
|
||||
});
|
||||
},
|
||||
handleBlurManualPage: function(e) {
|
||||
handleBlurManualPage: function (e) {
|
||||
this.setPage(e.target.value);
|
||||
},
|
||||
getLastPage: function() {
|
||||
getLastPage: function () {
|
||||
return Math.ceil(this.props.count / this.props.limit);
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
if(this.props.count === 0) {
|
||||
return false;
|
||||
} else {
|
||||
var pagination = false;
|
||||
var firstPage = (
|
||||
let pagination = false;
|
||||
let firstPage = (
|
||||
<span aria-hidden="true" className="tablenav-pages-navspan">«</span>
|
||||
);
|
||||
var previousPage = (
|
||||
let previousPage = (
|
||||
<span aria-hidden="true" className="tablenav-pages-navspan">‹</span>
|
||||
);
|
||||
var nextPage = (
|
||||
let nextPage = (
|
||||
<span aria-hidden="true" className="tablenav-pages-navspan">›</span>
|
||||
);
|
||||
var lastPage = (
|
||||
let lastPage = (
|
||||
<span aria-hidden="true" className="tablenav-pages-navspan">»</span>
|
||||
);
|
||||
|
||||
@ -159,12 +159,12 @@ define([
|
||||
);
|
||||
}
|
||||
|
||||
var classes = classNames(
|
||||
const classes = classNames(
|
||||
'tablenav-pages',
|
||||
{ 'one-page': (this.props.count <= this.props.limit) }
|
||||
);
|
||||
|
||||
var numberOfItemsLabel;
|
||||
let numberOfItemsLabel;
|
||||
if (this.props.count == 1) {
|
||||
numberOfItemsLabel = MailPoet.I18n.t('numberOfItemsSingular');
|
||||
} else {
|
||||
|
@ -1,22 +1,22 @@
|
||||
define([
|
||||
'mailpoet',
|
||||
'react'
|
||||
], function(
|
||||
'mailpoet',
|
||||
'react'
|
||||
], (
|
||||
MailPoet,
|
||||
React
|
||||
) {
|
||||
) => {
|
||||
|
||||
var ListingSearch = React.createClass({
|
||||
handleSearch: function(e) {
|
||||
const ListingSearch = React.createClass({
|
||||
handleSearch: function (e) {
|
||||
e.preventDefault();
|
||||
this.props.onSearch(
|
||||
this.refs.search.value
|
||||
);
|
||||
},
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
this.refs.search.value = nextProps.search
|
||||
componentWillReceiveProps: function (nextProps) {
|
||||
this.refs.search.value = nextProps.search;
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
if(this.props.search === false) {
|
||||
return false;
|
||||
} else {
|
||||
|
@ -61,8 +61,10 @@ define('mp2migrator', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
|
||||
}
|
||||
jQuery('#progressbar').progressbar('option', 'value', progress);
|
||||
jQuery('#progresslabel').html(progress + '%');
|
||||
if(Number(result.current !== 0)) {
|
||||
if(Number(result.current) !== 0) {
|
||||
jQuery('#skip-import').hide();
|
||||
jQuery('#progressbar').show();
|
||||
jQuery('#logger-container').show();
|
||||
}
|
||||
if(MailPoet.MP2Migrator.is_logging) {
|
||||
MailPoet.MP2Migrator.updateProgressbar_timeout = setTimeout(MailPoet.MP2Migrator.updateProgressbar, 1000);
|
||||
@ -129,6 +131,15 @@ define('mp2migrator', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
|
||||
jQuery('#stop-import').removeAttr('disabled'); // Enable the button
|
||||
MailPoet.MP2Migrator.reactivateImportButton();
|
||||
MailPoet.MP2Migrator.updateDisplay(); // Get the latest information after the import was stopped
|
||||
}).fail(function (response) {
|
||||
if(response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function (error) {
|
||||
return error.message;
|
||||
}),
|
||||
{scroll: true}
|
||||
);
|
||||
}
|
||||
});
|
||||
MailPoet.MP2Migrator.stopLogger();
|
||||
return false;
|
||||
@ -143,6 +154,15 @@ define('mp2migrator', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
|
||||
}
|
||||
}).done(function () {
|
||||
MailPoet.MP2Migrator.gotoWelcomePage();
|
||||
}).fail(function (response) {
|
||||
if(response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function (error) {
|
||||
return error.message;
|
||||
}),
|
||||
{scroll: true}
|
||||
);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
},
|
||||
|
@ -114,6 +114,7 @@ define([
|
||||
},
|
||||
})
|
||||
.preventDefault('auto')
|
||||
.styleCursor(false)
|
||||
.actionChecker(function (pointer, event, action) {
|
||||
// Disable dragging with right click
|
||||
if (event.button !== 0) {
|
||||
|
@ -52,6 +52,7 @@ define([
|
||||
modelEvents: {
|
||||
'change': 'render',
|
||||
'delete': 'deleteBlock',
|
||||
'duplicate': 'duplicateBlock',
|
||||
},
|
||||
events: {
|
||||
"mouseenter": "showTools",
|
||||
@ -142,6 +143,9 @@ define([
|
||||
this.model.destroy();
|
||||
}.bind(this));
|
||||
},
|
||||
duplicateBlock: function() {
|
||||
this.model.collection.add(this.model.toJSON(), {at: this.model.collection.findIndex(this.model)});
|
||||
},
|
||||
transitionIn: function() {
|
||||
return this._transition('slideDown', 'fadeIn', 'easeOut');
|
||||
},
|
||||
@ -180,11 +184,13 @@ define([
|
||||
"click .mailpoet_delete_block_activate": "showDeletionConfirmation",
|
||||
"click .mailpoet_delete_block_cancel": "hideDeletionConfirmation",
|
||||
"click .mailpoet_delete_block_confirm": "deleteBlock",
|
||||
"click .mailpoet_duplicate_block": "duplicateBlock",
|
||||
},
|
||||
// Markers of whether these particular tools will be used for this instance
|
||||
tools: {
|
||||
settings: true,
|
||||
delete: true,
|
||||
duplicate: true,
|
||||
move: true,
|
||||
},
|
||||
getSettingsView: function() { return Module.BlockSettingsView; },
|
||||
@ -221,6 +227,11 @@ define([
|
||||
this.model.trigger('delete');
|
||||
return false;
|
||||
},
|
||||
duplicateBlock: function(event) {
|
||||
event.preventDefault();
|
||||
this.model.trigger('duplicate');
|
||||
return false;
|
||||
},
|
||||
});
|
||||
|
||||
Module.BlockSettingsView = Marionette.View.extend({
|
||||
|
@ -161,6 +161,7 @@ define([
|
||||
tools: {
|
||||
settings: this.renderOptions.depth === 1,
|
||||
delete: this.renderOptions.depth === 1,
|
||||
duplicate: true,
|
||||
move: this.renderOptions.depth === 1,
|
||||
layerSelector: false,
|
||||
},
|
||||
|
@ -48,6 +48,7 @@ define([
|
||||
return this._getDefaults({
|
||||
type: 'posts',
|
||||
amount: '10',
|
||||
offset: 0,
|
||||
contentType: 'post', // 'post'|'page'|'mailpoet_page'
|
||||
postStatus: 'publish', // 'draft'|'pending'|'private'|'publish'|'future'
|
||||
terms: [], // List of category and tag objects
|
||||
@ -98,6 +99,7 @@ define([
|
||||
|
||||
this.fetchAvailablePosts();
|
||||
this.on('change:amount change:contentType change:terms change:inclusionType change:postStatus change:search change:sortBy', refreshAvailablePosts);
|
||||
this.on('loadMorePosts', this._loadMorePosts, this);
|
||||
|
||||
this.listenTo(this.get('_selectedPosts'), 'add remove reset', refreshTransformedPosts);
|
||||
this.on('change:displayType change:titleFormat change:featuredImagePosition change:titleAlignment change:titleIsLink change:imageFullWidth change:showAuthor change:authorPrecededBy change:showCategories change:categoriesPrecededBy change:readMoreType change:readMoreText change:showDivider', refreshTransformedPosts);
|
||||
@ -108,6 +110,7 @@ define([
|
||||
},
|
||||
fetchAvailablePosts: function() {
|
||||
var that = this;
|
||||
this.set('offset', 0);
|
||||
CommunicationComponent.getPosts(this.toJSON()).done(function(posts) {
|
||||
that.get('_availablePosts').reset(posts);
|
||||
that.get('_selectedPosts').reset(); // Empty out the collection
|
||||
@ -116,6 +119,27 @@ define([
|
||||
MailPoet.Notice.error(MailPoet.I18n.t('failedToFetchAvailablePosts'));
|
||||
});
|
||||
},
|
||||
_loadMorePosts: function() {
|
||||
var that = this,
|
||||
postCount = this.get('_availablePosts').length,
|
||||
nextOffset = this.get('offset') + Number(this.get('amount'));
|
||||
|
||||
if(postCount === 0 || postCount < nextOffset) {
|
||||
// No more posts to load
|
||||
return false;
|
||||
}
|
||||
this.set('offset', nextOffset);
|
||||
this.trigger('loadingMorePosts');
|
||||
|
||||
CommunicationComponent.getPosts(this.toJSON()).done(function(posts) {
|
||||
that.get('_availablePosts').add(posts);
|
||||
that.trigger('change:_availablePosts');
|
||||
}).fail(function() {
|
||||
MailPoet.Notice.error(MailPoet.I18n.t('failedToFetchAvailablePosts'));
|
||||
}).always(function() {
|
||||
that.trigger('morePostsLoaded');
|
||||
});
|
||||
},
|
||||
_refreshTransformedPosts: function() {
|
||||
var that = this,
|
||||
data = this.toJSON();
|
||||
@ -260,6 +284,7 @@ define([
|
||||
});
|
||||
|
||||
var PostsSelectionCollectionView = Marionette.CollectionView.extend({
|
||||
className: 'mailpoet_post_scroll_container',
|
||||
childView: function() { return SinglePostSelectionSettingsView; },
|
||||
emptyView: function() { return EmptyPostSelectionSettingsView; },
|
||||
childViewOptions: function() {
|
||||
@ -270,6 +295,16 @@ define([
|
||||
initialize: function(options) {
|
||||
this.blockModel = options.blockModel;
|
||||
},
|
||||
events: {
|
||||
'scroll': 'onPostsScroll',
|
||||
},
|
||||
onPostsScroll: function(event) {
|
||||
var $postsBox = jQuery(event.target);
|
||||
if($postsBox.scrollTop() + $postsBox.innerHeight() >= $postsBox[0].scrollHeight){
|
||||
// Load more posts if scrolled to bottom
|
||||
this.blockModel.trigger('loadMorePosts');
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
var PostSelectionSettingsView = Marionette.View.extend({
|
||||
@ -284,6 +319,20 @@ define([
|
||||
'input .mailpoet_posts_search_term': _.partial(this.changeField, 'search'),
|
||||
};
|
||||
},
|
||||
modelEvents: {
|
||||
'change:offset': function(model, value) {
|
||||
// Scroll posts view to top if settings are changed
|
||||
if (value === 0) {
|
||||
this.$('.mailpoet_post_scroll_container').scrollTop(0);
|
||||
}
|
||||
},
|
||||
'loadingMorePosts': function() {
|
||||
this.$('.mailpoet_post_selection_loading').css('visibility', 'visible');
|
||||
},
|
||||
'morePostsLoaded': function() {
|
||||
this.$('.mailpoet_post_selection_loading').css('visibility', 'hidden');
|
||||
}
|
||||
},
|
||||
onRender: function() {
|
||||
// Dynamically update available post types
|
||||
CommunicationComponent.getPostTypes().done(_.bind(this._updateContentTypes, this));
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import classNames from 'classnames'
|
||||
import ReactTooltip from 'react-tooltip'
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import ReactTooltip from 'react-tooltip';
|
||||
|
||||
class Badge extends React.Component {
|
||||
render() {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import MailPoet from 'mailpoet'
|
||||
import React from 'react'
|
||||
import MailPoet from 'mailpoet';
|
||||
import React from 'react';
|
||||
|
||||
import Badge from './badge.jsx'
|
||||
import Badge from './badge.jsx';
|
||||
|
||||
const badges = {
|
||||
excellent: {
|
||||
@ -51,7 +51,7 @@ const stats = {
|
||||
class StatsBadge extends React.Component {
|
||||
getBadgeType(stat, rate) {
|
||||
const len = stat.badgeRanges.length;
|
||||
for (var i = 0; i < len; i++) {
|
||||
for (let i = 0; i < len; i += 1) {
|
||||
if (rate > stat.badgeRanges[i]) {
|
||||
return stat.badgeTypes[i];
|
||||
}
|
||||
|
@ -5,16 +5,16 @@ define(
|
||||
'classnames',
|
||||
'mailpoet'
|
||||
],
|
||||
function(
|
||||
(
|
||||
React,
|
||||
Router,
|
||||
classNames,
|
||||
MailPoet
|
||||
) {
|
||||
var Link = Router.Link;
|
||||
) => {
|
||||
const Link = Router.Link;
|
||||
|
||||
var Breadcrumb = React.createClass({
|
||||
getInitialState: function() {
|
||||
const Breadcrumb = React.createClass({
|
||||
getInitialState: function () {
|
||||
return {
|
||||
step: null,
|
||||
steps: [
|
||||
@ -38,13 +38,13 @@ define(
|
||||
]
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
var steps = this.state.steps.map(function(step, index) {
|
||||
var stepClasses = classNames(
|
||||
render: function () {
|
||||
const steps = this.state.steps.map((step, index) => {
|
||||
const stepClasses = classNames(
|
||||
{ 'mailpoet_current': (this.props.step === step.name) }
|
||||
);
|
||||
|
||||
var label = step.label;
|
||||
let label = step.label;
|
||||
|
||||
if(step['link'] !== undefined && this.props.step !== step.name) {
|
||||
label = (
|
||||
@ -60,7 +60,7 @@ define(
|
||||
{ (index < (this.state.steps.length - 1) ) ? ' > ' : '' }
|
||||
</span>
|
||||
);
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
return (
|
||||
<p className="mailpoet_breadcrumb">
|
||||
|
@ -1,16 +1,16 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import ReactStringReplace from 'react-string-replace'
|
||||
import { Link } from 'react-router'
|
||||
import MailPoet from 'mailpoet'
|
||||
import classNames from 'classnames'
|
||||
import moment from 'moment'
|
||||
import jQuery from 'jquery'
|
||||
import Hooks from 'wp-js-hooks'
|
||||
import StatsBadge from 'newsletters/badges/stats.jsx'
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import ReactStringReplace from 'react-string-replace';
|
||||
import { Link } from 'react-router';
|
||||
import MailPoet from 'mailpoet';
|
||||
import classNames from 'classnames';
|
||||
import moment from 'moment';
|
||||
import jQuery from 'jquery';
|
||||
import Hooks from 'wp-js-hooks';
|
||||
import StatsBadge from 'newsletters/badges/stats.jsx';
|
||||
|
||||
const _QueueMixin = {
|
||||
pauseSending: function(newsletter) {
|
||||
pauseSending: function (newsletter) {
|
||||
MailPoet.Ajax.post({
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'sendingQueue',
|
||||
@ -18,19 +18,19 @@ const _QueueMixin = {
|
||||
data: {
|
||||
newsletter_id: newsletter.id
|
||||
}
|
||||
}).done(function() {
|
||||
}).done(() => {
|
||||
jQuery('#resume_'+newsletter.id).show();
|
||||
jQuery('#pause_'+newsletter.id).hide();
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
resumeSending: function(newsletter) {
|
||||
resumeSending: function (newsletter) {
|
||||
MailPoet.Ajax.post({
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'sendingQueue',
|
||||
@ -38,19 +38,19 @@ const _QueueMixin = {
|
||||
data: {
|
||||
newsletter_id: newsletter.id
|
||||
}
|
||||
}).done(function() {
|
||||
}).done(() => {
|
||||
jQuery('#pause_'+newsletter.id).show();
|
||||
jQuery('#resume_'+newsletter.id).hide();
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
renderQueueStatus: function(newsletter, mailer_log) {
|
||||
renderQueueStatus: function (newsletter, mailer_log) {
|
||||
if (!newsletter.queue) {
|
||||
return (
|
||||
<span>{MailPoet.I18n.t('notSentYet')}</span>
|
||||
@ -58,18 +58,18 @@ const _QueueMixin = {
|
||||
} else if (mailer_log.status === 'paused' && newsletter.queue.status !== 'completed') {
|
||||
return (
|
||||
<span>{MailPoet.I18n.t('paused')}</span>
|
||||
)
|
||||
);
|
||||
} else {
|
||||
if (newsletter.queue.status === 'scheduled') {
|
||||
return (
|
||||
<span>
|
||||
{ MailPoet.I18n.t('scheduledFor') } { MailPoet.Date.format(newsletter.queue.scheduled_at) }
|
||||
</span>
|
||||
)
|
||||
);
|
||||
}
|
||||
const progressClasses = classNames(
|
||||
'mailpoet_progress',
|
||||
{ 'mailpoet_progress_complete': newsletter.queue.status === 'completed'}
|
||||
{ 'mailpoet_progress_complete': newsletter.queue.status === 'completed' }
|
||||
);
|
||||
|
||||
// calculate percentage done
|
||||
@ -128,7 +128,7 @@ const _QueueMixin = {
|
||||
<div className={ progressClasses }>
|
||||
<span
|
||||
className="mailpoet_progress_bar"
|
||||
style={ { width: progress_bar_width + "%"} }
|
||||
style={ { width: progress_bar_width + "%" } }
|
||||
></span>
|
||||
<span className="mailpoet_progress_label">
|
||||
{ percentage }
|
||||
@ -144,12 +144,12 @@ const _QueueMixin = {
|
||||
};
|
||||
|
||||
const _StatisticsMixin = {
|
||||
renderStatistics: function(newsletter, is_sent, current_time) {
|
||||
renderStatistics: function (newsletter, is_sent, current_time) {
|
||||
if (is_sent === undefined) {
|
||||
// condition for standard and post notification listings
|
||||
is_sent = newsletter.statistics
|
||||
&& newsletter.queue
|
||||
&& newsletter.queue.status !== 'scheduled'
|
||||
&& newsletter.queue.status !== 'scheduled';
|
||||
}
|
||||
if (!is_sent) {
|
||||
return (
|
||||
@ -286,6 +286,7 @@ const _StatisticsMixin = {
|
||||
<Link
|
||||
key={ `stats-${newsletter.id}` }
|
||||
to={ params.link }
|
||||
onClick={ params.onClick || null }
|
||||
>
|
||||
{content}
|
||||
</Link>
|
||||
@ -301,10 +302,10 @@ const _StatisticsMixin = {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const _MailerMixin = {
|
||||
checkMailerStatus: function(state) {
|
||||
checkMailerStatus: function (state) {
|
||||
if (state.meta.mta_log.error && state.meta.mta_log.status === 'paused') {
|
||||
MailPoet.Notice.error(
|
||||
'',
|
||||
@ -321,10 +322,10 @@ const _MailerMixin = {
|
||||
},
|
||||
getMailerError(state) {
|
||||
let mailer_error_notice;
|
||||
let mailer_check_settings_notice = ReactStringReplace(
|
||||
const mailer_check_settings_notice = ReactStringReplace(
|
||||
MailPoet.I18n.t('mailerCheckSettingsNotice'),
|
||||
/\[link\](.*?)\[\/link\]/g,
|
||||
(match, i) => (
|
||||
match => (
|
||||
<a href={`?page=mailpoet-settings#mta`}>{ match }</a>
|
||||
)
|
||||
);
|
||||
@ -356,20 +357,20 @@ const _MailerMixin = {
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'mailer',
|
||||
action: 'resumeSending'
|
||||
}).done(function() {
|
||||
}).done(() => {
|
||||
MailPoet.Notice.hide('mailpoet_mailer_error');
|
||||
MailPoet.Notice.success(MailPoet.I18n.t('mailerSendingResumedNotice'));
|
||||
window.mailpoet_listing.forceUpdate();
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
@ -1,24 +1,20 @@
|
||||
import React from 'react'
|
||||
import { Router, Route, IndexRoute, Link, useRouterHistory } from 'react-router'
|
||||
import { createHashHistory } from 'history'
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
|
||||
import Listing from 'listing/listing.jsx'
|
||||
import ListingTabs from 'newsletters/listings/tabs.jsx'
|
||||
import Listing from 'listing/listing.jsx';
|
||||
import ListingTabs from 'newsletters/listings/tabs.jsx';
|
||||
|
||||
import { MailerMixin } from 'newsletters/listings/mixins.jsx'
|
||||
import { MailerMixin } from 'newsletters/listings/mixins.jsx';
|
||||
|
||||
import classNames from 'classnames'
|
||||
import jQuery from 'jquery'
|
||||
import MailPoet from 'mailpoet'
|
||||
import classNames from 'classnames';
|
||||
import MailPoet from 'mailpoet';
|
||||
|
||||
import {
|
||||
timeOfDayValues,
|
||||
weekDayValues,
|
||||
monthDayValues,
|
||||
nthWeekDayValues
|
||||
} from 'newsletters/scheduling/common.jsx'
|
||||
|
||||
const mailpoet_settings = window.mailpoet_settings || {};
|
||||
} from 'newsletters/scheduling/common.jsx';
|
||||
|
||||
const messages = {
|
||||
onTrash: (response) => {
|
||||
@ -106,7 +102,7 @@ const bulk_actions = [
|
||||
const newsletter_actions = [
|
||||
{
|
||||
name: 'view',
|
||||
link: function(newsletter) {
|
||||
link: function (newsletter) {
|
||||
return (
|
||||
<a href={ newsletter.preview_url } target="_blank">
|
||||
{MailPoet.I18n.t('preview')}
|
||||
@ -116,7 +112,7 @@ const newsletter_actions = [
|
||||
},
|
||||
{
|
||||
name: 'edit',
|
||||
link: function(newsletter) {
|
||||
link: function (newsletter) {
|
||||
return (
|
||||
<a href={ `?page=mailpoet-newsletter-editor&id=${ newsletter.id }` }>
|
||||
{MailPoet.I18n.t('edit')}
|
||||
@ -127,7 +123,7 @@ const newsletter_actions = [
|
||||
{
|
||||
name: 'duplicate',
|
||||
label: MailPoet.I18n.t('duplicate'),
|
||||
onClick: function(newsletter, refresh) {
|
||||
onClick: function (newsletter, refresh) {
|
||||
return MailPoet.Ajax.post({
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'newsletters',
|
||||
@ -145,7 +141,7 @@ const newsletter_actions = [
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
@ -159,7 +155,7 @@ const newsletter_actions = [
|
||||
|
||||
const NewsletterListNotification = React.createClass({
|
||||
mixins: [ MailerMixin ],
|
||||
updateStatus: function(e) {
|
||||
updateStatus: function (e) {
|
||||
// make the event persist so that we can still override the selected value
|
||||
// in the ajax callback
|
||||
e.persist();
|
||||
@ -185,7 +181,7 @@ const NewsletterListNotification = React.createClass({
|
||||
e.target.value = response.status;
|
||||
});
|
||||
},
|
||||
renderStatus: function(newsletter) {
|
||||
renderStatus: function (newsletter) {
|
||||
return (
|
||||
<select
|
||||
data-id={ newsletter.id }
|
||||
@ -197,13 +193,13 @@ const NewsletterListNotification = React.createClass({
|
||||
</select>
|
||||
);
|
||||
},
|
||||
renderSettings: function(newsletter) {
|
||||
renderSettings: function (newsletter) {
|
||||
let sendingFrequency;
|
||||
let sendingToSegments;
|
||||
|
||||
// get list of segments' name
|
||||
const segments = newsletter.segments.map(function(segment) {
|
||||
return segment.name
|
||||
const segments = newsletter.segments.map((segment) => {
|
||||
return segment.name;
|
||||
});
|
||||
|
||||
// check if the user has specified segments to send to
|
||||
@ -224,7 +220,7 @@ const NewsletterListNotification = React.createClass({
|
||||
sendingFrequency = MailPoet.I18n.t('sendDaily').replace(
|
||||
'%$1s', timeOfDayValues[newsletter.options.timeOfDay]
|
||||
);
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'weekly':
|
||||
sendingFrequency = MailPoet.I18n.t('sendWeekly').replace(
|
||||
@ -232,7 +228,7 @@ const NewsletterListNotification = React.createClass({
|
||||
).replace(
|
||||
'%$2s', timeOfDayValues[newsletter.options.timeOfDay]
|
||||
);
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'monthly':
|
||||
sendingFrequency = MailPoet.I18n.t('sendMonthly').replace(
|
||||
@ -240,7 +236,7 @@ const NewsletterListNotification = React.createClass({
|
||||
).replace(
|
||||
'%$2s', timeOfDayValues[newsletter.options.timeOfDay]
|
||||
);
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'nthWeekDay':
|
||||
sendingFrequency = MailPoet.I18n.t('sendNthWeekDay').replace(
|
||||
@ -250,11 +246,11 @@ const NewsletterListNotification = React.createClass({
|
||||
).replace(
|
||||
'%$3s', timeOfDayValues[newsletter.options.timeOfDay]
|
||||
);
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'immediately':
|
||||
sendingFrequency = MailPoet.I18n.t('sendImmediately');
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -264,7 +260,7 @@ const NewsletterListNotification = React.createClass({
|
||||
</span>
|
||||
);
|
||||
},
|
||||
renderHistoryLink: function(newsletter) {
|
||||
renderHistoryLink: function (newsletter) {
|
||||
const childrenCount = ~~(newsletter.children_count);
|
||||
if (childrenCount === 0) {
|
||||
return (
|
||||
@ -278,7 +274,7 @@ const NewsletterListNotification = React.createClass({
|
||||
);
|
||||
}
|
||||
},
|
||||
renderItem: function(newsletter, actions) {
|
||||
renderItem: function (newsletter, actions) {
|
||||
const rowClasses = classNames(
|
||||
'manage-column',
|
||||
'column-primary',
|
||||
@ -311,7 +307,7 @@ const NewsletterListNotification = React.createClass({
|
||||
</div>
|
||||
);
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="title">
|
||||
|
@ -1,21 +1,19 @@
|
||||
import React from 'react'
|
||||
import { Router, Link } from 'react-router'
|
||||
import classNames from 'classnames'
|
||||
import jQuery from 'jquery'
|
||||
import MailPoet from 'mailpoet'
|
||||
import Hooks from 'wp-js-hooks'
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import classNames from 'classnames';
|
||||
import MailPoet from 'mailpoet';
|
||||
import Hooks from 'wp-js-hooks';
|
||||
|
||||
import Listing from 'listing/listing.jsx'
|
||||
import ListingTabs from 'newsletters/listings/tabs.jsx'
|
||||
import Listing from 'listing/listing.jsx';
|
||||
import ListingTabs from 'newsletters/listings/tabs.jsx';
|
||||
|
||||
import {
|
||||
QueueMixin,
|
||||
StatisticsMixin,
|
||||
MailerMixin
|
||||
} from 'newsletters/listings/mixins.jsx'
|
||||
} from 'newsletters/listings/mixins.jsx';
|
||||
|
||||
const mailpoet_tracking_enabled = (!!(window['mailpoet_tracking_enabled']));
|
||||
const mailpoet_settings = window.mailpoet_settings || {};
|
||||
|
||||
const columns = [
|
||||
{
|
||||
@ -36,7 +34,7 @@ const columns = [
|
||||
display: mailpoet_tracking_enabled
|
||||
},
|
||||
{
|
||||
name: 'processed_at',
|
||||
name: 'sent_at',
|
||||
label: MailPoet.I18n.t('sentOn'),
|
||||
}
|
||||
];
|
||||
@ -44,7 +42,7 @@ const columns = [
|
||||
let newsletter_actions = [
|
||||
{
|
||||
name: 'view',
|
||||
link: function(newsletter) {
|
||||
link: function (newsletter) {
|
||||
return (
|
||||
<a href={ newsletter.preview_url } target="_blank">
|
||||
{MailPoet.I18n.t('preview')}
|
||||
@ -58,24 +56,17 @@ newsletter_actions = Hooks.applyFilters('mailpoet_newsletters_listings_notificat
|
||||
|
||||
const NewsletterListNotificationHistory = React.createClass({
|
||||
mixins: [ QueueMixin, StatisticsMixin, MailerMixin ],
|
||||
renderSentDate: function(newsletter) {
|
||||
return (newsletter.queue.status === 'completed')
|
||||
? ( <abbr>{ MailPoet.Date.format(newsletter.updated_at) }</abbr> )
|
||||
: MailPoet.I18n.t('notSentYet')
|
||||
},
|
||||
renderItem: function(newsletter, actions, meta) {
|
||||
renderItem: function (newsletter, actions, meta) {
|
||||
const rowClasses = classNames(
|
||||
'manage-column',
|
||||
'column-primary',
|
||||
'has-row-actions'
|
||||
);
|
||||
|
||||
const segments = newsletter.segments.map(function(segment) {
|
||||
return segment.name
|
||||
const segments = newsletter.segments.map((segment) => {
|
||||
return segment.name;
|
||||
}).join(', ');
|
||||
|
||||
const mailer_log = window.mailpoet_settings.mta_log || {};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<td className={ rowClasses }>
|
||||
@ -98,13 +89,13 @@ const NewsletterListNotificationHistory = React.createClass({
|
||||
{ this.renderStatistics(newsletter, undefined, meta.current_time) }
|
||||
</td>
|
||||
) : null }
|
||||
<td className="column-date" data-colname={ MailPoet.I18n.t('lastModifiedOn') }>
|
||||
{ this.renderSentDate(newsletter) }
|
||||
<td className="column-date" data-colname={ MailPoet.I18n.t('sentOn') }>
|
||||
{ (newsletter.sent_at) ? MailPoet.Date.format(newsletter.sent_at) : MailPoet.I18n.t('notSentYet') }
|
||||
</td>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="title">
|
||||
@ -129,7 +120,7 @@ const NewsletterListNotificationHistory = React.createClass({
|
||||
columns={columns}
|
||||
item_actions={ newsletter_actions }
|
||||
auto_refresh={ true }
|
||||
sort_by="updated_at"
|
||||
sort_by="sent_at"
|
||||
sort_order="desc"
|
||||
afterGetItems={ this.checkMailerStatus }
|
||||
/>
|
||||
|
@ -1,20 +1,19 @@
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router'
|
||||
import classNames from 'classnames'
|
||||
import MailPoet from 'mailpoet'
|
||||
import Hooks from 'wp-js-hooks'
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import classNames from 'classnames';
|
||||
import MailPoet from 'mailpoet';
|
||||
import Hooks from 'wp-js-hooks';
|
||||
|
||||
import Listing from 'listing/listing.jsx'
|
||||
import ListingTabs from 'newsletters/listings/tabs.jsx'
|
||||
import Listing from 'listing/listing.jsx';
|
||||
import ListingTabs from 'newsletters/listings/tabs.jsx';
|
||||
|
||||
import {
|
||||
QueueMixin,
|
||||
StatisticsMixin,
|
||||
MailerMixin
|
||||
} from 'newsletters/listings/mixins.jsx'
|
||||
} from 'newsletters/listings/mixins.jsx';
|
||||
|
||||
const mailpoet_tracking_enabled = (!!(window['mailpoet_tracking_enabled']));
|
||||
const mailpoet_settings = window.mailpoet_settings || {};
|
||||
|
||||
const messages = {
|
||||
onTrash: (response) => {
|
||||
@ -84,8 +83,8 @@ const columns = [
|
||||
display: mailpoet_tracking_enabled
|
||||
},
|
||||
{
|
||||
name: 'updated_at',
|
||||
label: MailPoet.I18n.t('lastModifiedOn'),
|
||||
name: 'sent_at',
|
||||
label: MailPoet.I18n.t('sentOn'),
|
||||
sortable: true
|
||||
}
|
||||
];
|
||||
@ -101,7 +100,7 @@ const bulk_actions = [
|
||||
let newsletter_actions = [
|
||||
{
|
||||
name: 'view',
|
||||
link: function(newsletter) {
|
||||
link: function (newsletter) {
|
||||
return (
|
||||
<a href={ newsletter.preview_url } target="_blank">
|
||||
{MailPoet.I18n.t('preview')}
|
||||
@ -111,7 +110,7 @@ let newsletter_actions = [
|
||||
},
|
||||
{
|
||||
name: 'edit',
|
||||
link: function(newsletter) {
|
||||
link: function (newsletter) {
|
||||
return (
|
||||
<a href={ `?page=mailpoet-newsletter-editor&id=${ newsletter.id }` }>
|
||||
{MailPoet.I18n.t('edit')}
|
||||
@ -122,7 +121,7 @@ let newsletter_actions = [
|
||||
{
|
||||
name: 'duplicate',
|
||||
label: MailPoet.I18n.t('duplicate'),
|
||||
onClick: function(newsletter, refresh) {
|
||||
onClick: function (newsletter, refresh) {
|
||||
return MailPoet.Ajax.post({
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'newsletters',
|
||||
@ -140,7 +139,7 @@ let newsletter_actions = [
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
@ -156,15 +155,15 @@ newsletter_actions = Hooks.applyFilters('mailpoet_newsletters_listings_standard_
|
||||
|
||||
const NewsletterListStandard = React.createClass({
|
||||
mixins: [ QueueMixin, StatisticsMixin, MailerMixin ],
|
||||
renderItem: function(newsletter, actions, meta) {
|
||||
renderItem: function (newsletter, actions, meta) {
|
||||
const rowClasses = classNames(
|
||||
'manage-column',
|
||||
'column-primary',
|
||||
'has-row-actions'
|
||||
);
|
||||
|
||||
const segments = newsletter.segments.map(function(segment) {
|
||||
return segment.name
|
||||
const segments = newsletter.segments.map((segment) => {
|
||||
return segment.name;
|
||||
}).join(', ');
|
||||
|
||||
return (
|
||||
@ -189,13 +188,13 @@ const NewsletterListStandard = React.createClass({
|
||||
{ this.renderStatistics(newsletter, undefined, meta.current_time) }
|
||||
</td>
|
||||
) : null }
|
||||
<td className="column-date" data-colname={ MailPoet.I18n.t('lastModifiedOn') }>
|
||||
<abbr>{ MailPoet.Date.format(newsletter.updated_at) }</abbr>
|
||||
<td className="column-date" data-colname={ MailPoet.I18n.t('sentOn') }>
|
||||
<abbr>{ (newsletter.sent_at) ? MailPoet.Date.format(newsletter.sent_at) : MailPoet.I18n.t('notSentYet') }</abbr>
|
||||
</td>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="title">
|
||||
@ -217,7 +216,7 @@ const NewsletterListStandard = React.createClass({
|
||||
item_actions={ newsletter_actions }
|
||||
messages={ messages }
|
||||
auto_refresh={ true }
|
||||
sort_by="updated_at"
|
||||
sort_by="sent_at"
|
||||
sort_order="desc"
|
||||
afterGetItems={ this.checkMailerStatus }
|
||||
/>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import { Link } from 'react-router'
|
||||
import classNames from 'classnames'
|
||||
import MailPoet from 'mailpoet'
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import classNames from 'classnames';
|
||||
import MailPoet from 'mailpoet';
|
||||
|
||||
const ListingTabs = React.createClass({
|
||||
getInitialState() {
|
||||
|
@ -1,22 +1,19 @@
|
||||
import React from 'react'
|
||||
import { Router, Route, IndexRoute, Link, useRouterHistory } from 'react-router'
|
||||
import { createHashHistory } from 'history'
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
|
||||
import Listing from 'listing/listing.jsx'
|
||||
import ListingTabs from 'newsletters/listings/tabs.jsx'
|
||||
import Listing from 'listing/listing.jsx';
|
||||
import ListingTabs from 'newsletters/listings/tabs.jsx';
|
||||
|
||||
import { StatisticsMixin, MailerMixin } from 'newsletters/listings/mixins.jsx'
|
||||
import { StatisticsMixin, MailerMixin } from 'newsletters/listings/mixins.jsx';
|
||||
|
||||
import classNames from 'classnames'
|
||||
import jQuery from 'jquery'
|
||||
import MailPoet from 'mailpoet'
|
||||
import _ from 'underscore'
|
||||
import Hooks from 'wp-js-hooks'
|
||||
import classNames from 'classnames';
|
||||
import MailPoet from 'mailpoet';
|
||||
import _ from 'underscore';
|
||||
import Hooks from 'wp-js-hooks';
|
||||
|
||||
const mailpoet_roles = window.mailpoet_roles || {};
|
||||
const mailpoet_segments = window.mailpoet_segments || {};
|
||||
const mailpoet_tracking_enabled = (!!(window['mailpoet_tracking_enabled']));
|
||||
const mailpoet_settings = window.mailpoet_settings || {};
|
||||
|
||||
const messages = {
|
||||
onTrash: (response) => {
|
||||
@ -104,7 +101,7 @@ const bulk_actions = [
|
||||
let newsletter_actions = [
|
||||
{
|
||||
name: 'view',
|
||||
link: function(newsletter) {
|
||||
link: function (newsletter) {
|
||||
return (
|
||||
<a href={ newsletter.preview_url } target="_blank">
|
||||
{MailPoet.I18n.t('preview')}
|
||||
@ -114,7 +111,7 @@ let newsletter_actions = [
|
||||
},
|
||||
{
|
||||
name: 'edit',
|
||||
link: function(newsletter) {
|
||||
link: function (newsletter) {
|
||||
return (
|
||||
<a href={ `?page=mailpoet-newsletter-editor&id=${ newsletter.id }` }>
|
||||
{MailPoet.I18n.t('edit')}
|
||||
@ -131,7 +128,7 @@ newsletter_actions = Hooks.applyFilters('mailpoet_newsletters_listings_welcome_n
|
||||
|
||||
const NewsletterListWelcome = React.createClass({
|
||||
mixins: [ StatisticsMixin, MailerMixin ],
|
||||
updateStatus: function(e) {
|
||||
updateStatus: function (e) {
|
||||
// make the event persist so that we can still override the selected value
|
||||
// in the ajax callback
|
||||
e.persist();
|
||||
@ -157,9 +154,8 @@ const NewsletterListWelcome = React.createClass({
|
||||
e.target.value = response.status;
|
||||
});
|
||||
},
|
||||
renderStatus: function(newsletter) {
|
||||
let total_sent;
|
||||
total_sent = (
|
||||
renderStatus: function (newsletter) {
|
||||
const total_sent = (
|
||||
MailPoet.I18n.t('sentToXSubscribers')
|
||||
.replace('%$1d', newsletter.total_sent.toLocaleString())
|
||||
);
|
||||
@ -180,7 +176,7 @@ const NewsletterListWelcome = React.createClass({
|
||||
</div>
|
||||
);
|
||||
},
|
||||
renderSettings: function(newsletter) {
|
||||
renderSettings: function (newsletter) {
|
||||
let sendingEvent;
|
||||
let sendingDelay;
|
||||
|
||||
@ -195,11 +191,11 @@ const NewsletterListWelcome = React.createClass({
|
||||
'%$1s', mailpoet_roles[newsletter.options.role]
|
||||
);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'segment':
|
||||
// get segment
|
||||
const segment = _.find(mailpoet_segments, function(segment) {
|
||||
const segment = _.find(mailpoet_segments, (segment) => {
|
||||
return (~~(segment.id) === ~~(newsletter.options.segment));
|
||||
});
|
||||
|
||||
@ -214,7 +210,7 @@ const NewsletterListWelcome = React.createClass({
|
||||
'%$1s', segment.name
|
||||
);
|
||||
}
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
// set sending delay
|
||||
@ -225,19 +221,19 @@ const NewsletterListWelcome = React.createClass({
|
||||
sendingDelay = MailPoet.I18n.t('sendingDelayHours').replace(
|
||||
'%$1d', newsletter.options.afterTimeNumber
|
||||
);
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'days':
|
||||
sendingDelay = MailPoet.I18n.t('sendingDelayDays').replace(
|
||||
'%$1d', newsletter.options.afterTimeNumber
|
||||
);
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'weeks':
|
||||
sendingDelay = MailPoet.I18n.t('sendingDelayWeeks').replace(
|
||||
'%$1d', newsletter.options.afterTimeNumber
|
||||
);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
sendingEvent += ' [' + sendingDelay + ']';
|
||||
}
|
||||
@ -251,7 +247,7 @@ const NewsletterListWelcome = React.createClass({
|
||||
</span>
|
||||
);
|
||||
},
|
||||
renderItem: function(newsletter, actions) {
|
||||
renderItem: function (newsletter, actions) {
|
||||
const rowClasses = classNames(
|
||||
'manage-column',
|
||||
'column-primary',
|
||||
@ -289,7 +285,7 @@ const NewsletterListWelcome = React.createClass({
|
||||
</div>
|
||||
);
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="title">
|
||||
|
@ -1,20 +1,20 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { Router, Route, IndexRedirect, Link, useRouterHistory } from 'react-router'
|
||||
import { createHashHistory } from 'history'
|
||||
import Hooks from 'wp-js-hooks'
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Router, Route, IndexRedirect, useRouterHistory } from 'react-router';
|
||||
import { createHashHistory } from 'history';
|
||||
import Hooks from 'wp-js-hooks';
|
||||
|
||||
import NewsletterTypes from 'newsletters/types.jsx'
|
||||
import NewsletterTemplates from 'newsletters/templates.jsx'
|
||||
import NewsletterSend from 'newsletters/send.jsx'
|
||||
import NewsletterTypes from 'newsletters/types.jsx';
|
||||
import NewsletterTemplates from 'newsletters/templates.jsx';
|
||||
import NewsletterSend from 'newsletters/send.jsx';
|
||||
|
||||
import NewsletterTypeStandard from 'newsletters/types/standard.jsx'
|
||||
import NewsletterTypeNotification from 'newsletters/types/notification/notification.jsx'
|
||||
import NewsletterTypeStandard from 'newsletters/types/standard.jsx';
|
||||
import NewsletterTypeNotification from 'newsletters/types/notification/notification.jsx';
|
||||
|
||||
import NewsletterListStandard from 'newsletters/listings/standard.jsx'
|
||||
import NewsletterListWelcome from 'newsletters/listings/welcome.jsx'
|
||||
import NewsletterListNotification from 'newsletters/listings/notification.jsx'
|
||||
import NewsletterListNotificationHistory from 'newsletters/listings/notification_history.jsx'
|
||||
import NewsletterListStandard from 'newsletters/listings/standard.jsx';
|
||||
import NewsletterListWelcome from 'newsletters/listings/welcome.jsx';
|
||||
import NewsletterListNotification from 'newsletters/listings/notification.jsx';
|
||||
import NewsletterListNotificationHistory from 'newsletters/listings/notification_history.jsx';
|
||||
|
||||
const history = useRouterHistory(createHashHistory)({ queryKey: false });
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import _ from 'underscore'
|
||||
import MailPoet from 'mailpoet'
|
||||
import _ from 'underscore';
|
||||
import MailPoet from 'mailpoet';
|
||||
|
||||
const timeFormat = window.mailpoet_time_format || 'H:i';
|
||||
|
||||
@ -25,14 +25,14 @@ const TIME_STEP_SECONDS = 3600;
|
||||
const numberOfTimeSteps = SECONDS_IN_DAY / TIME_STEP_SECONDS;
|
||||
|
||||
const _timeOfDayValues = _.object(_.map(
|
||||
_.times(numberOfTimeSteps,function(step) {
|
||||
_.times(numberOfTimeSteps,(step) => {
|
||||
return step * TIME_STEP_SECONDS;
|
||||
}), function(seconds) {
|
||||
let date = new Date(null);
|
||||
date.setSeconds(seconds);
|
||||
const timeLabel = MailPoet.Date.format(date, { format: timeFormat, offset: 0 });
|
||||
return [seconds, timeLabel];
|
||||
})
|
||||
}), (seconds) => {
|
||||
const date = new Date(null);
|
||||
date.setSeconds(seconds);
|
||||
const timeLabel = MailPoet.Date.format(date, { format: timeFormat, offset: 0 });
|
||||
return [seconds, timeLabel];
|
||||
})
|
||||
);
|
||||
|
||||
const _weekDayValues = {
|
||||
@ -48,22 +48,22 @@ const _weekDayValues = {
|
||||
const NUMBER_OF_DAYS_IN_MONTH = 28;
|
||||
const _monthDayValues = _.object(
|
||||
_.map(
|
||||
_.times(NUMBER_OF_DAYS_IN_MONTH, function(day) {
|
||||
_.times(NUMBER_OF_DAYS_IN_MONTH, (day) => {
|
||||
return day;
|
||||
}), function(day) {
|
||||
const labels = {
|
||||
0: MailPoet.I18n.t('first'),
|
||||
1: MailPoet.I18n.t('second'),
|
||||
2: MailPoet.I18n.t('third')
|
||||
};
|
||||
let label;
|
||||
if (labels[day] !== undefined) {
|
||||
label = labels[day];
|
||||
} else {
|
||||
label = MailPoet.I18n.t('nth').replace("%$1d", day + 1);
|
||||
}
|
||||
return [day + 1, label];
|
||||
}), (day) => {
|
||||
const labels = {
|
||||
0: MailPoet.I18n.t('first'),
|
||||
1: MailPoet.I18n.t('second'),
|
||||
2: MailPoet.I18n.t('third')
|
||||
};
|
||||
let label;
|
||||
if (labels[day] !== undefined) {
|
||||
label = labels[day];
|
||||
} else {
|
||||
label = MailPoet.I18n.t('nth').replace("%$1d", day + 1);
|
||||
}
|
||||
return [day + 1, label];
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -10,7 +10,7 @@ define(
|
||||
'newsletters/send/welcome.jsx',
|
||||
'newsletters/breadcrumb.jsx'
|
||||
],
|
||||
function(
|
||||
(
|
||||
React,
|
||||
Router,
|
||||
_,
|
||||
@ -20,47 +20,47 @@ define(
|
||||
NotificationNewsletterFields,
|
||||
WelcomeNewsletterFields,
|
||||
Breadcrumb
|
||||
) {
|
||||
) => {
|
||||
|
||||
var NewsletterSend = React.createClass({
|
||||
const NewsletterSend = React.createClass({
|
||||
contextTypes: {
|
||||
router: React.PropTypes.object.isRequired
|
||||
},
|
||||
getInitialState: function() {
|
||||
getInitialState: function () {
|
||||
return {
|
||||
fields: [],
|
||||
item: {},
|
||||
loading: false,
|
||||
};
|
||||
},
|
||||
getFieldsByNewsletter: function(newsletter) {
|
||||
var type = this.getSubtype(newsletter);
|
||||
getFieldsByNewsletter: function (newsletter) {
|
||||
const type = this.getSubtype(newsletter);
|
||||
return type.getFields(newsletter);
|
||||
},
|
||||
getSendButtonOptions: function() {
|
||||
var type = this.getSubtype(this.state.item);
|
||||
getSendButtonOptions: function () {
|
||||
const type = this.getSubtype(this.state.item);
|
||||
return type.getSendButtonOptions(this.state.item);
|
||||
},
|
||||
getSubtype: function(newsletter) {
|
||||
getSubtype: function (newsletter) {
|
||||
switch(newsletter.type) {
|
||||
case 'notification': return NotificationNewsletterFields;
|
||||
case 'welcome': return WelcomeNewsletterFields;
|
||||
default: return StandardNewsletterFields;
|
||||
}
|
||||
},
|
||||
isValid: function() {
|
||||
isValid: function () {
|
||||
return jQuery('#mailpoet_newsletter').parsley().isValid();
|
||||
},
|
||||
componentDidMount: function() {
|
||||
componentDidMount: function () {
|
||||
if(this.isMounted()) {
|
||||
this.loadItem(this.props.params.id);
|
||||
}
|
||||
jQuery('#mailpoet_newsletter').parsley();
|
||||
},
|
||||
componentWillReceiveProps: function(props) {
|
||||
componentWillReceiveProps: function (props) {
|
||||
this.loadItem(props.params.id);
|
||||
},
|
||||
loadItem: function(id) {
|
||||
loadItem: function (id) {
|
||||
this.setState({ loading: true });
|
||||
|
||||
MailPoet.Ajax.post({
|
||||
@ -76,7 +76,7 @@ define(
|
||||
item: response.data,
|
||||
fields: this.getFieldsByNewsletter(response.data)
|
||||
});
|
||||
}).fail((response) => {
|
||||
}).fail(() => {
|
||||
this.setState({
|
||||
loading: false,
|
||||
item: {}
|
||||
@ -85,7 +85,7 @@ define(
|
||||
});
|
||||
});
|
||||
},
|
||||
handleSend: function(e) {
|
||||
handleSend: function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
if(!this.isValid()) {
|
||||
@ -149,10 +149,10 @@ define(
|
||||
}
|
||||
return false;
|
||||
},
|
||||
handleSave: function(e) {
|
||||
handleSave: function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
this._save(e).done((response) => {
|
||||
this._save(e).done(() => {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('newsletterUpdated')
|
||||
);
|
||||
@ -160,11 +160,11 @@ define(
|
||||
this.context.router.push(`/${ this.state.item.type || '' }`);
|
||||
}).fail(this._showError);
|
||||
},
|
||||
handleRedirectToDesign: function(e) {
|
||||
handleRedirectToDesign: function (e) {
|
||||
e.preventDefault();
|
||||
var redirectTo = e.target.href;
|
||||
const redirectTo = e.target.href;
|
||||
|
||||
this._save(e).done((response) => {
|
||||
this._save(e).done(() => {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('newsletterUpdated')
|
||||
);
|
||||
@ -172,14 +172,14 @@ define(
|
||||
window.location = redirectTo;
|
||||
}).fail(this._showError);
|
||||
},
|
||||
_save: function(e) {
|
||||
var data = this.state.item;
|
||||
_save: function () {
|
||||
const data = this.state.item;
|
||||
this.setState({ loading: true });
|
||||
|
||||
// Store only properties that can be changed on this page
|
||||
const IGNORED_NEWSLETTER_PROPERTIES = [
|
||||
'preheader', 'body', 'created_at', 'deleted_at', 'hash',
|
||||
'status', 'updated_at', 'type'
|
||||
'preheader', 'body', 'created_at', 'deleted_at', 'hash',
|
||||
'status', 'updated_at', 'type'
|
||||
];
|
||||
const newsletterData = _.omit(
|
||||
data,
|
||||
@ -198,14 +198,14 @@ define(
|
||||
_showError: (response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
},
|
||||
handleFormChange: function(e) {
|
||||
var item = this.state.item,
|
||||
field = e.target.name;
|
||||
handleFormChange: function (e) {
|
||||
const item = this.state.item;
|
||||
const field = e.target.name;
|
||||
|
||||
item[field] = e.target.value;
|
||||
|
||||
@ -214,7 +214,7 @@ define(
|
||||
});
|
||||
return true;
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
return (
|
||||
<div>
|
||||
<h1>{MailPoet.I18n.t('finalNewsletterStep')}</h1>
|
||||
|
@ -5,16 +5,14 @@ define(
|
||||
'newsletters/types/notification/scheduling.jsx',
|
||||
'underscore'
|
||||
],
|
||||
function(
|
||||
(
|
||||
MailPoet,
|
||||
Hooks,
|
||||
Scheduling,
|
||||
_
|
||||
) {
|
||||
) => {
|
||||
|
||||
var settings = window.mailpoet_settings || {};
|
||||
|
||||
var fields = [
|
||||
let fields = [
|
||||
{
|
||||
name: 'subject',
|
||||
label: MailPoet.I18n.t('subjectLine'),
|
||||
@ -41,16 +39,16 @@ define(
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'segments',
|
||||
multiple: true,
|
||||
filter: function(segment) {
|
||||
filter: function (segment) {
|
||||
return !!(!segment.deleted_at);
|
||||
},
|
||||
getLabel: function(segment) {
|
||||
return segment.name + ' (' + parseInt(segment.subscribers).toLocaleString() + ')';
|
||||
getLabel: function (segment) {
|
||||
return segment.name + ' (' + parseInt(segment.subscribers, 10).toLocaleString() + ')';
|
||||
},
|
||||
transformChangedValue: function(segment_ids) {
|
||||
var all_segments = this.state.items;
|
||||
return _.map(segment_ids, function(id) {
|
||||
return _.find(all_segments, function(segment) {
|
||||
transformChangedValue: function (segment_ids) {
|
||||
const all_segments = this.state.items;
|
||||
return _.map(segment_ids, (id) => {
|
||||
return _.find(all_segments, (segment) => {
|
||||
return segment.id === id;
|
||||
});
|
||||
});
|
||||
@ -107,10 +105,10 @@ define(
|
||||
fields = Hooks.applyFilters('mailpoet_newsletters_3rd_step_fields', fields);
|
||||
|
||||
return {
|
||||
getFields: function(newsletter) {
|
||||
getFields: function () {
|
||||
return fields;
|
||||
},
|
||||
getSendButtonOptions: function(newsletter) {
|
||||
getSendButtonOptions: function () {
|
||||
return {
|
||||
value: MailPoet.I18n.t('activate')
|
||||
};
|
||||
|
@ -5,29 +5,22 @@ define(
|
||||
'underscore',
|
||||
'mailpoet',
|
||||
'wp-js-hooks',
|
||||
'form/fields/checkbox.jsx',
|
||||
'form/fields/select.jsx',
|
||||
'form/fields/text.jsx',
|
||||
],
|
||||
function(
|
||||
(
|
||||
React,
|
||||
jQuery,
|
||||
_,
|
||||
MailPoet,
|
||||
Hooks,
|
||||
Checkbox,
|
||||
Select,
|
||||
Text
|
||||
) {
|
||||
Hooks
|
||||
) => {
|
||||
|
||||
var settings = window.mailpoet_settings || {},
|
||||
currentTime = window.mailpoet_current_time || '00:00',
|
||||
defaultDateTime = window.mailpoet_current_date + ' ' + '00:00:00';
|
||||
timeOfDayItems = window.mailpoet_schedule_time_of_day,
|
||||
dateDisplayFormat = window.mailpoet_date_display_format,
|
||||
dateStorageFormat = window.mailpoet_date_storage_format;
|
||||
const currentTime = window.mailpoet_current_time || '00:00';
|
||||
const defaultDateTime = window.mailpoet_current_date + ' ' + '00:00:00';
|
||||
const timeOfDayItems = window.mailpoet_schedule_time_of_day;
|
||||
const dateDisplayFormat = window.mailpoet_date_display_format;
|
||||
const dateStorageFormat = window.mailpoet_date_storage_format;
|
||||
|
||||
var datepickerTranslations = {
|
||||
const datepickerTranslations = {
|
||||
closeText: MailPoet.I18n.t('close'),
|
||||
currentText: MailPoet.I18n.t('today'),
|
||||
nextText: MailPoet.I18n.t('next'),
|
||||
@ -89,30 +82,30 @@ define(
|
||||
],
|
||||
};
|
||||
|
||||
var DateText = React.createClass({
|
||||
onChange: function(event) {
|
||||
const DateText = React.createClass({
|
||||
onChange: function (event) {
|
||||
// Swap display format to storage format
|
||||
var displayDate = event.target.value,
|
||||
storageDate = this.getStorageDate(displayDate);
|
||||
const displayDate = event.target.value;
|
||||
const storageDate = this.getStorageDate(displayDate);
|
||||
|
||||
event.target.value = storageDate;
|
||||
this.props.onChange(event);
|
||||
},
|
||||
componentDidMount: function() {
|
||||
var $element = jQuery(this.refs.dateInput),
|
||||
that = this;
|
||||
componentDidMount: function () {
|
||||
const $element = jQuery(this.refs.dateInput);
|
||||
const that = this;
|
||||
if ($element.datepicker) {
|
||||
// Override jQuery UI datepicker Date parsing and formatting
|
||||
jQuery.datepicker.parseDate = function(format, value) {
|
||||
jQuery.datepicker.parseDate = function (format, value) {
|
||||
// Transform string format to Date object
|
||||
return MailPoet.Date.toDate(value, {
|
||||
parseFormat: dateDisplayFormat,
|
||||
format: format
|
||||
});
|
||||
};
|
||||
jQuery.datepicker.formatDate = function(format, value) {
|
||||
jQuery.datepicker.formatDate = function (format, value) {
|
||||
// Transform Date object to string format
|
||||
var newValue = MailPoet.Date.format(value, {
|
||||
const newValue = MailPoet.Date.format(value, {
|
||||
format: format
|
||||
});
|
||||
return newValue;
|
||||
@ -121,7 +114,7 @@ define(
|
||||
$element.datepicker(_.extend({
|
||||
dateFormat: this.props.displayFormat,
|
||||
isRTL: false,
|
||||
onSelect: function(value) {
|
||||
onSelect: function (value) {
|
||||
that.onChange({
|
||||
target: {
|
||||
name: that.getFieldName(),
|
||||
@ -134,27 +127,27 @@ define(
|
||||
this.datepickerInitialized = true;
|
||||
}
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
componentWillUnmount: function () {
|
||||
if (this.datepickerInitialized) {
|
||||
jQuery(this.refs.dateInput).datepicker('destroy');
|
||||
}
|
||||
},
|
||||
getFieldName: function() {
|
||||
getFieldName: function () {
|
||||
return this.props.name || 'date';
|
||||
},
|
||||
getDisplayDate: function(date) {
|
||||
getDisplayDate: function (date) {
|
||||
return MailPoet.Date.format(date, {
|
||||
parseFormat: this.props.storageFormat,
|
||||
format: this.props.displayFormat
|
||||
});
|
||||
},
|
||||
getStorageDate: function(date) {
|
||||
getStorageDate: function (date) {
|
||||
return MailPoet.Date.format(date, {
|
||||
parseFormat: this.props.displayFormat,
|
||||
format: this.props.storageFormat
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
return (
|
||||
<input
|
||||
type="text"
|
||||
@ -169,8 +162,8 @@ define(
|
||||
},
|
||||
});
|
||||
|
||||
var TimeSelect = React.createClass({
|
||||
render: function() {
|
||||
const TimeSelect = React.createClass({
|
||||
render: function () {
|
||||
const options = Object.keys(timeOfDayItems).map(
|
||||
(value, index) => {
|
||||
return (
|
||||
@ -196,44 +189,44 @@ define(
|
||||
}
|
||||
});
|
||||
|
||||
var DateTime = React.createClass({
|
||||
const DateTime = React.createClass({
|
||||
_DATE_TIME_SEPARATOR: " ",
|
||||
getInitialState: function() {
|
||||
getInitialState: function () {
|
||||
return this._buildStateFromProps(this.props);
|
||||
},
|
||||
componentWillReceiveProps: function(nextProps) {
|
||||
componentWillReceiveProps: function (nextProps) {
|
||||
this.setState(this._buildStateFromProps(nextProps));
|
||||
},
|
||||
_buildStateFromProps: function(props) {
|
||||
let value = props.value || defaultDateTime;
|
||||
const [date, time] = value.split(this._DATE_TIME_SEPARATOR)
|
||||
_buildStateFromProps: function (props) {
|
||||
const value = props.value || defaultDateTime;
|
||||
const [date, time] = value.split(this._DATE_TIME_SEPARATOR);
|
||||
return {
|
||||
date: date,
|
||||
time: time,
|
||||
};
|
||||
},
|
||||
handleChange: function(event) {
|
||||
var newState = {};
|
||||
handleChange: function (event) {
|
||||
const newState = {};
|
||||
newState[event.target.name] = event.target.value;
|
||||
|
||||
this.setState(newState, function() {
|
||||
this.setState(newState, function () {
|
||||
this.propagateChange();
|
||||
});
|
||||
},
|
||||
propagateChange: function() {
|
||||
propagateChange: function () {
|
||||
if (this.props.onChange) {
|
||||
return this.props.onChange({
|
||||
target: {
|
||||
name: this.props.name || '',
|
||||
value: this.getDateTime(),
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
},
|
||||
getDateTime: function() {
|
||||
getDateTime: function () {
|
||||
return [this.state.date, this.state.time].join(this._DATE_TIME_SEPARATOR);
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
return (
|
||||
<span>
|
||||
<DateText
|
||||
@ -253,8 +246,8 @@ define(
|
||||
}
|
||||
});
|
||||
|
||||
var StandardScheduling = React.createClass({
|
||||
_getCurrentValue: function() {
|
||||
const StandardScheduling = React.createClass({
|
||||
_getCurrentValue: function () {
|
||||
return _.defaults(
|
||||
this.props.item[this.props.field.name] || {},
|
||||
{
|
||||
@ -263,9 +256,9 @@ define(
|
||||
}
|
||||
);
|
||||
},
|
||||
handleValueChange: function(event) {
|
||||
var oldValue = this._getCurrentValue(),
|
||||
newValue = {};
|
||||
handleValueChange: function (event) {
|
||||
const oldValue = this._getCurrentValue();
|
||||
const newValue = {};
|
||||
newValue[event.target.name] = event.target.value;
|
||||
|
||||
return this.props.onValueChange({
|
||||
@ -275,22 +268,22 @@ define(
|
||||
}
|
||||
});
|
||||
},
|
||||
handleCheckboxChange: function(event) {
|
||||
handleCheckboxChange: function (event) {
|
||||
event.target.value = this.refs.isScheduled.checked ? '1' : '0';
|
||||
return this.handleValueChange(event);
|
||||
},
|
||||
isScheduled: function() {
|
||||
isScheduled: function () {
|
||||
return this._getCurrentValue().isScheduled === '1';
|
||||
},
|
||||
getDateValidation: function() {
|
||||
getDateValidation: function () {
|
||||
return {
|
||||
'data-parsley-required': true,
|
||||
'data-parsley-required-message': MailPoet.I18n.t('noScheduledDateError'),
|
||||
'data-parsley-errors-container': '#mailpoet_scheduling',
|
||||
};
|
||||
},
|
||||
render: function() {
|
||||
var schedulingOptions;
|
||||
render: function () {
|
||||
let schedulingOptions;
|
||||
|
||||
if (this.isScheduled()) {
|
||||
schedulingOptions = (
|
||||
@ -324,7 +317,7 @@ define(
|
||||
},
|
||||
});
|
||||
|
||||
var fields = [
|
||||
let fields = [
|
||||
{
|
||||
name: 'subject',
|
||||
label: MailPoet.I18n.t('subjectLine'),
|
||||
@ -345,16 +338,16 @@ define(
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'segments',
|
||||
multiple: true,
|
||||
filter: function(segment) {
|
||||
filter: function (segment) {
|
||||
return !!(!segment.deleted_at);
|
||||
},
|
||||
getLabel: function(segment) {
|
||||
return segment.name + ' (' + parseInt(segment.subscribers).toLocaleString() + ')';
|
||||
getLabel: function (segment) {
|
||||
return segment.name + ' (' + parseInt(segment.subscribers, 10).toLocaleString() + ')';
|
||||
},
|
||||
transformChangedValue: function(segment_ids) {
|
||||
var all_segments = this.state.items;
|
||||
return _.map(segment_ids, function(id) {
|
||||
return _.find(all_segments, function(segment) {
|
||||
transformChangedValue: function (segment_ids) {
|
||||
const all_segments = this.state.items;
|
||||
return _.map(segment_ids, (id) => {
|
||||
return _.find(all_segments, (segment) => {
|
||||
return segment.id === id;
|
||||
});
|
||||
});
|
||||
@ -417,17 +410,17 @@ define(
|
||||
fields = Hooks.applyFilters('mailpoet_newsletters_3rd_step_fields', fields);
|
||||
|
||||
return {
|
||||
getFields: function(newsletter) {
|
||||
getFields: function () {
|
||||
return fields;
|
||||
},
|
||||
getSendButtonOptions: function(newsletter) {
|
||||
getSendButtonOptions: function (newsletter) {
|
||||
newsletter = newsletter || {};
|
||||
|
||||
let isScheduled = (
|
||||
const isScheduled = (
|
||||
typeof newsletter.options === 'object'
|
||||
&& newsletter.options.isScheduled === '1'
|
||||
);
|
||||
let options = {
|
||||
const options = {
|
||||
value: (isScheduled
|
||||
? MailPoet.I18n.t('schedule')
|
||||
: MailPoet.I18n.t('send'))
|
||||
|
@ -4,15 +4,14 @@ define(
|
||||
'wp-js-hooks',
|
||||
'newsletters/types/welcome/scheduling.jsx'
|
||||
],
|
||||
function(
|
||||
(
|
||||
MailPoet,
|
||||
Hooks,
|
||||
Scheduling
|
||||
) {
|
||||
) => {
|
||||
|
||||
var settings = window.mailpoet_settings || {};
|
||||
|
||||
var fields = [
|
||||
let fields = [
|
||||
{
|
||||
name: 'subject',
|
||||
label: MailPoet.I18n.t('subjectLine'),
|
||||
@ -76,10 +75,10 @@ define(
|
||||
fields = Hooks.applyFilters('mailpoet_newsletters_3rd_step_fields', fields);
|
||||
|
||||
return {
|
||||
getFields: function(newsletter) {
|
||||
getFields: function () {
|
||||
return fields;
|
||||
},
|
||||
getSendButtonOptions: function(newsletter) {
|
||||
getSendButtonOptions: function () {
|
||||
return {
|
||||
value: MailPoet.I18n.t('activate')
|
||||
};
|
||||
|
@ -7,17 +7,17 @@ define(
|
||||
'classnames',
|
||||
'newsletters/breadcrumb.jsx'
|
||||
],
|
||||
function(
|
||||
(
|
||||
React,
|
||||
_,
|
||||
MailPoet,
|
||||
Router,
|
||||
classNames,
|
||||
Breadcrumb
|
||||
) {
|
||||
) => {
|
||||
|
||||
var ImportTemplate = React.createClass({
|
||||
saveTemplate: function(template) {
|
||||
const ImportTemplate = React.createClass({
|
||||
saveTemplate: function (template) {
|
||||
|
||||
// Stringify to enable transmission of primitive non-string value types
|
||||
if (!_.isUndefined(template.body)) {
|
||||
@ -31,27 +31,27 @@ define(
|
||||
endpoint: 'newsletterTemplates',
|
||||
action: 'save',
|
||||
data: template
|
||||
}).always(function() {
|
||||
}).always(() => {
|
||||
MailPoet.Modal.loading(false);
|
||||
}).done((response) => {
|
||||
this.props.onImport(response.data);
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
handleSubmit: function(e) {
|
||||
handleSubmit: function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
if (_.size(this.refs.templateFile.files) <= 0) return false;
|
||||
|
||||
var file = _.first(this.refs.templateFile.files);
|
||||
var reader = new FileReader();
|
||||
var saveTemplate = this.saveTemplate;
|
||||
const file = _.first(this.refs.templateFile.files);
|
||||
const reader = new FileReader();
|
||||
const saveTemplate = this.saveTemplate;
|
||||
|
||||
reader.onload = (e) => {
|
||||
try {
|
||||
@ -63,7 +63,7 @@ define(
|
||||
|
||||
reader.readAsText(file);
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
return (
|
||||
<div>
|
||||
<h2>{MailPoet.I18n.t('importTemplateTitle')}</h2>
|
||||
@ -82,17 +82,17 @@ define(
|
||||
},
|
||||
});
|
||||
|
||||
var NewsletterTemplates = React.createClass({
|
||||
getInitialState: function() {
|
||||
const NewsletterTemplates = React.createClass({
|
||||
getInitialState: function () {
|
||||
return {
|
||||
loading: false,
|
||||
templates: []
|
||||
};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
componentDidMount: function () {
|
||||
this.getTemplates();
|
||||
},
|
||||
getTemplates: function() {
|
||||
getTemplates: function () {
|
||||
this.setState({ loading: true });
|
||||
|
||||
MailPoet.Modal.loading(true);
|
||||
@ -121,10 +121,17 @@ define(
|
||||
loading: false
|
||||
});
|
||||
}
|
||||
}).fail((response) => {
|
||||
if(response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
handleSelectTemplate: function(template) {
|
||||
var body = template.body;
|
||||
handleSelectTemplate: function (template) {
|
||||
let body = template.body;
|
||||
|
||||
// Stringify to enable transmission of primitive non-string value types
|
||||
if (!_.isUndefined(body)) {
|
||||
@ -145,13 +152,13 @@ define(
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
handleDeleteTemplate: function(template) {
|
||||
handleDeleteTemplate: function (template) {
|
||||
this.setState({ loading: true });
|
||||
if(
|
||||
window.confirm(
|
||||
@ -167,26 +174,33 @@ define(
|
||||
data: {
|
||||
id: template.id
|
||||
}
|
||||
}).done((response) => {
|
||||
}).done(() => {
|
||||
this.getTemplates();
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.setState({ loading: false });
|
||||
this.setState({ loading: false });
|
||||
}
|
||||
},
|
||||
handleShowTemplate: function(template) {
|
||||
handleShowTemplate: function (template) {
|
||||
MailPoet.Modal.popup({
|
||||
title: template.name,
|
||||
template: '<div class="mailpoet_boxes_preview" style="background-color: {{ body.globalStyles.body.backgroundColor }}"><img src="{{ thumbnail }}" /></div>',
|
||||
data: template
|
||||
});
|
||||
},
|
||||
handleTemplateImport: function() {
|
||||
handleTemplateImport: function () {
|
||||
this.getTemplates();
|
||||
},
|
||||
render: function() {
|
||||
var templates = this.state.templates.map(function(template, index) {
|
||||
var deleteLink = (
|
||||
render: function () {
|
||||
const templates = this.state.templates.map((template, index) => {
|
||||
const deleteLink = (
|
||||
<div className="mailpoet_delete">
|
||||
<a
|
||||
href="javascript:;"
|
||||
@ -195,7 +209,8 @@ define(
|
||||
{MailPoet.I18n.t('delete')}
|
||||
</a>
|
||||
</div>
|
||||
), thumbnail = '';
|
||||
);
|
||||
let thumbnail = '';
|
||||
|
||||
if (typeof template.thumbnail === 'string'
|
||||
&& template.thumbnail.length > 0) {
|
||||
@ -236,9 +251,9 @@ define(
|
||||
{ (template.readonly === "1") ? false : deleteLink }
|
||||
</li>
|
||||
);
|
||||
}.bind(this));
|
||||
});
|
||||
|
||||
var boxClasses = classNames(
|
||||
const boxClasses = classNames(
|
||||
'mailpoet_boxes',
|
||||
'clearfix',
|
||||
{ 'mailpoet_boxes_loading': this.state.loading }
|
||||
|
@ -6,23 +6,23 @@ define(
|
||||
'react-router',
|
||||
'newsletters/breadcrumb.jsx'
|
||||
],
|
||||
function(
|
||||
(
|
||||
React,
|
||||
MailPoet,
|
||||
Hooks,
|
||||
Router,
|
||||
Breadcrumb
|
||||
) {
|
||||
var NewsletterTypes = React.createClass({
|
||||
) => {
|
||||
const NewsletterTypes = React.createClass({
|
||||
contextTypes: {
|
||||
router: React.PropTypes.object.isRequired
|
||||
},
|
||||
setupNewsletter: function(type) {
|
||||
setupNewsletter: function (type) {
|
||||
if(type !== undefined) {
|
||||
this.context.router.push(`/new/${type}`);
|
||||
}
|
||||
},
|
||||
createNewsletter: function(type) {
|
||||
createNewsletter: function (type) {
|
||||
MailPoet.Ajax.post({
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'newsletters',
|
||||
@ -36,50 +36,50 @@ define(
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
var types = [
|
||||
render: function () {
|
||||
let types = [
|
||||
{
|
||||
'id': 'standard',
|
||||
'title': MailPoet.I18n.t('regularNewsletterTypeTitle'),
|
||||
'description': MailPoet.I18n.t('regularNewsletterTypeDescription'),
|
||||
'action': function() {
|
||||
'action': function () {
|
||||
return (
|
||||
<a className="button button-primary" onClick={ this.createNewsletter.bind(null, 'standard') }>
|
||||
{MailPoet.I18n.t('create')}
|
||||
</a>
|
||||
)
|
||||
);
|
||||
}.bind(this)()
|
||||
},
|
||||
{
|
||||
'id': 'welcome',
|
||||
'title': MailPoet.I18n.t('welcomeNewsletterTypeTitle'),
|
||||
'description': MailPoet.I18n.t('welcomeNewsletterTypeDescription'),
|
||||
'action': function() {
|
||||
'action': function () {
|
||||
return (
|
||||
<div>
|
||||
<a href="?page=mailpoet-premium" target="_blank">
|
||||
{MailPoet.I18n.t('getPremiumVersion')}
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}()
|
||||
},
|
||||
{
|
||||
'id': 'notification',
|
||||
'title': MailPoet.I18n.t('postNotificationNewsletterTypeTitle'),
|
||||
'description': MailPoet.I18n.t('postNotificationNewsletterTypeDescription'),
|
||||
'action': function() {
|
||||
'action': function () {
|
||||
return (
|
||||
<a className="button button-primary" onClick={ this.setupNewsletter.bind(null, 'notification') }>
|
||||
{MailPoet.I18n.t('setUp')}
|
||||
</a>
|
||||
)
|
||||
);
|
||||
}.bind(this)()
|
||||
}
|
||||
];
|
||||
@ -93,7 +93,7 @@ define(
|
||||
<Breadcrumb step="type" />
|
||||
|
||||
<ul className="mailpoet_boxes clearfix">
|
||||
{types.map(function(type, index) {
|
||||
{types.map((type, index) => {
|
||||
return (
|
||||
<li key={index} data-type={type.id}>
|
||||
<div>
|
||||
@ -109,7 +109,7 @@ define(
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
)
|
||||
);
|
||||
}, this)}
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -7,26 +7,26 @@ define(
|
||||
'newsletters/types/notification/scheduling.jsx',
|
||||
'newsletters/breadcrumb.jsx'
|
||||
],
|
||||
function(
|
||||
(
|
||||
_,
|
||||
React,
|
||||
Router,
|
||||
MailPoet,
|
||||
Scheduling,
|
||||
Breadcrumb
|
||||
) {
|
||||
) => {
|
||||
|
||||
var field = {
|
||||
const field = {
|
||||
name: 'options',
|
||||
type: 'reactComponent',
|
||||
component: Scheduling,
|
||||
};
|
||||
|
||||
var NewsletterNotification = React.createClass({
|
||||
const NewsletterNotification = React.createClass({
|
||||
contextTypes: {
|
||||
router: React.PropTypes.object.isRequired
|
||||
},
|
||||
getInitialState: function() {
|
||||
getInitialState: function () {
|
||||
return {
|
||||
options: {
|
||||
intervalType: 'daily',
|
||||
@ -37,12 +37,12 @@ define(
|
||||
}
|
||||
};
|
||||
},
|
||||
handleValueChange: function(event) {
|
||||
var state = this.state;
|
||||
handleValueChange: function (event) {
|
||||
const state = this.state;
|
||||
state[event.target.name] = event.target.value;
|
||||
this.setState(state);
|
||||
},
|
||||
handleNext: function() {
|
||||
handleNext: function () {
|
||||
MailPoet.Ajax.post({
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'newsletters',
|
||||
@ -56,16 +56,16 @@ define(
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
showTemplateSelection: function(newsletterId) {
|
||||
showTemplateSelection: function (newsletterId) {
|
||||
this.context.router.push(`/template/${newsletterId}`);
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
return (
|
||||
<div>
|
||||
<h1>{MailPoet.I18n.t('postNotificationNewsletterTypeTitle')}</h1>
|
||||
|
@ -1,13 +1,13 @@
|
||||
import _ from 'underscore'
|
||||
import React from 'react'
|
||||
import Select from 'form/fields/select.jsx'
|
||||
import _ from 'underscore';
|
||||
import React from 'react';
|
||||
import Select from 'form/fields/select.jsx';
|
||||
import {
|
||||
intervalValues,
|
||||
timeOfDayValues,
|
||||
weekDayValues,
|
||||
monthDayValues,
|
||||
nthWeekDayValues
|
||||
} from 'newsletters/scheduling/common.jsx'
|
||||
} from 'newsletters/scheduling/common.jsx';
|
||||
|
||||
const intervalField = {
|
||||
name: 'intervalType',
|
||||
@ -35,12 +35,12 @@ const nthWeekDayField = {
|
||||
};
|
||||
|
||||
const NotificationScheduling = React.createClass({
|
||||
_getCurrentValue: function() {
|
||||
_getCurrentValue: function () {
|
||||
return (this.props.item[this.props.field.name] || {});
|
||||
},
|
||||
handleValueChange: function(name, value) {
|
||||
handleValueChange: function (name, value) {
|
||||
const oldValue = this._getCurrentValue();
|
||||
let newValue = {};
|
||||
const newValue = {};
|
||||
|
||||
newValue[name] = value;
|
||||
|
||||
@ -51,37 +51,37 @@ const NotificationScheduling = React.createClass({
|
||||
}
|
||||
});
|
||||
},
|
||||
handleIntervalChange: function(event) {
|
||||
handleIntervalChange: function (event) {
|
||||
return this.handleValueChange(
|
||||
'intervalType',
|
||||
event.target.value
|
||||
);
|
||||
},
|
||||
handleTimeOfDayChange: function(event) {
|
||||
handleTimeOfDayChange: function (event) {
|
||||
return this.handleValueChange(
|
||||
'timeOfDay',
|
||||
event.target.value
|
||||
);
|
||||
},
|
||||
handleWeekDayChange: function(event) {
|
||||
handleWeekDayChange: function (event) {
|
||||
return this.handleValueChange(
|
||||
'weekDay',
|
||||
event.target.value
|
||||
);
|
||||
},
|
||||
handleMonthDayChange: function(event) {
|
||||
handleMonthDayChange: function (event) {
|
||||
return this.handleValueChange(
|
||||
'monthDay',
|
||||
event.target.value
|
||||
);
|
||||
},
|
||||
handleNthWeekDayChange: function(event) {
|
||||
handleNthWeekDayChange: function (event) {
|
||||
return this.handleValueChange(
|
||||
'nthWeekDay',
|
||||
event.target.value
|
||||
);
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
const value = this._getCurrentValue();
|
||||
let timeOfDaySelection;
|
||||
let weekDaySelection;
|
||||
|
@ -5,21 +5,21 @@ define(
|
||||
'mailpoet',
|
||||
'newsletters/breadcrumb.jsx'
|
||||
],
|
||||
function(
|
||||
(
|
||||
React,
|
||||
Router,
|
||||
MailPoet,
|
||||
Breadcrumb
|
||||
) {
|
||||
) => {
|
||||
|
||||
var NewsletterStandard = React.createClass({
|
||||
const NewsletterStandard = React.createClass({
|
||||
contextTypes: {
|
||||
router: React.PropTypes.object.isRequired
|
||||
},
|
||||
showTemplateSelection: function(newsletterId) {
|
||||
showTemplateSelection: function (newsletterId) {
|
||||
this.context.router.push(`/template/${newsletterId}`);
|
||||
},
|
||||
componentDidMount: function() {
|
||||
componentDidMount: function () {
|
||||
// No options for this type, create a newsletter upon mounting
|
||||
MailPoet.Ajax.post({
|
||||
api_version: window.mailpoet_api_version,
|
||||
@ -33,13 +33,13 @@ define(
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
return (
|
||||
<div>
|
||||
<h1>{MailPoet.I18n.t('regularNewsletterTypeTitle')}</h1>
|
||||
|
@ -1,17 +1,14 @@
|
||||
import _ from 'underscore'
|
||||
import React from 'react'
|
||||
import MailPoet from 'mailpoet'
|
||||
import Select from 'form/fields/select.jsx'
|
||||
import Text from 'form/fields/text.jsx'
|
||||
import {
|
||||
timeDelayValues,
|
||||
intervalValues
|
||||
} from 'newsletters/scheduling/common.jsx'
|
||||
import _ from 'underscore';
|
||||
import React from 'react';
|
||||
import MailPoet from 'mailpoet';
|
||||
import Select from 'form/fields/select.jsx';
|
||||
import Text from 'form/fields/text.jsx';
|
||||
import { timeDelayValues } from 'newsletters/scheduling/common.jsx';
|
||||
|
||||
const availableRoles = window.mailpoet_roles || {};
|
||||
const availableSegments = _.filter(
|
||||
window.mailpoet_segments || [],
|
||||
function (segment) {
|
||||
(segment) => {
|
||||
return segment.type === 'default';
|
||||
}
|
||||
);
|
||||
@ -26,8 +23,8 @@ const events = {
|
||||
|
||||
const availableSegmentValues = _.object(_.map(
|
||||
availableSegments,
|
||||
function(segment) {
|
||||
let name = segment.name + ' (' + parseInt(segment.subscribers).toLocaleString() + ')';
|
||||
(segment) => {
|
||||
const name = segment.name + ' (' + parseInt(segment.subscribers, 10).toLocaleString() + ')';
|
||||
return [segment.id, name];
|
||||
}
|
||||
));
|
||||
@ -56,12 +53,12 @@ const WelcomeScheduling = React.createClass({
|
||||
contextTypes: {
|
||||
router: React.PropTypes.object.isRequired
|
||||
},
|
||||
_getCurrentValue: function() {
|
||||
_getCurrentValue: function () {
|
||||
return (this.props.item[this.props.field.name] || {});
|
||||
},
|
||||
handleValueChange: function(name, value) {
|
||||
handleValueChange: function (name, value) {
|
||||
const oldValue = this._getCurrentValue();
|
||||
let newValue = {};
|
||||
const newValue = {};
|
||||
|
||||
newValue[name] = value;
|
||||
|
||||
@ -72,37 +69,37 @@ const WelcomeScheduling = React.createClass({
|
||||
}
|
||||
});
|
||||
},
|
||||
handleEventChange: function(event) {
|
||||
handleEventChange: function (event) {
|
||||
return this.handleValueChange(
|
||||
'event',
|
||||
event.target.value
|
||||
);
|
||||
},
|
||||
handleSegmentChange: function(event) {
|
||||
handleSegmentChange: function (event) {
|
||||
return this.handleValueChange(
|
||||
'segment',
|
||||
event.target.value
|
||||
);
|
||||
},
|
||||
handleRoleChange: function(event) {
|
||||
handleRoleChange: function (event) {
|
||||
return this.handleValueChange(
|
||||
'role',
|
||||
event.target.value
|
||||
);
|
||||
},
|
||||
handleAfterTimeNumberChange: function(event) {
|
||||
handleAfterTimeNumberChange: function (event) {
|
||||
return this.handleValueChange(
|
||||
'afterTimeNumber',
|
||||
event.target.value
|
||||
);
|
||||
},
|
||||
handleAfterTimeTypeChange: function(event) {
|
||||
handleAfterTimeTypeChange: function (event) {
|
||||
return this.handleValueChange(
|
||||
'afterTimeType',
|
||||
event.target.value
|
||||
);
|
||||
},
|
||||
handleNext: function() {
|
||||
handleNext: function () {
|
||||
MailPoet.Ajax.post({
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'newsletters',
|
||||
@ -112,20 +109,20 @@ const WelcomeScheduling = React.createClass({
|
||||
options: this.state
|
||||
}
|
||||
}).done((response) => {
|
||||
this.showTemplateSelection(response.data.id);
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
this.showTemplateSelection(response.data.id);
|
||||
}).fail((response) => {
|
||||
if (response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
showTemplateSelection: function(newsletterId) {
|
||||
showTemplateSelection: function (newsletterId) {
|
||||
this.context.router.push(`/template/${ newsletterId }`);
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
const value = this._getCurrentValue();
|
||||
let roleSegmentSelection;
|
||||
let timeNumber;
|
||||
|
@ -5,14 +5,14 @@ define(
|
||||
'mailpoet',
|
||||
'form/form.jsx'
|
||||
],
|
||||
function(
|
||||
(
|
||||
React,
|
||||
Router,
|
||||
MailPoet,
|
||||
Form
|
||||
) {
|
||||
) => {
|
||||
|
||||
let fields = [
|
||||
const fields = [
|
||||
{
|
||||
name: 'name',
|
||||
label: MailPoet.I18n.t('name'),
|
||||
@ -27,18 +27,18 @@ define(
|
||||
];
|
||||
|
||||
const messages = {
|
||||
onUpdate: function() {
|
||||
onUpdate: function () {
|
||||
MailPoet.Notice.success(MailPoet.I18n.t('segmentUpdated'));
|
||||
},
|
||||
onCreate: function() {
|
||||
onCreate: function () {
|
||||
MailPoet.Notice.success(MailPoet.I18n.t('segmentAdded'));
|
||||
}
|
||||
};
|
||||
|
||||
var Link = Router.Link;
|
||||
const Link = Router.Link;
|
||||
|
||||
const SegmentForm = React.createClass({
|
||||
render: function() {
|
||||
render: function () {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="title">
|
||||
|
@ -1,12 +1,11 @@
|
||||
import React from 'react'
|
||||
import { Router, Link } from 'react-router'
|
||||
import jQuery from 'jquery'
|
||||
import MailPoet from 'mailpoet'
|
||||
import classNames from 'classnames'
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
import MailPoet from 'mailpoet';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import Listing from 'listing/listing.jsx'
|
||||
import Listing from 'listing/listing.jsx';
|
||||
|
||||
var columns = [
|
||||
const columns = [
|
||||
{
|
||||
name: 'name',
|
||||
label: MailPoet.I18n.t('name'),
|
||||
@ -98,12 +97,12 @@ const bulk_actions = [
|
||||
const item_actions = [
|
||||
{
|
||||
name: 'edit',
|
||||
link: function(item) {
|
||||
link: function (item) {
|
||||
return (
|
||||
<Link to={ `/edit/${item.id}` }>{MailPoet.I18n.t('edit')}</Link>
|
||||
);
|
||||
},
|
||||
display: function(segment) {
|
||||
display: function (segment) {
|
||||
return (segment.type !== 'wp_users');
|
||||
}
|
||||
},
|
||||
@ -125,18 +124,18 @@ const item_actions = [
|
||||
refresh();
|
||||
}).fail((response) => {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map(function(error) { return error.message; }),
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
});
|
||||
},
|
||||
display: function(segment) {
|
||||
display: function (segment) {
|
||||
return (segment.type !== 'wp_users');
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'read_more',
|
||||
link: function(item) {
|
||||
link: function () {
|
||||
return (
|
||||
<a
|
||||
href="http://docs.mailpoet.com/article/133-the-wordpress-users-list"
|
||||
@ -144,36 +143,42 @@ const item_actions = [
|
||||
>{MailPoet.I18n.t('readMore')}</a>
|
||||
);
|
||||
},
|
||||
display: function(segment) {
|
||||
display: function (segment) {
|
||||
return (segment.type === 'wp_users');
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'synchronize_segment',
|
||||
label: MailPoet.I18n.t('forceSync'),
|
||||
onClick: function(item, refresh) {
|
||||
onClick: function (item, refresh) {
|
||||
MailPoet.Modal.loading(true);
|
||||
MailPoet.Ajax.post({
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'segments',
|
||||
action: 'synchronize'
|
||||
}).done(function(response) {
|
||||
}).done(() => {
|
||||
MailPoet.Modal.loading(false);
|
||||
if(response === true) {
|
||||
MailPoet.Notice.success(
|
||||
(MailPoet.I18n.t('listSynchronized')).replace('%$1s', item.name)
|
||||
MailPoet.Notice.success(
|
||||
(MailPoet.I18n.t('listSynchronized')).replace('%$1s', item.name)
|
||||
);
|
||||
refresh();
|
||||
}).fail((response) => {
|
||||
MailPoet.Modal.loading(false);
|
||||
if(response.errors.length > 0) {
|
||||
MailPoet.Notice.error(
|
||||
response.errors.map((error) => { return error.message; }),
|
||||
{ scroll: true }
|
||||
);
|
||||
refresh();
|
||||
}
|
||||
});
|
||||
},
|
||||
display: function(segment) {
|
||||
display: function (segment) {
|
||||
return (segment.type === 'wp_users');
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'view_subscribers',
|
||||
link: function(item) {
|
||||
link: function (item) {
|
||||
return (
|
||||
<a href={ item.subscribers_url }>{MailPoet.I18n.t('viewSubscribers')}</a>
|
||||
);
|
||||
@ -181,15 +186,15 @@ const item_actions = [
|
||||
},
|
||||
{
|
||||
name: 'trash',
|
||||
display: function(segment) {
|
||||
display: function (segment) {
|
||||
return (segment.type !== 'wp_users');
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const SegmentList = React.createClass({
|
||||
renderItem: function(segment, actions) {
|
||||
var rowClasses = classNames(
|
||||
renderItem: function (segment, actions) {
|
||||
const rowClasses = classNames(
|
||||
'manage-column',
|
||||
'column-primary',
|
||||
'has-row-actions'
|
||||
@ -245,7 +250,7 @@ const SegmentList = React.createClass({
|
||||
</div>
|
||||
);
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="title">
|
||||
|
@ -1,16 +1,16 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { Router, Route, IndexRoute, Link, useRouterHistory } from 'react-router'
|
||||
import { createHashHistory } from 'history'
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Router, Route, IndexRoute, useRouterHistory } from 'react-router';
|
||||
import { createHashHistory } from 'history';
|
||||
|
||||
import SegmentList from 'segments/list.jsx'
|
||||
import SegmentForm from 'segments/form.jsx'
|
||||
import SegmentList from 'segments/list.jsx';
|
||||
import SegmentForm from 'segments/form.jsx';
|
||||
|
||||
const history = useRouterHistory(createHashHistory)({ queryKey: false });
|
||||
|
||||
const App = React.createClass({
|
||||
render() {
|
||||
return this.props.children
|
||||
return this.props.children;
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -70,6 +70,14 @@ define(
|
||||
|
||||
// show "save settings" button
|
||||
jQuery('.mailpoet_settings_submit').show();
|
||||
|
||||
MailPoet.trackEvent(
|
||||
'User has clicked a tab in Settings',
|
||||
{
|
||||
'MailPoet Free version': window.mailpoet_version,
|
||||
'Tab ID': tab
|
||||
}
|
||||
);
|
||||
}
|
||||
}));
|
||||
|
||||
|
@ -6,19 +6,19 @@ define(
|
||||
'form/form.jsx',
|
||||
'react-string-replace'
|
||||
],
|
||||
function(
|
||||
(
|
||||
React,
|
||||
Router,
|
||||
MailPoet,
|
||||
Form,
|
||||
ReactStringReplace
|
||||
) {
|
||||
var fields = [
|
||||
) => {
|
||||
const fields = [
|
||||
{
|
||||
name: 'email',
|
||||
label: MailPoet.I18n.t('email'),
|
||||
type: 'text',
|
||||
disabled: function(subscriber) {
|
||||
disabled: function (subscriber) {
|
||||
return ~~(subscriber.wp_user_id > 0);
|
||||
}
|
||||
},
|
||||
@ -26,7 +26,7 @@ define(
|
||||
name: 'first_name',
|
||||
label: MailPoet.I18n.t('firstname'),
|
||||
type: 'text',
|
||||
disabled: function(subscriber) {
|
||||
disabled: function (subscriber) {
|
||||
return ~~(subscriber.wp_user_id > 0);
|
||||
}
|
||||
},
|
||||
@ -34,7 +34,7 @@ define(
|
||||
name: 'last_name',
|
||||
label: MailPoet.I18n.t('lastname'),
|
||||
type: 'text',
|
||||
disabled: function(subscriber) {
|
||||
disabled: function (subscriber) {
|
||||
return ~~(subscriber.wp_user_id > 0);
|
||||
}
|
||||
},
|
||||
@ -48,7 +48,7 @@ define(
|
||||
'unsubscribed': MailPoet.I18n.t('unsubscribed'),
|
||||
'bounced': MailPoet.I18n.t('bounced')
|
||||
},
|
||||
filter: function(subscriber, value) {
|
||||
filter: function (subscriber, value) {
|
||||
if (~~(subscriber.wp_user_id) > 0 && value === 'unconfirmed') {
|
||||
return false;
|
||||
}
|
||||
@ -63,28 +63,28 @@ define(
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'segments',
|
||||
multiple: true,
|
||||
selected: function(subscriber) {
|
||||
selected: function (subscriber) {
|
||||
if (Array.isArray(subscriber.subscriptions) === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return subscriber.subscriptions.map(function(subscription) {
|
||||
return subscriber.subscriptions.map((subscription) => {
|
||||
if (subscription.status === 'subscribed') {
|
||||
return subscription.segment_id;
|
||||
}
|
||||
});
|
||||
},
|
||||
filter: function(segment) {
|
||||
filter: function (segment) {
|
||||
return !!(!segment.deleted_at && segment.type === 'default');
|
||||
},
|
||||
getLabel: function(segment) {
|
||||
getLabel: function (segment) {
|
||||
return segment.name + ' ('+ segment.subscribers +')';
|
||||
},
|
||||
getSearchLabel: function(segment, subscriber) {
|
||||
getSearchLabel: function (segment, subscriber) {
|
||||
let label = '';
|
||||
|
||||
if (subscriber.subscriptions !== undefined) {
|
||||
subscriber.subscriptions.map(function(subscription) {
|
||||
subscriber.subscriptions.map((subscription) => {
|
||||
if (segment.id === subscription.segment_id) {
|
||||
label = segment.name;
|
||||
|
||||
@ -107,9 +107,9 @@ define(
|
||||
}
|
||||
];
|
||||
|
||||
var custom_fields = window.mailpoet_custom_fields || [];
|
||||
custom_fields.map(custom_field => {
|
||||
let field = {
|
||||
const custom_fields = window.mailpoet_custom_fields || [];
|
||||
custom_fields.map((custom_field) => {
|
||||
const field = {
|
||||
name: 'cf_' + custom_field.id,
|
||||
label: custom_field.name,
|
||||
type: custom_field.type
|
||||
@ -128,26 +128,26 @@ define(
|
||||
field.year_placeholder = MailPoet.I18n.t('year');
|
||||
field.month_placeholder = MailPoet.I18n.t('month');
|
||||
field.day_placeholder = MailPoet.I18n.t('day');
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'select':
|
||||
field.placeholder = '-';
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
fields.push(field);
|
||||
});
|
||||
|
||||
var messages = {
|
||||
onUpdate: function() {
|
||||
const messages = {
|
||||
onUpdate: function () {
|
||||
MailPoet.Notice.success(MailPoet.I18n.t('subscriberUpdated'));
|
||||
},
|
||||
onCreate: function() {
|
||||
onCreate: function () {
|
||||
MailPoet.Notice.success(MailPoet.I18n.t('subscriberAdded'));
|
||||
}
|
||||
};
|
||||
|
||||
var beforeFormContent = function(subscriber) {
|
||||
const beforeFormContent = function (subscriber) {
|
||||
if (~~(subscriber.wp_user_id) > 0) {
|
||||
return (
|
||||
<p className="description">
|
||||
@ -167,7 +167,7 @@ define(
|
||||
}
|
||||
};
|
||||
|
||||
var afterFormContent = function(subscriber) {
|
||||
const afterFormContent = function () {
|
||||
return (
|
||||
<p className="description">
|
||||
<strong>
|
||||
@ -175,12 +175,12 @@ define(
|
||||
</strong> { MailPoet.I18n.t('customFieldsTip') }
|
||||
</p>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
var Link = Router.Link;
|
||||
const Link = Router.Link;
|
||||
|
||||
var SubscriberForm = React.createClass({
|
||||
render: function() {
|
||||
const SubscriberForm = React.createClass({
|
||||
render: function () {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="title">
|
||||
|
@ -1,12 +1,12 @@
|
||||
import React from 'react'
|
||||
import { Router, Route, Link } from 'react-router'
|
||||
import React from 'react';
|
||||
import { Link } from 'react-router';
|
||||
|
||||
import jQuery from 'jquery'
|
||||
import MailPoet from 'mailpoet'
|
||||
import classNames from 'classnames'
|
||||
import jQuery from 'jquery';
|
||||
import MailPoet from 'mailpoet';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import Listing from 'listing/listing.jsx'
|
||||
import Selection from 'form/fields/selection.jsx'
|
||||
import Listing from 'listing/listing.jsx';
|
||||
import Selection from 'form/fields/selection.jsx';
|
||||
|
||||
const columns = [
|
||||
{
|
||||
@ -104,12 +104,12 @@ const bulk_actions = [
|
||||
{
|
||||
name: 'moveToList',
|
||||
label: MailPoet.I18n.t('moveToList'),
|
||||
onSelect: function() {
|
||||
let field = {
|
||||
onSelect: function () {
|
||||
const field = {
|
||||
id: 'move_to_segment',
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'segments',
|
||||
filter: function(segment) {
|
||||
filter: function (segment) {
|
||||
return !!(
|
||||
!segment.deleted_at && segment.type === 'default'
|
||||
);
|
||||
@ -120,12 +120,12 @@ const bulk_actions = [
|
||||
<Selection field={ field }/>
|
||||
);
|
||||
},
|
||||
getData: function() {
|
||||
getData: function () {
|
||||
return {
|
||||
segment_id: ~~(jQuery('#move_to_segment').val())
|
||||
}
|
||||
};
|
||||
},
|
||||
onSuccess: function(response) {
|
||||
onSuccess: function (response) {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('multipleSubscribersMovedToList')
|
||||
.replace('%$1d', (~~(response.meta.count)).toLocaleString())
|
||||
@ -136,12 +136,12 @@ const bulk_actions = [
|
||||
{
|
||||
name: 'addToList',
|
||||
label: MailPoet.I18n.t('addToList'),
|
||||
onSelect: function() {
|
||||
let field = {
|
||||
onSelect: function () {
|
||||
const field = {
|
||||
id: 'add_to_segment',
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'segments',
|
||||
filter: function(segment) {
|
||||
filter: function (segment) {
|
||||
return !!(
|
||||
!segment.deleted_at && segment.type === 'default'
|
||||
);
|
||||
@ -152,12 +152,12 @@ const bulk_actions = [
|
||||
<Selection field={ field }/>
|
||||
);
|
||||
},
|
||||
getData: function() {
|
||||
getData: function () {
|
||||
return {
|
||||
segment_id: ~~(jQuery('#add_to_segment').val())
|
||||
}
|
||||
};
|
||||
},
|
||||
onSuccess: function(response) {
|
||||
onSuccess: function (response) {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('multipleSubscribersAddedToList')
|
||||
.replace('%$1d', (~~response.meta.count).toLocaleString())
|
||||
@ -168,12 +168,12 @@ const bulk_actions = [
|
||||
{
|
||||
name: 'removeFromList',
|
||||
label: MailPoet.I18n.t('removeFromList'),
|
||||
onSelect: function() {
|
||||
let field = {
|
||||
onSelect: function () {
|
||||
const field = {
|
||||
id: 'remove_from_segment',
|
||||
api_version: window.mailpoet_api_version,
|
||||
endpoint: 'segments',
|
||||
filter: function(segment) {
|
||||
filter: function (segment) {
|
||||
return !!(
|
||||
segment.type === 'default'
|
||||
);
|
||||
@ -184,12 +184,12 @@ const bulk_actions = [
|
||||
<Selection field={ field }/>
|
||||
);
|
||||
},
|
||||
getData: function() {
|
||||
getData: function () {
|
||||
return {
|
||||
segment_id: ~~(jQuery('#remove_from_segment').val())
|
||||
}
|
||||
};
|
||||
},
|
||||
onSuccess: function(response) {
|
||||
onSuccess: function (response) {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('multipleSubscribersRemovedFromList')
|
||||
.replace('%$1d', (~~response.meta.count).toLocaleString())
|
||||
@ -200,7 +200,7 @@ const bulk_actions = [
|
||||
{
|
||||
name: 'removeFromAllLists',
|
||||
label: MailPoet.I18n.t('removeFromAllLists'),
|
||||
onSuccess: function(response) {
|
||||
onSuccess: function (response) {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('multipleSubscribersRemovedFromAllLists')
|
||||
.replace('%$1d', (~~response.meta.count).toLocaleString())
|
||||
@ -210,7 +210,7 @@ const bulk_actions = [
|
||||
{
|
||||
name: 'sendConfirmationEmail',
|
||||
label: MailPoet.I18n.t('resendConfirmationEmail'),
|
||||
onSuccess: function(response) {
|
||||
onSuccess: function (response) {
|
||||
MailPoet.Notice.success(
|
||||
MailPoet.I18n.t('multipleConfirmationEmailsSent')
|
||||
.replace('%$1d', (~~response.meta.count).toLocaleString())
|
||||
@ -228,7 +228,7 @@ const item_actions = [
|
||||
{
|
||||
name: 'edit',
|
||||
label: MailPoet.I18n.t('edit'),
|
||||
link: function(subscriber) {
|
||||
link: function (subscriber) {
|
||||
return (
|
||||
<Link to={ `/edit/${subscriber.id}` }>{MailPoet.I18n.t('edit')}</Link>
|
||||
);
|
||||
@ -236,24 +236,24 @@ const item_actions = [
|
||||
},
|
||||
{
|
||||
name: 'trash',
|
||||
display: function(subscriber) {
|
||||
display: function (subscriber) {
|
||||
return !!(~~subscriber.wp_user_id === 0);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const SubscriberList = React.createClass({
|
||||
getSegmentFromId: function(segment_id) {
|
||||
getSegmentFromId: function (segment_id) {
|
||||
let result = false;
|
||||
mailpoet_segments.map(function(segment) {
|
||||
mailpoet_segments.map((segment) => {
|
||||
if (segment.id === segment_id) {
|
||||
result = segment;
|
||||
}
|
||||
});
|
||||
return result;
|
||||
},
|
||||
renderItem: function(subscriber, actions) {
|
||||
let row_classes = classNames(
|
||||
renderItem: function (subscriber, actions) {
|
||||
const row_classes = classNames(
|
||||
'manage-column',
|
||||
'column-primary',
|
||||
'has-row-actions',
|
||||
@ -265,26 +265,26 @@ const SubscriberList = React.createClass({
|
||||
switch(subscriber.status) {
|
||||
case 'subscribed':
|
||||
status = MailPoet.I18n.t('subscribed');
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'unconfirmed':
|
||||
status = MailPoet.I18n.t('unconfirmed');
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'unsubscribed':
|
||||
status = MailPoet.I18n.t('unsubscribed');
|
||||
break;
|
||||
break;
|
||||
|
||||
case 'bounced':
|
||||
status = MailPoet.I18n.t('bounced');
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
let segments = false;
|
||||
|
||||
// Subscriptions
|
||||
if (subscriber.subscriptions.length > 0) {
|
||||
let subscribed_segments = [];
|
||||
const subscribed_segments = [];
|
||||
|
||||
subscriber.subscriptions.map((subscription) => {
|
||||
const segment = this.getSegmentFromId(subscription.segment_id);
|
||||
@ -301,20 +301,6 @@ const SubscriberList = React.createClass({
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
let avatar = false;
|
||||
if (subscriber.avatar_url) {
|
||||
avatar = (
|
||||
<img
|
||||
className="avatar"
|
||||
src={ subscriber.avatar_url }
|
||||
title=""
|
||||
width="32"
|
||||
height="32"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<td className={ row_classes }>
|
||||
@ -324,7 +310,7 @@ const SubscriberList = React.createClass({
|
||||
to={ `/edit/${ subscriber.id }` }
|
||||
>{ subscriber.email }</Link>
|
||||
</strong>
|
||||
<p style={{margin: 0}}>
|
||||
<p style={{ margin: 0 }}>
|
||||
{ subscriber.first_name } { subscriber.last_name }
|
||||
</p>
|
||||
{ actions }
|
||||
@ -344,7 +330,7 @@ const SubscriberList = React.createClass({
|
||||
</div>
|
||||
);
|
||||
},
|
||||
render: function() {
|
||||
render: function () {
|
||||
return (
|
||||
<div>
|
||||
<h1 className="title">
|
||||
@ -377,7 +363,7 @@ const SubscriberList = React.createClass({
|
||||
sort_order={ 'desc' }
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { Router, Route, IndexRoute, Link, useRouterHistory } from 'react-router'
|
||||
import { createHashHistory } from 'history'
|
||||
import SubscriberList from 'subscribers/list.jsx'
|
||||
import SubscriberForm from 'subscribers/form.jsx'
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { Router, Route, IndexRoute, useRouterHistory } from 'react-router';
|
||||
import { createHashHistory } from 'history';
|
||||
import SubscriberList from 'subscribers/list.jsx';
|
||||
import SubscriberForm from 'subscribers/form.jsx';
|
||||
|
||||
const history = useRouterHistory(createHashHistory)({ queryKey: false });
|
||||
|
||||
@ -13,7 +13,7 @@ const App = React.createClass({
|
||||
}
|
||||
});
|
||||
|
||||
const container = document.getElementById('subscribers_container')
|
||||
const container = document.getElementById('subscribers_container');
|
||||
|
||||
if(container) {
|
||||
ReactDOM.render((
|
||||
|
15
build.sh
@ -38,10 +38,19 @@ rm -Rf $plugin_name/assets/js/src
|
||||
rm -Rf $plugin_name/lang/*.po
|
||||
|
||||
# Remove extra files (docs, examples,...) from 3rd party extensions
|
||||
unameString=`uname`
|
||||
if [[ "$unameString" == 'Darwin' ]]; then
|
||||
findPreArgs=' -E '
|
||||
findMidArgs=''
|
||||
else
|
||||
findPreArgs=''
|
||||
findMidArgs=' -regextype posix-egrep '
|
||||
fi
|
||||
|
||||
echo '[BUILD] Removing obsolete files from vendor libraries'
|
||||
find $plugin_name/vendor -type f -regextype posix-egrep -iregex ".*\/*\.(markdown|md|txt)" -print0 | xargs -0 rm -f
|
||||
find $plugin_name/vendor -type f -regextype posix-egrep -iregex ".*\/(readme|license|version|changes|changelog)" -print0 | xargs -0 rm -f
|
||||
find $plugin_name/vendor -type d -regextype posix-egrep -iregex ".*\/(docs?|examples?|\.git)" -print0 | xargs -0 rm -rf
|
||||
find $findPreArgs $plugin_name/vendor -type f $findMidArgs -iregex ".*\/*\.(markdown|md|txt)" -print0 | xargs -0 rm -f
|
||||
find $findPreArgs $plugin_name/vendor -type f $findMidArgs -iregex ".*\/(readme|license|version|changes|changelog)" -print0 | xargs -0 rm -f
|
||||
find $findPreArgs $plugin_name/vendor -type d $findMidArgs -iregex ".*\/(docs?|examples?|\.git)" -print0 | xargs -0 rm -rf
|
||||
|
||||
# Remove unit tests from 3rd party extensions
|
||||
echo '[BUILD] Removing unit tests from vendor libraries'
|
||||
|
71
circle.yml
@ -1,71 +0,0 @@
|
||||
machine:
|
||||
timezone:
|
||||
UTC
|
||||
|
||||
hosts:
|
||||
mailpoet.loc: 127.0.0.1
|
||||
|
||||
## Customize dependencies
|
||||
dependencies:
|
||||
pre:
|
||||
# install PHP dependencies for WordPress
|
||||
- sudo apt-get update
|
||||
- sudo apt-get --assume-yes install php5-mysql
|
||||
# Add a fake sendmail mailer
|
||||
- cp ./.circle_ci/mailpoet_php.ini /opt/circleci/php/$(phpenv global)/etc/conf.d/
|
||||
# configure Apache
|
||||
- sudo cp ./.circle_ci/apache/mailpoet.loc.conf /etc/apache2/sites-available
|
||||
- sudo a2ensite mailpoet.loc
|
||||
- sudo a2enmod rewrite
|
||||
- sudo service apache2 restart
|
||||
# install Phoenix dependencies
|
||||
- curl -sS https://getcomposer.org/installer | php
|
||||
- ./composer.phar install
|
||||
- ./do install
|
||||
# Set up Wordpress
|
||||
# No password is required for the MySQL user `ubuntu`
|
||||
- mysql -u ubuntu -e "create database wordpress"
|
||||
# Use cURL to fetch WP-CLI
|
||||
- curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
|
||||
# Make sure WP-CLI is executable
|
||||
- chmod +x wp-cli.phar
|
||||
# Download WordPress into `wordpress` directory
|
||||
- ./wp-cli.phar core download --allow-root --path=wordpress
|
||||
# Generate `wp-config.php` file
|
||||
- echo "define(\"WP_DEBUG\", true);" | ./wp-cli.phar core config --allow-root --dbname=wordpress --dbuser=ubuntu --dbhost=127.0.0.1:3306 --path=wordpress --extra-php
|
||||
# Install WordPress
|
||||
- ./wp-cli.phar core install --allow-root --admin_name=admin --admin_password=admin --admin_email=admin@mailpoet.loc --url=http://mailpoet.loc:8080 --title=WordPress --path=wordpress
|
||||
# Softlink MailPoet to plugin path
|
||||
- ln -s ../../.. wordpress/wp-content/plugins/mailpoet
|
||||
# Activate MailPoet
|
||||
- ./wp-cli.phar plugin activate mailpoet --path=wordpress
|
||||
# Create .env file with correct path to WP installation
|
||||
- echo "WP_TEST_PATH=\"/home/ubuntu/mailpoet/wordpress\"" > .env
|
||||
|
||||
# Enable XDebug for coverage reports.
|
||||
# Comment out if not running PHP coverage reports, for performance
|
||||
#- sed -i 's/^;//' /opt/circleci/php/$(phpenv global)/etc/conf.d/xdebug.ini
|
||||
|
||||
## tests override
|
||||
test:
|
||||
override:
|
||||
# Add default timezone to PHP's configuration (required for PHP >=5.4)
|
||||
- echo "date.timezone = UTC" > /opt/circleci/php/$(phpenv global)/etc/conf.d/date.ini
|
||||
# Run QA scripts
|
||||
- ./do qa
|
||||
# Run JS tests
|
||||
- mkdir $CIRCLE_TEST_REPORTS/mocha
|
||||
- ./do t:j $CIRCLE_TEST_REPORTS/mocha/junit.xml
|
||||
|
||||
# Run PHP tests
|
||||
- ./do t:u --xml
|
||||
# Uncomment to run coverage tests instead
|
||||
#- ./do t:c --xml
|
||||
# Copy the report
|
||||
- mkdir $CIRCLE_TEST_REPORTS/codeception
|
||||
- cp tests/_output/report.xml $CIRCLE_TEST_REPORTS/codeception/report.xml
|
||||
# Uncomment to copy PHP coverage report
|
||||
#- cp tests/_output/coverage.xml $CIRCLE_TEST_REPORTS/codeception/coverage.xml
|
||||
# Store any email output, sent via sendmail during tests
|
||||
- mkdir $CIRCLE_TEST_REPORTS/fake-mailer
|
||||
- cp /tmp/mailpoet-* $CIRCLE_TEST_REPORTS/fake-mailer
|
@ -19,6 +19,7 @@
|
||||
"symfony/polyfill-xml": "^1.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"codeception/aspect-mock": "^2.0",
|
||||
"codeception/codeception": "^2.2.9",
|
||||
"codeception/verify": "^0.3.3",
|
||||
"consolidation/robo": "^1.0.5",
|
||||
|
388
composer.lock
generated
@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "c8c2fdb08b7ab624890703dde640c5d1",
|
||||
"content-hash": "41f1dee36a4af45bcb91ca96c5f0872a",
|
||||
"packages": [
|
||||
{
|
||||
"name": "cerdic/css-tidy",
|
||||
@ -764,6 +764,49 @@
|
||||
],
|
||||
"time": "2016-10-30T11:50:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "codeception/aspect-mock",
|
||||
"version": "2.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Codeception/AspectMock.git",
|
||||
"reference": "b7f5c50da89419824102400bb4c71988ec33044f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Codeception/AspectMock/zipball/b7f5c50da89419824102400bb4c71988ec33044f",
|
||||
"reference": "b7f5c50da89419824102400bb4c71988ec33044f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"goaop/framework": "^2.0.0",
|
||||
"php": ">=5.6.0",
|
||||
"symfony/finder": "~2.4|~3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"codeception/base": "~2.1",
|
||||
"codeception/specify": "~0.3",
|
||||
"codeception/verify": "~0.2"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"AspectMock": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Michael Bodnarchuk",
|
||||
"email": "davert.php@mailican.com"
|
||||
}
|
||||
],
|
||||
"description": "Experimental Mocking Framework powered by Aspects",
|
||||
"time": "2017-01-31T20:29:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "codeception/codeception",
|
||||
"version": "2.2.9",
|
||||
@ -1148,6 +1191,74 @@
|
||||
"homepage": "https://github.com/container-interop/container-interop",
|
||||
"time": "2017-02-14T19:40:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/annotations",
|
||||
"version": "v1.4.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/annotations.git",
|
||||
"reference": "54cacc9b81758b14e3ce750f205a393d52339e97"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/annotations/zipball/54cacc9b81758b14e3ce750f205a393d52339e97",
|
||||
"reference": "54cacc9b81758b14e3ce750f205a393d52339e97",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/lexer": "1.*",
|
||||
"php": "^5.6 || ^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/cache": "1.*",
|
||||
"phpunit/phpunit": "^5.7"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.4.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Benjamin Eberlei",
|
||||
"email": "kontakt@beberlei.de"
|
||||
},
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Jonathan Wage",
|
||||
"email": "jonwage@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Johannes Schmitt",
|
||||
"email": "schmittjoh@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Docblock Annotations Parser",
|
||||
"homepage": "http://www.doctrine-project.org",
|
||||
"keywords": [
|
||||
"annotations",
|
||||
"docblock",
|
||||
"parser"
|
||||
],
|
||||
"time": "2017-02-24T16:22:25+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/instantiator",
|
||||
"version": "1.0.5",
|
||||
@ -1202,6 +1313,60 @@
|
||||
],
|
||||
"time": "2015-06-14T21:17:01+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/lexer",
|
||||
"version": "v1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/lexer.git",
|
||||
"reference": "83893c552fd2045dd78aef794c31e694c37c0b8c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c",
|
||||
"reference": "83893c552fd2045dd78aef794c31e694c37c0b8c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Doctrine\\Common\\Lexer\\": "lib/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Roman Borschel",
|
||||
"email": "roman@code-factory.org"
|
||||
},
|
||||
{
|
||||
"name": "Guilherme Blanco",
|
||||
"email": "guilhermeblanco@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Johannes Schmitt",
|
||||
"email": "schmittjoh@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.",
|
||||
"homepage": "http://www.doctrine-project.org",
|
||||
"keywords": [
|
||||
"lexer",
|
||||
"parser"
|
||||
],
|
||||
"time": "2014-09-09T13:34:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "facebook/webdriver",
|
||||
"version": "1.3.0",
|
||||
@ -1251,6 +1416,119 @@
|
||||
],
|
||||
"time": "2017-01-13T15:48:08+00:00"
|
||||
},
|
||||
{
|
||||
"name": "goaop/framework",
|
||||
"version": "2.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/goaop/framework.git",
|
||||
"reference": "c6fc1db1e623bbfbf3bc2f165e03250603ff27b8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/goaop/framework/zipball/c6fc1db1e623bbfbf3bc2f165e03250603ff27b8",
|
||||
"reference": "c6fc1db1e623bbfbf3bc2f165e03250603ff27b8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/annotations": "~1.0",
|
||||
"goaop/parser-reflection": "~1.2",
|
||||
"jakubledl/dissect": "~1.0",
|
||||
"php": ">=5.6.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"adlawson/vfs": "^0.12",
|
||||
"phpunit/phpunit": "^4.8",
|
||||
"symfony/console": "^2.7|^3.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/console": "Enables the usage of the command-line tool."
|
||||
},
|
||||
"bin": [
|
||||
"bin/aspect"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Go\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Lisachenko Alexander",
|
||||
"homepage": "https://github.com/lisachenko"
|
||||
}
|
||||
],
|
||||
"description": "Framework for aspect-oriented programming in PHP.",
|
||||
"homepage": "http://go.aopphp.com/",
|
||||
"keywords": [
|
||||
"aop",
|
||||
"aspect",
|
||||
"library",
|
||||
"php"
|
||||
],
|
||||
"time": "2017-04-25T11:27:19+00:00"
|
||||
},
|
||||
{
|
||||
"name": "goaop/parser-reflection",
|
||||
"version": "1.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/goaop/parser-reflection.git",
|
||||
"reference": "49e6cb828cb120104231a8b908b4ae794427b6a4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/goaop/parser-reflection/zipball/49e6cb828cb120104231a8b908b4ae794427b6a4",
|
||||
"reference": "49e6cb828cb120104231a8b908b4ae794427b6a4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"nikic/php-parser": "^1.2|^2.0|^3.0",
|
||||
"php": ">=5.6.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Go\\ParserReflection\\": "src"
|
||||
},
|
||||
"files": [
|
||||
"src/bootstrap.php"
|
||||
],
|
||||
"exclude-from-classmap": [
|
||||
"/tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Alexander Lisachenko",
|
||||
"email": "lisachenko.it@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Provides reflection information, based on raw source",
|
||||
"time": "2017-06-27T16:23:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "guzzlehttp/guzzle",
|
||||
"version": "6.2.3",
|
||||
@ -1488,6 +1766,61 @@
|
||||
],
|
||||
"time": "2016-03-16T15:22:20+00:00"
|
||||
},
|
||||
{
|
||||
"name": "jakubledl/dissect",
|
||||
"version": "v1.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/jakubledl/dissect.git",
|
||||
"reference": "d3a391de31e45a247e95cef6cf58a91c05af67c4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/jakubledl/dissect/zipball/d3a391de31e45a247e95cef6cf58a91c05af67c4",
|
||||
"reference": "d3a391de31e45a247e95cef6cf58a91c05af67c4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/console": "~2.1"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/console": "for the command-line tool"
|
||||
},
|
||||
"bin": [
|
||||
"bin/dissect.php",
|
||||
"bin/dissect"
|
||||
],
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Dissect": [
|
||||
"src/"
|
||||
]
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"unlicense"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Jakub Lédl",
|
||||
"email": "jakubledl@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "Lexing and parsing in pure PHP",
|
||||
"homepage": "https://github.com/jakubledl/dissect",
|
||||
"keywords": [
|
||||
"ast",
|
||||
"lexing",
|
||||
"parser",
|
||||
"parsing"
|
||||
],
|
||||
"time": "2013-01-29T21:29:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/container",
|
||||
"version": "2.4.0",
|
||||
@ -1595,6 +1928,57 @@
|
||||
],
|
||||
"time": "2017-01-26T22:05:40+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
"version": "v3.0.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/nikic/PHP-Parser.git",
|
||||
"reference": "0808939f81c1347a3c8a82a5925385a08074b0f1"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0808939f81c1347a3c8a82a5925385a08074b0f1",
|
||||
"reference": "0808939f81c1347a3c8a82a5925385a08074b0f1",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-tokenizer": "*",
|
||||
"php": ">=5.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.0|~5.0"
|
||||
},
|
||||
"bin": [
|
||||
"bin/php-parse"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"PhpParser\\": "lib/PhpParser"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nikita Popov"
|
||||
}
|
||||
],
|
||||
"description": "A PHP parser written in PHP",
|
||||
"keywords": [
|
||||
"parser",
|
||||
"php"
|
||||
],
|
||||
"time": "2017-06-28T20:53:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-common",
|
||||
"version": "1.0",
|
||||
@ -2956,7 +3340,7 @@
|
||||
"typo3"
|
||||
],
|
||||
"abandoned": true,
|
||||
"time": "2016-05-12T11:58:38+00:00"
|
||||
"time": "2016-05-12 11:58:38"
|
||||
},
|
||||
{
|
||||
"name": "squizlabs/php_codesniffer",
|
||||
|
@ -60,8 +60,8 @@ class Services extends APIEndpoint {
|
||||
default:
|
||||
$code = !empty($result['code']) ? $result['code'] : Bridge::CHECK_ERROR_UNKNOWN;
|
||||
$error = sprintf(
|
||||
__('Error validating MailPoet Sending Service key, please try again later (code: %s)', 'mailpoet'),
|
||||
$code
|
||||
__('Error validating MailPoet Sending Service key, please try again later (%s)', 'mailpoet'),
|
||||
$this->getErrorDescriptionByCode($code)
|
||||
);
|
||||
break;
|
||||
}
|
||||
@ -116,12 +116,28 @@ class Services extends APIEndpoint {
|
||||
default:
|
||||
$code = !empty($result['code']) ? $result['code'] : Bridge::CHECK_ERROR_UNKNOWN;
|
||||
$error = sprintf(
|
||||
__('Error validating Premium key, please try again later (code: %s)', 'mailpoet'),
|
||||
$code
|
||||
__('Error validating Premium key, please try again later (%s)', 'mailpoet'),
|
||||
$this->getErrorDescriptionByCode($code)
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return $this->errorResponse(array(APIError::BAD_REQUEST => $error));
|
||||
}
|
||||
|
||||
private function getErrorDescriptionByCode($code) {
|
||||
switch($code) {
|
||||
case Bridge::CHECK_ERROR_UNAVAILABLE:
|
||||
$text = __('Service unavailable', 'mailpoet');
|
||||
break;
|
||||
case Bridge::CHECK_ERROR_UNKNOWN:
|
||||
$text = __('Contact your hosting support to check the connection between your host and https://bridge.mailpoet.com', 'mailpoet');
|
||||
break;
|
||||
default:
|
||||
$text = sprintf(_x('code: %s', 'Error code (inside parentheses)', 'mailpoet'), $code);
|
||||
break;
|
||||
}
|
||||
|
||||
return $text;
|
||||
}
|
||||
}
|
||||
|
@ -2,31 +2,62 @@
|
||||
namespace MailPoet\Analytics;
|
||||
|
||||
use MailPoet\Config\Installer;
|
||||
use MailPoet\Config\ServicesChecker;
|
||||
use MailPoet\Cron\CronTrigger;
|
||||
use MailPoet\Models\Newsletter;
|
||||
use MailPoet\Models\Setting;
|
||||
use MailPoet\Models\Subscriber;
|
||||
use MailPoet\Settings\Pages;
|
||||
|
||||
class Reporter {
|
||||
|
||||
function getData() {
|
||||
|
||||
$mta = Setting::getValue('mta', array());
|
||||
$premium_status = Installer::getPremiumStatus();
|
||||
$newsletters = Newsletter::getAnalytics();
|
||||
$isCronTriggerMethodWP = Setting::getValue('cron_trigger.method') === CronTrigger::$available_methods['wordpress'];
|
||||
$checker = new ServicesChecker();
|
||||
$bounceAddress = Setting::getValue('bounce.address');
|
||||
|
||||
|
||||
return array(
|
||||
'MailPoet Free version' => MAILPOET_VERSION,
|
||||
'MailPoet Premium version' => (defined('MAILPOET_PREMIUM_VERSION')) ? MAILPOET_PREMIUM_VERSION : 'N/A',
|
||||
'Premium Plugin Installed' => $premium_status['premium_plugin_installed'],
|
||||
'Premium Plugin Active' => $premium_status['premium_plugin_active'],
|
||||
'Total number of subscribers' => Subscriber::getTotalSubscribers(),
|
||||
'Sending Method' => $mta['method'],
|
||||
'Sending Method' => isset($mta['method']) ? $mta['method'] : null,
|
||||
'Date of plugin installation' => Setting::getValue('installed_at'),
|
||||
'Subscribe in comments' => (boolean)Setting::getValue('subscribe.on_comment.enabled', false),
|
||||
'Subscribe in registration form' => (boolean)Setting::getValue('subscribe.on_register.enabled', false),
|
||||
'Manage Subscription page > MailPoet page' => (boolean)Pages::isMailpoetPage(intval(Setting::getValue('subscription.pages.manage'))),
|
||||
'Unsubscribe page > MailPoet page' => (boolean)Pages::isMailpoetPage(intval(Setting::getValue('subscription.pages.unsubscribe'))),
|
||||
'Sign-up confirmation' => (boolean)Setting::getValue('signup_confirmation.enabled', false),
|
||||
'Sign-up confirmation: Confirmation page > MailPoet page' => (boolean)Pages::isMailpoetPage(intval(Setting::getValue('subscription.pages.confirmation'))),
|
||||
'Bounce email address' => !empty($bounceAddress),
|
||||
'Newsletter task scheduler (cron)' => $isCronTriggerMethodWP ? 'visitors' : 'script',
|
||||
'Open and click tracking' => (boolean)Setting::getValue('tracking.enabled', false),
|
||||
'Premium key valid' => $checker->isPremiumKeyValid(),
|
||||
'Number of standard newsletters sent in last 3 months' => $newsletters['sent_newsletters'],
|
||||
'Number of active post notifications' => $newsletters['notifications_count'],
|
||||
'Number of active welcome emails' => $newsletters['welcome_newsletters_count'],
|
||||
'Is WooCommerce plugin installed' => is_plugin_active("woocommerce/woocommerce.php"),
|
||||
'Plugin > MailPoet Premium' => is_plugin_active('mailpoet-premium/mailpoet-premium.php'),
|
||||
'Plugin > bounce add-on' => is_plugin_active('mailpoet-bounce-handler/mailpoet-bounce-handler.php'),
|
||||
'Plugin > Bloom' => is_plugin_active('bloom-for-publishers/bloom.php'),
|
||||
'Plugin > WP Holler' => is_plugin_active('holler-box/holler-box.php'),
|
||||
'Plugin > WP-SMTP' => is_plugin_active('wp-mail-smtp/wp_mail_smtp.php'),
|
||||
'Plugin > WooCommerce' => is_plugin_active('woocommerce/woocommerce.php'),
|
||||
'Plugin > WooCommerce Subscription' => is_plugin_active('woocommerce-subscriptions/woocommerce-subscriptions.php'),
|
||||
'Plugin > WooCommerce Follow Up Emails' => is_plugin_active('woocommerce-follow-up-emails/woocommerce-follow-up-emails.php'),
|
||||
'Plugin > WooCommerce Email Customizer' => is_plugin_active('woocommerce-email-customizer/woocommerce-email-customizer.php'),
|
||||
'Plugin > WooCommerce Memberships' => is_plugin_active('woocommerce-memberships/woocommerce-memberships.php'),
|
||||
'Plugin > WooCommerce MailChimp' => is_plugin_active('woocommerce-mailchimp/woocommerce-mailchimp.php'),
|
||||
'Plugin > MailChimp for WooCommerce' => is_plugin_active('mailchimp-for-woocommerce/mailchimp-woocommerce.php'),
|
||||
'Plugin > The Event Calendar' => is_plugin_active('the-events-calendar/the-events-calendar.php'),
|
||||
'Plugin > Gravity Forms' => is_plugin_active('gravityforms/gravityforms.php'),
|
||||
'Plugin > Ninja Forms' => is_plugin_active('ninja-forms/ninja-forms.php'),
|
||||
'Plugin > WPForms' => is_plugin_active('wpforms-lite/wpforms.php'),
|
||||
'Plugin > Formidable Forms' => is_plugin_active('formidable/formidable.php'),
|
||||
'Plugin > Contact Form 7' => is_plugin_active('contact-form-7/wp-contact-form-7.php'),
|
||||
'Plugin > Easy Digital Downloads' => is_plugin_active('easy-digital-downloads/easy-digital-downloads.php'),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -42,17 +42,21 @@ class Database {
|
||||
$driver_options[] = $character_set;
|
||||
}
|
||||
|
||||
$current_options = ORM::for_table("")
|
||||
->raw_query('SELECT @@session.wait_timeout as wait_timeout')
|
||||
->findOne();
|
||||
if($current_options && (int)$current_options->wait_timeout < $this->driver_option_wait_timeout) {
|
||||
$driver_options[] = 'SESSION wait_timeout = ' . $this->driver_option_wait_timeout;
|
||||
}
|
||||
// reset the database
|
||||
ORM::set_db(null);
|
||||
ORM::configure('driver_options', array(
|
||||
PDO::MYSQL_ATTR_INIT_COMMAND => 'SET ' . implode(', ', $driver_options)
|
||||
));
|
||||
|
||||
try {
|
||||
$current_options = ORM::for_table("")
|
||||
->raw_query('SELECT @@session.wait_timeout as wait_timeout')
|
||||
->findOne();
|
||||
if($current_options && (int)$current_options->wait_timeout < $this->driver_option_wait_timeout) {
|
||||
ORM::raw_execute('SET SESSION wait_timeout = ' . $this->driver_option_wait_timeout);
|
||||
}
|
||||
} catch (\PDOException $e) {
|
||||
// Rethrow PDOExceptions to prevent exposing sensitive data in stack traces
|
||||
throw new \Exception($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
function defineTables() {
|
||||
@ -65,6 +69,8 @@ class Database {
|
||||
$subscriber_segment = Env::$db_prefix . 'subscriber_segment';
|
||||
$subscriber_custom_field = Env::$db_prefix . 'subscriber_custom_field';
|
||||
$newsletter_segment = Env::$db_prefix . 'newsletter_segment';
|
||||
$scheduled_tasks = Env::$db_prefix . 'scheduled_tasks';
|
||||
$scheduled_task_subscribers = Env::$db_prefix . 'scheduled_task_subscribers';
|
||||
$sending_queues = Env::$db_prefix . 'sending_queues';
|
||||
$newsletters = Env::$db_prefix . 'newsletters';
|
||||
$newsletter_templates = Env::$db_prefix . 'newsletter_templates';
|
||||
@ -86,6 +92,8 @@ class Database {
|
||||
define('MP_SUBSCRIBERS_TABLE', $subscribers);
|
||||
define('MP_SUBSCRIBER_SEGMENT_TABLE', $subscriber_segment);
|
||||
define('MP_SUBSCRIBER_CUSTOM_FIELD_TABLE', $subscriber_custom_field);
|
||||
define('MP_SCHEDULED_TASKS_TABLE', $scheduled_tasks);
|
||||
define('MP_SCHEDULED_TASK_SUBSCRIBERS_TABLE', $scheduled_task_subscribers);
|
||||
define('MP_SENDING_QUEUES_TABLE', $sending_queues);
|
||||
define('MP_NEWSLETTERS_TABLE', $newsletters);
|
||||
define('MP_NEWSLETTER_TEMPLATES_TABLE', $newsletter_templates);
|
||||
|
@ -13,6 +13,8 @@ require_once(ABSPATH . 'wp-admin/includes/plugin.php');
|
||||
|
||||
class Initializer {
|
||||
|
||||
const UNABLE_TO_CONNECT = '<strong>Mailpoet:</strong> Unable to connect to the database (the database is unable to open a file or folder), the connection is likely not configured correctly. Please read our <a href="http://beta.docs.mailpoet.com/article/200-solving-database-connection-issues">Knowledge Base article</a> for steps how to resolve it.';
|
||||
|
||||
protected $plugin_initialized = false;
|
||||
|
||||
function __construct($params = array(
|
||||
@ -31,7 +33,11 @@ class Initializer {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->setupDB();
|
||||
try {
|
||||
$this->setupDB();
|
||||
} catch(\Exception $e) {
|
||||
return WPNotice::displayWarning(self::UNABLE_TO_CONNECT);
|
||||
}
|
||||
|
||||
// activation function
|
||||
register_activation_hook(
|
||||
@ -193,8 +199,16 @@ class Initializer {
|
||||
}
|
||||
|
||||
function setupHooks() {
|
||||
$hooks = new Hooks();
|
||||
$hooks->init();
|
||||
if(!$this->plugin_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$hooks = new Hooks();
|
||||
$hooks->init();
|
||||
} catch(\Exception $e) {
|
||||
$this->handleFailedInitialization($e);
|
||||
}
|
||||
}
|
||||
|
||||
function setupJSONAPI() {
|
||||
@ -223,7 +237,11 @@ class Initializer {
|
||||
$conflict_resolver->init();
|
||||
}
|
||||
|
||||
function handleFailedInitialization($message) {
|
||||
return WPNotice::displayError($message);
|
||||
function handleFailedInitialization($exception) {
|
||||
// Check if we are able to add pages at this point
|
||||
if(function_exists('wp_get_current_user')) {
|
||||
Menu::addErrorPage();
|
||||
}
|
||||
return WPNotice::displayError($exception);
|
||||
}
|
||||
}
|