Compare commits
395 Commits
Author | SHA1 | Date | |
---|---|---|---|
6088497433 | |||
57f0b88299 | |||
f874ffc19c | |||
d11badf3ce | |||
3006c982cb | |||
b29e31fdd6 | |||
bc42c8e280 | |||
409697ee64 | |||
cfb4265971 | |||
13d78aac05 | |||
6f176f4e6c | |||
9b584296a5 | |||
5ea87c5eed | |||
7522084ccb | |||
214aa60d0e | |||
7a049ce1b7 | |||
94d293deb7 | |||
bd2d38d757 | |||
abec524daa | |||
cac6beb4ac | |||
cac995e15b | |||
b26380fd10 | |||
6c6a4070be | |||
8b001d820b | |||
2ae3d8ebdf | |||
459ec21f9d | |||
9c7790d07e | |||
f9c5b99e46 | |||
95b0b39366 | |||
4b6fa0e760 | |||
67a3440ced | |||
0de372344a | |||
7a04eeb650 | |||
8dbfe82922 | |||
7322f2151c | |||
c43d2f240d | |||
bbcd267b6f | |||
bbc4acb2a4 | |||
c89cc5a919 | |||
33075940de | |||
51c09b8360 | |||
2fbf85f371 | |||
24cb614adb | |||
55f851208b | |||
990dac7727 | |||
233020ca20 | |||
0c419cde16 | |||
35f9530d8e | |||
992fe2a6e9 | |||
c2cb88f995 | |||
ba69d659ab | |||
397d988eb1 | |||
d85f2341ec | |||
2b3c288b5f | |||
8ec28a23a7 | |||
12c9623e2f | |||
8ba9fdccbc | |||
a2ef62302f | |||
24ecc879d3 | |||
a1104a7f90 | |||
aa959810e9 | |||
45b7a79277 | |||
41c8c0dae5 | |||
2aeab7aaff | |||
4fd0c4b484 | |||
d4623cf763 | |||
181c4fed08 | |||
7884dd8389 | |||
b577d33414 | |||
70de0a01bf | |||
3b7f77d9af | |||
21847ca875 | |||
6153316047 | |||
32f8f07602 | |||
70a04d9bf6 | |||
bb1cc997cc | |||
24f96d9d7d | |||
46c7332da2 | |||
2f42f643ab | |||
63c87f3746 | |||
d4d575cda4 | |||
2cf03ec0a3 | |||
72ad98a77f | |||
b5094f568c | |||
7d224274fc | |||
f3b9f7be92 | |||
6e74f82ace | |||
831eb6af44 | |||
1e8e5aecee | |||
c0f98c9ba6 | |||
746c19d6ed | |||
894a9e8c90 | |||
8fea917337 | |||
c60425afb2 | |||
0776e9ad73 | |||
91981cc324 | |||
1906fafacb | |||
c11d95b402 | |||
b4c8fe6f45 | |||
d0e770e0fc | |||
3d6d1a4282 | |||
dc3b47db00 | |||
900d6694e2 | |||
e8074a61a5 | |||
64501a914a | |||
de70e855ad | |||
03e3b5a94b | |||
3331bed31c | |||
8c5a33a0fe | |||
01eb6c7a98 | |||
f502e0b677 | |||
a6b64a1c5d | |||
5019131b21 | |||
da483fb88f | |||
788bed4622 | |||
3fbe5423d0 | |||
8357295be2 | |||
8072b162d4 | |||
3f2f0ec1a9 | |||
5a5a777b7d | |||
6cac7f3652 | |||
6a9313107c | |||
72c9d301b7 | |||
ad925de801 | |||
1da28b7299 | |||
e837ad7014 | |||
daec56191f | |||
7bd25660df | |||
3b9821fbe1 | |||
cabe2d61b7 | |||
a6d802e2fa | |||
1732c4f634 | |||
bb77134224 | |||
f1cb64b240 | |||
3689545589 | |||
9b67c56281 | |||
dc38b19667 | |||
a574733217 | |||
b90aaa629e | |||
8de186c0e6 | |||
e3719967f9 | |||
138a631ed7 | |||
07b7636a72 | |||
a63ce3cdac | |||
f5c7bb87af | |||
2c8d925971 | |||
0c5beb2511 | |||
9c0316a87d | |||
46c1b682fa | |||
7954346a3f | |||
d87ff67f50 | |||
6642bb3bfa | |||
2cb32e7a78 | |||
fcea9adbd9 | |||
bbdd0dbb6e | |||
1b2cf7bd16 | |||
b7cfa549d5 | |||
ffc1d0a61c | |||
d1b160def7 | |||
493fd01754 | |||
9ced4b1757 | |||
17010e5ba9 | |||
42ad7584d4 | |||
dbc0f9b238 | |||
e62e9a5892 | |||
bc25fa61b4 | |||
2590967183 | |||
86eafd3c17 | |||
90a6f160c2 | |||
c774aec6a2 | |||
8f2fd1d76e | |||
4df11163a1 | |||
82a736ffbb | |||
87052986e8 | |||
0c73c0fadc | |||
5c7e11076d | |||
d1df94c759 | |||
53cc39c6f5 | |||
4955c72ee1 | |||
16661af8c3 | |||
bc80f69e41 | |||
0192934e65 | |||
2793e74858 | |||
5996696cc9 | |||
7f6cf5bbf3 | |||
c0ef2254cd | |||
0dbe04c3f8 | |||
ef1805d9b5 | |||
514f539e83 | |||
50f072705e | |||
f8f7bc3d3d | |||
f1bf2bb097 | |||
bbe2f69a7f | |||
c844488b0b | |||
112fe0cd6e | |||
c9e6dce785 | |||
d1c09c015a | |||
8d61866b77 | |||
0831c748b1 | |||
b2a0bc3860 | |||
1f99345e7b | |||
89782bc94b | |||
155ff09280 | |||
132e6d3342 | |||
f02699158f | |||
be3462925d | |||
3d82230d10 | |||
c20c46fd86 | |||
6e63c72aa5 | |||
e059eec5ea | |||
a2d38c9076 | |||
8d507b2ee0 | |||
5e2979c283 | |||
84ec0de3cd | |||
ee07780833 | |||
ed104156a9 | |||
90f2e9ff9d | |||
98fb7aa65e | |||
a51eb59cf8 | |||
270023b89c | |||
7d77e075e9 | |||
9bbe36b3cb | |||
7a904ed093 | |||
e3c065b353 | |||
4ca2872e0e | |||
ce338f7fe2 | |||
fa28b0a955 | |||
a298650187 | |||
95772ef68a | |||
e1c94db516 | |||
7be1a11d1e | |||
c04b95c09a | |||
cdfeb8d512 | |||
3ef8067968 | |||
9fb04bc3c0 | |||
25727ea0ba | |||
4c8ac369b7 | |||
268dabdc9f | |||
c0ba218949 | |||
ee85139089 | |||
b4f83fe1bd | |||
bd83001ef5 | |||
fb3a9f485f | |||
fd44776ae9 | |||
6dbe338b01 | |||
1f06a7dd0b | |||
37c218f782 | |||
25016f2a8d | |||
792744a270 | |||
c5fbfca132 | |||
c2fde308cb | |||
533d9b0d38 | |||
2035b802e3 | |||
a5e66ec6a0 | |||
beb939df9e | |||
44e342c692 | |||
3a417d460f | |||
1950d6661f | |||
da6e154642 | |||
acebf669a7 | |||
4a2bbe3f88 | |||
9b011c0281 | |||
bf58d8a22d | |||
72d1eb79a6 | |||
bb4893c0a0 | |||
9929cf0aee | |||
83967e84ba | |||
9621cb3ca9 | |||
a413f666fe | |||
d1e2c6c074 | |||
3b6a9f7a6e | |||
d2e5fb89c2 | |||
97d1e95037 | |||
48fbce22e7 | |||
916fe76795 | |||
e10310fb5c | |||
367afcf814 | |||
67fa9e0993 | |||
d7553a5f27 | |||
8c847825fa | |||
d21d9b99b0 | |||
8461c13532 | |||
3b7ffe9ba7 | |||
1724fa22c1 | |||
01089d7a72 | |||
717ebfd20c | |||
daff3d5016 | |||
98fb838169 | |||
f13a4dd4f3 | |||
62a164e4c6 | |||
04238f3339 | |||
bc62474f3c | |||
98005a2a6f | |||
b7fe8dc6d6 | |||
436faea591 | |||
4208b148b4 | |||
5ce5f0bf8a | |||
18518de397 | |||
68f747211a | |||
ebd26ddd98 | |||
924aa0439f | |||
3124d6a61b | |||
149d031b52 | |||
fa96c4697d | |||
d46c9d5412 | |||
9ab8b1f0c5 | |||
9425ac1593 | |||
4e32479609 | |||
7d95b38dc4 | |||
17c83c5bd4 | |||
23bb2f111f | |||
4655b2c64c | |||
84fede11b8 | |||
f37488fc0b | |||
20e2e03982 | |||
a5d96f1534 | |||
a516eb1a95 | |||
6dd8270bec | |||
981cbd579f | |||
52a0aae10f | |||
ebca4257a6 | |||
c3944095bc | |||
a1445d1b6a | |||
e62c24879b | |||
00f06ea202 | |||
32ca24ce38 | |||
44e3adb422 | |||
a1346ebecc | |||
25b51d0446 | |||
556a170903 | |||
7ac386a8e2 | |||
d91b55ec52 | |||
786fbc36a2 | |||
160e8b7a12 | |||
0b1f85da09 | |||
fbc6f54ddc | |||
a603e97b8c | |||
0875b627b6 | |||
035784ece0 | |||
aa93c7349f | |||
82cf4a28fd | |||
832e5ef342 | |||
e3de3a123a | |||
db91590159 | |||
28c61fca0b | |||
e62a8c2ec5 | |||
fdbd1245e3 | |||
0eef46db57 | |||
080ae88a04 | |||
225be9f3cd | |||
c9a42ebb76 | |||
ae9b3df92d | |||
63a08ebb55 | |||
2ef5096fa9 | |||
95cfe2d8ec | |||
49676b3fc5 | |||
c96ac06423 | |||
6a3166c311 | |||
0017df1c2d | |||
f2a0d4ce96 | |||
cb50517cbc | |||
0fedd1779f | |||
1625e1771b | |||
bde78b607b | |||
f3c58c27be | |||
9fec460295 | |||
162859529e | |||
3bdaaf8368 | |||
f6ab0050b2 | |||
10a20935c3 | |||
8135b677f7 | |||
90382bc86d | |||
47af8939cc | |||
4a0deb2182 | |||
3a206b2c88 | |||
70cfcbe7cc | |||
6342cb17bd | |||
64c35b12c8 | |||
6a14f97419 | |||
dfec34eda9 | |||
893231e8e5 | |||
e9110680ee | |||
7b54285ca6 | |||
33ea16eb0f | |||
b1ae07d38e | |||
3f168d052f | |||
158d26ef86 | |||
ae03ee2c46 | |||
ad0adb48e1 | |||
ff5353c894 | |||
abb2389378 | |||
3cf50810f9 | |||
20a6e6d6de | |||
0b1fc8f6c3 | |||
0a771acb02 |
16
.env.sample
@ -1,2 +1,16 @@
|
|||||||
WP_TEST_PATH="/var/www/wordpress"
|
WP_TEST_PATH="/var/www/wordpress"
|
||||||
|
WP_TEST_ENABLE_NETWORK_TESTS="true"
|
||||||
|
WP_TEST_IMPORT_MAILCHIMP_API=""
|
||||||
|
WP_TEST_IMPORT_MAILCHIMP_LISTS="" // (separated with comma)
|
||||||
|
WP_TEST_MAILER_ENABLE_SENDING="true"
|
||||||
|
WP_TEST_MAILER_AMAZON_ACCESS=""
|
||||||
|
WP_TEST_MAILER_AMAZON_SECRET=""
|
||||||
|
WP_TEST_MAILER_AMAZON_REGION=""
|
||||||
|
WP_TEST_MAILER_ELASTICEMAIL_API=""
|
||||||
|
WP_TEST_MAILER_MAILGUN_API=""
|
||||||
|
WP_TEST_MAILER_MAILGUN_DOMAIN=""
|
||||||
|
WP_TEST_MAILER_MAILPOET_API=""
|
||||||
|
WP_TEST_MAILER_SENDGRID_API=""
|
||||||
|
WP_TEST_MAILER_SMTP_HOST=""
|
||||||
|
WP_TEST_MAILER_SMTP_LOGIN=""
|
||||||
|
WP_TEST_MAILER_SMTP_PASSWORD=""
|
5
.gitignore
vendored
@ -1,7 +1,7 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
TODO
|
TODO
|
||||||
composer.phar
|
composer.phar
|
||||||
vendor
|
/vendor
|
||||||
tests/_output/*
|
tests/_output/*
|
||||||
tests/acceptance.suite.yml
|
tests/acceptance.suite.yml
|
||||||
tests/_support/_generated/*
|
tests/_support/_generated/*
|
||||||
@ -15,4 +15,5 @@ temp
|
|||||||
wysija-newsletters.zip
|
wysija-newsletters.zip
|
||||||
tests/javascript/testBundles
|
tests/javascript/testBundles
|
||||||
assets/css/*.css
|
assets/css/*.css
|
||||||
assets/js/*.js
|
assets/js/*.js
|
||||||
|
.vagrant
|
||||||
|
11
README.md
@ -8,7 +8,6 @@ MailPoet done the right way.
|
|||||||
```
|
```
|
||||||
php
|
php
|
||||||
nodejs
|
nodejs
|
||||||
phantomjs
|
|
||||||
wordpress
|
wordpress
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -47,16 +46,6 @@ $ ./do compile:all
|
|||||||
$ ./do test:unit
|
$ ./do test:unit
|
||||||
```
|
```
|
||||||
|
|
||||||
- Acceptance tests:
|
|
||||||
```sh
|
|
||||||
$ ./do test:acceptance
|
|
||||||
```
|
|
||||||
|
|
||||||
- Run all tests:
|
|
||||||
```sh
|
|
||||||
$ ./do test:all
|
|
||||||
```
|
|
||||||
|
|
||||||
- Debug tests:
|
- Debug tests:
|
||||||
```sh
|
```sh
|
||||||
$ ./do test:debug
|
$ ./do test:debug
|
||||||
|
29
RoboFile.php
@ -47,6 +47,19 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
->run();
|
->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function watchCss() {
|
||||||
|
$css_files = $this->rsearch('assets/css/src/', array('styl'));
|
||||||
|
$this->taskWatch()
|
||||||
|
->monitor($css_files, function() {
|
||||||
|
$this->compileCss();
|
||||||
|
})
|
||||||
|
->run();
|
||||||
|
}
|
||||||
|
|
||||||
|
function watchJs() {
|
||||||
|
$this->_exec('./node_modules/webpack/bin/webpack.js --watch');
|
||||||
|
}
|
||||||
|
|
||||||
function compileAll() {
|
function compileAll() {
|
||||||
$this->compileJs();
|
$this->compileJs();
|
||||||
$this->compileCss();
|
$this->compileCss();
|
||||||
@ -61,7 +74,8 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
'assets/css/src/admin.styl',
|
'assets/css/src/admin.styl',
|
||||||
'assets/css/src/newsletter_editor/newsletter_editor.styl',
|
'assets/css/src/newsletter_editor/newsletter_editor.styl',
|
||||||
'assets/css/src/public.styl',
|
'assets/css/src/public.styl',
|
||||||
'assets/css/src/rtl.styl'
|
'assets/css/src/rtl.styl',
|
||||||
|
'assets/css/src/importExport.styl'
|
||||||
);
|
);
|
||||||
|
|
||||||
$this->_exec(join(' ', array(
|
$this->_exec(join(' ', array(
|
||||||
@ -94,6 +108,17 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
$this->_exec('vendor/bin/codecept run unit -f '.(($file) ? $file : ''));
|
$this->_exec('vendor/bin/codecept run unit -f '.(($file) ? $file : ''));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function testCoverage($file = null) {
|
||||||
|
$this->loadEnv();
|
||||||
|
$this->_exec('vendor/bin/codecept build');
|
||||||
|
$this->_exec(join(' ', array(
|
||||||
|
'vendor/bin/codecept run',
|
||||||
|
(($file) ? $file : ''),
|
||||||
|
'--coverage',
|
||||||
|
'--coverage-html'
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
function testJavascript() {
|
function testJavascript() {
|
||||||
$this->compileJs();
|
$this->compileJs();
|
||||||
|
|
||||||
@ -120,4 +145,4 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
$dotenv = new Dotenv\Dotenv(__DIR__);
|
$dotenv = new Dotenv\Dotenv(__DIR__);
|
||||||
$dotenv->load();
|
$dotenv->load();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,12 +5,15 @@
|
|||||||
@require 'common'
|
@require 'common'
|
||||||
@require 'modal'
|
@require 'modal'
|
||||||
@require 'notice'
|
@require 'notice'
|
||||||
@require 'parsley'
|
|
||||||
|
|
||||||
@require 'form_editor'
|
@require 'form_editor'
|
||||||
@require 'listing'
|
@require 'listing'
|
||||||
@require 'box'
|
@require 'box'
|
||||||
@require 'breadcrumb'
|
@require 'breadcrumb'
|
||||||
@require 'form'
|
|
||||||
|
|
||||||
@require 'settings'
|
@require 'form'
|
||||||
|
@require 'parsley'
|
||||||
|
@require 'form_validation'
|
||||||
|
|
||||||
|
@require 'settings'
|
||||||
|
@require 'progress_bar'
|
||||||
|
@ -19,6 +19,8 @@ a:focus
|
|||||||
|
|
||||||
// select 2
|
// select 2
|
||||||
.select2-container
|
.select2-container
|
||||||
|
width: 25em !important
|
||||||
|
|
||||||
// textareas
|
// textareas
|
||||||
textarea.regular-text
|
textarea.regular-text
|
||||||
width: 25em !important
|
width: 25em !important
|
||||||
@ -26,3 +28,25 @@ textarea.regular-text
|
|||||||
@media screen and (max-width: 782px)
|
@media screen and (max-width: 782px)
|
||||||
.select2-container
|
.select2-container
|
||||||
width: 100% !important
|
width: 100% !important
|
||||||
|
|
||||||
|
// progress bars
|
||||||
|
progress-border-radius = 5px
|
||||||
|
progress-background = #efefef
|
||||||
|
progress-foreground = #69b1e9
|
||||||
|
|
||||||
|
progress
|
||||||
|
background-color: progress-background;
|
||||||
|
height: 2em
|
||||||
|
border: 0
|
||||||
|
width: 100%
|
||||||
|
|
||||||
|
progress::-webkit-progress-bar
|
||||||
|
background-color: progress-background;
|
||||||
|
|
||||||
|
progress::-webkit-progress-value
|
||||||
|
background-color: progress-foreground
|
||||||
|
border-radius: progress-border-radius
|
||||||
|
|
||||||
|
progress::-moz-progress-bar
|
||||||
|
background-color: progress-foreground
|
||||||
|
border-radius: progress-border-radius
|
||||||
|
@ -4,6 +4,9 @@
|
|||||||
icons = '../img/form_editor_icons.png'
|
icons = '../img/form_editor_icons.png'
|
||||||
handle_icon = '../img/handle.png'
|
handle_icon = '../img/handle.png'
|
||||||
|
|
||||||
|
#mailpoet_form_name
|
||||||
|
font-size: 23px
|
||||||
|
|
||||||
#mailpoet_form_history
|
#mailpoet_form_history
|
||||||
display: none
|
display: none
|
||||||
|
|
||||||
@ -99,6 +102,7 @@ handle_icon = '../img/handle.png'
|
|||||||
/* MailPoet Form wrapper */
|
/* MailPoet Form wrapper */
|
||||||
#mailpoet_form_wrapper
|
#mailpoet_form_wrapper
|
||||||
position: relative
|
position: relative
|
||||||
|
margin: 20px 0 0 0
|
||||||
|
|
||||||
/* MailPoet Form container */
|
/* MailPoet Form container */
|
||||||
#mailpoet_form_container
|
#mailpoet_form_container
|
||||||
@ -121,6 +125,7 @@ handle_icon = '../img/handle.png'
|
|||||||
float: none
|
float: none
|
||||||
|
|
||||||
#mailpoet_form_toolbar
|
#mailpoet_form_toolbar
|
||||||
|
z-index: 999
|
||||||
position: absolute
|
position: absolute
|
||||||
width: 400px
|
width: 400px
|
||||||
|
|
||||||
|
6
assets/css/src/form_validation.styl
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
.parsley-errors-list
|
||||||
|
margin-top: 8px
|
||||||
|
|
||||||
|
.parsley-required
|
||||||
|
.parsley-custom-error-message
|
||||||
|
color: #b94a48
|
78
assets/css/src/importExport.styl
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
.mailpoet_hidden, .mailpoet_validation_error
|
||||||
|
display none
|
||||||
|
|
||||||
|
.form-table
|
||||||
|
th
|
||||||
|
width 300px
|
||||||
|
|
||||||
|
#paste_input
|
||||||
|
width 100%
|
||||||
|
|
||||||
|
input[type="radio"]
|
||||||
|
margin-right 0.5em !important
|
||||||
|
& + span
|
||||||
|
margin-right 2.5em
|
||||||
|
|
||||||
|
span
|
||||||
|
&.mailpoet_mailchimp-key-status
|
||||||
|
&.mailpoet_mailchimp-ok
|
||||||
|
&:before
|
||||||
|
content "\2713"
|
||||||
|
color #0e90d2
|
||||||
|
margin-left 15px
|
||||||
|
&.mailpoet_mailchimp-error
|
||||||
|
&:before
|
||||||
|
content "\2717"
|
||||||
|
color #900
|
||||||
|
margin-left 15px
|
||||||
|
|
||||||
|
#subscribers_data
|
||||||
|
overflow auto
|
||||||
|
table
|
||||||
|
width auto
|
||||||
|
td
|
||||||
|
padding 0.5em
|
||||||
|
& > table
|
||||||
|
& > tbody
|
||||||
|
& > td
|
||||||
|
padding 0.5em
|
||||||
|
& > tr
|
||||||
|
&:nth-child(odd)
|
||||||
|
background #f9f9f9
|
||||||
|
.mailpoet_header
|
||||||
|
text-transform uppercase
|
||||||
|
font-weight 600
|
||||||
|
text-decoration underline
|
||||||
|
|
||||||
|
#subscribers_data th:first-child, #subscribers_data td:first-child
|
||||||
|
width 10em !important
|
||||||
|
text-align center !important
|
||||||
|
padding 0 1em 0 1em !important
|
||||||
|
vertical-align inherit !important
|
||||||
|
|
||||||
|
#subscribers_data
|
||||||
|
& > table
|
||||||
|
& > thead
|
||||||
|
& > tr
|
||||||
|
& > th
|
||||||
|
& > span
|
||||||
|
width 15em !important
|
||||||
|
|
||||||
|
.mailpoet_data_match
|
||||||
|
color #0e90d2
|
||||||
|
margin-left 0.25em
|
||||||
|
|
||||||
|
.mailpoet_import_error, .mailpoet_validation_error
|
||||||
|
color #900
|
||||||
|
|
||||||
|
tr
|
||||||
|
&.mailpoet_segments
|
||||||
|
& > td
|
||||||
|
& > a
|
||||||
|
margin-left 15px
|
||||||
|
|
||||||
|
span
|
||||||
|
&.select2-search
|
||||||
|
&.select2-search--dropdown
|
||||||
|
display none !important
|
||||||
|
|
@ -90,7 +90,7 @@ body.mailpoet_modal_opened
|
|||||||
padding: 0
|
padding: 0
|
||||||
margin: 0
|
margin: 0
|
||||||
width: 100%
|
width: 100%
|
||||||
transition: margin 0.3s ease-out
|
transition: margin 350ms ease-out
|
||||||
|
|
||||||
.mailpoet_panel_wrapper
|
.mailpoet_panel_wrapper
|
||||||
background-color: #f1f1f1
|
background-color: #f1f1f1
|
||||||
@ -159,23 +159,6 @@ body.mailpoet_modal_opened
|
|||||||
margin: 0
|
margin: 0
|
||||||
text-align: right
|
text-align: right
|
||||||
|
|
||||||
.mailpoet_button
|
|
||||||
padding: 3px 15px
|
|
||||||
border: 1px solid #444
|
|
||||||
font-weight: normal
|
|
||||||
cursor: pointer
|
|
||||||
background-color: #222
|
|
||||||
color: #cfcfcf
|
|
||||||
font-size: 1em
|
|
||||||
|
|
||||||
.mailpoet_button:hover
|
|
||||||
background-color: #00aacc
|
|
||||||
color: #fff
|
|
||||||
|
|
||||||
.mailpoet_button:active
|
|
||||||
background-color: #00ccff
|
|
||||||
color: #fff
|
|
||||||
|
|
||||||
@media screen and (max-width: 782px)
|
@media screen and (max-width: 782px)
|
||||||
#mailpoet_modal_overlay.mailpoet_panel_overlay
|
#mailpoet_modal_overlay.mailpoet_panel_overlay
|
||||||
top: 46px
|
top: 46px
|
||||||
@ -217,4 +200,4 @@ body.mailpoet_modal_opened
|
|||||||
0%
|
0%
|
||||||
50%
|
50%
|
||||||
background-color: #064E6D
|
background-color: #064E6D
|
||||||
100%
|
100%
|
||||||
|
@ -7,7 +7,6 @@ $tool-active-secondary-color = #ffffff
|
|||||||
|
|
||||||
$tool-width = 20px
|
$tool-width = 20px
|
||||||
$master-column-tool-width = 24px
|
$master-column-tool-width = 24px
|
||||||
$layer-selector-width = 30px
|
|
||||||
|
|
||||||
.mailpoet_tools
|
.mailpoet_tools
|
||||||
position: absolute
|
position: absolute
|
||||||
@ -33,10 +32,35 @@ $layer-selector-width = 30px
|
|||||||
width: $master-column-tool-width
|
width: $master-column-tool-width
|
||||||
height: $master-column-tool-width
|
height: $master-column-tool-width
|
||||||
|
|
||||||
|
|
||||||
|
.mailpoet_delete_block_activate
|
||||||
|
max-width: 100%
|
||||||
|
max-height: $master-column-tool-width
|
||||||
|
opacity: 1
|
||||||
|
display: block
|
||||||
|
|
||||||
|
.mailpoet_delete_block_confirm,
|
||||||
|
.mailpoet_delete_block_cancel
|
||||||
|
max-width: 100%
|
||||||
|
max-height: 0
|
||||||
|
opacity: 0
|
||||||
|
overflow: hidden
|
||||||
|
display: block
|
||||||
|
|
||||||
.mailpoet_delete_block_activated
|
.mailpoet_delete_block_activated
|
||||||
width: auto
|
width: auto
|
||||||
height: auto
|
height: auto
|
||||||
|
|
||||||
|
.mailpoet_delete_block_activate
|
||||||
|
overflow: hidden
|
||||||
|
max-height: 0
|
||||||
|
opacity: 0
|
||||||
|
|
||||||
|
.mailpoet_delete_block_confirm,
|
||||||
|
.mailpoet_delete_block_cancel
|
||||||
|
max-height: $master-column-tool-width*2
|
||||||
|
opacity: 1
|
||||||
|
|
||||||
.mailpoet_tool
|
.mailpoet_tool
|
||||||
display: inline-block
|
display: inline-block
|
||||||
width: $tool-width
|
width: $tool-width
|
||||||
@ -76,28 +100,45 @@ $layer-selector-width = 30px
|
|||||||
display: inline-block
|
display: inline-block
|
||||||
padding: 2px
|
padding: 2px
|
||||||
vertical-align: top
|
vertical-align: top
|
||||||
|
animation-background-color()
|
||||||
|
|
||||||
.mailpoet_tool
|
.mailpoet_tool
|
||||||
padding: 0
|
padding: 0
|
||||||
|
|
||||||
|
.mailpoet_delete_block_activate
|
||||||
|
max-width: $tool-width
|
||||||
|
display: inline-block
|
||||||
|
opacity: 1
|
||||||
|
animation-fade-in-and-scale-horizontally()
|
||||||
|
|
||||||
.mailpoet_delete_block_confirm,
|
.mailpoet_delete_block_confirm,
|
||||||
.mailpoet_delete_block_cancel
|
.mailpoet_delete_block_cancel
|
||||||
display: none
|
max-width: 0
|
||||||
|
opacity: 0
|
||||||
|
overflow: hidden
|
||||||
|
display: inline-block
|
||||||
|
animation-fade-in-and-scale-horizontally()
|
||||||
|
|
||||||
.mailpoet_delete_block_activated
|
.mailpoet_delete_block_activated
|
||||||
|
height: auto
|
||||||
width: auto
|
width: auto
|
||||||
border-radius(3px)
|
border-radius(3px)
|
||||||
background-color: $warning-background-color
|
background-color: $warning-background-color
|
||||||
padding: 3px 5px
|
padding: 3px 5px
|
||||||
line-height: 1.2em
|
line-height: 1.2em
|
||||||
height: auto
|
|
||||||
|
|
||||||
.mailpoet_delete_block_activate
|
.mailpoet_delete_block_activate
|
||||||
display: none
|
overflow: hidden
|
||||||
|
max-width: 0
|
||||||
|
opacity: 0
|
||||||
|
|
||||||
.mailpoet_delete_block_confirm,
|
.mailpoet_delete_block_confirm,
|
||||||
.mailpoet_delete_block_cancel
|
.mailpoet_delete_block_cancel
|
||||||
display: inline-block
|
max-width: 100%
|
||||||
|
opacity: 1
|
||||||
|
|
||||||
|
.mailpoet_delete_block_cancel
|
||||||
|
margin-left: 3px
|
||||||
|
|
||||||
.mailpoet_delete_block_confirm
|
.mailpoet_delete_block_confirm
|
||||||
color: $warning-text-color
|
color: $warning-text-color
|
||||||
|
@ -52,6 +52,7 @@ $draggable-widget-z-index = 2
|
|||||||
padding: 0
|
padding: 0
|
||||||
margin: 0
|
margin: 0
|
||||||
z-index: $draggable-widget-z-index
|
z-index: $draggable-widget-z-index
|
||||||
|
animation-fade-in()
|
||||||
|
|
||||||
.mailpoet_widget_icon
|
.mailpoet_widget_icon
|
||||||
padding: 0
|
padding: 0
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
.mailpoet_save_as_template_container,
|
.mailpoet_save_as_template_container,
|
||||||
.mailpoet_export_template_container
|
.mailpoet_export_template_container
|
||||||
border-radius(3px)
|
border-radius(3px)
|
||||||
float: left
|
display: inline-block
|
||||||
clear: both
|
clear: both
|
||||||
|
|
||||||
margin-top: 5px
|
margin-top: 5px
|
||||||
|
@ -26,13 +26,9 @@ $widget-icon-width = 30px
|
|||||||
border-right: 0
|
border-right: 0
|
||||||
|
|
||||||
&.closed .mailpoet_region_content
|
&.closed .mailpoet_region_content
|
||||||
max-height: 0px
|
display: none
|
||||||
overflow: hidden
|
|
||||||
margin-top: 0
|
|
||||||
|
|
||||||
.mailpoet_region_content
|
.mailpoet_region_content
|
||||||
max-height: 2000px
|
|
||||||
transition: max-height 0.2s ease
|
|
||||||
padding: 0 20px
|
padding: 0 20px
|
||||||
margin-top: 12px
|
margin-top: 12px
|
||||||
|
|
||||||
|
@ -18,3 +18,6 @@
|
|||||||
|
|
||||||
& > .mailpoet_block
|
& > .mailpoet_block
|
||||||
width: 100%
|
width: 100%
|
||||||
|
|
||||||
|
.mailpoet_automated_latest_content_display_options
|
||||||
|
animation-slide-open-downwards()
|
||||||
|
@ -79,3 +79,4 @@ $three-column-width = ($newsletter-width / 3) - (2 * $column-margin)
|
|||||||
box-shadow(inset 1px 2px 1px $primary-inactive-color)
|
box-shadow(inset 1px 2px 1px $primary-inactive-color)
|
||||||
color: #656565
|
color: #656565
|
||||||
border-radius(3px)
|
border-radius(3px)
|
||||||
|
animation-background-color()
|
||||||
|
@ -19,6 +19,10 @@ $divider-hover-border-color = $primary-active-color
|
|||||||
width: 100%
|
width: 100%
|
||||||
border: 1px solid transparent
|
border: 1px solid transparent
|
||||||
|
|
||||||
|
.mailpoet_active_divider_style
|
||||||
|
border: 1px solid $active-divider-border-color
|
||||||
|
background: $active-divider-background-color
|
||||||
|
|
||||||
.mailpoet_field_divider_style:hover
|
.mailpoet_field_divider_style:hover
|
||||||
border: 1px solid $divider-hover-border-color
|
border: 1px solid $divider-hover-border-color
|
||||||
|
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
.mailpoet_image_block
|
.mailpoet_image_block
|
||||||
|
|
||||||
|
img
|
||||||
|
vertical-align: bottom
|
||||||
|
max-width: 100%
|
||||||
|
width: auto
|
||||||
|
height: auto
|
||||||
|
|
||||||
&.mailpoet_full_image
|
&.mailpoet_full_image
|
||||||
padding-left: 0
|
padding-left: 0
|
||||||
padding-right: 0
|
padding-right: 0
|
||||||
margin-bottom: 0
|
margin-bottom: 0
|
||||||
|
|
||||||
|
img
|
||||||
|
width: 100%
|
||||||
|
|
||||||
.mailpoet_content a:hover
|
.mailpoet_content a:hover
|
||||||
cursor: all-scroll
|
cursor: all-scroll
|
||||||
|
|
||||||
img
|
|
||||||
vertical-align: bottom
|
|
||||||
max-width: $newsletter-width
|
|
||||||
width: 100%
|
|
||||||
height: auto
|
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
.mailpoet_posts_block
|
.mailpoet_posts_block
|
||||||
box-shadow(none)
|
padding-left: 0
|
||||||
|
padding-right: 0
|
||||||
|
|
||||||
& > .mailpoet_content
|
.mailpoet_posts_block_posts
|
||||||
font-size: 1em
|
overflow: auto
|
||||||
text-align: center
|
|
||||||
background-color: $primary-active-color
|
& > .mailpoet_block
|
||||||
margin: 20px 0
|
width: 100%
|
||||||
padding: 15px
|
|
||||||
box-shadow(inset 1px 2px 1px $primary-inset-shadow-color)
|
|
||||||
color: $white-color
|
|
||||||
border-radius(3px)
|
|
||||||
|
|
||||||
.mailpoet_post_selection_filter_row
|
.mailpoet_post_selection_filter_row
|
||||||
margin-top: 5px
|
margin-top: 5px
|
||||||
@ -18,7 +15,11 @@
|
|||||||
.mailpoet_posts_categories_and_tags
|
.mailpoet_posts_categories_and_tags
|
||||||
width: 100%
|
width: 100%
|
||||||
|
|
||||||
.mailpoet_settings_posts_show_display_options
|
.mailpoet_settings_posts_display_options
|
||||||
|
.mailpoet_settings_posts_selection
|
||||||
|
animation-slide-open-downwards()
|
||||||
|
|
||||||
|
.mailpoet_settings_posts_show_display_options,
|
||||||
.mailpoet_settings_posts_show_post_selection
|
.mailpoet_settings_posts_show_post_selection
|
||||||
display: block
|
display: block
|
||||||
margin-top: 10px
|
margin-top: 10px
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* Fix select2 z-index to work with MailPoet.Modal */
|
/* Fix select2 z-index to work with MailPoet.Modal */
|
||||||
.select2-dropdown
|
.select2-dropdown
|
||||||
z-index: 101000
|
z-index: 101000 !important
|
||||||
|
|
||||||
/* Remove input field styles from select2 type input */
|
/* Remove input field styles from select2 type input */
|
||||||
.select2-container
|
.select2-container
|
||||||
@ -129,3 +129,7 @@ body
|
|||||||
|
|
||||||
#mailpoet_modal_close
|
#mailpoet_modal_close
|
||||||
display: none
|
display: none
|
||||||
|
|
||||||
|
.wrap > .mailpoet_notice,
|
||||||
|
.update-nag
|
||||||
|
margin-left: 2px + 15px !important
|
||||||
|
31
assets/css/src/newsletter_editor/mixins/transitions.styl
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
animation-slide-open-downwards()
|
||||||
|
transition: all 250ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
||||||
|
max-height: 2000px
|
||||||
|
opacity: 1
|
||||||
|
|
||||||
|
&.mailpoet_closed
|
||||||
|
max-height: 0
|
||||||
|
opacity: 0
|
||||||
|
overflow-y: hidden
|
||||||
|
|
||||||
|
animation-background-color()
|
||||||
|
transition: background 250ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
||||||
|
|
||||||
|
animation-fade-in()
|
||||||
|
animation-name: fadeIn
|
||||||
|
animation-duration: 300ms
|
||||||
|
animation-fill-mode: forwards
|
||||||
|
animation-timing-function: ease-in
|
||||||
|
|
||||||
|
animation-fade-in-and-scale-horizontally()
|
||||||
|
transition: all 250ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
0% {
|
||||||
|
opacity: 0.3
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 1
|
||||||
|
}
|
||||||
|
}
|
@ -6,6 +6,7 @@
|
|||||||
@require 'mixins/border-radius'
|
@require 'mixins/border-radius'
|
||||||
@require 'mixins/box-shadow'
|
@require 'mixins/box-shadow'
|
||||||
@require 'mixins/filter-shadow'
|
@require 'mixins/filter-shadow'
|
||||||
|
@require 'mixins/transitions'
|
||||||
|
|
||||||
@require 'variables'
|
@require 'variables'
|
||||||
@require 'common'
|
@require 'common'
|
||||||
|
29
assets/css/src/progress_bar.styl
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
.mailpoet_progress
|
||||||
|
background-color: #efefef
|
||||||
|
height: 25px
|
||||||
|
padding: 0
|
||||||
|
width: 100%
|
||||||
|
margin: 0
|
||||||
|
border-radius: 5px
|
||||||
|
position: relative
|
||||||
|
|
||||||
|
.mailpoet_progress_label
|
||||||
|
position: absolute
|
||||||
|
width: 100%
|
||||||
|
text-align: center
|
||||||
|
display: inline-block
|
||||||
|
margin: 2px 0 0 0
|
||||||
|
|
||||||
|
.mailpoet_progress_bar
|
||||||
|
position: absolute
|
||||||
|
display: inline-block
|
||||||
|
height: 100%
|
||||||
|
border-radius: 3px
|
||||||
|
box-shadow: 0 1px 0 rgba(255, 255, 255, .5) inset
|
||||||
|
background-color: #34c2e3
|
||||||
|
background-image: linear-gradient(top, #34c2e3, darken(#34c2e3, 20%))
|
||||||
|
|
||||||
|
.mailpoet_progress_complete
|
||||||
|
.mailpoet_progress_bar
|
||||||
|
background-color: #fecf23
|
||||||
|
background-image: linear-gradient(top, #fecf23, #fd9215)
|
@ -1,3 +1,4 @@
|
|||||||
@import 'nib'
|
@import 'nib'
|
||||||
|
|
||||||
@require 'parsley'
|
@require 'parsley'
|
||||||
|
@require 'form_validation'
|
||||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
BIN
assets/img/post_notifications_template/ALC-widget-icon.png
Executable file
After Width: | Height: | Size: 3.9 KiB |
BIN
assets/img/post_notifications_template/settings-icon-highlight.png
Executable file
After Width: | Height: | Size: 7.2 KiB |
12
assets/img/preview_magnifying_glass.svg
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 16.0.4, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
width="47.002px" height="38.003px" viewBox="0 0 47.002 38.003" enable-background="new 0 0 47.002 38.003" xml:space="preserve">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" fill="#565656" d="M46.328,36.365c-1.188,1.725-3.553,2.158-5.273,0.962L25.479,26.52
|
||||||
|
c-1.104-0.763-1.674-2.007-1.631-3.257c-2.006,2.157-4.642,3.606-7.594,4.145c-3.626,0.663-7.288-0.13-10.311-2.227
|
||||||
|
c-3.024-2.098-5.054-5.253-5.714-8.887c-0.661-3.636,0.127-7.31,2.221-10.344c4.325-6.264,12.927-7.834,19.177-3.5
|
||||||
|
c5.672,3.938,7.486,11.412,4.537,17.443c1.152-0.486,2.519-0.392,3.627,0.377l15.58,10.808C47.09,32.274,47.52,34.641,46.328,36.365
|
||||||
|
z M23.235,12.09c-0.459-2.534-1.874-4.734-3.982-6.196C14.897,2.87,8.896,3.963,5.878,8.331c-3.014,4.373-1.922,10.388,2.435,13.408
|
||||||
|
c4.356,3.025,10.356,1.932,13.374-2.438C23.146,17.187,23.696,14.625,23.235,12.09z"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
BIN
assets/img/sample_template/coffee-grain.jpg
Normal file
After Width: | Height: | Size: 178 KiB |
BIN
assets/img/sample_template/header-v2.jpg
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
assets/img/sample_template/map-v2.jpg
Normal file
After Width: | Height: | Size: 130 KiB |
BIN
assets/img/sample_template/sandwich.jpg
Normal file
After Width: | Height: | Size: 63 KiB |
BIN
assets/img/welcome_template/logo-header.gif
Executable file
After Width: | Height: | Size: 4.8 KiB |
8
assets/js/lib/analytics.js
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
(function(e,b){if(!b.__SV){var a,f,i,g;window.mixpanel=b;b._i=[];b.init=function(a,e,d){function f(b,h){var a=h.split(".");2==a.length&&(b=b[a[0]],h=a[1]);b[h]=function(){b.push([h].concat(Array.prototype.slice.call(arguments,0)))}}var c=b;"undefined"!==typeof d?c=b[d]=[]:d="mixpanel";c.people=c.people||[];c.toString=function(b){var a="mixpanel";"mixpanel"!==d&&(a+="."+d);b||(a+=" (stub)");return a};c.people.toString=function(){return c.toString(1)+".people (stub)"};i="disable time_event track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.set_once people.increment people.append people.union people.track_charge people.clear_charges people.delete_user".split(" ");
|
||||||
|
for(g=0;g<i.length;g++)f(c,i[g]);b._i.push([a,e,d])};b.__SV=1.2;a=e.createElement("script");a.type="text/javascript";a.async=!0;a.src="undefined"!==typeof MIXPANEL_CUSTOM_LIB_URL?MIXPANEL_CUSTOM_LIB_URL:"file:"===e.location.protocol&&"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js".match(/^\/\//)?"https://cdn.mxpnl.com/libs/mixpanel-2-latest.min.js":"//cdn.mxpnl.com/libs/mixpanel-2-latest.min.js";f=e.getElementsByTagName("script")[0];f.parentNode.insertBefore(a,f)}})(document,window.mixpanel||[]);
|
||||||
|
|
||||||
|
mixpanel.init("f683d388fb25fcf331f1b2b5c4449798");
|
||||||
|
|
||||||
|
if (typeof mailpoet_analytics_data === 'object') {
|
||||||
|
mixpanel.track('Wysija Usage', mailpoet_analytics_data || {});
|
||||||
|
}
|
106
assets/js/src/cron.jsx
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
define(
|
||||||
|
[
|
||||||
|
'react',
|
||||||
|
'react-dom',
|
||||||
|
'mailpoet'
|
||||||
|
],
|
||||||
|
function(
|
||||||
|
React,
|
||||||
|
ReactDOM,
|
||||||
|
MailPoet
|
||||||
|
) {
|
||||||
|
var CronControl = React.createClass({
|
||||||
|
getInitialState: function() {
|
||||||
|
return {
|
||||||
|
status: 'loading'
|
||||||
|
};
|
||||||
|
},
|
||||||
|
getCronData: function() {
|
||||||
|
MailPoet.Ajax.post({
|
||||||
|
endpoint: 'cron',
|
||||||
|
action: 'getStatus'
|
||||||
|
})
|
||||||
|
.done(function(response) {
|
||||||
|
jQuery('.button-primary')
|
||||||
|
.removeClass('disabled');
|
||||||
|
if(response.status !== undefined) {
|
||||||
|
this.setState(response);
|
||||||
|
} else {
|
||||||
|
this.replaceState();
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
componentDidMount: function() {
|
||||||
|
if(this.isMounted()) {
|
||||||
|
this.getCronData();
|
||||||
|
setInterval(this.getCronData, 5000);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
controlCron: function(action) {
|
||||||
|
if(jQuery('.button-primary').hasClass('disabled')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
jQuery('.button-primary')
|
||||||
|
.addClass('disabled');
|
||||||
|
MailPoet.Ajax.post({
|
||||||
|
endpoint: 'cron',
|
||||||
|
action: action,
|
||||||
|
})
|
||||||
|
.done(function(response) {
|
||||||
|
if(!response.result) {
|
||||||
|
MailPoet.Notice.error(MailPoetI18n.daemonControlError);
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
if(this.state.status === 'loading') {
|
||||||
|
return(<div>Loading daemon status...</div>);
|
||||||
|
}
|
||||||
|
switch(this.state.status) {
|
||||||
|
case 'started':
|
||||||
|
return(
|
||||||
|
<div>
|
||||||
|
Cron daemon is running.
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
It was started
|
||||||
|
<strong> {this.state.timeSinceStart} </strong> and last executed
|
||||||
|
<strong> {this.state.timeSinceUpdate} </strong> for a total of
|
||||||
|
<strong> {this.state.counter} </strong> times (once every 30 seconds, unless it was interrupted and restarted).
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<a href="#" className="button-primary" onClick={this.controlCron.bind(null, 'stop')}>Stop</a>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'starting':
|
||||||
|
case 'stopping':
|
||||||
|
return(
|
||||||
|
<div>
|
||||||
|
Daemon is {this.state.status}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'stopped':
|
||||||
|
return(
|
||||||
|
<div>
|
||||||
|
Daemon is {this.state.status}
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<a href="#" className="button-primary" onClick={this.controlCron.bind(null, 'start')}>Start</a>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const container = document.getElementById('cron_container');
|
||||||
|
|
||||||
|
if(container) {
|
||||||
|
ReactDOM.render(
|
||||||
|
<CronControl />,
|
||||||
|
container
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
@ -1,31 +1,31 @@
|
|||||||
define([
|
define([
|
||||||
'react',
|
'react'
|
||||||
'react-checkbox-group'
|
|
||||||
],
|
],
|
||||||
function(
|
function(
|
||||||
React,
|
React
|
||||||
CheckboxGroup
|
|
||||||
) {
|
) {
|
||||||
var FormFieldCheckbox = React.createClass({
|
const FormFieldCheckbox = React.createClass({
|
||||||
|
onValueChange: function(e) {
|
||||||
|
e.target.value = this.refs.checkbox.checked ? '1' : '';
|
||||||
|
return this.props.onValueChange(e);
|
||||||
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
var selected_values = this.props.item[this.props.field.name] || '';
|
const isChecked = !!(this.props.item[this.props.field.name]);
|
||||||
if(
|
|
||||||
selected_values !== undefined
|
|
||||||
&& selected_values.constructor !== Array
|
|
||||||
) {
|
|
||||||
selected_values = selected_values.split(';').map(function(value) {
|
|
||||||
return value.trim();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
var count = Object.keys(this.props.field.values).length;
|
|
||||||
|
|
||||||
var options = Object.keys(this.props.field.values).map(
|
const options = Object.keys(this.props.field.values).map(
|
||||||
function(value, index) {
|
function(value, index) {
|
||||||
return (
|
return (
|
||||||
<p key={ 'checkbox-' + index }>
|
<p key={ 'checkbox-' + index }>
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" value={ value } />
|
<input
|
||||||
{ this.props.field.values[value] }
|
ref="checkbox"
|
||||||
|
type="checkbox"
|
||||||
|
value="1"
|
||||||
|
checked={ isChecked }
|
||||||
|
onChange={ this.onValueChange }
|
||||||
|
name={ this.props.field.name }
|
||||||
|
/>
|
||||||
|
{ this.props.field.values[value] }
|
||||||
</label>
|
</label>
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
@ -33,30 +33,10 @@ function(
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<CheckboxGroup
|
<div>
|
||||||
name={ this.props.field.name }
|
|
||||||
value={ selected_values }
|
|
||||||
ref={ this.props.field.name }
|
|
||||||
onChange={ this.handleValueChange }>
|
|
||||||
{ options }
|
{ options }
|
||||||
</CheckboxGroup>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
|
||||||
handleValueChange: function() {
|
|
||||||
var field = this.props.field.name;
|
|
||||||
var group = this.refs[field];
|
|
||||||
var selected_values = [];
|
|
||||||
|
|
||||||
if(group !== undefined) {
|
|
||||||
selected_values = group.getCheckedValues();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.props.onValueChange({
|
|
||||||
target: {
|
|
||||||
name: field,
|
|
||||||
value: selected_values.join(';')
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
196
assets/js/src/form/fields/date.jsx
Normal file
@ -0,0 +1,196 @@
|
|||||||
|
define([
|
||||||
|
'react',
|
||||||
|
'moment',
|
||||||
|
], function(
|
||||||
|
React,
|
||||||
|
Moment
|
||||||
|
) {
|
||||||
|
class FormFieldDateYear extends React.Component {
|
||||||
|
render() {
|
||||||
|
const yearsRange = 100;
|
||||||
|
const years = [];
|
||||||
|
const currentYear = Moment().year();
|
||||||
|
for (let i = currentYear; i >= currentYear - yearsRange; i--) {
|
||||||
|
years.push((
|
||||||
|
<option
|
||||||
|
key={ i }
|
||||||
|
value={ i }
|
||||||
|
>{ i }</option>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<select
|
||||||
|
name={ this.props.name + '[year]' }
|
||||||
|
value={ this.props.year }
|
||||||
|
onChange={ this.props.onValueChange }
|
||||||
|
>
|
||||||
|
{ years }
|
||||||
|
</select>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FormFieldDateMonth extends React.Component {
|
||||||
|
render() {
|
||||||
|
const months = [];
|
||||||
|
for (let i = 1; i <= 12; i++) {
|
||||||
|
months.push((
|
||||||
|
<option
|
||||||
|
key={ i }
|
||||||
|
value={ i }
|
||||||
|
>{ this.props.monthNames[i - 1] }</option>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<select
|
||||||
|
name={ this.props.name + '[month]' }
|
||||||
|
value={ this.props.month }
|
||||||
|
onChange={ this.props.onValueChange }
|
||||||
|
>
|
||||||
|
{ months }
|
||||||
|
</select>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FormFieldDateDay extends React.Component {
|
||||||
|
render() {
|
||||||
|
const days = [];
|
||||||
|
for (let i = 1; i <= 31; i++) {
|
||||||
|
days.push((
|
||||||
|
<option
|
||||||
|
key={ i }
|
||||||
|
value={ i }
|
||||||
|
>{ i }</option>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<select
|
||||||
|
name={ this.props.name + '[day]' }
|
||||||
|
value={ this.props.day }
|
||||||
|
onChange={ this.props.onValueChange }
|
||||||
|
>
|
||||||
|
{ days }
|
||||||
|
</select>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FormFieldDate extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
year: Moment().year(),
|
||||||
|
month: 1,
|
||||||
|
day: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
componentDidMount() {
|
||||||
|
}
|
||||||
|
componentDidUpdate(prevProps, prevState) {
|
||||||
|
if (
|
||||||
|
(this.props.item !== undefined && prevProps.item !== undefined)
|
||||||
|
&& (this.props.item.id !== prevProps.item.id)
|
||||||
|
) {
|
||||||
|
this.extractTimeStamp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extractTimeStamp() {
|
||||||
|
const timeStamp = parseInt(this.props.item[this.props.field.name], 10);
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
year: Moment.unix(timeStamp).year(),
|
||||||
|
// Moment returns the month as [0..11]
|
||||||
|
// We increment it to match PHP's mktime() which expects [1..12]
|
||||||
|
month: Moment.unix(timeStamp).month() + 1,
|
||||||
|
day: Moment.unix(timeStamp).date()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
updateTimeStamp(field) {
|
||||||
|
let newTimeStamp = Moment(
|
||||||
|
`${this.state.month}/${this.state.day}/${this.state.year}`,
|
||||||
|
'M/D/YYYY'
|
||||||
|
).valueOf();
|
||||||
|
if (!isNaN(newTimeStamp) && parseInt(newTimeStamp, 10) > 0) {
|
||||||
|
// convert milliseconds to seconds
|
||||||
|
newTimeStamp /= 1000;
|
||||||
|
return this.props.onValueChange({
|
||||||
|
target: {
|
||||||
|
name: field,
|
||||||
|
value: newTimeStamp
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onValueChange(e) {
|
||||||
|
// extract property from name
|
||||||
|
const matches = e.target.name.match(/(.*?)\[(.*?)\]/);
|
||||||
|
let field = null;
|
||||||
|
let property = null;
|
||||||
|
|
||||||
|
if (matches !== null && matches.length === 3) {
|
||||||
|
field = matches[1];
|
||||||
|
property = matches[2];
|
||||||
|
|
||||||
|
let value = parseInt(e.target.value, 10);
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
[`${property}`]: value
|
||||||
|
}, () => {
|
||||||
|
this.updateTimeStamp(field);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render() {
|
||||||
|
const monthNames = window.mailpoet_month_names || [];
|
||||||
|
|
||||||
|
const dateType = this.props.field.params.date_type;
|
||||||
|
|
||||||
|
const dateSelects = dateType.split('_');
|
||||||
|
|
||||||
|
const fields = dateSelects.map(type => {
|
||||||
|
switch(type) {
|
||||||
|
case 'year':
|
||||||
|
return (<FormFieldDateYear
|
||||||
|
onValueChange={ this.onValueChange.bind(this) }
|
||||||
|
ref={ 'year' }
|
||||||
|
key={ 'year' }
|
||||||
|
name={ this.props.field.name }
|
||||||
|
year={ this.state.year }
|
||||||
|
/>);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'month':
|
||||||
|
return (<FormFieldDateMonth
|
||||||
|
onValueChange={ this.onValueChange.bind(this) }
|
||||||
|
ref={ 'month' }
|
||||||
|
key={ 'month' }
|
||||||
|
name={ this.props.field.name }
|
||||||
|
month={ this.state.month }
|
||||||
|
monthNames={ monthNames }
|
||||||
|
/>);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'day':
|
||||||
|
return (<FormFieldDateDay
|
||||||
|
onValueChange={ this.onValueChange.bind(this) }
|
||||||
|
ref={ 'day' }
|
||||||
|
key={ 'day' }
|
||||||
|
name={ this.props.field.name }
|
||||||
|
day={ this.state.day }
|
||||||
|
/>);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{fields}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return FormFieldDate;
|
||||||
|
});
|
@ -5,7 +5,8 @@ define([
|
|||||||
'form/fields/select.jsx',
|
'form/fields/select.jsx',
|
||||||
'form/fields/radio.jsx',
|
'form/fields/radio.jsx',
|
||||||
'form/fields/checkbox.jsx',
|
'form/fields/checkbox.jsx',
|
||||||
'form/fields/selection.jsx'
|
'form/fields/selection.jsx',
|
||||||
|
'form/fields/date.jsx',
|
||||||
],
|
],
|
||||||
function(
|
function(
|
||||||
React,
|
React,
|
||||||
@ -14,7 +15,8 @@ function(
|
|||||||
FormFieldSelect,
|
FormFieldSelect,
|
||||||
FormFieldRadio,
|
FormFieldRadio,
|
||||||
FormFieldCheckbox,
|
FormFieldCheckbox,
|
||||||
FormFieldSelection
|
FormFieldSelection,
|
||||||
|
FormFieldDate
|
||||||
) {
|
) {
|
||||||
var FormField = React.createClass({
|
var FormField = React.createClass({
|
||||||
renderField: function(data, inline = false) {
|
renderField: function(data, inline = false) {
|
||||||
@ -55,6 +57,10 @@ function(
|
|||||||
case 'selection':
|
case 'selection':
|
||||||
field = (<FormFieldSelection {...data} />);
|
field = (<FormFieldSelection {...data} />);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'date':
|
||||||
|
field = (<FormFieldDate {...data} />);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(inline === true) {
|
if(inline === true) {
|
||||||
@ -66,10 +72,10 @@ function(
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<p key={ 'field-' + (data.index || 0) }>
|
<div key={ 'field-' + (data.index || 0) }>
|
||||||
{ field }
|
{ field }
|
||||||
{ description }
|
{ description }
|
||||||
</p>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -7,7 +7,6 @@ function(
|
|||||||
var FormFieldRadio = React.createClass({
|
var FormFieldRadio = React.createClass({
|
||||||
render: function() {
|
render: function() {
|
||||||
var selected_value = this.props.item[this.props.field.name];
|
var selected_value = this.props.item[this.props.field.name];
|
||||||
var count = Object.keys(this.props.field.values).length;
|
|
||||||
|
|
||||||
var options = Object.keys(this.props.field.values).map(
|
var options = Object.keys(this.props.field.values).map(
|
||||||
function(value, index) {
|
function(value, index) {
|
||||||
@ -20,7 +19,7 @@ function(
|
|||||||
value={ value }
|
value={ value }
|
||||||
onChange={ this.props.onValueChange }
|
onChange={ this.props.onValueChange }
|
||||||
name={ this.props.field.name } />
|
name={ this.props.field.name } />
|
||||||
{ this.props.field.values[value] }
|
{ this.props.field.values[value] }
|
||||||
</label>
|
</label>
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
|
@ -23,7 +23,9 @@ function(
|
|||||||
name={ this.props.field.name }
|
name={ this.props.field.name }
|
||||||
id={ 'field_'+this.props.field.name }
|
id={ 'field_'+this.props.field.name }
|
||||||
value={ this.props.item[this.props.field.name] }
|
value={ this.props.item[this.props.field.name] }
|
||||||
onChange={ this.props.onValueChange }>
|
onChange={ this.props.onValueChange }
|
||||||
|
{...this.props.field.validation}
|
||||||
|
>
|
||||||
{options}
|
{options}
|
||||||
</select>
|
</select>
|
||||||
);
|
);
|
||||||
|
@ -20,8 +20,15 @@ function(
|
|||||||
this.loadCachedItems();
|
this.loadCachedItems();
|
||||||
this.setupSelect2();
|
this.setupSelect2();
|
||||||
},
|
},
|
||||||
componentDidUpdate: function() {
|
componentDidUpdate: function(prevProps, prevState) {
|
||||||
this.setupSelect2();
|
if(
|
||||||
|
(this.props.item !== undefined && prevProps.item !== undefined)
|
||||||
|
&& (this.props.item.id !== prevProps.item.id)
|
||||||
|
) {
|
||||||
|
jQuery('#'+this.refs.select.id)
|
||||||
|
.val(this.props.item[this.props.field.name])
|
||||||
|
.trigger('change');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
setupSelect2: function() {
|
setupSelect2: function() {
|
||||||
if(
|
if(
|
||||||
@ -43,7 +50,19 @@ function(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var hasRemoved = false;
|
||||||
|
select2.on('select2:unselecting', function(e) {
|
||||||
|
hasRemoved = true;
|
||||||
|
});
|
||||||
|
select2.on('select2:opening', function(e) {
|
||||||
|
if(hasRemoved === true) {
|
||||||
|
hasRemoved = false;
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
select2.on('change', this.handleChange);
|
select2.on('change', this.handleChange);
|
||||||
|
|
||||||
select2.select2(
|
select2.select2(
|
||||||
'val',
|
'val',
|
||||||
this.props.item[this.props.field.name]
|
this.props.item[this.props.field.name]
|
||||||
@ -54,6 +73,11 @@ function(
|
|||||||
loadCachedItems: function() {
|
loadCachedItems: function() {
|
||||||
if(typeof(window['mailpoet_'+this.props.field.endpoint]) !== 'undefined') {
|
if(typeof(window['mailpoet_'+this.props.field.endpoint]) !== 'undefined') {
|
||||||
var items = window['mailpoet_'+this.props.field.endpoint];
|
var items = window['mailpoet_'+this.props.field.endpoint];
|
||||||
|
|
||||||
|
if(this.props.field['filter'] !== undefined) {
|
||||||
|
items = items.filter(this.props.field.filter);
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
items: items
|
items: items
|
||||||
});
|
});
|
||||||
@ -62,7 +86,7 @@ function(
|
|||||||
handleChange: function(e) {
|
handleChange: function(e) {
|
||||||
if(this.props.onValueChange !== undefined) {
|
if(this.props.onValueChange !== undefined) {
|
||||||
if(this.props.field.multiple) {
|
if(this.props.field.multiple) {
|
||||||
value = jQuery('#'+this.refs.select.id).select2('val');
|
value = jQuery('#'+this.refs.select.id).val();
|
||||||
} else {
|
} else {
|
||||||
value = e.target.value;
|
value = e.target.value;
|
||||||
}
|
}
|
||||||
@ -73,40 +97,35 @@ function(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
if(this.state.items.length === 0) {
|
var options = this.state.items.map(function(item, index) {
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
var options = this.state.items.map(function(item, index) {
|
|
||||||
return (
|
|
||||||
<option
|
|
||||||
key={ item.id }
|
|
||||||
value={ item.id }
|
|
||||||
>
|
|
||||||
{ item.name }
|
|
||||||
</option>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
var default_value = (
|
|
||||||
(this.props.item !== undefined && this.props.field.name !== undefined)
|
|
||||||
? this.props.item[this.props.field.name]
|
|
||||||
: null
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<select
|
<option
|
||||||
id={ this.props.field.id || this.props.field.name }
|
key={ item.id }
|
||||||
ref="select"
|
value={ item.id }
|
||||||
placeholder={ this.props.field.placeholder }
|
>
|
||||||
multiple={ this.props.field.multiple }
|
{ item.name }
|
||||||
onChange={ this.handleChange }
|
</option>
|
||||||
defaultValue={ default_value }
|
|
||||||
>{ options }</select>
|
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
|
var default_value = (
|
||||||
|
(this.props.item !== undefined && this.props.field.name !== undefined)
|
||||||
|
? this.props.item[this.props.field.name]
|
||||||
|
: null
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<select
|
||||||
|
id={ this.props.field.id || this.props.field.name }
|
||||||
|
ref="select"
|
||||||
|
data-placeholder={ this.props.field.placeholder }
|
||||||
|
multiple={ this.props.field.multiple }
|
||||||
|
defaultValue={ default_value }
|
||||||
|
{...this.props.field.validation}
|
||||||
|
>{ options }</select>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -6,6 +6,8 @@ function(
|
|||||||
) {
|
) {
|
||||||
var FormFieldText = React.createClass({
|
var FormFieldText = React.createClass({
|
||||||
render: function() {
|
render: function() {
|
||||||
|
var value = this.props.item[this.props.field.name];
|
||||||
|
if(!value) { value = null; }
|
||||||
return (
|
return (
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
@ -17,10 +19,12 @@ function(
|
|||||||
}
|
}
|
||||||
name={ this.props.field.name }
|
name={ this.props.field.name }
|
||||||
id={ 'field_'+this.props.field.name }
|
id={ 'field_'+this.props.field.name }
|
||||||
value={ this.props.item[this.props.field.name] }
|
value={ value }
|
||||||
placeholder={ this.props.field.placeholder }
|
placeholder={ this.props.field.placeholder }
|
||||||
defaultValue={ this.props.field.defaultValue }
|
defaultValue={ this.props.field.defaultValue }
|
||||||
onChange={ this.props.onValueChange } />
|
onChange={ this.props.onValueChange }
|
||||||
|
{...this.props.field.validation}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -15,7 +15,9 @@ function(
|
|||||||
value={ this.props.item[this.props.field.name] }
|
value={ this.props.item[this.props.field.name] }
|
||||||
placeholder={ this.props.field.placeholder }
|
placeholder={ this.props.field.placeholder }
|
||||||
defaultValue={ this.props.field.defaultValue }
|
defaultValue={ this.props.field.defaultValue }
|
||||||
onChange={ this.props.onValueChange } />
|
onChange={ this.props.onValueChange }
|
||||||
|
{...this.props.field.validation}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -48,7 +48,7 @@ define(
|
|||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
endpoint: this.props.endpoint,
|
endpoint: this.props.endpoint,
|
||||||
action: 'get',
|
action: 'get',
|
||||||
data: { id: id }
|
data: id
|
||||||
}).done(function(response) {
|
}).done(function(response) {
|
||||||
if(response === false) {
|
if(response === false) {
|
||||||
this.setState({
|
this.setState({
|
||||||
@ -68,12 +68,25 @@ define(
|
|||||||
handleSubmit: function(e) {
|
handleSubmit: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
// handle validation
|
||||||
|
if(this.props.isValid !== undefined) {
|
||||||
|
if(this.props.isValid() === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({ loading: true });
|
this.setState({ loading: true });
|
||||||
|
|
||||||
// only get values from displayed fields
|
// only get values from displayed fields
|
||||||
item = {};
|
var item = {};
|
||||||
this.props.fields.map(function(field) {
|
this.props.fields.map(function(field) {
|
||||||
item[field.name] = this.state.item[field.name];
|
if(field['fields'] !== undefined) {
|
||||||
|
field.fields.map(function(subfield) {
|
||||||
|
item[subfield.name] = this.state.item[subfield.name];
|
||||||
|
}.bind(this));
|
||||||
|
} else {
|
||||||
|
item[field.name] = this.state.item[field.name];
|
||||||
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
// set id if specified
|
// set id if specified
|
||||||
@ -88,23 +101,23 @@ define(
|
|||||||
}).done(function(response) {
|
}).done(function(response) {
|
||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
|
|
||||||
if(response === true) {
|
if(response.result === true) {
|
||||||
if(this.props.onSuccess !== undefined) {
|
if(this.props.onSuccess !== undefined) {
|
||||||
this.props.onSuccess()
|
this.props.onSuccess();
|
||||||
} else {
|
} else {
|
||||||
this.history.pushState(null, '/')
|
this.history.pushState(null, '/')
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.props.params.id !== undefined) {
|
if(this.props.params.id !== undefined) {
|
||||||
this.props.messages['updated']();
|
this.props.messages.onUpdate();
|
||||||
} else {
|
} else {
|
||||||
this.props.messages['created']();
|
this.props.messages.onCreate();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(response === false) {
|
if(response.result === false) {
|
||||||
// unknown error occurred
|
if(response.errors.length > 0) {
|
||||||
} else {
|
this.setState({ errors: response.errors });
|
||||||
this.setState({ errors: response });
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
@ -121,13 +134,15 @@ define(
|
|||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
var errors = this.state.errors.map(function(error, index) {
|
if(this.state.errors !== undefined) {
|
||||||
return (
|
var errors = this.state.errors.map(function(error, index) {
|
||||||
<p key={ 'error-'+index } className="mailpoet_error">
|
return (
|
||||||
{ error }
|
<p key={ 'error-'+index } className="mailpoet_error">
|
||||||
</p>
|
{ error }
|
||||||
);
|
</p>
|
||||||
});
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var formClasses = classNames(
|
var formClasses = classNames(
|
||||||
'mailpoet_form',
|
'mailpoet_form',
|
||||||
|
@ -231,7 +231,7 @@ var WysijaHistory = {
|
|||||||
|
|
||||||
/* MailPoet Form */
|
/* MailPoet Form */
|
||||||
var WysijaForm = {
|
var WysijaForm = {
|
||||||
version: '0.6',
|
version: '0.7',
|
||||||
options: {
|
options: {
|
||||||
container: 'mailpoet_form_container',
|
container: 'mailpoet_form_container',
|
||||||
editor: 'mailpoet_form_editor',
|
editor: 'mailpoet_form_editor',
|
||||||
@ -317,6 +317,7 @@ var WysijaForm = {
|
|||||||
save: function() {
|
save: function() {
|
||||||
var position = 1,
|
var position = 1,
|
||||||
data = {
|
data = {
|
||||||
|
'name': $F('mailpoet_form_name'),
|
||||||
'settings': $('mailpoet_form_settings').serialize(true),
|
'settings': $('mailpoet_form_settings').serialize(true),
|
||||||
'body': [],
|
'body': [],
|
||||||
'styles': (MailPoet.CodeEditor !== undefined) ? MailPoet.CodeEditor.getValue() : null
|
'styles': (MailPoet.CodeEditor !== undefined) ? MailPoet.CodeEditor.getValue() : null
|
||||||
@ -616,6 +617,28 @@ var WysijaForm = {
|
|||||||
// this is a url, so do not encode the protocol
|
// this is a url, so do not encode the protocol
|
||||||
return encodeURI(str).replace(/[!'()*]/g, escape);
|
return encodeURI(str).replace(/[!'()*]/g, escape);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
updateBlock: function(field) {
|
||||||
|
var hasUpdated = false;
|
||||||
|
WysijaForm.getBlocks().each(function(b) {
|
||||||
|
if(b.block.getData().id === field.id) {
|
||||||
|
hasUpdated = true;
|
||||||
|
b.block.redraw(field);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return hasUpdated;
|
||||||
|
},
|
||||||
|
removeBlock: function(field, callback) {
|
||||||
|
var hasRemoved = false;
|
||||||
|
WysijaForm.getBlocks().each(function(b) {
|
||||||
|
if(b.block.getData().id === field.id) {
|
||||||
|
hasRemoved = true;
|
||||||
|
b.block.removeBlock(callback);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return hasRemoved;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -824,10 +847,6 @@ WysijaForm.Block = Class.create({
|
|||||||
Effect.Fade(this.element.identify(), {
|
Effect.Fade(this.element.identify(), {
|
||||||
duration: 0.2,
|
duration: 0.2,
|
||||||
afterFinish: function(effect) {
|
afterFinish: function(effect) {
|
||||||
if(effect.element.next('.mailpoet_form_block') !== undefined && callback !== false) {
|
|
||||||
// show controls of next block to allow mass delete
|
|
||||||
WysijaForm.get(effect.element.next('.mailpoet_form_block')).block.showControls();
|
|
||||||
}
|
|
||||||
// remove placeholder
|
// remove placeholder
|
||||||
if(effect.element.previous('.block_placeholder') !== undefined) {
|
if(effect.element.previous('.block_placeholder') !== undefined) {
|
||||||
effect.element.previous('.block_placeholder').remove();
|
effect.element.previous('.block_placeholder').remove();
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
import React from 'react'
|
|
||||||
import ReactDOM from 'react-dom'
|
|
||||||
import { Router, History } from 'react-router'
|
|
||||||
import MailPoet from 'mailpoet'
|
|
||||||
import Form from 'form/form.jsx'
|
|
||||||
|
|
||||||
const fields = [
|
|
||||||
{
|
|
||||||
name: 'name',
|
|
||||||
label: 'Name',
|
|
||||||
type: 'text'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'segments',
|
|
||||||
label: 'Lists',
|
|
||||||
type: 'selection',
|
|
||||||
endpoint: 'segments',
|
|
||||||
multiple: true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
const messages = {
|
|
||||||
updated: function() {
|
|
||||||
MailPoet.Notice.success('Form successfully updated!');
|
|
||||||
},
|
|
||||||
created: function() {
|
|
||||||
MailPoet.Notice.success('Form successfully added!');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const FormForm = React.createClass({
|
|
||||||
mixins: [
|
|
||||||
History
|
|
||||||
],
|
|
||||||
render() {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<h2 className="title">
|
|
||||||
Form <a
|
|
||||||
href="javascript:;"
|
|
||||||
className="add-new-h2"
|
|
||||||
onClick={ this.history.goBack }
|
|
||||||
>Back to list</a>
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<Form
|
|
||||||
endpoint="forms"
|
|
||||||
fields={ fields }
|
|
||||||
params={ this.props.params }
|
|
||||||
messages={ messages }
|
|
||||||
onSuccess={ this.history.goBack } />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
module.exports = FormForm
|
|
@ -2,7 +2,6 @@ import React from 'react'
|
|||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import { Router, Route, IndexRoute } from 'react-router'
|
import { Router, Route, IndexRoute } from 'react-router'
|
||||||
import FormList from 'forms/list.jsx'
|
import FormList from 'forms/list.jsx'
|
||||||
import FormForm from 'forms/form.jsx'
|
|
||||||
import createHashHistory from 'history/lib/createHashHistory'
|
import createHashHistory from 'history/lib/createHashHistory'
|
||||||
|
|
||||||
let history = createHashHistory({ queryKey: false })
|
let history = createHashHistory({ queryKey: false })
|
||||||
@ -20,8 +19,6 @@ if(container) {
|
|||||||
<Router history={ history }>
|
<Router history={ history }>
|
||||||
<Route path="/" component={ App }>
|
<Route path="/" component={ App }>
|
||||||
<IndexRoute component={ FormList } />
|
<IndexRoute component={ FormList } />
|
||||||
<Route path="new" component={ FormForm } />
|
|
||||||
<Route path="edit/:id" component={ FormForm } />
|
|
||||||
<Route path="*" component={ FormList } />
|
<Route path="*" component={ FormList } />
|
||||||
</Route>
|
</Route>
|
||||||
</Router>
|
</Router>
|
||||||
|
@ -25,58 +25,49 @@ const columns = [
|
|||||||
|
|
||||||
const messages = {
|
const messages = {
|
||||||
onTrash: function(response) {
|
onTrash: function(response) {
|
||||||
if(response) {
|
var count = ~~response;
|
||||||
let message = null;
|
var message = null;
|
||||||
if(~~response === 1) {
|
|
||||||
message = (
|
|
||||||
'1 form was moved to the trash.'
|
|
||||||
);
|
|
||||||
} else if(~~response > 1) {
|
|
||||||
message = (
|
|
||||||
'%$1d forms were moved to the trash.'
|
|
||||||
).replace('%$1d', ~~response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(message !== null) {
|
if(count === 1) {
|
||||||
MailPoet.Notice.success(message);
|
message = (
|
||||||
}
|
'1 form was moved to the trash.'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
'%$1d forms were moved to the trash.'
|
||||||
|
).replace('%$1d', count);
|
||||||
}
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
},
|
},
|
||||||
onDelete: function(response) {
|
onDelete: function(response) {
|
||||||
if(response) {
|
var count = ~~response;
|
||||||
let message = null;
|
var message = null;
|
||||||
if(~~response === 1) {
|
|
||||||
message = (
|
|
||||||
'1 form was permanently deleted.'
|
|
||||||
);
|
|
||||||
} else if(~~response > 1) {
|
|
||||||
message = (
|
|
||||||
'%$1d forms were permanently deleted.'
|
|
||||||
).replace('%$1d', ~~response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(message !== null) {
|
if(count === 1) {
|
||||||
MailPoet.Notice.success(message);
|
message = (
|
||||||
}
|
'1 form was permanently deleted.'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
'%$1d forms were permanently deleted.'
|
||||||
|
).replace('%$1d', count);
|
||||||
}
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
},
|
},
|
||||||
onRestore: function(response) {
|
onRestore: function(response) {
|
||||||
if(response) {
|
var count = ~~response;
|
||||||
let message = null;
|
var message = null;
|
||||||
if(~~response === 1) {
|
|
||||||
message = (
|
|
||||||
'1 form has been restored from the trash.'
|
|
||||||
);
|
|
||||||
} else if(~~response > 1) {
|
|
||||||
message = (
|
|
||||||
'%$1d forms have been restored from the trash.'
|
|
||||||
).replace('%$1d', ~~response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(message !== null) {
|
if(count === 1) {
|
||||||
MailPoet.Notice.success(message);
|
message = (
|
||||||
}
|
'1 form has been restored from the trash.'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
'%$1d forms have been restored from the trash.'
|
||||||
|
).replace('%$1d', count);
|
||||||
}
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -105,6 +96,9 @@ const item_actions = [
|
|||||||
refresh();
|
refresh();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'trash'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -122,8 +116,8 @@ const FormList = React.createClass({
|
|||||||
endpoint: 'forms',
|
endpoint: 'forms',
|
||||||
action: 'create'
|
action: 'create'
|
||||||
}).done(function(response) {
|
}).done(function(response) {
|
||||||
if(response !== false) {
|
if(response.result && response.form_id) {
|
||||||
window.location = response;
|
window.location = mailpoet_form_edit_url + response.form_id;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
3
assets/js/src/helpscout.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
define([], function() {
|
||||||
|
!function(e,o,n){window.HSCW=o,window.HS=n,n.beacon=n.beacon||{};var t=n.beacon;t.userConfig={},t.readyQueue=[],t.config=function(e){this.userConfig=e},t.ready=function(e){this.readyQueue.push(e)},o.config={docs:{enabled:!1,baseUrl:""},contact:{enabled:!0,formId:"e5c408c7-895e-11e5-9e75-0a7d6919297d"}};var r=e.getElementsByTagName("script")[0],c=e.createElement("script");c.type="text/javascript",c.async=!0,c.src="https://djtflbt20bdde.cloudfront.net/",r.parentNode.insertBefore(c,r)}(document,window.HSCW||{},window.HS||{});
|
||||||
|
});
|
@ -15,16 +15,16 @@ function(
|
|||||||
this.setState({
|
this.setState({
|
||||||
action: e.target.value,
|
action: e.target.value,
|
||||||
extra: false
|
extra: false
|
||||||
});
|
}, function() {
|
||||||
|
var action = this.getSelectedAction();
|
||||||
|
|
||||||
var action = this.getSelectedAction();
|
// action on select callback
|
||||||
|
if(action !== null && action['onSelect'] !== undefined) {
|
||||||
// action on select callback
|
this.setState({
|
||||||
if(action !== null && action['onSelect'] !== undefined) {
|
extra: action.onSelect(e)
|
||||||
this.setState({
|
});
|
||||||
extra: action.onSelect(e)
|
}
|
||||||
});
|
}.bind(this));
|
||||||
}
|
|
||||||
},
|
},
|
||||||
handleApplyAction: function(e) {
|
handleApplyAction: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -85,7 +85,12 @@ function(
|
|||||||
Select bulk action
|
Select bulk action
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<select ref="action" value={ this.state.action } onChange={this.handleChangeAction}>
|
<select
|
||||||
|
name="bulk_actions"
|
||||||
|
ref="action"
|
||||||
|
value={ this.state.action }
|
||||||
|
onChange={this.handleChangeAction}
|
||||||
|
>
|
||||||
<option value="">Bulk Actions</option>
|
<option value="">Bulk Actions</option>
|
||||||
{ this.props.bulk_actions.map(function(action, index) {
|
{ this.props.bulk_actions.map(function(action, index) {
|
||||||
return (
|
return (
|
||||||
|
@ -14,6 +14,9 @@ function(
|
|||||||
})
|
})
|
||||||
return this.props.onSelectFilter(filters);
|
return this.props.onSelectFilter(filters);
|
||||||
},
|
},
|
||||||
|
handleEmptyTrash: function() {
|
||||||
|
return this.props.onEmptyTrash();
|
||||||
|
},
|
||||||
getAvailableFilters: function() {
|
getAvailableFilters: function() {
|
||||||
let filters = this.props.filters;
|
let filters = this.props.filters;
|
||||||
|
|
||||||
@ -34,7 +37,7 @@ function(
|
|||||||
const available_filters = this.getAvailableFilters()
|
const available_filters = this.getAvailableFilters()
|
||||||
.map(function(filter, i) {
|
.map(function(filter, i) {
|
||||||
let default_value = false;
|
let default_value = false;
|
||||||
if(selected_filters[filter] !== undefined && selected_filters[filter]) {
|
if (selected_filters[filter] !== undefined && selected_filters[filter]) {
|
||||||
default_value = selected_filters[filter]
|
default_value = selected_filters[filter]
|
||||||
} else {
|
} else {
|
||||||
jQuery(`select[name="${filter}"]`).val('');
|
jQuery(`select[name="${filter}"]`).val('');
|
||||||
@ -60,9 +63,10 @@ function(
|
|||||||
|
|
||||||
let button = false;
|
let button = false;
|
||||||
|
|
||||||
if(available_filters.length > 0) {
|
if (available_filters.length > 0) {
|
||||||
button = (
|
button = (
|
||||||
<input
|
<input
|
||||||
|
id="post-query-submit"
|
||||||
onClick={ this.handleFilterAction }
|
onClick={ this.handleFilterAction }
|
||||||
type="submit"
|
type="submit"
|
||||||
defaultValue="Filter"
|
defaultValue="Filter"
|
||||||
@ -70,10 +74,23 @@ function(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let empty_trash = false;
|
||||||
|
if (this.props.group === 'trash') {
|
||||||
|
empty_trash = (
|
||||||
|
<input
|
||||||
|
onClick={ this.handleEmptyTrash }
|
||||||
|
type="submit"
|
||||||
|
value="Empty Trash"
|
||||||
|
className="button"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="alignleft actions actions">
|
<div className="alignleft actions actions">
|
||||||
{ available_filters }
|
{ available_filters }
|
||||||
{ button }
|
{ button }
|
||||||
|
{ empty_trash }
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ define(['react', 'classnames'], function(React, classNames) {
|
|||||||
column.is_primary = (index === 0);
|
column.is_primary = (index === 0);
|
||||||
column.sorted = (this.props.sort_by === column.name)
|
column.sorted = (this.props.sort_by === column.name)
|
||||||
? this.props.sort_order
|
? this.props.sort_order
|
||||||
: 'asc';
|
: 'desc';
|
||||||
return (
|
return (
|
||||||
<ListingColumn
|
<ListingColumn
|
||||||
onSort={this.props.onSort}
|
onSort={this.props.onSort}
|
||||||
@ -32,6 +32,7 @@ define(['react', 'classnames'], function(React, classNames) {
|
|||||||
</label>
|
</label>
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
|
name="select_all"
|
||||||
ref="toggle"
|
ref="toggle"
|
||||||
checked={ this.props.selection }
|
checked={ this.props.selection }
|
||||||
onChange={ this.handleSelectItems } />
|
onChange={ this.handleSelectItems } />
|
||||||
|
@ -79,27 +79,48 @@ define(
|
|||||||
|
|
||||||
if(custom_actions.length > 0) {
|
if(custom_actions.length > 0) {
|
||||||
item_actions = custom_actions.map(function(action, index) {
|
item_actions = custom_actions.map(function(action, index) {
|
||||||
if(action.refresh) {
|
if(action.display !== undefined) {
|
||||||
|
if(action.display(this.props.item) === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(action.name === 'trash') {
|
||||||
|
return (
|
||||||
|
<span key={ 'action-'+index } className="trash">
|
||||||
|
{(index > 0) ? ' | ' : ''}
|
||||||
|
<a
|
||||||
|
href="javascript:;"
|
||||||
|
onClick={ this.handleTrashItem.bind(
|
||||||
|
null,
|
||||||
|
this.props.item.id
|
||||||
|
) }>
|
||||||
|
Trash
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
} else if(action.refresh) {
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
onClick={ this.props.onRefreshItems }
|
onClick={ this.props.onRefreshItems }
|
||||||
key={ 'action-'+index } className={ action.name }>
|
key={ 'action-'+index } className={ action.name }>
|
||||||
|
{(index > 0) ? ' | ' : ''}
|
||||||
{ action.link(this.props.item) }
|
{ action.link(this.props.item) }
|
||||||
{(index < (custom_actions.length - 1)) ? ' | ' : ''}
|
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
} else if(action.link) {
|
} else if(action.link) {
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
key={ 'action-'+index } className={ action.name }>
|
key={ 'action-'+index } className={ action.name }>
|
||||||
|
{(index > 0) ? ' | ' : ''}
|
||||||
{ action.link(this.props.item) }
|
{ action.link(this.props.item) }
|
||||||
{(index < (custom_actions.length - 1)) ? ' | ' : ''}
|
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
key={ 'action-'+index } className={ action.name }>
|
key={ 'action-'+index } className={ action.name }>
|
||||||
|
{(index > 0) ? ' | ' : ''}
|
||||||
<a href="javascript:;" onClick={
|
<a href="javascript:;" onClick={
|
||||||
(action.onClick !== undefined)
|
(action.onClick !== undefined)
|
||||||
? action.onClick.bind(null,
|
? action.onClick.bind(null,
|
||||||
@ -108,7 +129,6 @@ define(
|
|||||||
)
|
)
|
||||||
: false
|
: false
|
||||||
}>{ action.label }</a>
|
}>{ action.label }</a>
|
||||||
{(index < (custom_actions.length - 1)) ? ' | ' : ''}
|
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -158,17 +178,6 @@ define(
|
|||||||
<div>
|
<div>
|
||||||
<div className="row-actions">
|
<div className="row-actions">
|
||||||
{ item_actions }
|
{ item_actions }
|
||||||
{ ' | ' }
|
|
||||||
<span className="trash">
|
|
||||||
<a
|
|
||||||
href="javascript:;"
|
|
||||||
onClick={ this.handleTrashItem.bind(
|
|
||||||
null,
|
|
||||||
this.props.item.id
|
|
||||||
) }>
|
|
||||||
Trash
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={ this.handleToggleItem.bind(null, this.props.item.id) }
|
onClick={ this.handleToggleItem.bind(null, this.props.item.id) }
|
||||||
@ -388,6 +397,12 @@ define(
|
|||||||
if(this.isMounted()) {
|
if(this.isMounted()) {
|
||||||
const params = this.props.params || {}
|
const params = this.props.params || {}
|
||||||
this.initWithParams(params)
|
this.initWithParams(params)
|
||||||
|
|
||||||
|
if(this.props.auto_refresh) {
|
||||||
|
jQuery(document).on('heartbeat-tick.mailpoet', function(e, data) {
|
||||||
|
this.getItems();
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
componentWillReceiveProps: function(nextProps) {
|
componentWillReceiveProps: function(nextProps) {
|
||||||
@ -419,7 +434,13 @@ define(
|
|||||||
groups: response.groups || [],
|
groups: response.groups || [],
|
||||||
count: response.count || 0,
|
count: response.count || 0,
|
||||||
loading: false
|
loading: false
|
||||||
});
|
}, function() {
|
||||||
|
if(this.props['onGetItems'] !== undefined) {
|
||||||
|
this.props.onGetItems(
|
||||||
|
~~(this.state.groups[0]['count'])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}.bind(this));
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -483,10 +504,21 @@ define(
|
|||||||
this.getItems();
|
this.getItems();
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
handleEmptyTrash: function() {
|
||||||
|
this.handleBulkAction('all', {
|
||||||
|
action: 'delete',
|
||||||
|
group: 'trash'
|
||||||
|
}, function(response) {
|
||||||
|
MailPoet.Notice.success(
|
||||||
|
MailPoetI18n.permanentlyDeleted.replace('%d', response)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
handleBulkAction: function(selected_ids, params, callback) {
|
handleBulkAction: function(selected_ids, params, callback) {
|
||||||
if(
|
if(
|
||||||
this.state.selection === false
|
this.state.selection === false
|
||||||
&& this.state.selected_ids.length === 0
|
&& this.state.selected_ids.length === 0
|
||||||
|
&& selected_ids !== 'all'
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -499,8 +531,10 @@ define(
|
|||||||
limit: 0,
|
limit: 0,
|
||||||
filter: this.state.filter,
|
filter: this.state.filter,
|
||||||
group: this.state.group,
|
group: this.state.group,
|
||||||
search: this.state.search,
|
search: this.state.search
|
||||||
selection: selected_ids
|
}
|
||||||
|
if(selected_ids !== 'all') {
|
||||||
|
data.listing.selection = selected_ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
@ -631,7 +665,7 @@ define(
|
|||||||
// bulk actions
|
// bulk actions
|
||||||
var bulk_actions = this.props.bulk_actions || [];
|
var bulk_actions = this.props.bulk_actions || [];
|
||||||
|
|
||||||
if(this.state.group === 'trash') {
|
if(this.state.group === 'trash' && bulk_actions.length > 0) {
|
||||||
bulk_actions = [
|
bulk_actions = [
|
||||||
{
|
{
|
||||||
name: 'restore',
|
name: 'restore',
|
||||||
@ -694,7 +728,10 @@ define(
|
|||||||
<ListingFilters
|
<ListingFilters
|
||||||
filters={ this.state.filters }
|
filters={ this.state.filters }
|
||||||
filter={ this.state.filter }
|
filter={ this.state.filter }
|
||||||
onSelectFilter={ this.handleFilter } />
|
group={ this.state.group }
|
||||||
|
onSelectFilter={ this.handleFilter }
|
||||||
|
onEmptyTrash={ this.handleEmptyTrash }
|
||||||
|
/>
|
||||||
<ListingPages
|
<ListingPages
|
||||||
count={ this.state.count }
|
count={ this.state.count }
|
||||||
page={ this.state.page }
|
page={ this.state.page }
|
||||||
|
@ -7,7 +7,11 @@ define(['react', 'classnames'], function(React, classNames) {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
setPage: function(page) {
|
setPage: function(page) {
|
||||||
this.props.onSetPage(page);
|
this.setState({
|
||||||
|
page: null
|
||||||
|
}, function () {
|
||||||
|
this.props.onSetPage(this.constrainPage(page));
|
||||||
|
}.bind(this));
|
||||||
},
|
},
|
||||||
setFirstPage: function() {
|
setFirstPage: function() {
|
||||||
this.setPage(1);
|
this.setPage(1);
|
||||||
@ -16,10 +20,14 @@ define(['react', 'classnames'], function(React, classNames) {
|
|||||||
this.setPage(this.getLastPage());
|
this.setPage(this.getLastPage());
|
||||||
},
|
},
|
||||||
setPreviousPage: function() {
|
setPreviousPage: function() {
|
||||||
this.setPage(this.constrainPage(this.props.page - 1));
|
this.setPage(this.constrainPage(
|
||||||
|
parseInt(this.props.page, 10) - 1)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
setNextPage: function() {
|
setNextPage: function() {
|
||||||
this.setPage(this.constrainPage(this.props.page + 1));
|
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());
|
return Math.min(Math.max(1, Math.abs(~~page)), this.getLastPage());
|
||||||
@ -27,14 +35,16 @@ define(['react', 'classnames'], function(React, classNames) {
|
|||||||
handleSetManualPage: function(e) {
|
handleSetManualPage: function(e) {
|
||||||
if(e.which === 13) {
|
if(e.which === 13) {
|
||||||
this.setPage(this.state.page);
|
this.setPage(this.state.page);
|
||||||
this.setState({ page: null });
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleChangeManualPage: function(e) {
|
handleChangeManualPage: function(e) {
|
||||||
this.setState({
|
this.setState({
|
||||||
page: this.constrainPage(e.target.value)
|
page: e.target.value
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
handleBlurManualPage: function(e) {
|
||||||
|
this.setPage(e.target.value);
|
||||||
|
},
|
||||||
getLastPage: function() {
|
getLastPage: function() {
|
||||||
return Math.ceil(this.props.count / this.props.limit);
|
return Math.ceil(this.props.count / this.props.limit);
|
||||||
},
|
},
|
||||||
@ -101,6 +111,11 @@ define(['react', 'classnames'], function(React, classNames) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let pageValue = this.props.page;
|
||||||
|
if(this.state.page !== null) {
|
||||||
|
pageValue = this.state.page;
|
||||||
|
}
|
||||||
|
|
||||||
pagination = (
|
pagination = (
|
||||||
<span className="pagination-links">
|
<span className="pagination-links">
|
||||||
{firstPage}
|
{firstPage}
|
||||||
@ -115,10 +130,11 @@ define(['react', 'classnames'], function(React, classNames) {
|
|||||||
type="text"
|
type="text"
|
||||||
onChange={ this.handleChangeManualPage }
|
onChange={ this.handleChangeManualPage }
|
||||||
onKeyUp={ this.handleSetManualPage }
|
onKeyUp={ this.handleSetManualPage }
|
||||||
|
onBlur={ this.handleBlurManualPage }
|
||||||
aria-describedby="table-paging"
|
aria-describedby="table-paging"
|
||||||
size="1"
|
size="1"
|
||||||
ref="page"
|
ref="page"
|
||||||
value={ this.state.page || this.props.page }
|
value={ pageValue }
|
||||||
name="paged"
|
name="paged"
|
||||||
id="current-page-selector"
|
id="current-page-selector"
|
||||||
className="current-page" />
|
className="current-page" />
|
||||||
|
@ -47,7 +47,6 @@ define([
|
|||||||
autoScroll: true,
|
autoScroll: true,
|
||||||
|
|
||||||
onstart: function(event) {
|
onstart: function(event) {
|
||||||
console.log('Drag start', event, this);
|
|
||||||
|
|
||||||
if (that.options.cloneOriginal === true) {
|
if (that.options.cloneOriginal === true) {
|
||||||
// Use substitution instead of a clone
|
// Use substitution instead of a clone
|
||||||
|
@ -11,10 +11,10 @@ define([
|
|||||||
'newsletter_editor/blocks/base',
|
'newsletter_editor/blocks/base',
|
||||||
'newsletter_editor/blocks/button',
|
'newsletter_editor/blocks/button',
|
||||||
'newsletter_editor/blocks/divider',
|
'newsletter_editor/blocks/divider',
|
||||||
'newsletter_editor/components/wordpress',
|
'newsletter_editor/components/communication',
|
||||||
'underscore',
|
'underscore',
|
||||||
'jquery'
|
'jquery'
|
||||||
], function(App, BaseBlock, ButtonBlock, DividerBlock, WordpressComponent, _, jQuery) {
|
], function(App, BaseBlock, ButtonBlock, DividerBlock, CommunicationComponent, _, jQuery) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ define([
|
|||||||
titlePosition: 'inTextBlock', // 'inTextBlock'|'aboveBlock',
|
titlePosition: 'inTextBlock', // 'inTextBlock'|'aboveBlock',
|
||||||
titleAlignment: 'left', // 'left'|'center'|'right'
|
titleAlignment: 'left', // 'left'|'center'|'right'
|
||||||
titleIsLink: false, // false|true
|
titleIsLink: false, // false|true
|
||||||
imagePadded: true, // true|false
|
imageFullWidth: false, // true|false
|
||||||
//imageAlignment: 'centerPadded', // 'centerFull'|'centerPadded'|'left'|'right'|'alternate'|'none'
|
//imageAlignment: 'centerPadded', // 'centerFull'|'centerPadded'|'left'|'right'|'alternate'|'none'
|
||||||
showAuthor: 'no', // 'no'|'aboveText'|'belowText'
|
showAuthor: 'no', // 'no'|'aboveText'|'belowText'
|
||||||
authorPrecededBy: 'Author:',
|
authorPrecededBy: 'Author:',
|
||||||
@ -63,15 +63,15 @@ define([
|
|||||||
initialize: function() {
|
initialize: function() {
|
||||||
base.BlockView.prototype.initialize.apply(this, arguments);
|
base.BlockView.prototype.initialize.apply(this, arguments);
|
||||||
this.fetchPosts();
|
this.fetchPosts();
|
||||||
this.on('change:amount change:contentType change:terms change:inclusionType change:displayType change:titleFormat change:titlePosition change:titleAlignment change:titleIsLink change:imagePadded change:showAuthor change:authorPrecededBy change:showCategories change:categoriesPrecededBy change:readMoreType change:readMoreText change:sortBy change:showDivider', this._scheduleFetchPosts, this);
|
this.on('change:amount change:contentType change:terms change:inclusionType change:displayType change:titleFormat change:titlePosition change:titleAlignment change:titleIsLink change:imageFullWidth change:showAuthor change:authorPrecededBy change:showCategories change:categoriesPrecededBy change:readMoreType change:readMoreText change:sortBy change:showDivider', this._scheduleFetchPosts, this);
|
||||||
this.listenTo(this.get('readMoreButton'), 'change', this._scheduleFetchPosts);
|
this.listenTo(this.get('readMoreButton'), 'change', this._scheduleFetchPosts);
|
||||||
this.listenTo(this.get('divider'), 'change', this._scheduleFetchPosts);
|
this.listenTo(this.get('divider'), 'change', this._scheduleFetchPosts);
|
||||||
},
|
},
|
||||||
fetchPosts: function() {
|
fetchPosts: function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
WordpressComponent.getTransformedPosts(this.toJSON()).done(function(content) {
|
CommunicationComponent.getTransformedPosts(this.toJSON()).done(function(content) {
|
||||||
console.log('ALC fetched', arguments);
|
|
||||||
that.get('_container').get('blocks').reset(content, {parse: true});
|
that.get('_container').get('blocks').reset(content, {parse: true});
|
||||||
|
that.trigger('postsChanged');
|
||||||
}).fail(function(error) {
|
}).fail(function(error) {
|
||||||
console.log('ALC fetchPosts error', arguments);
|
console.log('ALC fetchPosts error', arguments);
|
||||||
});
|
});
|
||||||
@ -100,6 +100,11 @@ define([
|
|||||||
toolsRegion: '.mailpoet_tools',
|
toolsRegion: '.mailpoet_tools',
|
||||||
postsRegion: '.mailpoet_automated_latest_content_block_posts',
|
postsRegion: '.mailpoet_automated_latest_content_block_posts',
|
||||||
},
|
},
|
||||||
|
modelEvents: _.extend(
|
||||||
|
_.omit(base.BlockView.prototype.modelEvents, 'change'),
|
||||||
|
{
|
||||||
|
'postsChanged': 'render',
|
||||||
|
}),
|
||||||
events: _.extend(base.BlockView.prototype.events, {
|
events: _.extend(base.BlockView.prototype.events, {
|
||||||
'click .mailpoet_automated_latest_content_block_overlay': 'showSettings',
|
'click .mailpoet_automated_latest_content_block_overlay': 'showSettings',
|
||||||
}),
|
}),
|
||||||
@ -139,7 +144,7 @@ define([
|
|||||||
"change .mailpoet_automated_latest_content_include_or_exclude": _.partial(this.changeField, "inclusionType"),
|
"change .mailpoet_automated_latest_content_include_or_exclude": _.partial(this.changeField, "inclusionType"),
|
||||||
"change .mailpoet_automated_latest_content_title_position": _.partial(this.changeField, "titlePosition"),
|
"change .mailpoet_automated_latest_content_title_position": _.partial(this.changeField, "titlePosition"),
|
||||||
"change .mailpoet_automated_latest_content_title_alignment": _.partial(this.changeField, "titleAlignment"),
|
"change .mailpoet_automated_latest_content_title_alignment": _.partial(this.changeField, "titleAlignment"),
|
||||||
"change .mailpoet_automated_latest_content_image_padded": _.partial(this.changeBoolField, "imagePadded"),
|
"change .mailpoet_automated_latest_content_image_full_width": _.partial(this.changeBoolField, "imageFullWidth"),
|
||||||
"change .mailpoet_automated_latest_content_show_author": _.partial(this.changeField, "showAuthor"),
|
"change .mailpoet_automated_latest_content_show_author": _.partial(this.changeField, "showAuthor"),
|
||||||
"keyup .mailpoet_automated_latest_content_author_preceded_by": _.partial(this.changeField, "authorPrecededBy"),
|
"keyup .mailpoet_automated_latest_content_author_preceded_by": _.partial(this.changeField, "authorPrecededBy"),
|
||||||
"change .mailpoet_automated_latest_content_show_categories": _.partial(this.changeField, "showCategories"),
|
"change .mailpoet_automated_latest_content_show_categories": _.partial(this.changeField, "showCategories"),
|
||||||
@ -161,7 +166,7 @@ define([
|
|||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
// Dynamically update available post types
|
// Dynamically update available post types
|
||||||
WordpressComponent.getPostTypes().done(_.bind(this._updateContentTypes, this));
|
CommunicationComponent.getPostTypes().done(_.bind(this._updateContentTypes, this));
|
||||||
|
|
||||||
this.$('.mailpoet_automated_latest_content_categories_and_tags').select2({
|
this.$('.mailpoet_automated_latest_content_categories_and_tags').select2({
|
||||||
multiple: true,
|
multiple: true,
|
||||||
@ -174,10 +179,10 @@ define([
|
|||||||
},
|
},
|
||||||
transport: function(options, success, failure) {
|
transport: function(options, success, failure) {
|
||||||
var taxonomies,
|
var taxonomies,
|
||||||
promise = WordpressComponent.getTaxonomies(that.model.get('contentType')).then(function(tax) {
|
promise = CommunicationComponent.getTaxonomies(that.model.get('contentType')).then(function(tax) {
|
||||||
taxonomies = tax;
|
taxonomies = tax;
|
||||||
// Fetch available terms based on the list of taxonomies already fetched
|
// Fetch available terms based on the list of taxonomies already fetched
|
||||||
var promise = WordpressComponent.getTerms({
|
var promise = CommunicationComponent.getTerms({
|
||||||
search: options.data.term,
|
search: options.data.term,
|
||||||
taxonomies: _.keys(taxonomies)
|
taxonomies: _.keys(taxonomies)
|
||||||
}).then(function(terms) {
|
}).then(function(terms) {
|
||||||
@ -226,11 +231,11 @@ define([
|
|||||||
toggleDisplayOptions: function(event) {
|
toggleDisplayOptions: function(event) {
|
||||||
var el = this.$('.mailpoet_automated_latest_content_display_options'),
|
var el = this.$('.mailpoet_automated_latest_content_display_options'),
|
||||||
showControl = this.$('.mailpoet_automated_latest_content_show_display_options');
|
showControl = this.$('.mailpoet_automated_latest_content_show_display_options');
|
||||||
if (el.hasClass('mailpoet_hidden')) {
|
if (el.hasClass('mailpoet_closed')) {
|
||||||
el.removeClass('mailpoet_hidden');
|
el.removeClass('mailpoet_closed');
|
||||||
showControl.addClass('mailpoet_hidden');
|
showControl.addClass('mailpoet_hidden');
|
||||||
} else {
|
} else {
|
||||||
el.addClass('mailpoet_hidden');
|
el.addClass('mailpoet_closed');
|
||||||
showControl.removeClass('mailpoet_hidden');
|
showControl.removeClass('mailpoet_hidden');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -306,7 +311,7 @@ define([
|
|||||||
_.each(postTypes, function(type) {
|
_.each(postTypes, function(type) {
|
||||||
select.append(jQuery('<option>', {
|
select.append(jQuery('<option>', {
|
||||||
value: type.name,
|
value: type.name,
|
||||||
text: type.labels.singular_name,
|
text: type.label,
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
select.val(selectedValue);
|
select.val(selectedValue);
|
||||||
|
@ -48,6 +48,7 @@ define([
|
|||||||
},
|
},
|
||||||
modelEvents: {
|
modelEvents: {
|
||||||
'change': 'render',
|
'change': 'render',
|
||||||
|
'delete': 'deleteBlock',
|
||||||
},
|
},
|
||||||
events: {
|
events: {
|
||||||
"mouseenter": "showTools",
|
"mouseenter": "showTools",
|
||||||
@ -88,7 +89,9 @@ define([
|
|||||||
this.$el.addClass('mailpoet_editor_view_' + this.cid);
|
this.$el.addClass('mailpoet_editor_view_' + this.cid);
|
||||||
},
|
},
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
this.on('showSettings', this.showSettings);
|
this.on('showSettings', this.showSettings, this);
|
||||||
|
this.on('dom:refresh', this.showBlock, this);
|
||||||
|
this._isFirstRender = true;
|
||||||
},
|
},
|
||||||
showTools: function(_event) {
|
showTools: function(_event) {
|
||||||
if (!this.showingToolsDisabled) {
|
if (!this.showingToolsDisabled) {
|
||||||
@ -114,12 +117,49 @@ define([
|
|||||||
* Defines drop behavior of BlockView instance
|
* Defines drop behavior of BlockView instance
|
||||||
*/
|
*/
|
||||||
getDropFunc: function() {
|
getDropFunc: function() {
|
||||||
var that = this;
|
|
||||||
return function() {
|
return function() {
|
||||||
var newModel = that.model.clone();
|
return this.model.clone();
|
||||||
//that.model.destroy();
|
}.bind(this);
|
||||||
return newModel;
|
},
|
||||||
};
|
showBlock: function() {
|
||||||
|
if (this._isFirstRender) {
|
||||||
|
this.transitionIn();
|
||||||
|
this._isFirstRender = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteBlock: function() {
|
||||||
|
this.transitionOut().then(function() {
|
||||||
|
this.model.destroy();
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
transitionIn: function() {
|
||||||
|
return this._transition('slideDown', 'fadeIn', 'easeOut');
|
||||||
|
},
|
||||||
|
transitionOut: function() {
|
||||||
|
return this._transition('slideUp', 'fadeOut', 'easeIn');
|
||||||
|
},
|
||||||
|
_transition: function(slideDirection, fadeDirection, easing) {
|
||||||
|
var promise = jQuery.Deferred();
|
||||||
|
|
||||||
|
this.$el.velocity(
|
||||||
|
slideDirection,
|
||||||
|
{
|
||||||
|
duration: 250,
|
||||||
|
easing: easing,
|
||||||
|
complete: function() {
|
||||||
|
promise.resolve();
|
||||||
|
}.bind(this),
|
||||||
|
}
|
||||||
|
).velocity(
|
||||||
|
fadeDirection,
|
||||||
|
{
|
||||||
|
duration: 250,
|
||||||
|
easing: easing,
|
||||||
|
queue: false, // Do not enqueue, trigger animation in parallel
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return promise;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -168,24 +208,22 @@ define([
|
|||||||
},
|
},
|
||||||
deleteBlock: function(event) {
|
deleteBlock: function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
this.model.destroy();
|
this.model.trigger('delete');
|
||||||
return false;
|
return false;
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Module.BlockSettingsView = Marionette.LayoutView.extend({
|
Module.BlockSettingsView = Marionette.LayoutView.extend({
|
||||||
className: 'mailpoet_editor_settings',
|
className: 'mailpoet_editor_settings',
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
var that = this;
|
|
||||||
|
|
||||||
MailPoet.Modal.panel({
|
MailPoet.Modal.panel({
|
||||||
element: this.$el,
|
element: this.$el,
|
||||||
template: '',
|
template: '',
|
||||||
position: 'right',
|
position: 'right',
|
||||||
width: App.getConfig().get('sidepanelWidth'),
|
width: App.getConfig().get('sidepanelWidth'),
|
||||||
onCancel: function() {
|
onCancel: function() {
|
||||||
that.destroy();
|
this.destroy();
|
||||||
},
|
}.bind(this),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
close: function(event) {
|
close: function(event) {
|
||||||
@ -203,6 +241,9 @@ define([
|
|||||||
changeBoolField: function(field, event) {
|
changeBoolField: function(field, event) {
|
||||||
this.model.set(field, (jQuery(event.target).val() === 'true') ? true : false);
|
this.model.set(field, (jQuery(event.target).val() === 'true') ? true : false);
|
||||||
},
|
},
|
||||||
|
changeBoolCheckboxField: function(field, event) {
|
||||||
|
this.model.set(field, (!!jQuery(event.target).prop('checked')));
|
||||||
|
},
|
||||||
changeColorField: function(field, event) {
|
changeColorField: function(field, event) {
|
||||||
var value = jQuery(event.target).val();
|
var value = jQuery(event.target).val();
|
||||||
if (value === '') {
|
if (value === '') {
|
||||||
|
@ -42,16 +42,12 @@ define([
|
|||||||
Module.ButtonBlockView = base.BlockView.extend({
|
Module.ButtonBlockView = base.BlockView.extend({
|
||||||
className: "mailpoet_block mailpoet_button_block mailpoet_droppable_block",
|
className: "mailpoet_block mailpoet_button_block mailpoet_droppable_block",
|
||||||
getTemplate: function() { return templates.buttonBlock; },
|
getTemplate: function() { return templates.buttonBlock; },
|
||||||
modelEvents: {
|
|
||||||
'change': 'render',
|
|
||||||
},
|
|
||||||
onDragSubstituteBy: function() { return Module.ButtonWidgetView; },
|
onDragSubstituteBy: function() { return Module.ButtonWidgetView; },
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
base.BlockView.prototype.initialize.apply(this, arguments);
|
base.BlockView.prototype.initialize.apply(this, arguments);
|
||||||
var that = this;
|
|
||||||
|
|
||||||
// Listen for attempts to change all dividers in one go
|
// Listen for attempts to change all dividers in one go
|
||||||
this._replaceButtonStylesHandler = function(data) { that.model.set(data); };
|
this._replaceButtonStylesHandler = function(data) { this.model.set(data); }.bind(this);
|
||||||
App.getChannel().on('replaceAllButtonStyles', this._replaceButtonStylesHandler);
|
App.getChannel().on('replaceAllButtonStyles', this._replaceButtonStylesHandler);
|
||||||
},
|
},
|
||||||
onRender: function() {
|
onRender: function() {
|
||||||
|
@ -75,7 +75,8 @@ define([
|
|||||||
getEmptyView: function() { return Module.ContainerBlockEmptyView; },
|
getEmptyView: function() { return Module.ContainerBlockEmptyView; },
|
||||||
emptyViewOptions: function() { return { renderOptions: this.renderOptions }; },
|
emptyViewOptions: function() { return { renderOptions: this.renderOptions }; },
|
||||||
modelEvents: {
|
modelEvents: {
|
||||||
'change': 'render'
|
'change': 'render',
|
||||||
|
'delete': 'deleteBlock',
|
||||||
},
|
},
|
||||||
events: {
|
events: {
|
||||||
"mouseenter": "showTools",
|
"mouseenter": "showTools",
|
||||||
@ -136,6 +137,8 @@ define([
|
|||||||
},
|
},
|
||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
this.renderOptions = _.defaults(options.renderOptions || {}, {});
|
this.renderOptions = _.defaults(options.renderOptions || {}, {});
|
||||||
|
this.on('dom:refresh', this.showBlock, this);
|
||||||
|
this._isFirstRender = true;
|
||||||
},
|
},
|
||||||
// Determines which view type should be used for a child
|
// Determines which view type should be used for a child
|
||||||
getChildView: function(model) {
|
getChildView: function(model) {
|
||||||
@ -162,10 +165,10 @@ define([
|
|||||||
this.toolsView = new Module.ContainerBlockToolsView({
|
this.toolsView = new Module.ContainerBlockToolsView({
|
||||||
model: this.model,
|
model: this.model,
|
||||||
tools: {
|
tools: {
|
||||||
settings: this.renderOptions.depth > 1,
|
settings: this.renderOptions.depth === 1,
|
||||||
delete: this.renderOptions.depth === 1,
|
delete: this.renderOptions.depth === 1,
|
||||||
move: this.renderOptions.depth === 1,
|
move: this.renderOptions.depth === 1,
|
||||||
layerSelector: this.renderOptions.depth === 1,
|
layerSelector: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
this.toolsRegion.show(this.toolsView);
|
this.toolsRegion.show(this.toolsView);
|
||||||
@ -229,12 +232,49 @@ define([
|
|||||||
_.extend(this, this._buildRegions(this.regions));
|
_.extend(this, this._buildRegions(this.regions));
|
||||||
},
|
},
|
||||||
getDropFunc: function() {
|
getDropFunc: function() {
|
||||||
var that = this;
|
|
||||||
return function() {
|
return function() {
|
||||||
var newModel = that.model.clone();
|
return this.model.clone();
|
||||||
that.model.destroy();
|
}.bind(this);
|
||||||
return newModel;
|
},
|
||||||
};
|
showBlock: function() {
|
||||||
|
if (this._isFirstRender) {
|
||||||
|
this.transitionIn();
|
||||||
|
this._isFirstRender = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteBlock: function() {
|
||||||
|
this.transitionOut().done(function() {
|
||||||
|
this.model.destroy();
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
transitionIn: function() {
|
||||||
|
return this._transition('slideDown', 'fadeIn', 'easeIn');
|
||||||
|
},
|
||||||
|
transitionOut: function() {
|
||||||
|
return this._transition('slideUp', 'fadeOut', 'easeOut');
|
||||||
|
},
|
||||||
|
_transition: function(slideDirection, fadeDirection, easing) {
|
||||||
|
var promise = jQuery.Deferred();
|
||||||
|
|
||||||
|
this.$el.velocity(
|
||||||
|
slideDirection,
|
||||||
|
{
|
||||||
|
duration: 250,
|
||||||
|
easing: easing,
|
||||||
|
complete: function() {
|
||||||
|
promise.resolve();
|
||||||
|
}.bind(this),
|
||||||
|
}
|
||||||
|
).velocity(
|
||||||
|
fadeDirection,
|
||||||
|
{
|
||||||
|
duration: 250,
|
||||||
|
easing: easing,
|
||||||
|
queue: false, // Do not enqueue, trigger animation in parallel
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return promise;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -265,6 +305,41 @@ define([
|
|||||||
behaviors: {
|
behaviors: {
|
||||||
ColorPickerBehavior: {},
|
ColorPickerBehavior: {},
|
||||||
},
|
},
|
||||||
|
regions: {
|
||||||
|
columnsSettingsRegion: '.mailpoet_container_columns_settings',
|
||||||
|
},
|
||||||
|
initialize: function() {
|
||||||
|
base.BlockSettingsView.prototype.initialize.apply(this, arguments);
|
||||||
|
|
||||||
|
this._columnsSettingsView = new (Module.ContainerBlockColumnsSettingsView)({
|
||||||
|
collection: this.model.get('blocks'),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
onRender: function() {
|
||||||
|
this.columnsSettingsRegion.show(this._columnsSettingsView);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Module.ContainerBlockColumnsSettingsView = Marionette.CollectionView.extend({
|
||||||
|
getChildView: function() { return Module.ContainerBlockColumnSettingsView; },
|
||||||
|
childViewOptions: function(model, index) {
|
||||||
|
return {
|
||||||
|
columnIndex: index,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Module.ContainerBlockColumnSettingsView = Marionette.ItemView.extend({
|
||||||
|
getTemplate: function() { return templates.containerBlockColumnSettings; },
|
||||||
|
initialize: function(options) {
|
||||||
|
this.columnNumber = (options.columnIndex || 0) + 1;
|
||||||
|
},
|
||||||
|
templateHelpers: function() {
|
||||||
|
return {
|
||||||
|
model: this.model.toJSON(),
|
||||||
|
columnNumber: this.columnNumber,
|
||||||
|
};
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Module.OneColumnContainerWidgetView = base.WidgetView.extend({
|
Module.OneColumnContainerWidgetView = base.WidgetView.extend({
|
||||||
|
@ -57,11 +57,9 @@ define([
|
|||||||
this.listenTo(this.model, 'change:styles.block.padding', this.changePadding);
|
this.listenTo(this.model, 'change:styles.block.padding', this.changePadding);
|
||||||
},
|
},
|
||||||
templateHelpers: function() {
|
templateHelpers: function() {
|
||||||
return {
|
return _.extend({
|
||||||
model: this.model.toJSON(),
|
|
||||||
viewCid: this.cid,
|
|
||||||
totalHeight: parseInt(this.model.get('styles.block.padding'), 10)*2 + parseInt(this.model.get('styles.block.borderWidth')) + 'px',
|
totalHeight: parseInt(this.model.get('styles.block.padding'), 10)*2 + parseInt(this.model.get('styles.block.borderWidth')) + 'px',
|
||||||
};
|
}, base.BlockView.prototype.templateHelpers.apply(this));
|
||||||
},
|
},
|
||||||
onRender: function() {
|
onRender: function() {
|
||||||
this.toolsView = new Module.DividerBlockToolsView({ model: this.model });
|
this.toolsView = new Module.DividerBlockToolsView({ model: this.model });
|
||||||
|
@ -39,9 +39,9 @@ define([
|
|||||||
Module.FooterBlockView = base.BlockView.extend({
|
Module.FooterBlockView = base.BlockView.extend({
|
||||||
className: "mailpoet_block mailpoet_footer_block mailpoet_droppable_block",
|
className: "mailpoet_block mailpoet_footer_block mailpoet_droppable_block",
|
||||||
getTemplate: function() { return templates.footerBlock; },
|
getTemplate: function() { return templates.footerBlock; },
|
||||||
modelEvents: {
|
modelEvents: _.extend({
|
||||||
'change:styles.block.backgroundColor change:styles.text.fontColor change:styles.text.fontFamily change:styles.text.fontSize change:styles.text.textAlign change:styles.link.fontColor change:styles.link.textDecoration': 'render',
|
'change:styles.block.backgroundColor change:styles.text.fontColor change:styles.text.fontFamily change:styles.text.fontSize change:styles.text.textAlign change:styles.link.fontColor change:styles.link.textDecoration': 'render',
|
||||||
},
|
}, base.BlockView.prototype.modelEvents),
|
||||||
onDragSubstituteBy: function() { return Module.FooterWidgetView; },
|
onDragSubstituteBy: function() { return Module.FooterWidgetView; },
|
||||||
onRender: function() {
|
onRender: function() {
|
||||||
this.toolsView = new Module.FooterBlockToolsView({ model: this.model });
|
this.toolsView = new Module.FooterBlockToolsView({ model: this.model });
|
||||||
|
@ -39,9 +39,9 @@ define([
|
|||||||
Module.HeaderBlockView = base.BlockView.extend({
|
Module.HeaderBlockView = base.BlockView.extend({
|
||||||
className: "mailpoet_block mailpoet_header_block mailpoet_droppable_block",
|
className: "mailpoet_block mailpoet_header_block mailpoet_droppable_block",
|
||||||
getTemplate: function() { return templates.headerBlock; },
|
getTemplate: function() { return templates.headerBlock; },
|
||||||
modelEvents: {
|
modelEvents: _.extend({
|
||||||
'change:styles.block.backgroundColor change:styles.text.fontColor change:styles.text.fontFamily change:styles.text.fontSize change:styles.text.textAlign change:styles.link.fontColor change:styles.link.textDecoration': 'render',
|
'change:styles.block.backgroundColor change:styles.text.fontColor change:styles.text.fontFamily change:styles.text.fontSize change:styles.text.textAlign change:styles.link.fontColor change:styles.link.textDecoration': 'render',
|
||||||
},
|
}, base.BlockView.prototype.modelEvents),
|
||||||
onDragSubstituteBy: function() { return Module.HeaderWidgetView; },
|
onDragSubstituteBy: function() { return Module.HeaderWidgetView; },
|
||||||
onRender: function() {
|
onRender: function() {
|
||||||
this.toolsView = new Module.HeaderBlockToolsView({ model: this.model });
|
this.toolsView = new Module.HeaderBlockToolsView({ model: this.model });
|
||||||
|
@ -20,7 +20,7 @@ define([
|
|||||||
link: 'http://example.org',
|
link: 'http://example.org',
|
||||||
src: 'no-image.png',
|
src: 'no-image.png',
|
||||||
alt: 'An image of...',
|
alt: 'An image of...',
|
||||||
padded: true, // true | false - Padded or full width
|
fullWidth: true, // true | false
|
||||||
width: '64px',
|
width: '64px',
|
||||||
height: '64px',
|
height: '64px',
|
||||||
styles: {
|
styles: {
|
||||||
@ -37,20 +37,18 @@ define([
|
|||||||
getTemplate: function() { return templates.imageBlock; },
|
getTemplate: function() { return templates.imageBlock; },
|
||||||
onDragSubstituteBy: function() { return Module.ImageWidgetView; },
|
onDragSubstituteBy: function() { return Module.ImageWidgetView; },
|
||||||
templateHelpers: function() {
|
templateHelpers: function() {
|
||||||
return {
|
return _.extend({
|
||||||
model: this.model.toJSON(),
|
|
||||||
viewCid: this.cid,
|
|
||||||
imageMissingSrc: App.getConfig().get('urls.imageMissing'),
|
imageMissingSrc: App.getConfig().get('urls.imageMissing'),
|
||||||
};
|
}, base.BlockView.prototype.templateHelpers.apply(this));
|
||||||
},
|
},
|
||||||
onRender: function() {
|
onRender: function() {
|
||||||
this.toolsView = new Module.ImageBlockToolsView({ model: this.model });
|
this.toolsView = new Module.ImageBlockToolsView({ model: this.model });
|
||||||
this.toolsRegion.show(this.toolsView);
|
this.toolsRegion.show(this.toolsView);
|
||||||
|
|
||||||
if (this.model.get('padded')) {
|
if (this.model.get('fullWidth')) {
|
||||||
this.$el.removeClass('mailpoet_full_image');
|
|
||||||
} else {
|
|
||||||
this.$el.addClass('mailpoet_full_image');
|
this.$el.addClass('mailpoet_full_image');
|
||||||
|
} else {
|
||||||
|
this.$el.removeClass('mailpoet_full_image');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -66,7 +64,7 @@ define([
|
|||||||
"keyup .mailpoet_field_image_link": _.partial(this.changeField, "link"),
|
"keyup .mailpoet_field_image_link": _.partial(this.changeField, "link"),
|
||||||
"keyup .mailpoet_field_image_address": _.partial(this.changeField, "src"),
|
"keyup .mailpoet_field_image_address": _.partial(this.changeField, "src"),
|
||||||
"keyup .mailpoet_field_image_alt_text": _.partial(this.changeField, "alt"),
|
"keyup .mailpoet_field_image_alt_text": _.partial(this.changeField, "alt"),
|
||||||
"change .mailpoet_field_image_padded": _.partial(this.changeBoolField, "padded"),
|
"change .mailpoet_field_image_full_width": _.partial(this.changeBoolCheckboxField, "fullWidth"),
|
||||||
"change .mailpoet_field_image_alignment": _.partial(this.changeField, "styles.block.textAlign"),
|
"change .mailpoet_field_image_alignment": _.partial(this.changeField, "styles.block.textAlign"),
|
||||||
"click .mailpoet_field_image_select_another_image": "showMediaManager",
|
"click .mailpoet_field_image_select_another_image": "showMediaManager",
|
||||||
"click .mailpoet_done_editing": "close",
|
"click .mailpoet_done_editing": "close",
|
||||||
|
@ -18,12 +18,12 @@ define([
|
|||||||
'jquery',
|
'jquery',
|
||||||
'mailpoet',
|
'mailpoet',
|
||||||
'newsletter_editor/App',
|
'newsletter_editor/App',
|
||||||
'newsletter_editor/components/wordpress',
|
'newsletter_editor/components/communication',
|
||||||
'newsletter_editor/blocks/base',
|
'newsletter_editor/blocks/base',
|
||||||
'newsletter_editor/blocks/button',
|
'newsletter_editor/blocks/button',
|
||||||
'newsletter_editor/blocks/divider',
|
'newsletter_editor/blocks/divider',
|
||||||
'select2'
|
'select2'
|
||||||
], function(Backbone, Marionette, Radio, _, jQuery, MailPoet, App, WordpressComponent, BaseBlock, ButtonBlock, DividerBlock) {
|
], function(Backbone, Marionette, Radio, _, jQuery, MailPoet, App, CommunicationComponent, BaseBlock, ButtonBlock, DividerBlock) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ define([
|
|||||||
base = BaseBlock;
|
base = BaseBlock;
|
||||||
|
|
||||||
Module.PostsBlockModel = base.BlockModel.extend({
|
Module.PostsBlockModel = base.BlockModel.extend({
|
||||||
stale: ['_selectedPosts', '_availablePosts'],
|
stale: ['_selectedPosts', '_availablePosts', '_transformedPosts'],
|
||||||
defaults: function() {
|
defaults: function() {
|
||||||
return this._getDefaults({
|
return this._getDefaults({
|
||||||
type: 'posts',
|
type: 'posts',
|
||||||
@ -46,7 +46,7 @@ define([
|
|||||||
titlePosition: 'inTextBlock', // 'inTextBlock'|'aboveBlock',
|
titlePosition: 'inTextBlock', // 'inTextBlock'|'aboveBlock',
|
||||||
titleAlignment: 'left', // 'left'|'center'|'right'
|
titleAlignment: 'left', // 'left'|'center'|'right'
|
||||||
titleIsLink: false, // false|true
|
titleIsLink: false, // false|true
|
||||||
imagePadded: true, // true|false
|
imageFullWidth: false, // true|false
|
||||||
//imageAlignment: 'centerPadded', // 'centerFull'|'centerPadded'|'left'|'right'|'alternate'|'none'
|
//imageAlignment: 'centerPadded', // 'centerFull'|'centerPadded'|'left'|'right'|'alternate'|'none'
|
||||||
showAuthor: 'no', // 'no'|'aboveText'|'belowText'
|
showAuthor: 'no', // 'no'|'aboveText'|'belowText'
|
||||||
authorPrecededBy: 'Author:',
|
authorPrecededBy: 'Author:',
|
||||||
@ -63,6 +63,7 @@ define([
|
|||||||
divider: {},
|
divider: {},
|
||||||
_selectedPosts: [],
|
_selectedPosts: [],
|
||||||
_availablePosts: [],
|
_availablePosts: [],
|
||||||
|
_transformedPosts: new (App.getBlockTypeModel('container'))(),
|
||||||
}, App.getConfig().get('blockDefaults.posts'));
|
}, App.getConfig().get('blockDefaults.posts'));
|
||||||
},
|
},
|
||||||
relations: function() {
|
relations: function() {
|
||||||
@ -71,21 +72,31 @@ define([
|
|||||||
divider: App.getBlockTypeModel('divider'),
|
divider: App.getBlockTypeModel('divider'),
|
||||||
_selectedPosts: Backbone.Collection,
|
_selectedPosts: Backbone.Collection,
|
||||||
_availablePosts: Backbone.Collection,
|
_availablePosts: Backbone.Collection,
|
||||||
|
_transformedPosts: App.getBlockTypeModel('container'),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
var that = this;
|
var that = this,
|
||||||
|
POST_REFRESH_DELAY_MS = 500,
|
||||||
|
refreshAvailablePosts = _.debounce(this.fetchAvailablePosts.bind(this), POST_REFRESH_DELAY_MS),
|
||||||
|
refreshTransformedPosts = _.debounce(this._refreshTransformedPosts.bind(this), POST_REFRESH_DELAY_MS);
|
||||||
|
|
||||||
// Attach Radio.Requests API primarily for highlighting
|
// Attach Radio.Requests API primarily for highlighting
|
||||||
_.extend(this, Radio.Requests);
|
_.extend(this, Radio.Requests);
|
||||||
|
|
||||||
this.fetchAvailablePosts();
|
this.fetchAvailablePosts();
|
||||||
this.on('change:amount change:contentType change:terms change:inclusionType change:postStatus change:search change:sortBy', this._scheduleFetchAvailablePosts, this);
|
this.on('change:amount change:contentType change:terms change:inclusionType change:postStatus change:search change:sortBy', refreshAvailablePosts);
|
||||||
|
|
||||||
|
this.listenTo(this.get('_selectedPosts'), 'add remove reset', refreshTransformedPosts);
|
||||||
|
this.on('change:displayType change:titleFormat change:titlePosition change:titleAlignment change:titleIsLink change:imageFullWidth change:showAuthor change:authorPrecededBy change:showCategories change:categoriesPrecededBy change:readMoreType change:readMoreText change:showDivider', refreshTransformedPosts);
|
||||||
|
this.listenTo(this.get('readMoreButton'), 'change', refreshTransformedPosts);
|
||||||
|
this.listenTo(this.get('divider'), 'change', refreshTransformedPosts);
|
||||||
|
|
||||||
this.on('insertSelectedPosts', this._insertSelectedPosts, this);
|
this.on('insertSelectedPosts', this._insertSelectedPosts, this);
|
||||||
},
|
},
|
||||||
fetchAvailablePosts: function() {
|
fetchAvailablePosts: function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
WordpressComponent.getPosts(this.toJSON()).done(function(posts) {
|
CommunicationComponent.getPosts(this.toJSON()).done(function(posts) {
|
||||||
console.log('Posts fetched', arguments);
|
|
||||||
that.get('_availablePosts').reset(posts);
|
that.get('_availablePosts').reset(posts);
|
||||||
that.get('_selectedPosts').reset(); // Empty out the collection
|
that.get('_selectedPosts').reset(); // Empty out the collection
|
||||||
that.trigger('change:_availablePosts');
|
that.trigger('change:_availablePosts');
|
||||||
@ -93,20 +104,22 @@ define([
|
|||||||
console.log('Posts fetchPosts error', arguments);
|
console.log('Posts fetchPosts error', arguments);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
/**
|
_refreshTransformedPosts: function() {
|
||||||
* Batch more changes during a specific time, instead of fetching
|
var that = this,
|
||||||
* ALC posts on each model change
|
data = this.toJSON();
|
||||||
*/
|
|
||||||
_scheduleFetchAvailablePosts: function() {
|
data.posts = this.get('_selectedPosts').pluck('ID');
|
||||||
var timeout = 500,
|
|
||||||
that = this;
|
if (data.posts.length === 0) {
|
||||||
if (this._fetchPostsTimer !== undefined) {
|
this.get('_transformedPosts.blocks').reset();
|
||||||
clearTimeout(this._fetchPostsTimer);
|
return;
|
||||||
}
|
}
|
||||||
this._fetchPostsTimer = setTimeout(function() {
|
|
||||||
that.fetchAvailablePosts();
|
CommunicationComponent.getTransformedPosts(data).done(function(posts) {
|
||||||
that._fetchPostsTimer = undefined;
|
that.get('_transformedPosts').get('blocks').reset(posts, {parse: true});
|
||||||
}, timeout);
|
}).fail(function() {
|
||||||
|
console.log('Posts _refreshTransformedPosts error', arguments);
|
||||||
|
});
|
||||||
},
|
},
|
||||||
_insertSelectedPosts: function() {
|
_insertSelectedPosts: function() {
|
||||||
var that = this,
|
var that = this,
|
||||||
@ -118,8 +131,7 @@ define([
|
|||||||
|
|
||||||
if (data.posts.length === 0) return;
|
if (data.posts.length === 0) return;
|
||||||
|
|
||||||
WordpressComponent.getTransformedPosts(data).done(function(posts) {
|
CommunicationComponent.getTransformedPosts(data).done(function(posts) {
|
||||||
console.log('Available posts fetched', arguments);
|
|
||||||
collection.add(posts, { at: index });
|
collection.add(posts, { at: index });
|
||||||
}).fail(function() {
|
}).fail(function() {
|
||||||
console.log('Posts fetchPosts error', arguments);
|
console.log('Posts fetchPosts error', arguments);
|
||||||
@ -130,10 +142,14 @@ define([
|
|||||||
Module.PostsBlockView = base.BlockView.extend({
|
Module.PostsBlockView = base.BlockView.extend({
|
||||||
className: "mailpoet_block mailpoet_posts_block mailpoet_droppable_block",
|
className: "mailpoet_block mailpoet_posts_block mailpoet_droppable_block",
|
||||||
getTemplate: function() { return templates.postsBlock; },
|
getTemplate: function() { return templates.postsBlock; },
|
||||||
modelEvents: {},
|
modelEvents: {}, // Forcefully disable all events
|
||||||
|
regions: _.extend({
|
||||||
|
postsRegion: '.mailpoet_posts_block_posts',
|
||||||
|
}, base.BlockView.prototype.regions),
|
||||||
onDragSubstituteBy: function() { return Module.PostsWidgetView; },
|
onDragSubstituteBy: function() { return Module.PostsWidgetView; },
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
base.BlockView.prototype.initialize.apply(this, arguments);
|
base.BlockView.prototype.initialize.apply(this, arguments);
|
||||||
|
|
||||||
this.toolsView = new Module.PostsBlockToolsView({ model: this.model });
|
this.toolsView = new Module.PostsBlockToolsView({ model: this.model });
|
||||||
this.model.reply('blockView', this.notifyAboutSelf, this);
|
this.model.reply('blockView', this.notifyAboutSelf, this);
|
||||||
},
|
},
|
||||||
@ -142,6 +158,13 @@ define([
|
|||||||
this.toolsRegion.show(this.toolsView);
|
this.toolsRegion.show(this.toolsView);
|
||||||
}
|
}
|
||||||
this.trigger('showSettings');
|
this.trigger('showSettings');
|
||||||
|
|
||||||
|
var ContainerView = App.getBlockTypeView('container'),
|
||||||
|
renderOptions = {
|
||||||
|
disableTextEditor: true,
|
||||||
|
disableDragAndDrop: true,
|
||||||
|
};
|
||||||
|
this.postsRegion.show(new ContainerView({ model: this.model.get('_transformedPosts'), renderOptions: renderOptions }));
|
||||||
},
|
},
|
||||||
notifyAboutSelf: function() {
|
notifyAboutSelf: function() {
|
||||||
return this;
|
return this;
|
||||||
@ -197,8 +220,8 @@ define([
|
|||||||
},
|
},
|
||||||
switchToDisplayOptions: function() {
|
switchToDisplayOptions: function() {
|
||||||
// Switch content view
|
// Switch content view
|
||||||
this.$('.mailpoet_settings_posts_selection').addClass('mailpoet_hidden');
|
this.$('.mailpoet_settings_posts_selection').addClass('mailpoet_closed');
|
||||||
this.$('.mailpoet_settings_posts_display_options').removeClass('mailpoet_hidden');
|
this.$('.mailpoet_settings_posts_display_options').removeClass('mailpoet_closed');
|
||||||
|
|
||||||
// Switch controls
|
// Switch controls
|
||||||
this.$('.mailpoet_settings_posts_show_display_options').addClass('mailpoet_hidden');
|
this.$('.mailpoet_settings_posts_show_display_options').addClass('mailpoet_hidden');
|
||||||
@ -206,8 +229,8 @@ define([
|
|||||||
},
|
},
|
||||||
switchToPostSelection: function() {
|
switchToPostSelection: function() {
|
||||||
// Switch content view
|
// Switch content view
|
||||||
this.$('.mailpoet_settings_posts_display_options').addClass('mailpoet_hidden');
|
this.$('.mailpoet_settings_posts_display_options').addClass('mailpoet_closed');
|
||||||
this.$('.mailpoet_settings_posts_selection').removeClass('mailpoet_hidden');
|
this.$('.mailpoet_settings_posts_selection').removeClass('mailpoet_closed');
|
||||||
|
|
||||||
// Switch controls
|
// Switch controls
|
||||||
this.$('.mailpoet_settings_posts_show_post_selection').addClass('mailpoet_hidden');
|
this.$('.mailpoet_settings_posts_show_post_selection').addClass('mailpoet_hidden');
|
||||||
@ -216,6 +239,7 @@ define([
|
|||||||
insertPosts: function() {
|
insertPosts: function() {
|
||||||
this.model.trigger('insertSelectedPosts');
|
this.model.trigger('insertSelectedPosts');
|
||||||
this.model.destroy();
|
this.model.destroy();
|
||||||
|
this.close();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -245,7 +269,7 @@ define([
|
|||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
// Dynamically update available post types
|
// Dynamically update available post types
|
||||||
WordpressComponent.getPostTypes().done(_.bind(this._updateContentTypes, this));
|
CommunicationComponent.getPostTypes().done(_.bind(this._updateContentTypes, this));
|
||||||
|
|
||||||
this.$('.mailpoet_posts_categories_and_tags').select2({
|
this.$('.mailpoet_posts_categories_and_tags').select2({
|
||||||
multiple: true,
|
multiple: true,
|
||||||
@ -258,10 +282,10 @@ define([
|
|||||||
},
|
},
|
||||||
transport: function(options, success, failure) {
|
transport: function(options, success, failure) {
|
||||||
var taxonomies,
|
var taxonomies,
|
||||||
promise = WordpressComponent.getTaxonomies(that.model.get('contentType')).then(function(tax) {
|
promise = CommunicationComponent.getTaxonomies(that.model.get('contentType')).then(function(tax) {
|
||||||
taxonomies = tax;
|
taxonomies = tax;
|
||||||
// Fetch available terms based on the list of taxonomies already fetched
|
// Fetch available terms based on the list of taxonomies already fetched
|
||||||
var promise = WordpressComponent.getTerms({
|
var promise = CommunicationComponent.getTerms({
|
||||||
search: options.data.term,
|
search: options.data.term,
|
||||||
taxonomies: _.keys(taxonomies)
|
taxonomies: _.keys(taxonomies)
|
||||||
}).then(function(terms) {
|
}).then(function(terms) {
|
||||||
@ -307,11 +331,6 @@ define([
|
|||||||
},
|
},
|
||||||
}).trigger( 'change' );
|
}).trigger( 'change' );
|
||||||
},
|
},
|
||||||
onBeforeDestroy: function() {
|
|
||||||
base.BlockSettingsView.prototype.onBeforeDestroy.apply(this, arguments);
|
|
||||||
// Force close select2 if it hasn't closed yet
|
|
||||||
this.$('.mailpoet_posts_categories_and_tags').select2('close');
|
|
||||||
},
|
|
||||||
changeField: function(field, event) {
|
changeField: function(field, event) {
|
||||||
this.model.set(field, jQuery(event.target).val());
|
this.model.set(field, jQuery(event.target).val());
|
||||||
},
|
},
|
||||||
@ -323,7 +342,7 @@ define([
|
|||||||
_.each(postTypes, function(type) {
|
_.each(postTypes, function(type) {
|
||||||
select.append(jQuery('<option>', {
|
select.append(jQuery('<option>', {
|
||||||
value: type.name,
|
value: type.name,
|
||||||
text: type.labels.singular_name,
|
text: type.label,
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
select.val(selectedValue);
|
select.val(selectedValue);
|
||||||
@ -377,7 +396,7 @@ define([
|
|||||||
"change .mailpoet_posts_include_or_exclude": _.partial(this.changeField, "inclusionType"),
|
"change .mailpoet_posts_include_or_exclude": _.partial(this.changeField, "inclusionType"),
|
||||||
"change .mailpoet_posts_title_position": _.partial(this.changeField, "titlePosition"),
|
"change .mailpoet_posts_title_position": _.partial(this.changeField, "titlePosition"),
|
||||||
"change .mailpoet_posts_title_alignment": _.partial(this.changeField, "titleAlignment"),
|
"change .mailpoet_posts_title_alignment": _.partial(this.changeField, "titleAlignment"),
|
||||||
"change .mailpoet_posts_image_padded": _.partial(this.changeBoolField, "imagePadded"),
|
"change .mailpoet_posts_image_full_width": _.partial(this.changeBoolField, "imageFullWidth"),
|
||||||
"change .mailpoet_posts_show_author": _.partial(this.changeField, "showAuthor"),
|
"change .mailpoet_posts_show_author": _.partial(this.changeField, "showAuthor"),
|
||||||
"keyup .mailpoet_posts_author_preceded_by": _.partial(this.changeField, "authorPrecededBy"),
|
"keyup .mailpoet_posts_author_preceded_by": _.partial(this.changeField, "authorPrecededBy"),
|
||||||
"change .mailpoet_posts_show_categories": _.partial(this.changeField, "showCategories"),
|
"change .mailpoet_posts_show_categories": _.partial(this.changeField, "showCategories"),
|
||||||
|
@ -103,7 +103,8 @@ define([
|
|||||||
getTemplate: function() { return templates.socialBlock; },
|
getTemplate: function() { return templates.socialBlock; },
|
||||||
childViewContainer: '.mailpoet_social',
|
childViewContainer: '.mailpoet_social',
|
||||||
modelEvents: {
|
modelEvents: {
|
||||||
'change': 'render'
|
'change': 'render',
|
||||||
|
'delete': 'deleteBlock',
|
||||||
},
|
},
|
||||||
events: {
|
events: {
|
||||||
"mouseover": "showTools",
|
"mouseover": "showTools",
|
||||||
@ -145,6 +146,10 @@ define([
|
|||||||
arguments[0].collection = arguments[0].model.get('icons');
|
arguments[0].collection = arguments[0].model.get('icons');
|
||||||
Marionette.CompositeView.apply(this, arguments);
|
Marionette.CompositeView.apply(this, arguments);
|
||||||
},
|
},
|
||||||
|
initialize: function() {
|
||||||
|
this.on('dom:refresh', this.showBlock, this);
|
||||||
|
this._isFirstRender = true;
|
||||||
|
},
|
||||||
// Determines which view type should be used for a child
|
// Determines which view type should be used for a child
|
||||||
childView: SocialIconView,
|
childView: SocialIconView,
|
||||||
templateHelpers: function() {
|
templateHelpers: function() {
|
||||||
@ -170,12 +175,9 @@ define([
|
|||||||
_event.stopPropagation();
|
_event.stopPropagation();
|
||||||
},
|
},
|
||||||
getDropFunc: function() {
|
getDropFunc: function() {
|
||||||
var that = this;
|
|
||||||
return function() {
|
return function() {
|
||||||
var newModel = that.model.clone();
|
return this.model.clone();
|
||||||
//that.model.destroy();
|
}.bind(this);
|
||||||
return newModel;
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
_buildRegions: function(regions) {
|
_buildRegions: function(regions) {
|
||||||
var that = this;
|
var that = this;
|
||||||
@ -194,6 +196,46 @@ define([
|
|||||||
this.regionManager.destroy();
|
this.regionManager.destroy();
|
||||||
_.extend(this, this._buildRegions(this.regions));
|
_.extend(this, this._buildRegions(this.regions));
|
||||||
},
|
},
|
||||||
|
showBlock: function() {
|
||||||
|
if (this._isFirstRender) {
|
||||||
|
this.transitionIn();
|
||||||
|
this._isFirstRender = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteBlock: function() {
|
||||||
|
this.transitionOut().done(function() {
|
||||||
|
this.model.destroy();
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
transitionIn: function() {
|
||||||
|
return this._transition('slideDown', 'fadeIn', 'easeIn');
|
||||||
|
},
|
||||||
|
transitionOut: function() {
|
||||||
|
return this._transition('slideUp', 'fadeOut', 'easeOut');
|
||||||
|
},
|
||||||
|
_transition: function(slideDirection, fadeDirection, easing) {
|
||||||
|
var promise = jQuery.Deferred();
|
||||||
|
|
||||||
|
this.$el.velocity(
|
||||||
|
slideDirection,
|
||||||
|
{
|
||||||
|
duration: 250,
|
||||||
|
easing: easing,
|
||||||
|
complete: function() {
|
||||||
|
promise.resolve();
|
||||||
|
}.bind(this),
|
||||||
|
}
|
||||||
|
).velocity(
|
||||||
|
fadeDirection,
|
||||||
|
{
|
||||||
|
duration: 250,
|
||||||
|
easing: easing,
|
||||||
|
queue: false, // Do not enqueue, trigger animation in parallel
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return promise;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Module.SocialBlockToolsView = base.BlockToolsView.extend({
|
Module.SocialBlockToolsView = base.BlockToolsView.extend({
|
||||||
|
@ -26,6 +26,8 @@ define([
|
|||||||
getTemplate: function() { return templates.textBlock; },
|
getTemplate: function() { return templates.textBlock; },
|
||||||
modelEvents: _.omit(base.BlockView.prototype.modelEvents, 'change'), // Prevent rerendering on model change due to text editor redrawing
|
modelEvents: _.omit(base.BlockView.prototype.modelEvents, 'change'), // Prevent rerendering on model change due to text editor redrawing
|
||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
|
base.BlockView.prototype.initialize.apply(this, arguments);
|
||||||
|
|
||||||
this.renderOptions = _.defaults(options.renderOptions || {}, {
|
this.renderOptions = _.defaults(options.renderOptions || {}, {
|
||||||
disableTextEditor: false,
|
disableTextEditor: false,
|
||||||
});
|
});
|
||||||
|
@ -9,7 +9,7 @@ define([
|
|||||||
|
|
||||||
Module._query = function(args) {
|
Module._query = function(args) {
|
||||||
return MailPoet.Ajax.post({
|
return MailPoet.Ajax.post({
|
||||||
endpoint: 'wordpress',
|
endpoint: 'automatedLatestContent',
|
||||||
action: args.action,
|
action: args.action,
|
||||||
data: args.options || {},
|
data: args.options || {},
|
||||||
});
|
});
|
||||||
@ -63,16 +63,18 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
Module.saveNewsletter = function(options) {
|
Module.saveNewsletter = function(options) {
|
||||||
return Module._query({
|
return MailPoet.Ajax.post({
|
||||||
|
endpoint: 'newsletters',
|
||||||
action: 'save',
|
action: 'save',
|
||||||
options: options,
|
data: options || {},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Module.previewNewsletter = function(options) {
|
Module.previewNewsletter = function(options) {
|
||||||
return Module._query({
|
return MailPoet.Ajax.post({
|
||||||
action: 'preview',
|
endpoint: 'newsletters',
|
||||||
options: options,
|
action: 'sendPreview',
|
||||||
|
data: options || {},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -11,7 +11,7 @@ define([
|
|||||||
// Does not hold newsletter content nor newsletter styles, those are
|
// Does not hold newsletter content nor newsletter styles, those are
|
||||||
// handled by other components.
|
// handled by other components.
|
||||||
Module.NewsletterModel = SuperModel.extend({
|
Module.NewsletterModel = SuperModel.extend({
|
||||||
stale: ['body'],
|
stale: ['body', 'created_at', 'deleted_at', 'updated_at'],
|
||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
this.on('change', function() {
|
this.on('change', function() {
|
||||||
App.getChannel().trigger('autoSave');
|
App.getChannel().trigger('autoSave');
|
||||||
@ -44,10 +44,10 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
Module.getBody = function() {
|
Module.getBody = function() {
|
||||||
return JSON.stringify({
|
return {
|
||||||
content: App._contentContainer.toJSON(),
|
content: App._contentContainer.toJSON(),
|
||||||
globalStyles: App.getGlobalStyles().toJSON(),
|
globalStyles: App.getGlobalStyles().toJSON(),
|
||||||
});
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
Module.toJSON = function() {
|
Module.toJSON = function() {
|
||||||
@ -73,8 +73,7 @@ define([
|
|||||||
});
|
});
|
||||||
|
|
||||||
App.on('start', function(options) {
|
App.on('start', function(options) {
|
||||||
// TODO: Other newsletter information will be needed as well.
|
var body = options.newsletter.body;
|
||||||
var body = JSON.parse(options.newsletter.body);
|
|
||||||
App._contentContainer = new (App.getBlockTypeModel('container'))(body.content, {parse: true});
|
App._contentContainer = new (App.getBlockTypeModel('container'))(body.content, {parse: true});
|
||||||
App._contentContainerView = new (App.getBlockTypeView('container'))({
|
App._contentContainerView = new (App.getBlockTypeView('container'))({
|
||||||
model: App._contentContainer,
|
model: App._contentContainer,
|
||||||
|
@ -1,13 +1,26 @@
|
|||||||
define([
|
define([
|
||||||
'newsletter_editor/App',
|
'newsletter_editor/App',
|
||||||
|
'newsletter_editor/components/communication',
|
||||||
'mailpoet',
|
'mailpoet',
|
||||||
'notice',
|
'notice',
|
||||||
'backbone',
|
'backbone',
|
||||||
'backbone.marionette',
|
'backbone.marionette',
|
||||||
'jquery',
|
'jquery',
|
||||||
'blob',
|
'blob',
|
||||||
'filesaver'
|
'filesaver',
|
||||||
], function(App, MailPoet, Notice, Backbone, Marionette, jQuery, Blob, FileSaver) {
|
'html2canvas'
|
||||||
|
], function(
|
||||||
|
App,
|
||||||
|
CommunicationComponent,
|
||||||
|
MailPoet,
|
||||||
|
Notice,
|
||||||
|
Backbone,
|
||||||
|
Marionette,
|
||||||
|
jQuery,
|
||||||
|
Blob,
|
||||||
|
FileSaver,
|
||||||
|
html2canvas
|
||||||
|
) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
@ -16,26 +29,33 @@ define([
|
|||||||
|
|
||||||
// Save editor contents to server
|
// Save editor contents to server
|
||||||
Module.save = function() {
|
Module.save = function() {
|
||||||
App.getChannel().trigger('beforeEditorSave');
|
|
||||||
|
|
||||||
var json = App.toJSON();
|
var json = App.toJSON();
|
||||||
|
|
||||||
|
// Stringify to enable transmission of primitive non-string value types
|
||||||
|
if (!_.isUndefined(json.body)) {
|
||||||
|
json.body = JSON.stringify(json.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
App.getChannel().trigger('beforeEditorSave', json);
|
||||||
|
|
||||||
// save newsletter
|
// save newsletter
|
||||||
MailPoet.Ajax.post({
|
CommunicationComponent.saveNewsletter(json).done(function(response) {
|
||||||
endpoint: 'newsletters',
|
|
||||||
action: 'save',
|
|
||||||
data: json,
|
|
||||||
}).done(function(response) {
|
|
||||||
if(response.success !== undefined && response.success === true) {
|
if(response.success !== undefined && response.success === true) {
|
||||||
// TODO: Handle translations
|
// TODO: Handle translations
|
||||||
//MailPoet.Notice.success("<?php _e('Newsletter has been saved.'); ?>");
|
//MailPoet.Notice.success("<?php _e('Newsletter has been saved.'); ?>");
|
||||||
} else if(response.error !== undefined) {
|
} else if(response.error !== undefined) {
|
||||||
if(response.error.length === 0) {
|
if(response.error.length === 0) {
|
||||||
// TODO: Handle translations
|
// TODO: Handle translations
|
||||||
MailPoet.Notice.error("<?php _e('An unknown error occurred, please check your settings.'); ?>");
|
MailPoet.Notice.error(
|
||||||
|
"An unknown error occurred, please check your settings.",
|
||||||
|
{
|
||||||
|
scroll: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
$(response.error).each(function(i, error) {
|
$(response.error).each(function(i, error) {
|
||||||
MailPoet.Notice.error(error);
|
MailPoet.Notice.error(error, { scroll: true });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,26 +66,52 @@ define([
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Module.getThumbnail = function(element, options) {
|
||||||
|
return html2canvas(element, options || {});
|
||||||
|
};
|
||||||
|
|
||||||
Module.saveTemplate = function(options) {
|
Module.saveTemplate = function(options) {
|
||||||
return MailPoet.Ajax.post({
|
var that = this,
|
||||||
endpoint: 'newsletterTemplates',
|
promise = jQuery.Deferred();
|
||||||
action: 'save',
|
|
||||||
data: _.extend(options || {}, {
|
promise.then(function(thumbnail) {
|
||||||
body: App.getBody(),
|
var data = _.extend(options || {}, {
|
||||||
}),
|
thumbnail: thumbnail.toDataURL('image/jpeg'),
|
||||||
|
body: JSON.stringify(App.getBody()),
|
||||||
|
});
|
||||||
|
|
||||||
|
return MailPoet.Ajax.post({
|
||||||
|
endpoint: 'newsletterTemplates',
|
||||||
|
action: 'save',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Module.getThumbnail(
|
||||||
|
jQuery('#mailpoet_editor_content > .mailpoet_block').get(0)
|
||||||
|
).then(function(thumbnail) {
|
||||||
|
promise.resolve(thumbnail);
|
||||||
|
});
|
||||||
|
|
||||||
|
return promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
Module.exportTemplate = function(options) {
|
Module.exportTemplate = function(options) {
|
||||||
var data = _.extend(options || {}, {
|
var that = this;
|
||||||
body: App.getBody(),
|
return Module.getThumbnail(
|
||||||
});
|
jQuery('#mailpoet_editor_content > .mailpoet_block').get(0)
|
||||||
var blob = new Blob(
|
).then(function(thumbnail) {
|
||||||
[JSON.stringify(data)],
|
var data = _.extend(options || {}, {
|
||||||
{ type: 'application/json;charset=utf-8' }
|
thumbnail: thumbnail.toDataURL('image/jpeg'),
|
||||||
);
|
body: App.getBody(),
|
||||||
|
});
|
||||||
|
var blob = new Blob(
|
||||||
|
[JSON.stringify(data)],
|
||||||
|
{ type: 'application/json;charset=utf-8' }
|
||||||
|
);
|
||||||
|
|
||||||
FileSaver.saveAs(blob, 'template.json');
|
FileSaver.saveAs(blob, 'template.json');
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Module.SaveView = Marionette.LayoutView.extend({
|
Module.SaveView = Marionette.LayoutView.extend({
|
||||||
@ -119,20 +165,52 @@ define([
|
|||||||
},
|
},
|
||||||
saveAsTemplate: function() {
|
saveAsTemplate: function() {
|
||||||
var templateName = this.$('.mailpoet_save_as_template_name').val(),
|
var templateName = this.$('.mailpoet_save_as_template_name').val(),
|
||||||
templateDescription = this.$('.mailpoet_save_as_template_description').val();
|
templateDescription = this.$('.mailpoet_save_as_template_description').val(),
|
||||||
|
that = this;
|
||||||
|
|
||||||
console.log('Saving template with ', templateName, templateDescription);
|
if (templateName === '') {
|
||||||
Module.saveTemplate({
|
MailPoet.Notice.error(
|
||||||
name: templateName,
|
App.getConfig().get('translations.templateNameMissing'),
|
||||||
description: templateDescription,
|
{
|
||||||
}).done(function() {
|
positionAfter: that.$el,
|
||||||
console.log('Template saved', arguments);
|
scroll: true,
|
||||||
}).fail(function() {
|
}
|
||||||
// TODO: Handle error messages
|
);
|
||||||
console.log('Template save failed', arguments);
|
} else if (templateDescription === '') {
|
||||||
});
|
MailPoet.Notice.error(
|
||||||
|
App.getConfig().get('translations.templateDescriptionMissing'),
|
||||||
|
{
|
||||||
|
positionAfter: that.$el,
|
||||||
|
scroll: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
console.log('Saving template with ', templateName, templateDescription);
|
||||||
|
Module.saveTemplate({
|
||||||
|
name: templateName,
|
||||||
|
description: templateDescription,
|
||||||
|
}).done(function() {
|
||||||
|
console.log('Template saved', arguments);
|
||||||
|
MailPoet.Notice.success(
|
||||||
|
App.getConfig().get('translations.templateSaved'),
|
||||||
|
{
|
||||||
|
positionAfter: that.$el,
|
||||||
|
scroll: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}).fail(function() {
|
||||||
|
console.log('Template save failed', arguments);
|
||||||
|
MailPoet.Notice.error(
|
||||||
|
App.getConfig().get('translations.templateSaveFailed'),
|
||||||
|
{
|
||||||
|
positionAfter: that.$el,
|
||||||
|
scroll: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
this.hideOptionContents();
|
||||||
|
}
|
||||||
|
|
||||||
this.hideOptionContents();
|
|
||||||
},
|
},
|
||||||
toggleExportTemplate: function() {
|
toggleExportTemplate: function() {
|
||||||
this.$('.mailpoet_export_template_container').toggleClass('mailpoet_hidden');
|
this.$('.mailpoet_export_template_container').toggleClass('mailpoet_hidden');
|
||||||
@ -143,12 +221,25 @@ define([
|
|||||||
},
|
},
|
||||||
exportTemplate: function() {
|
exportTemplate: function() {
|
||||||
var templateName = this.$('.mailpoet_export_template_name').val(),
|
var templateName = this.$('.mailpoet_export_template_name').val(),
|
||||||
templateDescription = this.$('.mailpoet_export_template_description').val();
|
templateDescription = this.$('.mailpoet_export_template_description').val(),
|
||||||
|
that = this;
|
||||||
|
|
||||||
if (templateName === '') {
|
if (templateName === '') {
|
||||||
MailPoet.Notice.error(App.getConfig().get('translations.templateNameMissing'));
|
MailPoet.Notice.error(
|
||||||
|
App.getConfig().get('translations.templateNameMissing'),
|
||||||
|
{
|
||||||
|
positionAfter: that.$el,
|
||||||
|
scroll: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
} else if (templateDescription === '') {
|
} else if (templateDescription === '') {
|
||||||
MailPoet.Notice.error(App.getConfig().get('translations.templateDescriptionMissing'));
|
MailPoet.Notice.error(
|
||||||
|
App.getConfig().get('translations.templateDescriptionMissing'),
|
||||||
|
{
|
||||||
|
positionAfter: that.$el,
|
||||||
|
scroll: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
console.log('Exporting template with ', templateName, templateDescription);
|
console.log('Exporting template with ', templateName, templateDescription);
|
||||||
Module.exportTemplate({
|
Module.exportTemplate({
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
define([
|
define([
|
||||||
'newsletter_editor/App',
|
'newsletter_editor/App',
|
||||||
|
'newsletter_editor/components/communication',
|
||||||
'backbone',
|
'backbone',
|
||||||
'backbone.marionette',
|
'backbone.marionette',
|
||||||
'backbone.supermodel',
|
'backbone.supermodel',
|
||||||
'underscore',
|
'underscore',
|
||||||
'jquery',
|
'jquery',
|
||||||
'sticky-kit'
|
'sticky-kit'
|
||||||
], function(App, Backbone, Marionette, SuperModel, _, jQuery, StickyKit) {
|
], function(App, CommunicationComponent, Backbone, Marionette, SuperModel, _, jQuery, StickyKit) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
@ -50,8 +51,33 @@ define([
|
|||||||
},
|
},
|
||||||
events: {
|
events: {
|
||||||
'click .mailpoet_sidebar_region h3, .mailpoet_sidebar_region .handlediv': function(event) {
|
'click .mailpoet_sidebar_region h3, .mailpoet_sidebar_region .handlediv': function(event) {
|
||||||
this.$el.find('.mailpoet_sidebar_region').addClass('closed');
|
var $openRegion = this.$el.find('.mailpoet_sidebar_region:not(.closed)'),
|
||||||
this.$el.find(event.target).parent().parent().removeClass('closed');
|
$targetRegion = this.$el.find(event.target).closest('.mailpoet_sidebar_region');
|
||||||
|
|
||||||
|
if ($openRegion.get(0) === $targetRegion.get(0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$openRegion.find('.mailpoet_region_content').velocity(
|
||||||
|
'slideUp',
|
||||||
|
{
|
||||||
|
duration: 250,
|
||||||
|
easing: "easeOut",
|
||||||
|
complete: function() {
|
||||||
|
$openRegion.addClass('closed');
|
||||||
|
}.bind(this)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$targetRegion.find('.mailpoet_region_content').velocity(
|
||||||
|
'slideDown',
|
||||||
|
{
|
||||||
|
duration: 250,
|
||||||
|
easing: "easeIn",
|
||||||
|
complete: function() {
|
||||||
|
$targetRegion.removeClass('closed');
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
@ -90,7 +116,6 @@ define([
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
onDomRefresh: function() {
|
onDomRefresh: function() {
|
||||||
var that = this;
|
|
||||||
this.$el.parent().stick_in_parent({
|
this.$el.parent().stick_in_parent({
|
||||||
offset_top: 32,
|
offset_top: 32,
|
||||||
});
|
});
|
||||||
@ -169,10 +194,8 @@ define([
|
|||||||
},
|
},
|
||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
this.availableStyles = options.availableStyles;
|
this.availableStyles = options.availableStyles;
|
||||||
var that = this;
|
|
||||||
},
|
},
|
||||||
onRender: function() {
|
onRender: function() {
|
||||||
var that = this;
|
|
||||||
this.$('.mailpoet_color').spectrum({
|
this.$('.mailpoet_color').spectrum({
|
||||||
clickoutFiresChange: true,
|
clickoutFiresChange: true,
|
||||||
showInput: true,
|
showInput: true,
|
||||||
@ -202,6 +225,11 @@ define([
|
|||||||
showPreview: function() {
|
showPreview: function() {
|
||||||
var json = App.toJSON();
|
var json = App.toJSON();
|
||||||
|
|
||||||
|
// Stringify to enable transmission of primitive non-string value types
|
||||||
|
if (!_.isUndefined(json.body)) {
|
||||||
|
json.body = JSON.stringify(json.body);
|
||||||
|
}
|
||||||
|
|
||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
endpoint: 'newsletters',
|
endpoint: 'newsletters',
|
||||||
action: 'render',
|
action: 'render',
|
||||||
@ -219,26 +247,29 @@ define([
|
|||||||
console.log('trying to send a preview');
|
console.log('trying to send a preview');
|
||||||
// get form data
|
// get form data
|
||||||
var data = {
|
var data = {
|
||||||
from_name: this.$('#mailpoet_preview_from_name').val(),
|
subscriber: this.$('#mailpoet_preview_to_email').val(),
|
||||||
from_email: this.$('#mailpoet_preview_from_email').val(),
|
id: App.getNewsletter().get('id'),
|
||||||
to_email: this.$('#mailpoet_preview_to_email').val(),
|
|
||||||
newsletter: App.newsletterId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// send test email
|
// send test email
|
||||||
MailPoet.Modal.loading(true);
|
MailPoet.Modal.loading(true);
|
||||||
|
|
||||||
// TODO: Migrate logic to new AJAX format
|
CommunicationComponent.previewNewsletter(data).done(function(response) {
|
||||||
Wordpress.previewNewsletter(data).done(function(response) {
|
if(response.result !== undefined && response.result === true) {
|
||||||
if(response.success !== undefined && response.success === true) {
|
MailPoet.Notice.success(App.getConfig().get('translations.newsletterPreviewSent'), { scroll: true });
|
||||||
MailPoet.Notice.success(App.getConfig().get('translations.testEmailSent'));
|
} else {
|
||||||
} else if(response.error !== undefined) {
|
if (_.isArray(response.errors)) {
|
||||||
if(response.error.length === 0) {
|
response.errors.map(function(error) {
|
||||||
MailPoet.Notice.error(App.getConfig().get('translations.unknownErrorOccurred'));
|
MailPoet.Notice.error(error, { scroll: true });
|
||||||
} else {
|
|
||||||
$(response.error).each(function(i, error) {
|
|
||||||
MailPoet.Notice.error(error);
|
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
MailPoet.Notice.error(
|
||||||
|
App.getConfig().get('translations.newsletterPreviewFailedToSend'),
|
||||||
|
{
|
||||||
|
scroll: true,
|
||||||
|
static: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MailPoet.Modal.loading(false);
|
MailPoet.Modal.loading(false);
|
||||||
|
@ -17,7 +17,7 @@ define([
|
|||||||
},
|
},
|
||||||
h1: {
|
h1: {
|
||||||
fontColor: '#111111',
|
fontColor: '#111111',
|
||||||
fontFamily: 'Arial Black',
|
fontFamily: 'Arial',
|
||||||
fontSize: '40px'
|
fontSize: '40px'
|
||||||
},
|
},
|
||||||
h2: {
|
h2: {
|
||||||
@ -72,7 +72,7 @@ define([
|
|||||||
|
|
||||||
App.getAvailableStyles = Module.getAvailableStyles;
|
App.getAvailableStyles = Module.getAvailableStyles;
|
||||||
|
|
||||||
var body = JSON.parse(options.newsletter.body);
|
var body = options.newsletter.body;
|
||||||
this.setGlobalStyles(body.globalStyles);
|
this.setGlobalStyles(body.globalStyles);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -21,6 +21,10 @@ define(
|
|||||||
label: 'Subject',
|
label: 'Subject',
|
||||||
sortable: true
|
sortable: true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'status',
|
||||||
|
label: 'Status'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'segments',
|
name: 'segments',
|
||||||
label: 'Lists'
|
label: 'Lists'
|
||||||
@ -39,58 +43,49 @@ define(
|
|||||||
|
|
||||||
var messages = {
|
var messages = {
|
||||||
onTrash: function(response) {
|
onTrash: function(response) {
|
||||||
var count = ~~response.newsletters;
|
var count = ~~response;
|
||||||
var message = null;
|
var message = null;
|
||||||
|
|
||||||
if(count === 1 || response === true) {
|
if(count === 1) {
|
||||||
message = (
|
message = (
|
||||||
'1 newsletter was moved to the trash.'
|
'1 newsletter was moved to the trash.'
|
||||||
);
|
);
|
||||||
} else if(count > 1) {
|
} else {
|
||||||
message = (
|
message = (
|
||||||
'%$1d newsletters were moved to the trash.'
|
'%$1d newsletters were moved to the trash.'
|
||||||
).replace('%$1d', count);
|
).replace('%$1d', count);
|
||||||
}
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
if(message !== null) {
|
|
||||||
MailPoet.Notice.success(message);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onDelete: function(response) {
|
onDelete: function(response) {
|
||||||
var count = ~~response.newsletters;
|
var count = ~~response;
|
||||||
var message = null;
|
var message = null;
|
||||||
|
|
||||||
if(count === 1 || response === true) {
|
if(count === 1) {
|
||||||
message = (
|
message = (
|
||||||
'1 newsletter was permanently deleted.'
|
'1 newsletter was permanently deleted.'
|
||||||
);
|
);
|
||||||
} else if(count > 1) {
|
} else {
|
||||||
message = (
|
message = (
|
||||||
'%$1d newsletters were permanently deleted.'
|
'%$1d newsletters were permanently deleted.'
|
||||||
).replace('%$1d', count);
|
).replace('%$1d', count);
|
||||||
}
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
if(message !== null) {
|
|
||||||
MailPoet.Notice.success(message);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
onRestore: function(response) {
|
onRestore: function(response) {
|
||||||
var count = ~~response.newsletters;
|
var count = ~~response;
|
||||||
var message = null;
|
var message = null;
|
||||||
|
|
||||||
if(count === 1 || response === true) {
|
if(count === 1) {
|
||||||
message = (
|
message = (
|
||||||
'1 newsletter has been restored from the trash.'
|
'1 newsletter has been restored from the trash.'
|
||||||
);
|
);
|
||||||
} else if(count > 1) {
|
} else {
|
||||||
message = (
|
message = (
|
||||||
'%$1d newsletters have been restored from the trash.'
|
'%$1d newsletters have been restored from the trash.'
|
||||||
).replace('%$1d', count);
|
).replace('%$1d', count);
|
||||||
}
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
if(message !== null) {
|
|
||||||
MailPoet.Notice.success(message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -112,12 +107,101 @@ define(
|
|||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'trash'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
var NewsletterList = React.createClass({
|
var NewsletterList = React.createClass({
|
||||||
renderItem: function(newsletter, actions) {
|
pauseSending: function(item) {
|
||||||
|
MailPoet.Ajax.post({
|
||||||
|
endpoint: 'sendingQueue',
|
||||||
|
action: 'pause',
|
||||||
|
data: item.id
|
||||||
|
}).done(function() {
|
||||||
|
jQuery('#resume_'+item.id).show();
|
||||||
|
jQuery('#pause_'+item.id).hide();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
resumeSending: function(item) {
|
||||||
|
MailPoet.Ajax.post({
|
||||||
|
endpoint: 'sendingQueue',
|
||||||
|
action: 'resume',
|
||||||
|
data: item.id
|
||||||
|
}).done(function() {
|
||||||
|
jQuery('#pause_'+item.id).show();
|
||||||
|
jQuery('#resume_'+item.id).hide();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
renderStatus: function(item) {
|
||||||
|
if(item.queue === null) {
|
||||||
|
return (
|
||||||
|
<span>Not sent yet.</span>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
var progressClasses = classNames(
|
||||||
|
'mailpoet_progress',
|
||||||
|
{ 'mailpoet_progress_complete': item.queue.status === 'completed'}
|
||||||
|
);
|
||||||
|
|
||||||
|
// calculate percentage done
|
||||||
|
var percentage = Math.round(
|
||||||
|
(item.queue.count_processed * 100) / (item.queue.count_total)
|
||||||
|
);
|
||||||
|
|
||||||
|
var label = false;
|
||||||
|
|
||||||
|
if(item.queue.status === 'completed') {
|
||||||
|
label = (
|
||||||
|
<span>
|
||||||
|
Sent to {
|
||||||
|
item.queue.count_processed - item.queue.count_failed
|
||||||
|
} out of { item.queue.count_total }.
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
label = (
|
||||||
|
<span>
|
||||||
|
{ item.queue.count_processed } / { item.queue.count_total }
|
||||||
|
|
||||||
|
<a
|
||||||
|
id={ 'resume_'+item.id }
|
||||||
|
className="button"
|
||||||
|
style={{ display: (item.queue.status === 'paused') ? 'inline-block': 'none' }}
|
||||||
|
href="javascript:;"
|
||||||
|
onClick={ this.resumeSending.bind(null, item) }
|
||||||
|
>Resume</a>
|
||||||
|
<a
|
||||||
|
id={ 'pause_'+item.id }
|
||||||
|
className="button mailpoet_pause"
|
||||||
|
style={{ display: (item.queue.status === null) ? 'inline-block': 'none' }}
|
||||||
|
href="javascript:;"
|
||||||
|
onClick={ this.pauseSending.bind(null, item) }
|
||||||
|
>Pause</a>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className={ progressClasses }>
|
||||||
|
<span
|
||||||
|
className="mailpoet_progress_bar"
|
||||||
|
style={ { width: percentage + "%"} }
|
||||||
|
></span>
|
||||||
|
<span className="mailpoet_progress_label">
|
||||||
|
{ percentage + "%" }
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p style={{ textAlign:'center' }}>
|
||||||
|
{ label }
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
renderItem: function(newsletter, actions) {
|
||||||
var rowClasses = classNames(
|
var rowClasses = classNames(
|
||||||
'manage-column',
|
'manage-column',
|
||||||
'column-primary',
|
'column-primary',
|
||||||
@ -138,6 +222,9 @@ define(
|
|||||||
</strong>
|
</strong>
|
||||||
{ actions }
|
{ actions }
|
||||||
</td>
|
</td>
|
||||||
|
<td className="column" data-colname="Lists">
|
||||||
|
{ this.renderStatus(newsletter) }
|
||||||
|
</td>
|
||||||
<td className="column" data-colname="Lists">
|
<td className="column" data-colname="Lists">
|
||||||
{ segments }
|
{ segments }
|
||||||
</td>
|
</td>
|
||||||
@ -164,7 +251,8 @@ define(
|
|||||||
columns={columns}
|
columns={columns}
|
||||||
bulk_actions={ bulk_actions }
|
bulk_actions={ bulk_actions }
|
||||||
item_actions={ item_actions }
|
item_actions={ item_actions }
|
||||||
messages={ messages } />
|
messages={ messages }
|
||||||
|
auto_refresh={ true } />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ define(
|
|||||||
Breadcrumb
|
Breadcrumb
|
||||||
) {
|
) {
|
||||||
|
|
||||||
var settings = window.mailpoet_settings || {};
|
var settings = window.mailpoet_settings || {};
|
||||||
|
|
||||||
var fields = [
|
var fields = [
|
||||||
{
|
{
|
||||||
@ -24,17 +24,26 @@ define(
|
|||||||
label: 'Subject line',
|
label: 'Subject line',
|
||||||
tip: "Be creative! It's the first thing your subscribers see."+
|
tip: "Be creative! It's the first thing your subscribers see."+
|
||||||
"Tempt them to open your email.",
|
"Tempt them to open your email.",
|
||||||
type: 'text'
|
type: 'text',
|
||||||
|
validation: {
|
||||||
|
'data-parsley-required': true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'segments',
|
name: 'segments',
|
||||||
label: 'Lists',
|
label: 'Segments',
|
||||||
tip: "The subscriber list that will be used for this campaign.",
|
tip: "The subscriber segment that will be used for this campaign.",
|
||||||
type: 'selection',
|
type: 'selection',
|
||||||
placeholder: "Select a list",
|
placeholder: "Select a segment",
|
||||||
id: "mailpoet_segments",
|
id: "mailpoet_segments",
|
||||||
endpoint: "segments",
|
endpoint: "segments",
|
||||||
multiple: true
|
multiple: true,
|
||||||
|
filter: function(segment) {
|
||||||
|
return !!(!segment.deleted_at);
|
||||||
|
},
|
||||||
|
validation: {
|
||||||
|
'data-parsley-required': true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'sender',
|
name: 'sender',
|
||||||
@ -42,17 +51,24 @@ define(
|
|||||||
tip: "Name & email of yourself or your company.",
|
tip: "Name & email of yourself or your company.",
|
||||||
fields: [
|
fields: [
|
||||||
{
|
{
|
||||||
name: 'from_name',
|
name: 'sender_name',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
placeholder: 'John Doe',
|
placeholder: 'John Doe',
|
||||||
defaultValue: settings.from_name
|
defaultValue: (settings.sender !== undefined) ? settings.sender.name : '',
|
||||||
|
validation: {
|
||||||
|
'data-parsley-required': true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'from_email',
|
name: 'sender_address',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
placeholder: 'john.doe@email.com',
|
placeholder: 'john.doe@email.com',
|
||||||
defaultValue: settings.from_address
|
defaultValue: (settings.sender !== undefined) ? settings.sender.address : '',
|
||||||
},
|
validation: {
|
||||||
|
'data-parsley-required': true,
|
||||||
|
'data-parsley-type': 'email'
|
||||||
|
}
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -65,20 +81,25 @@ define(
|
|||||||
{
|
{
|
||||||
name: 'reply_to_name',
|
name: 'reply_to_name',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
placeholder: 'John Doe'
|
placeholder: 'John Doe',
|
||||||
|
defaultValue: (settings.reply_to !== undefined) ? settings.reply_to.name : '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'reply_to_email',
|
name: 'reply_to_address',
|
||||||
type: 'text',
|
type: 'text',
|
||||||
placeholder: 'john.doe@email.com'
|
placeholder: 'john.doe@email.com',
|
||||||
|
defaultValue: (settings.reply_to !== undefined) ? settings.reply_to.address : ''
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
var messages = {
|
var messages = {
|
||||||
updated: function() {
|
onUpdate: function() {
|
||||||
MailPoet.Notice.success('The newsletter has been updated!');
|
MailPoet.Notice.success('Newsletter successfully updated!');
|
||||||
|
},
|
||||||
|
onCreate: function() {
|
||||||
|
MailPoet.Notice.success('Newsletter successfully added!');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -87,34 +108,42 @@ define(
|
|||||||
Router.History
|
Router.History
|
||||||
],
|
],
|
||||||
handleSend: function() {
|
handleSend: function() {
|
||||||
MailPoet.Ajax.post({
|
if(jQuery('#mailpoet_newsletter').parsley().validate() === true) {
|
||||||
endpoint: 'newsletters',
|
MailPoet.Ajax.post({
|
||||||
action: 'send',
|
endpoint: 'sendingQueue',
|
||||||
data: {
|
action: 'add',
|
||||||
id: this.props.params.id,
|
data: {
|
||||||
newsletter: jQuery('#mailpoet_newsletter').serializeObject(),
|
newsletter_id: this.props.params.id,
|
||||||
segments: jQuery('#mailpoet_segments').val()
|
segments: jQuery('#mailpoet_segments').val(),
|
||||||
}
|
sender: {
|
||||||
}).done(function(response) {
|
'name': jQuery('#mailpoet_newsletter [name="sender_name"]').val(),
|
||||||
if(response === true) {
|
'address': jQuery('#mailpoet_newsletter [name="sender_address"]').val()
|
||||||
this.history.pushState(null, '/');
|
},
|
||||||
|
reply_to: {
|
||||||
MailPoet.Notice.success(
|
'name': jQuery('#mailpoet_newsletter [name="reply_to_name"]').val(),
|
||||||
'The newsletter has been sent!'
|
'address': jQuery('#mailpoet_newsletter [name="reply_to_address"]').val()
|
||||||
);
|
}
|
||||||
} else {
|
}
|
||||||
if(response.errors) {
|
}).done(function(response) {
|
||||||
MailPoet.Notice.error(
|
if(response.result === true) {
|
||||||
response.errors.join("<br />")
|
this.history.pushState(null, '/');
|
||||||
|
MailPoet.Notice.success(
|
||||||
|
'The newsletter is being sent...'
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
MailPoet.Notice.error(
|
if(response.errors) {
|
||||||
'An error occurred while trying to send. '+
|
MailPoet.Notice.error(
|
||||||
'<a href="?page=mailpoet-settings">Check your settings.</a>'
|
response.errors.join("<br />")
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
MailPoet.Notice.error(
|
||||||
|
'An error occurred while trying to send. '+
|
||||||
|
'<a href="?page=mailpoet-settings">Check your settings.</a>'
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}.bind(this));
|
||||||
}.bind(this));
|
}
|
||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
return (
|
return (
|
||||||
@ -128,8 +157,8 @@ define(
|
|||||||
endpoint="newsletters"
|
endpoint="newsletters"
|
||||||
fields={ fields }
|
fields={ fields }
|
||||||
params={ this.props.params }
|
params={ this.props.params }
|
||||||
messages={ messages }>
|
messages={ messages }
|
||||||
|
>
|
||||||
<p className="submit">
|
<p className="submit">
|
||||||
<input
|
<input
|
||||||
className="button button-primary"
|
className="button button-primary"
|
||||||
|
@ -18,12 +18,18 @@ define(
|
|||||||
|
|
||||||
var ImportTemplate = React.createClass({
|
var ImportTemplate = React.createClass({
|
||||||
saveTemplate: function(template) {
|
saveTemplate: function(template) {
|
||||||
|
|
||||||
|
// Stringify to enable transmission of primitive non-string value types
|
||||||
|
if (!_.isUndefined(template.body)) {
|
||||||
|
template.body = JSON.stringify(template.body);
|
||||||
|
}
|
||||||
|
|
||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
endpoint: 'newsletterTemplates',
|
endpoint: 'newsletterTemplates',
|
||||||
action: 'save',
|
action: 'save',
|
||||||
data: template
|
data: template
|
||||||
}).done(function(response) {
|
}).done(function(response) {
|
||||||
if(response === true) {
|
if(response.result === true) {
|
||||||
this.props.onImport(template);
|
this.props.onImport(template);
|
||||||
} else {
|
} else {
|
||||||
response.map(function(error) {
|
response.map(function(error) {
|
||||||
@ -99,7 +105,7 @@ define(
|
|||||||
"MailPoet's Guide",
|
"MailPoet's Guide",
|
||||||
description:
|
description:
|
||||||
"This is the standard template that comes with MailPoet.",
|
"This is the standard template that comes with MailPoet.",
|
||||||
readonly: true
|
readonly: "1"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -111,19 +117,26 @@ define(
|
|||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
handleSelectTemplate: function(template) {
|
handleSelectTemplate: function(template) {
|
||||||
|
var body = template.body;
|
||||||
|
|
||||||
|
// Stringify to enable transmission of primitive non-string value types
|
||||||
|
if (!_.isUndefined(body)) {
|
||||||
|
body = JSON.stringify(body);
|
||||||
|
}
|
||||||
|
|
||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
endpoint: 'newsletters',
|
endpoint: 'newsletters',
|
||||||
action: 'save',
|
action: 'save',
|
||||||
data: {
|
data: {
|
||||||
id: this.props.params.id,
|
id: this.props.params.id,
|
||||||
body: template.body
|
body: body
|
||||||
}
|
}
|
||||||
}).done(function(response) {
|
}).done(function(response) {
|
||||||
if(response === true) {
|
if(response.result === true) {
|
||||||
// TODO: Move this URL elsewhere
|
// TODO: Move this URL elsewhere
|
||||||
window.location = 'admin.php?page=mailpoet-newsletter-editor&id=' + this.props.params.id;
|
window.location = 'admin.php?page=mailpoet-newsletter-editor&id=' + this.props.params.id;
|
||||||
} else {
|
} else {
|
||||||
response.map(function(error) {
|
response.errors.map(function(error) {
|
||||||
MailPoet.Notice.error(error);
|
MailPoet.Notice.error(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -150,6 +163,13 @@ define(
|
|||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
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();
|
this.getTemplates();
|
||||||
},
|
},
|
||||||
@ -164,11 +184,22 @@ define(
|
|||||||
Delete
|
Delete
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
), thumbnail = '';
|
||||||
|
|
||||||
|
if (typeof template.thumbnail === 'string'
|
||||||
|
&& template.thumbnail.length > 0) {
|
||||||
|
thumbnail = (
|
||||||
|
<a href="javascript:;" onClick={this.handleShowTemplate.bind(null, template)}>
|
||||||
|
<img src={ template.thumbnail } />
|
||||||
|
<div className="mailpoet_overlay"></div>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li key={ 'template-'+index }>
|
<li key={ 'template-'+index }>
|
||||||
<div className="mailpoet_thumbnail">
|
<div className="mailpoet_thumbnail">
|
||||||
|
{ thumbnail }
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mailpoet_description">
|
<div className="mailpoet_description">
|
||||||
@ -192,7 +223,7 @@ define(
|
|||||||
Preview
|
Preview
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{ (template.readonly) ? false : deleteLink }
|
{ (template.readonly === "1") ? false : deleteLink }
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
@ -26,14 +26,17 @@ define(
|
|||||||
action: 'create',
|
action: 'create',
|
||||||
data: {
|
data: {
|
||||||
type: type,
|
type: type,
|
||||||
|
subject: 'Draft newsletter',
|
||||||
}
|
}
|
||||||
}).done(function(response) {
|
}).done(function(response) {
|
||||||
if(response.id !== undefined) {
|
if(response.result && response.newsletter.id) {
|
||||||
this.history.pushState(null, `/template/${response.id}`);
|
this.history.pushState(null, `/template/${response.newsletter.id}`);
|
||||||
} else {
|
} else {
|
||||||
response.map(function(error) {
|
if(response.errors.length > 0) {
|
||||||
MailPoet.Notice.error(error);
|
response.errors.map(function(error) {
|
||||||
});
|
MailPoet.Notice.error(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
@ -138,12 +138,14 @@ define(
|
|||||||
options: this.state,
|
options: this.state,
|
||||||
},
|
},
|
||||||
}).done(function(response) {
|
}).done(function(response) {
|
||||||
if(response.id !== undefined) {
|
if(response.result && response.newsletter.id) {
|
||||||
this.showTemplateSelection(response.id);
|
this.showTemplateSelection(response.newsletter.id);
|
||||||
} else {
|
} else {
|
||||||
response.map(function(error) {
|
if(response.errors.length > 0) {
|
||||||
MailPoet.Notice.error(error);
|
response.errors.map(function(error) {
|
||||||
});
|
MailPoet.Notice.error(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
@ -32,12 +32,15 @@ define(
|
|||||||
type: 'standard',
|
type: 'standard',
|
||||||
}
|
}
|
||||||
}).done(function(response) {
|
}).done(function(response) {
|
||||||
if(response.id !== undefined) {
|
console.log(response);
|
||||||
this.showTemplateSelection(response.id);
|
if(response.result && response.newsletter.id) {
|
||||||
|
this.showTemplateSelection(response.newsletter.id);
|
||||||
} else {
|
} else {
|
||||||
response.map(function(error) {
|
if(response.errors.length > 0) {
|
||||||
MailPoet.Notice.error(error);
|
response.errors.map(function(error) {
|
||||||
});
|
MailPoet.Notice.error(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
@ -111,12 +111,14 @@ define(
|
|||||||
options: this.state,
|
options: this.state,
|
||||||
},
|
},
|
||||||
}).done(function(response) {
|
}).done(function(response) {
|
||||||
if(response.id !== undefined) {
|
if(response.result && response.newsletter.id) {
|
||||||
this.showTemplateSelection(response.id);
|
this.showTemplateSelection(response.newsletter.id);
|
||||||
} else {
|
} else {
|
||||||
response.map(function(error) {
|
if(response.errors.length > 0) {
|
||||||
MailPoet.Notice.error(error);
|
response.errors.map(function(error) {
|
||||||
});
|
MailPoet.Notice.error(error);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
|
@ -1,191 +1,219 @@
|
|||||||
define('notice', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
|
define('notice', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
|
||||||
"use strict";
|
"use strict";
|
||||||
/*==================================================================================================
|
/*==================================================================================================
|
||||||
|
|
||||||
MailPoet Notice:
|
MailPoet Notice:
|
||||||
|
|
||||||
description: Handles notices
|
description: Handles notices
|
||||||
version: 0.2
|
version: 0.2
|
||||||
author: Jonathan Labreuille
|
author: Jonathan Labreuille
|
||||||
company: Wysija
|
company: Wysija
|
||||||
dependencies: jQuery
|
dependencies: jQuery
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
|
||||||
// success message (static: false)
|
// success message (static: false)
|
||||||
MailPoet.Notice.success('Yatta!');
|
MailPoet.Notice.success('Yatta!');
|
||||||
|
|
||||||
// error message (static: false)
|
// error message (static: false)
|
||||||
MailPoet.Notice.error('Boo!');
|
MailPoet.Notice.error('Boo!');
|
||||||
|
|
||||||
// system message (static: true)
|
// system message (static: true)
|
||||||
MailPoet.Notice.system('You need to updated ASAP!');
|
MailPoet.Notice.system('You need to updated ASAP!');
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
MailPoet.Notice.success('- success #1 -');
|
MailPoet.Notice.success('- success #1 -');
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
MailPoet.Notice.success('- success #2 -');
|
MailPoet.Notice.success('- success #2 -');
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
MailPoet.Notice.error('- error -');
|
MailPoet.Notice.error('- error -');
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
MailPoet.Notice.system('- system -');
|
MailPoet.Notice.system('- system -');
|
||||||
|
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
MailPoet.Notice.hide();
|
MailPoet.Notice.hide();
|
||||||
}, 2500);
|
}, 2500);
|
||||||
}, 300);
|
}, 300);
|
||||||
}, 400);
|
}, 400);
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
==================================================================================================*/
|
==================================================================================================*/
|
||||||
|
|
||||||
MailPoet.Notice = {
|
MailPoet.Notice = {
|
||||||
version: 0.2,
|
version: 0.2,
|
||||||
// default options
|
// default options
|
||||||
defaults: {
|
defaults: {
|
||||||
type: 'success',
|
type: 'success',
|
||||||
message: '',
|
message: '',
|
||||||
static: false,
|
static: false,
|
||||||
scroll: false,
|
hideClose: false,
|
||||||
timeout: 2000,
|
id: null,
|
||||||
onOpen: null,
|
positionAfter: false,
|
||||||
onClose: null
|
scroll: false,
|
||||||
},
|
timeout: 2000,
|
||||||
options: {},
|
onOpen: null,
|
||||||
init: function(options) {
|
onClose: null
|
||||||
// set options
|
},
|
||||||
this.options = jQuery.extend({}, this.defaults, options);
|
options: {},
|
||||||
|
init: function(options) {
|
||||||
// clone element
|
// set options
|
||||||
this.element = jQuery('#mailpoet_notice_'+this.options.type).clone();
|
this.options = jQuery.extend({}, this.defaults, options);
|
||||||
|
|
||||||
// remove id from clone
|
// clone element
|
||||||
this.element.removeAttr('id');
|
this.element = jQuery('#mailpoet_notice_'+this.options.type).clone();
|
||||||
|
|
||||||
// insert notice after its parent
|
// add data-id to the element
|
||||||
jQuery('#mailpoet_notice_'+this.options.type).after(this.element);
|
if (this.options.id) this.element.attr('data-id', 'notice_' + this.options.id);
|
||||||
|
|
||||||
// setup onClose callback
|
// remove id from clone
|
||||||
var onClose = null;
|
this.element.removeAttr('id');
|
||||||
if(this.options.onClose !== null) {
|
|
||||||
onClose = this.options.onClose;
|
// insert notice after its parent
|
||||||
}
|
var positionAfter;
|
||||||
|
if (typeof this.options.positionAfter === 'object') {
|
||||||
// listen to remove event
|
positionAfter = this.options.positionAfter;
|
||||||
var element = this.element;
|
} else if (typeof this.options.positionAfter === 'string') {
|
||||||
jQuery(this.element).on('close', function() {
|
positionAfter = jQuery(this.options.positionAfter);
|
||||||
jQuery(this).fadeOut(200, function() {
|
} else {
|
||||||
// on close callback
|
positionAfter = jQuery('#mailpoet_notice_'+this.options.type);
|
||||||
if(onClose !== null) {
|
}
|
||||||
onClose();
|
positionAfter.after(this.element);
|
||||||
}
|
|
||||||
// remove notice
|
// setup onClose callback
|
||||||
jQuery(this).remove();
|
var onClose = null;
|
||||||
});
|
if(this.options.onClose !== null) {
|
||||||
}.bind(this.element));
|
onClose = this.options.onClose;
|
||||||
|
}
|
||||||
// listen to message event
|
|
||||||
jQuery(this.element).on('message', function(e, message) {
|
// listen to remove event
|
||||||
MailPoet.Notice.setMessage(message);
|
jQuery(this.element).on('close', function() {
|
||||||
}.bind(this.element));
|
jQuery(this).fadeOut(200, function() {
|
||||||
|
// on close callback
|
||||||
return this;
|
if(onClose !== null) {
|
||||||
},
|
onClose();
|
||||||
isHTML: function(str) {
|
}
|
||||||
var a = document.createElement('div');
|
// remove notice
|
||||||
a.innerHTML = str;
|
jQuery(this).remove();
|
||||||
for(var c = a.childNodes, i = c.length; i--;) {
|
});
|
||||||
if(c[i].nodeType == 1) return true;
|
}.bind(this.element));
|
||||||
}
|
|
||||||
return false;
|
// listen to message event
|
||||||
},
|
jQuery(this.element).on('message', function(e, message) {
|
||||||
setMessage: function(message) {
|
MailPoet.Notice.setMessage(message);
|
||||||
// if it's not an html message, let's sugar coat the message with a fancy <p>
|
}.bind(this.element));
|
||||||
if(this.isHTML(message) === false) {
|
|
||||||
message = '<p>'+message+'</p>';
|
return this;
|
||||||
}
|
},
|
||||||
// set message
|
isHTML: function(str) {
|
||||||
return this.element.html(message);
|
var a = document.createElement('div');
|
||||||
},
|
a.innerHTML = str;
|
||||||
show: function(options) {
|
for(var c = a.childNodes, i = c.length; i--;) {
|
||||||
// initialize
|
if(c[i].nodeType == 1) return true;
|
||||||
this.init(options);
|
}
|
||||||
|
return false;
|
||||||
// show notice
|
},
|
||||||
this.showNotice();
|
setMessage: function(message) {
|
||||||
|
// if it's not an html message, let's sugar coat the message with a fancy <p>
|
||||||
// return this;
|
if(this.isHTML(message) === false) {
|
||||||
},
|
message = '<p>'+message+'</p>';
|
||||||
showNotice: function() {
|
}
|
||||||
// set message
|
// set message
|
||||||
this.setMessage(this.options.message);
|
return this.element.html(message);
|
||||||
|
},
|
||||||
// position notice
|
show: function(options) {
|
||||||
this.element.insertAfter(jQuery('h2.title'));
|
// initialize
|
||||||
|
this.init(options);
|
||||||
// set class name
|
|
||||||
switch(this.options.type) {
|
// show notice
|
||||||
case 'success':
|
this.showNotice();
|
||||||
this.element.addClass('updated');
|
|
||||||
break;
|
// return this;
|
||||||
case 'system':
|
},
|
||||||
this.element.addClass('update-nag');
|
showNotice: function() {
|
||||||
break;
|
// set message
|
||||||
case 'error':
|
this.setMessage(this.options.message);
|
||||||
this.element.addClass('error');
|
|
||||||
break;
|
// position notice
|
||||||
}
|
this.element.insertAfter(jQuery('h2.title'));
|
||||||
|
|
||||||
// make the notice appear
|
// set class name
|
||||||
this.element.fadeIn(200);
|
switch(this.options.type) {
|
||||||
|
case 'success':
|
||||||
// if scroll option is enabled, scroll to the notice
|
this.element.addClass('updated');
|
||||||
if(this.options.scroll === true) {
|
break;
|
||||||
this.element.get(0).scrollIntoView(false);
|
case 'system':
|
||||||
}
|
this.element.addClass('update-nag');
|
||||||
|
break;
|
||||||
// if the notice is not static, it has to disappear after a timeout
|
case 'error':
|
||||||
if(this.options.static === false) {
|
this.element.addClass('error');
|
||||||
this.element.delay(this.options.timeout).trigger('close');
|
break;
|
||||||
} else {
|
}
|
||||||
this.element.append('<a href="javascript:;" class="mailpoet_notice_close"><span class="dashicons dashicons-dismiss"></span></a>');
|
|
||||||
this.element.find('.mailpoet_notice_close').on('click', function() {
|
// make the notice appear
|
||||||
jQuery(this).trigger('close');
|
this.element.fadeIn(200);
|
||||||
});
|
|
||||||
}
|
// if scroll option is enabled, scroll to the notice
|
||||||
|
if(this.options.scroll === true) {
|
||||||
// call onOpen callback
|
this.element.get(0).scrollIntoView(false);
|
||||||
if(this.options.onOpen !== null) {
|
}
|
||||||
this.options.onOpen(this.element);
|
|
||||||
}
|
// if the notice is not static, it has to disappear after a timeout
|
||||||
},
|
if(this.options.static === false) {
|
||||||
hide: function(all) {
|
this.element.delay(this.options.timeout).trigger('close');
|
||||||
if(all !== undefined && all === true) {
|
} else if (this.options.hideClose === false) {
|
||||||
jQuery('.mailpoet_notice:not([id])').trigger('close');
|
this.element.append('<a href="javascript:;" class="mailpoet_notice_close"><span class="dashicons dashicons-dismiss"></span></a>');
|
||||||
} else {
|
this.element.find('.mailpoet_notice_close').on('click', function() {
|
||||||
jQuery('.mailpoet_notice.updated:not([id]), .mailpoet_notice.error:not([id])')
|
jQuery(this).trigger('close');
|
||||||
.trigger('close');
|
});
|
||||||
}
|
}
|
||||||
},
|
|
||||||
error: function(message, options) {
|
// call onOpen callback
|
||||||
this.show(jQuery.extend({}, {
|
if(this.options.onOpen !== null) {
|
||||||
type: 'error',
|
this.options.onOpen(this.element);
|
||||||
message: '<p>'+message+'</p>'
|
}
|
||||||
}, options));
|
},
|
||||||
},
|
hide: function(all) {
|
||||||
success: function(message, options) {
|
if(all !== undefined && all === true) {
|
||||||
this.show(jQuery.extend({}, {
|
jQuery('.mailpoet_notice:not([id])').trigger('close');
|
||||||
type: 'success',
|
} else if (all !== undefined && jQuery.isArray(all)) {
|
||||||
message: '<p>'+message+'</p>'
|
for (var id in all) {
|
||||||
}, options));
|
jQuery('[data-id="notice_' + all[id] + '"]')
|
||||||
},
|
.trigger('close');
|
||||||
system: function(message, options) {
|
}
|
||||||
this.show(jQuery.extend({}, {
|
} if (all !== undefined) {
|
||||||
type: 'system',
|
jQuery('[data-id="notice_' + all + '"]')
|
||||||
static: true,
|
.trigger('close');
|
||||||
message: message
|
} else {
|
||||||
}, options));
|
jQuery('.mailpoet_notice.updated:not([id]), .mailpoet_notice.error:not([id])')
|
||||||
}
|
.trigger('close');
|
||||||
};
|
}
|
||||||
});
|
},
|
||||||
|
error: function(message, options) {
|
||||||
|
this.show(jQuery.extend({}, {
|
||||||
|
type: 'error',
|
||||||
|
message: '<p>'+this.formatMessage(message)+'</p>'
|
||||||
|
}, options));
|
||||||
|
},
|
||||||
|
success: function(message, options) {
|
||||||
|
this.show(jQuery.extend({}, {
|
||||||
|
type: 'success',
|
||||||
|
message: '<p>'+this.formatMessage(message)+'</p>'
|
||||||
|
}, options));
|
||||||
|
},
|
||||||
|
system: function(message, options) {
|
||||||
|
this.show(jQuery.extend({}, {
|
||||||
|
type: 'system',
|
||||||
|
static: true,
|
||||||
|
message: '<p>'+this.formatMessage(message)+'</p>'
|
||||||
|
}, options));
|
||||||
|
},
|
||||||
|
formatMessage: function(message) {
|
||||||
|
if(Array.isArray(message)) {
|
||||||
|
return message.join('<br />');
|
||||||
|
} else {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
@ -26,10 +26,10 @@ define(
|
|||||||
];
|
];
|
||||||
|
|
||||||
var messages = {
|
var messages = {
|
||||||
updated: function() {
|
onUpdate: function() {
|
||||||
MailPoet.Notice.success('Segment successfully updated!');
|
MailPoet.Notice.success('Segment successfully updated!');
|
||||||
},
|
},
|
||||||
created: function() {
|
onCreate: function() {
|
||||||
MailPoet.Notice.success('Segment successfully added!');
|
MailPoet.Notice.success('Segment successfully added!');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -42,11 +42,7 @@ define(
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h2 className="title">
|
<h2 className="title">
|
||||||
Segment <a
|
Segment
|
||||||
href="javascript:;"
|
|
||||||
className="add-new-h2"
|
|
||||||
onClick={ this.history.goBack }
|
|
||||||
>Back to list</a>
|
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<Form
|
<Form
|
||||||
@ -54,7 +50,7 @@ define(
|
|||||||
fields={ fields }
|
fields={ fields }
|
||||||
params={ this.props.params }
|
params={ this.props.params }
|
||||||
messages={ messages }
|
messages={ messages }
|
||||||
onSuccess={ this.history.goBack } />
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -42,58 +42,49 @@ var columns = [
|
|||||||
|
|
||||||
const messages = {
|
const messages = {
|
||||||
onTrash: function(response) {
|
onTrash: function(response) {
|
||||||
if(response) {
|
var count = ~~response;
|
||||||
let message = null;
|
var message = null;
|
||||||
if(~~response === 1) {
|
|
||||||
message = (
|
|
||||||
'1 segment was moved to the trash.'
|
|
||||||
);
|
|
||||||
} else if(~~response > 1) {
|
|
||||||
message = (
|
|
||||||
'%$1d segments were moved to the trash.'
|
|
||||||
).replace('%$1d', ~~response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(message !== null) {
|
if(count === 1) {
|
||||||
MailPoet.Notice.success(message);
|
message = (
|
||||||
}
|
'1 segment was moved to the trash.'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
'%$1d segments were moved to the trash.'
|
||||||
|
).replace('%$1d', count);
|
||||||
}
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
},
|
},
|
||||||
onDelete: function(response) {
|
onDelete: function(response) {
|
||||||
if(response) {
|
var count = ~~response;
|
||||||
let message = null;
|
var message = null;
|
||||||
if(~~response === 1) {
|
|
||||||
message = (
|
|
||||||
'1 segment was permanently deleted.'
|
|
||||||
);
|
|
||||||
} else if(~~response > 1) {
|
|
||||||
message = (
|
|
||||||
'%$1d segments were permanently deleted.'
|
|
||||||
).replace('%$1d', ~~response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(message !== null) {
|
if(count === 1) {
|
||||||
MailPoet.Notice.success(message);
|
message = (
|
||||||
}
|
'1 segment was permanently deleted.'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
'%$1d segments were permanently deleted.'
|
||||||
|
).replace('%$1d', count);
|
||||||
}
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
},
|
},
|
||||||
onRestore: function(response) {
|
onRestore: function(response) {
|
||||||
if(response) {
|
var count = ~~response;
|
||||||
let message = null;
|
var message = null;
|
||||||
if(~~response === 1) {
|
|
||||||
message = (
|
|
||||||
'1 segment has been restored from the trash.'
|
|
||||||
);
|
|
||||||
} else if(~~response > 1) {
|
|
||||||
message = (
|
|
||||||
'%$1d segments have been restored from the trash.'
|
|
||||||
).replace('%$1d', ~~response);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(message !== null) {
|
if(count === 1) {
|
||||||
MailPoet.Notice.success(message);
|
message = (
|
||||||
}
|
'1 segment has been restored from the trash.'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
'%$1d segments have been restored from the trash.'
|
||||||
|
).replace('%$1d', count);
|
||||||
}
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -121,6 +112,32 @@ const item_actions = [
|
|||||||
);
|
);
|
||||||
refresh();
|
refresh();
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
display: function(segment) {
|
||||||
|
return (segment.type !== 'wp_users');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'synchronize_segment',
|
||||||
|
label: 'Update',
|
||||||
|
className: 'update',
|
||||||
|
onClick: function(item, refresh) {
|
||||||
|
MailPoet.Modal.loading(true);
|
||||||
|
MailPoet.Ajax.post({
|
||||||
|
endpoint: 'segments',
|
||||||
|
action: 'synchronize'
|
||||||
|
}).done(function(response) {
|
||||||
|
MailPoet.Modal.loading(false);
|
||||||
|
if(response === true) {
|
||||||
|
MailPoet.Notice.success(
|
||||||
|
('List "%$1s" has been synchronized.').replace('%$1s', item.name)
|
||||||
|
);
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
display: function(segment) {
|
||||||
|
return (segment.type === 'wp_users');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -130,15 +147,16 @@ const item_actions = [
|
|||||||
<a href={ item.subscribers_url }>View subscribers</a>
|
<a href={ item.subscribers_url }>View subscribers</a>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'trash',
|
||||||
|
display: function(segment) {
|
||||||
|
return (segment.type !== 'wp_users');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
const bulk_actions = [
|
const bulk_actions = [
|
||||||
{
|
|
||||||
name: 'trash',
|
|
||||||
label: 'Trash',
|
|
||||||
onSuccess: messages.onTrash
|
|
||||||
}
|
|
||||||
];
|
];
|
||||||
|
|
||||||
const SegmentList = React.createClass({
|
const SegmentList = React.createClass({
|
||||||
@ -148,7 +166,6 @@ const SegmentList = React.createClass({
|
|||||||
'column-primary',
|
'column-primary',
|
||||||
'has-row-actions'
|
'has-row-actions'
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<td className={ rowClasses }>
|
<td className={ rowClasses }>
|
||||||
|
@ -15,10 +15,10 @@ define(
|
|||||||
|
|
||||||
MailPoet.Router = new (Backbone.Router.extend({
|
MailPoet.Router = new (Backbone.Router.extend({
|
||||||
routes: {
|
routes: {
|
||||||
'mta(/:method)': 'sendingMethod',
|
'mta(/:group)': 'sendingMethodGroup',
|
||||||
'(:tab)': 'tabs',
|
'(:tab)': 'tabs',
|
||||||
},
|
},
|
||||||
sendingMethod: function(method) {
|
sendingMethodGroup: function(group) {
|
||||||
// display mta tab
|
// display mta tab
|
||||||
this.tabs('mta');
|
this.tabs('mta');
|
||||||
|
|
||||||
@ -30,13 +30,13 @@ define(
|
|||||||
// hide "save settings" button
|
// hide "save settings" button
|
||||||
jQuery('.mailpoet_settings_submit').hide();
|
jQuery('.mailpoet_settings_submit').hide();
|
||||||
|
|
||||||
if(method === null) {
|
if(group === null) {
|
||||||
// show sending methods
|
// show sending methods
|
||||||
jQuery('.mailpoet_sending_methods').fadeIn();
|
jQuery('.mailpoet_sending_methods').fadeIn();
|
||||||
} else {
|
} else {
|
||||||
// hide DKIM option when using MailPoet's API
|
// hide DKIM option when using MailPoet's API
|
||||||
jQuery('#mailpoet_mta_dkim')[
|
jQuery('#mailpoet_mta_dkim')[
|
||||||
(method === 'mailpoet')
|
(group === 'mailpoet')
|
||||||
? 'hide'
|
? 'hide'
|
||||||
: 'show'
|
: 'show'
|
||||||
]();
|
]();
|
||||||
@ -45,7 +45,7 @@ define(
|
|||||||
jQuery('.mailpoet_sending_methods').hide();
|
jQuery('.mailpoet_sending_methods').hide();
|
||||||
|
|
||||||
// display selected sending method's settings
|
// display selected sending method's settings
|
||||||
jQuery('.mailpoet_sending_method[data-method="'+ method +'"]').show();
|
jQuery('.mailpoet_sending_method[data-group="'+ group +'"]').show();
|
||||||
jQuery('#mailpoet_sending_method_setup').fadeIn();
|
jQuery('#mailpoet_sending_method_setup').fadeIn();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -73,7 +73,7 @@ define(
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
jQuery(document).ready(function() {
|
jQuery(document).ready(function() {
|
||||||
Backbone.history.start();
|
if (!Backbone.History.started) Backbone.history.start();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
@ -37,14 +37,43 @@ define(
|
|||||||
'subscribed': 'Subscribed',
|
'subscribed': 'Subscribed',
|
||||||
'unsubscribed': 'Unsubscribed'
|
'unsubscribed': 'Unsubscribed'
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'segments',
|
||||||
|
label: 'Lists',
|
||||||
|
type: 'selection',
|
||||||
|
placeholder: "Select a list",
|
||||||
|
endpoint: "segments",
|
||||||
|
multiple: true,
|
||||||
|
filter: function(segment) {
|
||||||
|
return !!(!segment.deleted_at);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
var custom_fields = window.mailpoet_custom_fields || [];
|
||||||
|
custom_fields.map(custom_field => {
|
||||||
|
let field = {
|
||||||
|
name: 'cf_' + custom_field.id,
|
||||||
|
label: custom_field.name,
|
||||||
|
type: custom_field.type
|
||||||
|
};
|
||||||
|
if(custom_field.params) {
|
||||||
|
field.params = custom_field.params;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(custom_field.params.values) {
|
||||||
|
field.values = custom_field.params.values;
|
||||||
|
}
|
||||||
|
|
||||||
|
fields.push(field);
|
||||||
|
});
|
||||||
|
|
||||||
var messages = {
|
var messages = {
|
||||||
updated: function() {
|
onUpdate: function() {
|
||||||
MailPoet.Notice.success('Subscriber successfully updated!');
|
MailPoet.Notice.success('Subscriber successfully updated!');
|
||||||
},
|
},
|
||||||
created: function() {
|
onCreate: function() {
|
||||||
MailPoet.Notice.success('Subscriber successfully added!');
|
MailPoet.Notice.success('Subscriber successfully added!');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -59,11 +88,7 @@ define(
|
|||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h2 className="title">
|
<h2 className="title">
|
||||||
Subscriber <a
|
Subscriber
|
||||||
href="javascript:;"
|
|
||||||
className="add-new-h2"
|
|
||||||
onClick={ this.history.goBack }
|
|
||||||
>Back to list</a>
|
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<Form
|
<Form
|
||||||
@ -71,7 +96,7 @@ define(
|
|||||||
fields={ fields }
|
fields={ fields }
|
||||||
params={ this.props.params }
|
params={ this.props.params }
|
||||||
messages={ messages }
|
messages={ messages }
|
||||||
onSuccess={ this.history.goBack } />
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
170
assets/js/src/subscribers/importExport/export.js
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
define(
|
||||||
|
[
|
||||||
|
'underscore',
|
||||||
|
'jquery',
|
||||||
|
'mailpoet',
|
||||||
|
'handlebars',
|
||||||
|
'select2'
|
||||||
|
],
|
||||||
|
function (
|
||||||
|
_,
|
||||||
|
jQuery,
|
||||||
|
MailPoet,
|
||||||
|
Handlebars
|
||||||
|
) {
|
||||||
|
if (!jQuery("#mailpoet_subscribers_export").length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
jQuery(document).ready(function () {
|
||||||
|
if (!exportData.segments) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var subscribers_export_template =
|
||||||
|
Handlebars.compile(jQuery('#mailpoet_subscribers_export_template').html());
|
||||||
|
|
||||||
|
//render template
|
||||||
|
jQuery('#mailpoet_subscribers_export > div.inside').html(subscribers_export_template(exportData));
|
||||||
|
|
||||||
|
// define reusable variables
|
||||||
|
var segmentsContainerElement = jQuery("#export_lists"),
|
||||||
|
subscriberFieldsContainerElement = jQuery("#export_columns"),
|
||||||
|
exportConfirmedOptionElement = jQuery(':radio[name="option_confirmed"]'),
|
||||||
|
groupBySegmentOptionElement = jQuery(':checkbox[name="option_group_by_list"]'),
|
||||||
|
nextStepButton = jQuery("a.mailpoet_export_process"),
|
||||||
|
renderSegmentsAndFields = function (container, data) {
|
||||||
|
if (container.data('select2')) {
|
||||||
|
container
|
||||||
|
.html('')
|
||||||
|
.select2('destroy');
|
||||||
|
}
|
||||||
|
container
|
||||||
|
.select2({
|
||||||
|
data: data,
|
||||||
|
width: '20em',
|
||||||
|
templateResult: function (item) {
|
||||||
|
return (item.subscriberCount > 0)
|
||||||
|
? item.name + ' (' + item.subscriberCount + ')'
|
||||||
|
: item.name;
|
||||||
|
},
|
||||||
|
templateSelection: function (item) {
|
||||||
|
return (item.subscriberCount > 0)
|
||||||
|
? item.name + ' (' + item.subscriberCount + ')'
|
||||||
|
: item.name;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on('select2:selecting', function (selectEvent) {
|
||||||
|
var selectElement = this,
|
||||||
|
selectedOptionId = selectEvent.params.args.data.id,
|
||||||
|
fieldsToExclude = [
|
||||||
|
'select',
|
||||||
|
'deselect'
|
||||||
|
];
|
||||||
|
if (_.contains(fieldsToExclude, selectedOptionId)) {
|
||||||
|
selectEvent.preventDefault();
|
||||||
|
if (selectedOptionId === 'deselect') {
|
||||||
|
jQuery(selectElement).val('').trigger('change');
|
||||||
|
} else {
|
||||||
|
var allOptions = [];
|
||||||
|
_.each(container.find('option'), function (field) {
|
||||||
|
if (!_.contains(fieldsToExclude, field.value)) {
|
||||||
|
allOptions.push(field.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
jQuery(selectElement).val(allOptions).trigger('change');
|
||||||
|
}
|
||||||
|
jQuery(selectElement).select2('close');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on('change', function () {
|
||||||
|
if ((exportData.segments && segmentsContainerElement.select2('data').length && subscriberFieldsContainerElement.select2('data').length)
|
||||||
|
||
|
||||||
|
(!exportData.segments && subscriberFieldsContainerElement.select2('data').length)
|
||||||
|
) {
|
||||||
|
toggleNextStepButton('on');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
toggleNextStepButton('off');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (segmentsContainerElement.select2('data').length > 1 && exportData.groupBySegmentOption) {
|
||||||
|
jQuery('.mailpoet_group_by_list').show();
|
||||||
|
}
|
||||||
|
else if (exportData.groupBySegmentOption) {
|
||||||
|
jQuery('.mailpoet_group_by_list').hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
renderSegmentsAndFields(subscriberFieldsContainerElement, subscriberFieldsSelect2);
|
||||||
|
renderSegmentsAndFields(segmentsContainerElement, segments);
|
||||||
|
|
||||||
|
subscriberFieldsContainerElement.select2('val', [
|
||||||
|
'status',
|
||||||
|
'email',
|
||||||
|
'first_name',
|
||||||
|
'last_name'
|
||||||
|
]);
|
||||||
|
|
||||||
|
exportConfirmedOptionElement.change(function () {
|
||||||
|
var selectedSegments = segmentsContainerElement.val();
|
||||||
|
if (this.value == 1) {
|
||||||
|
exportData.exportConfirmedOption = true;
|
||||||
|
renderSegmentsAndFields(segmentsContainerElement, segmentsWithConfirmedSubscribers);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
exportData.exportConfirmedOption = false;
|
||||||
|
renderSegmentsAndFields(segmentsContainerElement, segments);
|
||||||
|
}
|
||||||
|
segmentsContainerElement.select2('val', selectedSegments);
|
||||||
|
});
|
||||||
|
|
||||||
|
function toggleNextStepButton(condition) {
|
||||||
|
var disabled = 'button-disabled';
|
||||||
|
if (condition === 'on') {
|
||||||
|
nextStepButton.removeClass(disabled);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nextStepButton.addClass(disabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nextStepButton.click(function () {
|
||||||
|
if (jQuery(this).hasClass('button-disabled')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MailPoet.Modal.loading(true);
|
||||||
|
MailPoet.Ajax
|
||||||
|
.post({
|
||||||
|
endpoint: 'ImportExport',
|
||||||
|
action: 'processExport',
|
||||||
|
data: JSON.stringify({
|
||||||
|
'export_confirmed_option': exportData.exportConfirmedOption,
|
||||||
|
'export_format_option': jQuery(':radio[name="option_format"]:checked').val(),
|
||||||
|
'group_by_segment_option': (groupBySegmentOptionElement.is(":visible")) ? groupBySegmentOptionElement.prop('checked') : false,
|
||||||
|
'segments': (exportData.segments) ? segmentsContainerElement.val() : false,
|
||||||
|
'subscriber_fields': subscriberFieldsContainerElement.val()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.done(function (response) {
|
||||||
|
MailPoet.Modal.loading(false);
|
||||||
|
if (response.result === false) {
|
||||||
|
MailPoet.Notice.error(response.error);
|
||||||
|
} else {
|
||||||
|
resultMessage = MailPoetI18n.exportMessage
|
||||||
|
.replace('%1$s', '<strong>' + response.data.totalExported + '</strong>')
|
||||||
|
.replace('[link]', '<a href="' + response.data.exportFileURL + '" target="_blank" >')
|
||||||
|
.replace('[/link]', '</a>');
|
||||||
|
jQuery('#export_result_notice > ul > li').html(resultMessage);
|
||||||
|
jQuery('#export_result_notice').show();
|
||||||
|
window.location.href = response.data.exportFileURL;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.error(function (error) {
|
||||||
|
MailPoet.Modal.loading(false);
|
||||||
|
MailPoet.Notice.error(
|
||||||
|
MailPoetI18n.serverError + error.statusText.toLowerCase() + '.'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
1170
assets/js/src/subscribers/importExport/import.js
Normal file
@ -101,7 +101,12 @@ const bulk_actions = [
|
|||||||
onSelect: function() {
|
onSelect: function() {
|
||||||
let field = {
|
let field = {
|
||||||
id: 'move_to_segment',
|
id: 'move_to_segment',
|
||||||
endpoint: 'segments'
|
endpoint: 'segments',
|
||||||
|
filter: function(segment) {
|
||||||
|
return !!(
|
||||||
|
!segment.deleted_at && segment.type === 'default'
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -127,7 +132,12 @@ const bulk_actions = [
|
|||||||
onSelect: function() {
|
onSelect: function() {
|
||||||
let field = {
|
let field = {
|
||||||
id: 'add_to_segment',
|
id: 'add_to_segment',
|
||||||
endpoint: 'segments'
|
endpoint: 'segments',
|
||||||
|
filter: function(segment) {
|
||||||
|
return !!(
|
||||||
|
!segment.deleted_at && segment.type === 'default'
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -153,7 +163,12 @@ const bulk_actions = [
|
|||||||
onSelect: function() {
|
onSelect: function() {
|
||||||
let field = {
|
let field = {
|
||||||
id: 'remove_from_segment',
|
id: 'remove_from_segment',
|
||||||
endpoint: 'segments'
|
endpoint: 'segments',
|
||||||
|
filter: function(segment) {
|
||||||
|
return !!(
|
||||||
|
segment.type === 'default'
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -200,6 +215,21 @@ const bulk_actions = [
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const item_actions = [
|
||||||
|
{
|
||||||
|
name: 'edit',
|
||||||
|
label: 'Edit',
|
||||||
|
link: function(item) {
|
||||||
|
return (
|
||||||
|
<Link to={ `/edit/${item.id}` }>Edit</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'trash'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
const SubscriberList = React.createClass({
|
const SubscriberList = React.createClass({
|
||||||
renderItem: function(subscriber, actions) {
|
renderItem: function(subscriber, actions) {
|
||||||
let row_classes = classNames(
|
let row_classes = classNames(
|
||||||
@ -270,11 +300,16 @@ const SubscriberList = React.createClass({
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
onGetItems: function(count) {
|
||||||
|
jQuery('#mailpoet_export_button')[(count > 0) ? 'show' : 'hide']();
|
||||||
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h2 className="title">
|
<h2 className="title">
|
||||||
Subscribers <Link className="add-new-h2" to="/new">New</Link>
|
Subscribers <Link className="add-new-h2" to="/new">New</Link>
|
||||||
|
<a className="add-new-h2" href="?page=mailpoet-import#step1">Import</a>
|
||||||
|
<a id="mailpoet_export_button" className="add-new-h2" href="?page=mailpoet-export">Export</a>
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<Listing
|
<Listing
|
||||||
@ -284,7 +319,9 @@ const SubscriberList = React.createClass({
|
|||||||
onRenderItem={ this.renderItem }
|
onRenderItem={ this.renderItem }
|
||||||
columns={ columns }
|
columns={ columns }
|
||||||
bulk_actions={ bulk_actions }
|
bulk_actions={ bulk_actions }
|
||||||
|
item_actions={ item_actions }
|
||||||
messages={ messages }
|
messages={ messages }
|
||||||
|
onGetItems={ this.onGetItems }
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
264
assets/js/src/vendor/jquery.sticky-kit.js
vendored
Normal file
@ -0,0 +1,264 @@
|
|||||||
|
// Generated by CoffeeScript 1.9.2
|
||||||
|
|
||||||
|
/**
|
||||||
|
@license Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
var $, win;
|
||||||
|
|
||||||
|
$ = this.jQuery || window.jQuery;
|
||||||
|
|
||||||
|
win = $(window);
|
||||||
|
|
||||||
|
$.fn.stick_in_parent = function(opts) {
|
||||||
|
var doc, elm, enable_bottoming, fn, i, inner_scrolling, len, manual_spacer, offset_top, outer_width, parent_selector, recalc_every, sticky_class;
|
||||||
|
if (opts == null) {
|
||||||
|
opts = {};
|
||||||
|
}
|
||||||
|
sticky_class = opts.sticky_class, inner_scrolling = opts.inner_scrolling, recalc_every = opts.recalc_every, parent_selector = opts.parent, offset_top = opts.offset_top, manual_spacer = opts.spacer, enable_bottoming = opts.bottoming;
|
||||||
|
if (offset_top == null) {
|
||||||
|
offset_top = 0;
|
||||||
|
}
|
||||||
|
if (parent_selector == null) {
|
||||||
|
parent_selector = void 0;
|
||||||
|
}
|
||||||
|
if (inner_scrolling == null) {
|
||||||
|
inner_scrolling = true;
|
||||||
|
}
|
||||||
|
if (sticky_class == null) {
|
||||||
|
sticky_class = "is_stuck";
|
||||||
|
}
|
||||||
|
doc = $(document);
|
||||||
|
if (enable_bottoming == null) {
|
||||||
|
enable_bottoming = true;
|
||||||
|
}
|
||||||
|
outer_width = function(el) {
|
||||||
|
var _el, computed, w;
|
||||||
|
if (window.getComputedStyle) {
|
||||||
|
_el = el[0];
|
||||||
|
computed = window.getComputedStyle(el[0]);
|
||||||
|
w = parseFloat(computed.getPropertyValue("width")) + parseFloat(computed.getPropertyValue("margin-left")) + parseFloat(computed.getPropertyValue("margin-right"));
|
||||||
|
if (computed.getPropertyValue("box-sizing") !== "border-box") {
|
||||||
|
w += parseFloat(computed.getPropertyValue("border-left-width")) + parseFloat(computed.getPropertyValue("border-right-width")) + parseFloat(computed.getPropertyValue("padding-left")) + parseFloat(computed.getPropertyValue("padding-right"));
|
||||||
|
}
|
||||||
|
return w;
|
||||||
|
} else {
|
||||||
|
return el.outerWidth(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fn = function(elm, padding_bottom, parent_top, parent_height, top, height, el_float, detached) {
|
||||||
|
var bottomed, detach, fixed, last_pos, last_scroll_height, offset, parent, recalc, recalc_and_tick, recalc_counter, spacer, tick;
|
||||||
|
if (elm.data("sticky_kit")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
elm.data("sticky_kit", true);
|
||||||
|
last_scroll_height = doc.height();
|
||||||
|
parent = elm.parent();
|
||||||
|
if (parent_selector != null) {
|
||||||
|
parent = parent.closest(parent_selector);
|
||||||
|
}
|
||||||
|
if (!parent.length) {
|
||||||
|
throw "failed to find stick parent";
|
||||||
|
}
|
||||||
|
fixed = false;
|
||||||
|
bottomed = false;
|
||||||
|
spacer = manual_spacer != null ? manual_spacer && elm.closest(manual_spacer) : $("<div />");
|
||||||
|
if (spacer) {
|
||||||
|
spacer.css('position', elm.css('position'));
|
||||||
|
}
|
||||||
|
recalc = function() {
|
||||||
|
var border_top, padding_top, restore;
|
||||||
|
if (detached) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
last_scroll_height = doc.height();
|
||||||
|
border_top = parseInt(parent.css("border-top-width"), 10);
|
||||||
|
padding_top = parseInt(parent.css("padding-top"), 10);
|
||||||
|
padding_bottom = parseInt(parent.css("padding-bottom"), 10);
|
||||||
|
parent_top = parent.offset().top + border_top + padding_top;
|
||||||
|
parent_height = parent.height();
|
||||||
|
if (fixed) {
|
||||||
|
fixed = false;
|
||||||
|
bottomed = false;
|
||||||
|
if (manual_spacer == null) {
|
||||||
|
elm.insertAfter(spacer);
|
||||||
|
spacer.detach();
|
||||||
|
}
|
||||||
|
elm.css({
|
||||||
|
position: "",
|
||||||
|
top: "",
|
||||||
|
width: "",
|
||||||
|
bottom: ""
|
||||||
|
}).removeClass(sticky_class);
|
||||||
|
restore = true;
|
||||||
|
}
|
||||||
|
top = elm.offset().top - (parseInt(elm.css("margin-top"), 10) || 0) - offset_top;
|
||||||
|
height = elm.outerHeight(true);
|
||||||
|
el_float = elm.css("float");
|
||||||
|
if (spacer) {
|
||||||
|
spacer.css({
|
||||||
|
width: outer_width(elm),
|
||||||
|
height: height,
|
||||||
|
display: elm.css("display"),
|
||||||
|
"vertical-align": elm.css("vertical-align"),
|
||||||
|
"float": el_float
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (restore) {
|
||||||
|
return tick();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
recalc();
|
||||||
|
|
||||||
|
last_pos = void 0;
|
||||||
|
offset = offset_top;
|
||||||
|
recalc_counter = recalc_every;
|
||||||
|
tick = function() {
|
||||||
|
var css, delta, recalced, scroll, will_bottom, win_height;
|
||||||
|
if (detached) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
recalced = false;
|
||||||
|
if (recalc_counter != null) {
|
||||||
|
recalc_counter -= 1;
|
||||||
|
if (recalc_counter <= 0) {
|
||||||
|
recalc_counter = recalc_every;
|
||||||
|
recalc();
|
||||||
|
recalced = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!recalced && doc.height() !== last_scroll_height) {
|
||||||
|
recalc();
|
||||||
|
recalced = true;
|
||||||
|
}
|
||||||
|
scroll = win.scrollTop();
|
||||||
|
if (last_pos != null) {
|
||||||
|
delta = scroll - last_pos;
|
||||||
|
}
|
||||||
|
last_pos = scroll;
|
||||||
|
if (fixed) {
|
||||||
|
if (enable_bottoming) {
|
||||||
|
will_bottom = scroll + height + offset > parent_height + parent_top;
|
||||||
|
if (bottomed && !will_bottom) {
|
||||||
|
bottomed = false;
|
||||||
|
elm.css({
|
||||||
|
position: "fixed",
|
||||||
|
bottom: "",
|
||||||
|
top: offset
|
||||||
|
}).trigger("sticky_kit:unbottom");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (scroll < top) {
|
||||||
|
fixed = false;
|
||||||
|
offset = offset_top;
|
||||||
|
if (manual_spacer == null) {
|
||||||
|
if (el_float === "left" || el_float === "right") {
|
||||||
|
elm.insertAfter(spacer);
|
||||||
|
}
|
||||||
|
spacer.detach();
|
||||||
|
}
|
||||||
|
css = {
|
||||||
|
position: "",
|
||||||
|
width: "",
|
||||||
|
top: ""
|
||||||
|
};
|
||||||
|
elm.css(css).removeClass(sticky_class).trigger("sticky_kit:unstick");
|
||||||
|
}
|
||||||
|
if (inner_scrolling) {
|
||||||
|
win_height = win.height();
|
||||||
|
if (height + offset_top > win_height) {
|
||||||
|
if (!bottomed) {
|
||||||
|
offset -= delta;
|
||||||
|
offset = Math.max(win_height - height, offset);
|
||||||
|
offset = Math.min(offset_top, offset);
|
||||||
|
if (fixed) {
|
||||||
|
elm.css({
|
||||||
|
top: offset + "px"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (scroll > top) {
|
||||||
|
fixed = true;
|
||||||
|
css = {
|
||||||
|
position: "fixed",
|
||||||
|
top: offset
|
||||||
|
};
|
||||||
|
css.width = elm.css("box-sizing") === "border-box" ? elm.outerWidth() + "px" : elm.width() + "px";
|
||||||
|
elm.css(css).addClass(sticky_class);
|
||||||
|
if (manual_spacer == null) {
|
||||||
|
elm.after(spacer);
|
||||||
|
if (el_float === "left" || el_float === "right") {
|
||||||
|
spacer.append(elm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elm.trigger("sticky_kit:stick");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fixed && enable_bottoming) {
|
||||||
|
if (will_bottom == null) {
|
||||||
|
will_bottom = scroll + height + offset > parent_height + parent_top;
|
||||||
|
}
|
||||||
|
if (!bottomed && will_bottom) {
|
||||||
|
bottomed = true;
|
||||||
|
if (parent.css("position") === "static") {
|
||||||
|
parent.css({
|
||||||
|
position: "relative"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return elm.css({
|
||||||
|
position: "absolute",
|
||||||
|
bottom: padding_bottom,
|
||||||
|
top: "auto"
|
||||||
|
}).trigger("sticky_kit:bottom");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
recalc_and_tick = function() {
|
||||||
|
recalc();
|
||||||
|
return tick();
|
||||||
|
};
|
||||||
|
detach = function() {
|
||||||
|
detached = true;
|
||||||
|
win.off("touchmove", tick);
|
||||||
|
win.off("scroll", tick);
|
||||||
|
win.off("resize", recalc_and_tick);
|
||||||
|
$(document.body).off("sticky_kit:recalc", recalc_and_tick);
|
||||||
|
elm.off("sticky_kit:detach", detach);
|
||||||
|
elm.removeData("sticky_kit");
|
||||||
|
elm.css({
|
||||||
|
position: "",
|
||||||
|
bottom: "",
|
||||||
|
top: "",
|
||||||
|
width: ""
|
||||||
|
});
|
||||||
|
parent.position("position", "");
|
||||||
|
if (fixed) {
|
||||||
|
if (manual_spacer == null) {
|
||||||
|
if (el_float === "left" || el_float === "right") {
|
||||||
|
elm.insertAfter(spacer);
|
||||||
|
}
|
||||||
|
spacer.remove();
|
||||||
|
}
|
||||||
|
return elm.removeClass(sticky_class);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
win.on("touchmove", tick);
|
||||||
|
win.on("scroll", tick);
|
||||||
|
win.on("resize", recalc_and_tick);
|
||||||
|
$(document.body).on("sticky_kit:recalc", recalc_and_tick);
|
||||||
|
elm.on("sticky_kit:detach", detach);
|
||||||
|
return setTimeout(tick, 0);
|
||||||
|
};
|
||||||
|
for (i = 0, len = this.length; i < len; i++) {
|
||||||
|
elm = this[i];
|
||||||
|
fn($(elm));
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
|
|
42
build
@ -1,42 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
# Remove previous build.
|
|
||||||
rm wysija-newsletters.zip;
|
|
||||||
|
|
||||||
# Create temp dir.
|
|
||||||
mkdir wysija-newsletters;
|
|
||||||
|
|
||||||
# Production assets.
|
|
||||||
./do compile:all;
|
|
||||||
|
|
||||||
# Production libraries.
|
|
||||||
rm -rf vendor;
|
|
||||||
rm composer.lock;
|
|
||||||
./composer.phar install --no-dev;
|
|
||||||
|
|
||||||
# Copy release folders.
|
|
||||||
cp -rf lang wysija-newsletters;
|
|
||||||
cp -rfL assets wysija-newsletters;
|
|
||||||
cp -rf lib wysija-newsletters;
|
|
||||||
cp -rf vendor wysija-newsletters;
|
|
||||||
cp -rf views wysija-newsletters;
|
|
||||||
rm -rf wysija-newsletters/assets/css/src;
|
|
||||||
rm -rf wysija-newsletters/assets/js/src;
|
|
||||||
|
|
||||||
# Copy release files.
|
|
||||||
cp LICENSE wysija-newsletters;
|
|
||||||
cp index.php wysija-newsletters;
|
|
||||||
cp mailpoet.php wysija-newsletters;
|
|
||||||
cp readme.txt wysija-newsletters;
|
|
||||||
cp uninstall.php wysija-newsletters;
|
|
||||||
|
|
||||||
# Zip final release.
|
|
||||||
zip -r wysija-newsletters.zip wysija-newsletters;
|
|
||||||
|
|
||||||
# Remove temp dir.
|
|
||||||
rm -rf wysija-newsletters;
|
|
||||||
|
|
||||||
# Reinstall dev dependencies.
|
|
||||||
rm composer.lock;
|
|
||||||
./composer.phar install;
|
|
||||||
./do install;
|
|
42
build.sh
Executable file
@ -0,0 +1,42 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
plugin_name='mailpoet'
|
||||||
|
|
||||||
|
# Remove previous build.
|
||||||
|
rm $plugin_name.zip
|
||||||
|
|
||||||
|
# Create temp dir.
|
||||||
|
mkdir $plugin_name
|
||||||
|
|
||||||
|
# Production assets.
|
||||||
|
rm -rf node_modules
|
||||||
|
npm install
|
||||||
|
./do compile:all
|
||||||
|
|
||||||
|
# Production libraries.
|
||||||
|
./composer.phar install --no-dev
|
||||||
|
|
||||||
|
# Copy release folders.
|
||||||
|
cp -Rf lang $plugin_name
|
||||||
|
cp -RfL assets $plugin_name
|
||||||
|
cp -Rf lib $plugin_name
|
||||||
|
cp -Rf vendor $plugin_name
|
||||||
|
cp -Rf views $plugin_name
|
||||||
|
rm -Rf $plugin_name/assets/css/src
|
||||||
|
rm -Rf $plugin_name/assets/js/src
|
||||||
|
|
||||||
|
# Copy release files.
|
||||||
|
cp LICENSE $plugin_name
|
||||||
|
cp index.php $plugin_name
|
||||||
|
cp $plugin_name.php $plugin_name
|
||||||
|
cp readme.txt $plugin_name
|
||||||
|
cp uninstall.php $plugin_name
|
||||||
|
|
||||||
|
# Zip final release.
|
||||||
|
zip -r $plugin_name.zip $plugin_name
|
||||||
|
|
||||||
|
# Remove temp dir.
|
||||||
|
rm -rf $plugin_name
|
||||||
|
|
||||||
|
# Reinstall dev dependencies.
|
||||||
|
./composer.phar install
|
@ -19,3 +19,12 @@ modules:
|
|||||||
user: ''
|
user: ''
|
||||||
password: ''
|
password: ''
|
||||||
dump: tests/_data/dump.sql
|
dump: tests/_data/dump.sql
|
||||||
|
coverage:
|
||||||
|
enabled: true
|
||||||
|
whitelist:
|
||||||
|
include:
|
||||||
|
- lib/*
|
||||||
|
exclude:
|
||||||
|
blacklist:
|
||||||
|
include:
|
||||||
|
exclude:
|
@ -8,7 +8,10 @@
|
|||||||
"tburry/pquery": "*",
|
"tburry/pquery": "*",
|
||||||
"j4mie/paris": "1.5.4",
|
"j4mie/paris": "1.5.4",
|
||||||
"swiftmailer/swiftmailer": "^5.4",
|
"swiftmailer/swiftmailer": "^5.4",
|
||||||
"phpseclib/phpseclib": "*"
|
"phpseclib/phpseclib": "*",
|
||||||
|
"mtdowling/cron-expression": "^1.0",
|
||||||
|
"nesbot/carbon": "^1.21",
|
||||||
|
"soundasleep/html2text": "^0.3.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"codeception/codeception": "*",
|
"codeception/codeception": "*",
|
||||||
|
954
composer.lock
generated
25
lib/Analytics/Reporter.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Analytics;
|
||||||
|
|
||||||
|
class Reporter {
|
||||||
|
|
||||||
|
private $fields = array(
|
||||||
|
'Plugin Version' => 'pluginVersion',
|
||||||
|
);
|
||||||
|
|
||||||
|
function __construct() {}
|
||||||
|
|
||||||
|
function getData() {
|
||||||
|
$_this = $this;
|
||||||
|
|
||||||
|
$analytics_data = array_map(function($func) use ($_this) {
|
||||||
|
return $_this->$func();
|
||||||
|
}, $this->fields);
|
||||||
|
|
||||||
|
return $analytics_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function pluginVersion() {
|
||||||
|
return MAILPOET_VERSION;
|
||||||
|
}
|
||||||
|
}
|
@ -9,13 +9,6 @@ class Activator {
|
|||||||
function __construct() {
|
function __construct() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
|
||||||
register_activation_hook(
|
|
||||||
Env::$file,
|
|
||||||
array($this, 'activate')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function activate() {
|
function activate() {
|
||||||
$migrator = new Migrator();
|
$migrator = new Migrator();
|
||||||
$migrator->up();
|
$migrator->up();
|
||||||
@ -23,4 +16,9 @@ class Activator {
|
|||||||
$populator = new Populator();
|
$populator = new Populator();
|
||||||
$populator->up();
|
$populator->up();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function deactivate() {
|
||||||
|
$migrator = new Migrator();
|
||||||
|
$migrator->down();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
33
lib/Config/Analytics.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Config;
|
||||||
|
use \MailPoet\Analytics\Reporter;
|
||||||
|
use \MailPoet\Models\Setting;
|
||||||
|
|
||||||
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
class Analytics {
|
||||||
|
function __construct() {
|
||||||
|
}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
// review: this creates a fatal error when mailpoet tables are dropped.
|
||||||
|
//add_action('admin_enqueue_scripts', array($this, 'setupAdminDependencies'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupAdminDependencies() {
|
||||||
|
if(Setting::getValue('send_analytics_now', false)) {
|
||||||
|
$analytics = new Reporter();
|
||||||
|
wp_enqueue_script(
|
||||||
|
'analytics',
|
||||||
|
Env::$assets_url . '/js/lib/analytics.js',
|
||||||
|
array(),
|
||||||
|
Env::$version
|
||||||
|
);
|
||||||
|
wp_localize_script(
|
||||||
|
'analytics',
|
||||||
|
'mailpoet_analytics_data',
|
||||||
|
$analytics->getData()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
61
lib/Config/Changelog.php
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Config;
|
||||||
|
use \MailPoet\Models\Setting;
|
||||||
|
|
||||||
|
class Changelog {
|
||||||
|
function init() {
|
||||||
|
$doing_ajax = (bool)(defined('DOING_AJAX') && DOING_AJAX);
|
||||||
|
|
||||||
|
// don't run any check when it's an ajax request
|
||||||
|
if($doing_ajax) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't run any check when we're not on our pages
|
||||||
|
if(
|
||||||
|
!(isset($_GET['page']))
|
||||||
|
or
|
||||||
|
(isset($_GET['page']) && strpos($_GET['page'], 'mailpoet') !== 0)
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
add_action(
|
||||||
|
'admin_init',
|
||||||
|
array($this, 'check')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function check() {
|
||||||
|
$version = Setting::getValue('version', null);
|
||||||
|
$redirect_url = null;
|
||||||
|
|
||||||
|
if($version === null) {
|
||||||
|
// new install
|
||||||
|
$redirect_url = admin_url('admin.php?page=mailpoet-welcome');
|
||||||
|
} else if($version !== Env::$version) {
|
||||||
|
// update
|
||||||
|
$redirect_url = admin_url('admin.php?page=mailpoet-update');
|
||||||
|
}
|
||||||
|
|
||||||
|
if($redirect_url !== null) {
|
||||||
|
// save version number
|
||||||
|
Setting::setValue('version', Env::$version);
|
||||||
|
|
||||||
|
global $wp;
|
||||||
|
$current_url = home_url(add_query_arg($wp->query_string, $wp->request));
|
||||||
|
|
||||||
|
if($redirect_url !== $current_url) {
|
||||||
|
wp_safe_redirect(
|
||||||
|
add_query_arg(
|
||||||
|
array(
|
||||||
|
'mailpoet_redirect' => urlencode($current_url)
|
||||||
|
),
|
||||||
|
$redirect_url
|
||||||
|
)
|
||||||
|
);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,53 +4,73 @@ namespace MailPoet\Config;
|
|||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
class Env {
|
class Env {
|
||||||
public static $version;
|
static $version;
|
||||||
public static $plugin_name;
|
static $plugin_name;
|
||||||
public static $file;
|
static $plugin_path;
|
||||||
public static $path;
|
static $file;
|
||||||
public static $views_path;
|
static $path;
|
||||||
public static $assets_path;
|
static $views_path;
|
||||||
public static $assets_url;
|
static $assets_path;
|
||||||
public static $languages_path;
|
static $assets_url;
|
||||||
public static $lib_path;
|
static $temp_path;
|
||||||
public static $plugin_prefix;
|
static $temp_URL;
|
||||||
public static $db_prefix;
|
static $languages_path;
|
||||||
public static $db_source_name;
|
static $lib_path;
|
||||||
public static $db_host;
|
static $plugin_prefix;
|
||||||
public static $db_name;
|
static $db_prefix;
|
||||||
public static $db_username;
|
static $db_source_name;
|
||||||
public static $db_password;
|
static $db_host;
|
||||||
public static $db_charset;
|
static $db_socket;
|
||||||
|
static $db_port;
|
||||||
|
static $db_name;
|
||||||
|
static $db_username;
|
||||||
|
static $db_password;
|
||||||
|
static $db_charset;
|
||||||
|
|
||||||
public static function init($file, $version) {
|
static function init($file, $version) {
|
||||||
global $wpdb;
|
global $wpdb;
|
||||||
self::$version = $version;
|
self::$version = $version;
|
||||||
self::$plugin_name = 'mailpoet';
|
|
||||||
self::$file = $file;
|
self::$file = $file;
|
||||||
self::$path = dirname(self::$file);
|
self::$path = dirname(self::$file);
|
||||||
|
self::$plugin_name = 'mailpoet';
|
||||||
self::$views_path = self::$path . '/views';
|
self::$views_path = self::$path . '/views';
|
||||||
self::$assets_path = self::$path . '/assets';
|
self::$assets_path = self::$path . '/assets';
|
||||||
self::$assets_url = plugins_url('/assets', $file);
|
self::$assets_url = plugins_url('/assets', $file);
|
||||||
|
$wp_upload_dir = wp_upload_dir();
|
||||||
|
self::$temp_path = $wp_upload_dir['path'];
|
||||||
|
self::$temp_URL = $wp_upload_dir['url'];
|
||||||
self::$languages_path = self::$path . '/lang';
|
self::$languages_path = self::$path . '/lang';
|
||||||
self::$lib_path = self::$path . '/lib';
|
self::$lib_path = self::$path . '/lib';
|
||||||
self::$plugin_prefix = 'mailpoet_';
|
self::$plugin_prefix = 'mailpoet_';
|
||||||
self::$db_prefix = $wpdb->prefix . self::$plugin_prefix;
|
self::$db_prefix = $wpdb->prefix . self::$plugin_prefix;
|
||||||
self::$db_source_name = self::dbSourceName();
|
|
||||||
self::$db_host = DB_HOST;
|
self::$db_host = DB_HOST;
|
||||||
|
self::$db_port = 3306;
|
||||||
|
self::$db_socket = false;
|
||||||
|
if(preg_match('/(?=:\d+$)/', DB_HOST)) {
|
||||||
|
list(self::$db_host, self::$db_port) = explode(':', DB_HOST);
|
||||||
|
} else {
|
||||||
|
if(preg_match('/:/', DB_HOST)) {
|
||||||
|
self::$db_socket = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
self::$db_name = DB_NAME;
|
self::$db_name = DB_NAME;
|
||||||
self::$db_username = DB_USER;
|
self::$db_username = DB_USER;
|
||||||
self::$db_password = DB_PASSWORD;
|
self::$db_password = DB_PASSWORD;
|
||||||
self::$db_charset = $wpdb->get_charset_collate();
|
self::$db_charset = $wpdb->get_charset_collate();
|
||||||
|
self::$db_source_name = self::dbSourceName(self::$db_host, self::$db_socket, self::$db_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function dbSourceName() {
|
private static function dbSourceName($host, $socket, $port) {
|
||||||
$source_name = array(
|
$source_name = array(
|
||||||
'mysql:host=',
|
(!$socket) ? 'mysql:host=' : 'mysql:unix_socket=',
|
||||||
DB_HOST,
|
$host,
|
||||||
|
';',
|
||||||
|
'port=',
|
||||||
|
$port,
|
||||||
';',
|
';',
|
||||||
'dbname=',
|
'dbname=',
|
||||||
DB_NAME
|
DB_NAME
|
||||||
);
|
);
|
||||||
return implode('', $source_name);
|
return implode('', $source_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
113
lib/Config/Hooks.php
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
<?php
|
||||||
|
namespace MailPoet\Config;
|
||||||
|
use \MailPoet\Models\Setting;
|
||||||
|
|
||||||
|
class Hooks {
|
||||||
|
function __construct() {
|
||||||
|
}
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
// Subscribe in comments
|
||||||
|
if((bool)Setting::getValue('subscribe.on_comment.enabled')) {
|
||||||
|
if(is_user_logged_in()) {
|
||||||
|
add_action(
|
||||||
|
'comment_form_field_comment',
|
||||||
|
'\MailPoet\Subscription\Comment::extendLoggedInForm'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
add_action(
|
||||||
|
'comment_form_after_fields',
|
||||||
|
'\MailPoet\Subscription\Comment::extendLoggedOutForm'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
add_action(
|
||||||
|
'comment_post',
|
||||||
|
'\MailPoet\Subscription\Comment::onSubmit',
|
||||||
|
60,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
|
||||||
|
add_action(
|
||||||
|
'wp_set_comment_status',
|
||||||
|
'\MailPoet\Subscription\Comment::onStatusUpdate',
|
||||||
|
60,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subscribe in registration form
|
||||||
|
if((bool)Setting::getValue('subscribe.on_register.enabled')) {
|
||||||
|
if(is_multisite()) {
|
||||||
|
add_action(
|
||||||
|
'signup_extra_fields',
|
||||||
|
'\MailPoet\Subscription\Registration::extendForm'
|
||||||
|
);
|
||||||
|
add_action(
|
||||||
|
'wpmu_validate_user_signup',
|
||||||
|
'\MailPoet\Subscription\Registration::onMultiSiteRegister',
|
||||||
|
60,
|
||||||
|
1
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
add_action(
|
||||||
|
'register_form',
|
||||||
|
'\MailPoet\Subscription\Registration::extendForm'
|
||||||
|
);
|
||||||
|
add_action(
|
||||||
|
'register_post',
|
||||||
|
'\MailPoet\Subscription\Registration::onRegister',
|
||||||
|
60,
|
||||||
|
3
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WP Users synchronization
|
||||||
|
add_action(
|
||||||
|
'user_register',
|
||||||
|
'\MailPoet\Segments\WP::synchronizeUser',
|
||||||
|
1
|
||||||
|
);
|
||||||
|
add_action(
|
||||||
|
'added_existing_user',
|
||||||
|
'\MailPoet\Segments\WP::synchronizeUser',
|
||||||
|
1
|
||||||
|
);
|
||||||
|
add_action(
|
||||||
|
'profile_update',
|
||||||
|
'\MailPoet\Segments\WP::synchronizeUser',
|
||||||
|
1
|
||||||
|
);
|
||||||
|
add_action(
|
||||||
|
'delete_user',
|
||||||
|
'\MailPoet\Segments\WP::synchronizeUser',
|
||||||
|
1
|
||||||
|
);
|
||||||
|
// multisite
|
||||||
|
add_action(
|
||||||
|
'deleted_user',
|
||||||
|
'\MailPoet\Segments\WP::synchronizeUser',
|
||||||
|
1
|
||||||
|
);
|
||||||
|
add_action(
|
||||||
|
'remove_user_from_blog',
|
||||||
|
'\MailPoet\Segments\WP::synchronizeUser',
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
|
add_filter(
|
||||||
|
'image_size_names_choose',
|
||||||
|
array(
|
||||||
|
$this,
|
||||||
|
'appendImageSizes'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function appendImageSizes($sizes) {
|
||||||
|
return array_merge($sizes, array(
|
||||||
|
'mailpoet_newsletter_max' => __('MailPoet Newsletter'),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
@ -2,10 +2,15 @@
|
|||||||
namespace MailPoet\Config;
|
namespace MailPoet\Config;
|
||||||
|
|
||||||
use MailPoet\Models;
|
use MailPoet\Models;
|
||||||
|
use MailPoet\Cron\Supervisor;
|
||||||
use MailPoet\Router;
|
use MailPoet\Router;
|
||||||
|
use MailPoet\Models\Setting;
|
||||||
|
use MailPoet\Settings\Pages;
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
|
require_once(ABSPATH . 'wp-admin/includes/plugin.php');
|
||||||
|
|
||||||
class Initializer {
|
class Initializer {
|
||||||
function __construct($params = array(
|
function __construct($params = array(
|
||||||
'file' => '',
|
'file' => '',
|
||||||
@ -16,13 +21,34 @@ class Initializer {
|
|||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
$this->setupDB();
|
$this->setupDB();
|
||||||
$this->setupActivator();
|
|
||||||
$this->setupRenderer();
|
register_activation_hook(Env::$file, array($this, 'runMigrator'));
|
||||||
$this->setupLocalizer();
|
register_activation_hook(Env::$file, array($this, 'runPopulator'));
|
||||||
$this->setupMenu();
|
|
||||||
$this->setupRouter();
|
add_action('plugins_loaded', array($this, 'setup'));
|
||||||
$this->setupWidget();
|
add_action('widgets_init', array($this, 'setupWidget'));
|
||||||
$this->setupPermissions();
|
}
|
||||||
|
|
||||||
|
function setup() {
|
||||||
|
try {
|
||||||
|
$this->setupRenderer();
|
||||||
|
$this->setupLocalizer();
|
||||||
|
$this->setupMenu();
|
||||||
|
$this->setupRouter();
|
||||||
|
$this->setupPermissions();
|
||||||
|
$this->setupPublicAPI();
|
||||||
|
$this->setupAnalytics();
|
||||||
|
$this->setupChangelog();
|
||||||
|
$this->runQueueSupervisor();
|
||||||
|
$this->setupShortcodes();
|
||||||
|
$this->setupHooks();
|
||||||
|
$this->setupPages();
|
||||||
|
$this->setupImages();
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
// if anything goes wrong during init
|
||||||
|
// automatically deactivate the plugin
|
||||||
|
deactivate_plugins(Env::$file);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupDB() {
|
function setupDB() {
|
||||||
@ -31,7 +57,8 @@ class Initializer {
|
|||||||
\ORM::configure('password', Env::$db_password);
|
\ORM::configure('password', Env::$db_password);
|
||||||
\ORM::configure('logging', WP_DEBUG);
|
\ORM::configure('logging', WP_DEBUG);
|
||||||
\ORM::configure('driver_options', array(
|
\ORM::configure('driver_options', array(
|
||||||
\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'
|
\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8',
|
||||||
|
\PDO::MYSQL_ATTR_INIT_COMMAND => 'SET TIME_ZONE = "+00:00"'
|
||||||
));
|
));
|
||||||
|
|
||||||
$subscribers = Env::$db_prefix . 'subscribers';
|
$subscribers = Env::$db_prefix . 'subscribers';
|
||||||
@ -46,6 +73,8 @@ class Initializer {
|
|||||||
$subscriber_custom_field = Env::$db_prefix . 'subscriber_custom_field';
|
$subscriber_custom_field = Env::$db_prefix . 'subscriber_custom_field';
|
||||||
$newsletter_option_fields = Env::$db_prefix . 'newsletter_option_fields';
|
$newsletter_option_fields = Env::$db_prefix . 'newsletter_option_fields';
|
||||||
$newsletter_option = Env::$db_prefix . 'newsletter_option';
|
$newsletter_option = Env::$db_prefix . 'newsletter_option';
|
||||||
|
$sending_queues = Env::$db_prefix . 'sending_queues';
|
||||||
|
$newsletter_statistics = Env::$db_prefix . 'newsletter_statistics';
|
||||||
|
|
||||||
define('MP_SUBSCRIBERS_TABLE', $subscribers);
|
define('MP_SUBSCRIBERS_TABLE', $subscribers);
|
||||||
define('MP_SETTINGS_TABLE', $settings);
|
define('MP_SETTINGS_TABLE', $settings);
|
||||||
@ -59,11 +88,18 @@ class Initializer {
|
|||||||
define('MP_SUBSCRIBER_CUSTOM_FIELD_TABLE', $subscriber_custom_field);
|
define('MP_SUBSCRIBER_CUSTOM_FIELD_TABLE', $subscriber_custom_field);
|
||||||
define('MP_NEWSLETTER_OPTION_FIELDS_TABLE', $newsletter_option_fields);
|
define('MP_NEWSLETTER_OPTION_FIELDS_TABLE', $newsletter_option_fields);
|
||||||
define('MP_NEWSLETTER_OPTION_TABLE', $newsletter_option);
|
define('MP_NEWSLETTER_OPTION_TABLE', $newsletter_option);
|
||||||
|
define('MP_SENDING_QUEUES_TABLE', $sending_queues);
|
||||||
|
define('MP_NEWSLETTER_STATISTICS_TABLE', $newsletter_statistics);
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupActivator() {
|
function runMigrator() {
|
||||||
$activator = new Activator();
|
$migrator = new Migrator();
|
||||||
$activator->init();
|
$migrator->up();
|
||||||
|
}
|
||||||
|
|
||||||
|
function runPopulator() {
|
||||||
|
$populator = new Populator();
|
||||||
|
$populator->up();
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupRenderer() {
|
function setupRenderer() {
|
||||||
@ -77,10 +113,7 @@ class Initializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setupMenu() {
|
function setupMenu() {
|
||||||
$menu = new Menu(
|
$menu = new Menu($this->renderer, Env::$assets_url);
|
||||||
$this->renderer,
|
|
||||||
Env::$assets_url
|
|
||||||
);
|
|
||||||
$menu->init();
|
$menu->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,8 +127,51 @@ class Initializer {
|
|||||||
$widget->init();
|
$widget->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setupAnalytics() {
|
||||||
|
$widget = new Analytics();
|
||||||
|
$widget->init();
|
||||||
|
}
|
||||||
|
|
||||||
function setupPermissions() {
|
function setupPermissions() {
|
||||||
$permissions = new Permissions();
|
$permissions = new Permissions();
|
||||||
$permissions->init();
|
$permissions->init();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
function setupChangelog() {
|
||||||
|
$changelog = new Changelog();
|
||||||
|
$changelog->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupPages() {
|
||||||
|
$pages = new Pages();
|
||||||
|
$pages->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupShortcodes() {
|
||||||
|
$shortcodes = new Shortcodes();
|
||||||
|
$shortcodes->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupHooks() {
|
||||||
|
$hooks = new Hooks();
|
||||||
|
$hooks->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupPublicAPI() {
|
||||||
|
$publicAPI = new PublicAPI();
|
||||||
|
$publicAPI->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
function runQueueSupervisor() {
|
||||||
|
if(php_sapi_name() === 'cli') return;
|
||||||
|
try {
|
||||||
|
$supervisor = new Supervisor();
|
||||||
|
$supervisor->checkDaemon();
|
||||||
|
} catch(\Exception $e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupImages() {
|
||||||
|
add_image_size('mailpoet_newsletter_max', 1320);
|
||||||
|
}
|
||||||
|
}
|