Compare commits
684 Commits
0.0.29
...
3.0.0-beta
Author | SHA1 | Date | |
---|---|---|---|
b2d4bfc760 | |||
57f5f16bb6 | |||
7d2e13b9a3 | |||
6d39f9fa78 | |||
a4395f2350 | |||
411969b3eb | |||
1868ca3155 | |||
e765471f5d | |||
bdce7c5e5a | |||
773be9f5c8 | |||
6ae46b05e5 | |||
217894745d | |||
a03891895c | |||
3368e84a99 | |||
e90df2f08d | |||
2391ae1cad | |||
83114a8be4 | |||
d08d5a3b6c | |||
8330bfc884 | |||
ef21a8cca7 | |||
e32c46a755 | |||
092f69538a | |||
7a75367d75 | |||
0b2701ade2 | |||
1ac288d286 | |||
516bc73092 | |||
4088abef68 | |||
f6cefc3f5c | |||
202e4b90e1 | |||
ee89bf0722 | |||
876d21300a | |||
0ca5b7a79f | |||
5d0ee43921 | |||
cc523a3c0b | |||
2787998d32 | |||
38f6c95059 | |||
cc03b631ff | |||
a3c77fb685 | |||
3817e28960 | |||
c3a78b1ea3 | |||
42877236c8 | |||
6e87f3539c | |||
7704ea4b68 | |||
12a3931b7b | |||
25a55dbb67 | |||
6758f60a81 | |||
5e9e53ec41 | |||
1285252a8c | |||
98f95f72ad | |||
09ca788371 | |||
b48cc5a959 | |||
812d138c4e | |||
07bc35d4cd | |||
90b95a2c25 | |||
78c50c41e3 | |||
7eee7def63 | |||
9ba6e9806f | |||
8c28dc3d8a | |||
9197e39fb4 | |||
37f59814e5 | |||
bf894fc26f | |||
0b2b42cf4d | |||
542015a4f6 | |||
f5a8323f5d | |||
55942cd88b | |||
f26a2cbd26 | |||
4402f826c3 | |||
b9745b555a | |||
f923a8063b | |||
f4367b9146 | |||
a3395e41c9 | |||
be61135daf | |||
21b4187a11 | |||
1c3c1e35e7 | |||
ded373557e | |||
280c4762bb | |||
bbd02260be | |||
1b1e9abd68 | |||
b0ab9e0408 | |||
d32abff78d | |||
7fbf84db1f | |||
8c5aebc7d6 | |||
42202f676a | |||
ba6198f956 | |||
120af4170b | |||
1faa53b978 | |||
e565a7a234 | |||
90b6b57a8d | |||
548253d68e | |||
e1c5f609ff | |||
226befdef6 | |||
a9d57654b4 | |||
ed00ae0516 | |||
48d738e8c4 | |||
132b4ed2e8 | |||
9a513cb27b | |||
5d692c0395 | |||
991ab67fff | |||
dd00640119 | |||
fa04173cfb | |||
a328d3b48a | |||
d5cff4f0d3 | |||
52bf24b6db | |||
50e134d696 | |||
ea5c73721b | |||
4799882b80 | |||
2e4c5ca39a | |||
13ed3aa3b9 | |||
6091751a4b | |||
c4d9e85dff | |||
1a85914c1b | |||
0ba48234de | |||
1c2a532949 | |||
9087be6ee8 | |||
5b2ede8b83 | |||
2fa5e5ead2 | |||
d5107be65e | |||
379dfb5f6e | |||
8360377992 | |||
4538cab6c8 | |||
1bf0988297 | |||
e1caf49ea5 | |||
0dfae97b32 | |||
ef2187c175 | |||
6157d17c5b | |||
8e879047c2 | |||
bff6aecd0d | |||
a121583c2d | |||
e11fd66fec | |||
b37e85eeb5 | |||
f88dabffe8 | |||
8c436180d9 | |||
b834a6af4d | |||
1bd8aed192 | |||
cfdf72867e | |||
5888620fc1 | |||
55ba605eb0 | |||
7a73ca7d1a | |||
1918894c5c | |||
0c5589a3e3 | |||
d6eaa4ac8a | |||
b0571b97f5 | |||
6d51ca8011 | |||
d3289dfb84 | |||
bfffdd7274 | |||
c5b8b2aef0 | |||
d7bcf1b817 | |||
f30ed153ce | |||
f436088a16 | |||
db8cb7499d | |||
49c4adc754 | |||
405e743171 | |||
3508ac36b4 | |||
f17c8228cd | |||
3dd5ac0536 | |||
4ebdff49e0 | |||
4a72995bf4 | |||
ef27ac0b84 | |||
2b4adef6c2 | |||
f650455a90 | |||
afbe25e215 | |||
d93249f077 | |||
6223ef77d9 | |||
a423123b66 | |||
1b3d3082b0 | |||
fa117cc7dd | |||
acd407c1f1 | |||
9baf4b068f | |||
18d852e147 | |||
b8dc306741 | |||
6ea056c042 | |||
bcf1b37c6a | |||
2986cdba85 | |||
53a8ae74e2 | |||
8bab01506c | |||
c664045444 | |||
6b8149210d | |||
f31d30b318 | |||
d9fbbdc02d | |||
8136ee2d9b | |||
f7cf6e2131 | |||
f2d1787bd5 | |||
fb51765d3f | |||
088ad5fb42 | |||
2f5b3c0c0a | |||
04ac4d896c | |||
f3b96af863 | |||
eb42b0b98d | |||
304667eb49 | |||
dad1082cd7 | |||
37cf0f3d29 | |||
d61c6dff58 | |||
3734ac578d | |||
b3f56c9d8e | |||
3603eeee77 | |||
59d30cc139 | |||
6ff3bbbb72 | |||
a561e10156 | |||
99f2cf6702 | |||
c6b72e729b | |||
c5bc0f36a4 | |||
efc5c34bf9 | |||
3929efbdd9 | |||
0e0c41882e | |||
79cc708fc6 | |||
8fa98879b8 | |||
331ba385e9 | |||
71ce46d78d | |||
c493de6569 | |||
ff2c2ace86 | |||
7fa789cfd1 | |||
ae6269eb63 | |||
a8f4779bfe | |||
6868142e35 | |||
133d123919 | |||
05c128d12d | |||
bdab0c12fa | |||
75b94690e2 | |||
80fddd6c58 | |||
c807ead5fd | |||
f004bb5368 | |||
1d756e95a7 | |||
1fb0da9fda | |||
a0017b91ee | |||
444ab17342 | |||
44f3058326 | |||
ec09fbcb78 | |||
ed352bb1d3 | |||
375bbd2759 | |||
9fb9d25132 | |||
30f79aa589 | |||
69f8daac95 | |||
03f3a6080c | |||
44f84c6cdb | |||
31008a6895 | |||
2490d8c919 | |||
5886dbfd25 | |||
e48d55f0b1 | |||
42339927cf | |||
b492bcecc0 | |||
6ab7debb7b | |||
b76ce6c26f | |||
6fbc7b1593 | |||
69c8670b01 | |||
da44a87415 | |||
9fb17d4a6b | |||
16dd286f9d | |||
5025f10f9f | |||
1278d9648c | |||
289811a595 | |||
916ae97f73 | |||
876e386966 | |||
9582e58dda | |||
213bca8050 | |||
dc97d3115e | |||
90eb443965 | |||
1b40f02715 | |||
c5a02c6136 | |||
492cd8c96b | |||
7f091d7188 | |||
1c081623b9 | |||
87332037c2 | |||
62023397f4 | |||
37ec6dc1a6 | |||
81c277ca93 | |||
f8fea75130 | |||
a4457649f7 | |||
1d6a09f010 | |||
faec553521 | |||
37fcf3a234 | |||
68a56aada8 | |||
f744305834 | |||
7a9402f5b5 | |||
de6d7e0cae | |||
a3c56b84ce | |||
3d4defd563 | |||
52da08abb2 | |||
b9637b52e9 | |||
0369a23fe8 | |||
f690e1a095 | |||
22e8e34213 | |||
12b46736c5 | |||
4950e47297 | |||
d7c5c8c3e7 | |||
46b0fcf37b | |||
b07c4d0e6e | |||
eb107799a7 | |||
4eec0a42f9 | |||
9a5a3a08c6 | |||
151683c632 | |||
fd2103d1aa | |||
7696b6ec5d | |||
d972b96255 | |||
35ccfb8bcf | |||
7ff036b1e9 | |||
983d56c29b | |||
a2528939ba | |||
c136d91dd2 | |||
bf00e82596 | |||
0e10f6c820 | |||
c056e95249 | |||
1be7fda1cf | |||
0b0c0f5759 | |||
59a4428965 | |||
3f5c36d2d4 | |||
3cc5812c1d | |||
3e616201ad | |||
5558ebad45 | |||
63bd093f35 | |||
ec6559b8be | |||
3421406dc7 | |||
a2917c08f6 | |||
5fa9b5a8dd | |||
41ad86ba1f | |||
067b3ff3e6 | |||
9b9cb1455a | |||
a5569a6a55 | |||
71c1026729 | |||
f102e847bf | |||
3158e2c460 | |||
a438f13bb0 | |||
5ed0a5819c | |||
6dd3c6acda | |||
ca2c1c2e6f | |||
1305a10ee0 | |||
5e36eb818b | |||
cfde82ff5f | |||
af98ade650 | |||
598432466e | |||
9469ce83f1 | |||
5624f4c7a0 | |||
82a001dc05 | |||
a9b424fb79 | |||
d31af9d71c | |||
ff7a24590f | |||
ea87a7acf8 | |||
9d36a17261 | |||
9c3cb5a509 | |||
4dd7f32f3a | |||
1c6fca7f83 | |||
c5b376bd21 | |||
5d2800bc25 | |||
6675d5a20d | |||
28c39d301c | |||
afa0d3af63 | |||
b05344b1d3 | |||
2e88d7cce0 | |||
cb558ce2ab | |||
ed30d8f639 | |||
9410d4f10a | |||
354d249e1d | |||
008fdb94c5 | |||
d0fb94b3f8 | |||
a451f00ed3 | |||
0e0c371b28 | |||
2e52f3bb92 | |||
a3a5016278 | |||
cb5d7cb9a0 | |||
a44d4ed0b5 | |||
7bd23288f6 | |||
08c663759c | |||
c46ee07674 | |||
18398a3bfb | |||
88d9315f8b | |||
8bc95db0c9 | |||
c05a20cff9 | |||
08cb994252 | |||
543ad81e28 | |||
641ba04685 | |||
8e4d07c658 | |||
420650f37f | |||
775f7faee4 | |||
13b91ad051 | |||
2d3ec13473 | |||
3094cfc076 | |||
6aadd1fdc4 | |||
13589a4660 | |||
5f124659d0 | |||
d3ebc9706c | |||
e83d01ff28 | |||
9600e4f220 | |||
3e746d1545 | |||
3cc43aa302 | |||
c610d87e85 | |||
362ee49ce4 | |||
515515ba9f | |||
ed7da1a8fe | |||
12c036dbef | |||
1dd4ade04d | |||
0706450f9a | |||
b837a153d1 | |||
6d22a85fd7 | |||
3d706414b7 | |||
ef0cbb3e9f | |||
f5552847a3 | |||
101ef0cff4 | |||
9e70ba5e6e | |||
8f1a7ed3de | |||
6aa976ba1f | |||
db85604f18 | |||
7605fc71ac | |||
2c98270084 | |||
a5300624c2 | |||
2714c7fa9a | |||
49b65729db | |||
e053b62a70 | |||
88113cf22e | |||
5bf352e9fc | |||
5a7d5ac3f0 | |||
05848ce7aa | |||
b58d996ac7 | |||
16fa4491a5 | |||
456deede14 | |||
4ef50ca551 | |||
5ff7d98b00 | |||
3018dff1ff | |||
9386fe8328 | |||
e4213437e9 | |||
386bdceed3 | |||
87eda71931 | |||
cef9f1dcf8 | |||
c78b2088eb | |||
150364de3a | |||
1cd9f3eb67 | |||
89253125af | |||
e7ee356f90 | |||
a88017400b | |||
f557881462 | |||
8dba4727c4 | |||
8ec094089f | |||
3c353e715b | |||
ab33a9c352 | |||
406b509ac4 | |||
bd814baf28 | |||
2db681d908 | |||
37e3af584e | |||
5fc863bd82 | |||
76649f9590 | |||
cb2faec8b2 | |||
e8604284fe | |||
d2ccdef6c7 | |||
38199dc96f | |||
630b219e96 | |||
64155bc121 | |||
7fb45a15ee | |||
ed5294477f | |||
d152b073a6 | |||
f8efb3934b | |||
5a21d3fdc8 | |||
710ede15ce | |||
150286ab6b | |||
9e758e8a33 | |||
059165e5d2 | |||
fe154d9251 | |||
a8ffbc2d0e | |||
9de3a245b0 | |||
5eef709af5 | |||
7b0c130d0a | |||
7f265675b0 | |||
ba15db9829 | |||
d15473a8e4 | |||
d9f93dc6e7 | |||
634c5b699d | |||
23e8ce38dd | |||
c62ae2ce80 | |||
d0813bb4e2 | |||
0ac701eb20 | |||
607395be6f | |||
55d48df8a4 | |||
e0282ae45b | |||
235fdea00f | |||
b8c6d54f48 | |||
67661e3aad | |||
c03facdc45 | |||
9ddc1ef555 | |||
9cfc2fd940 | |||
24e108bce7 | |||
48f0c03425 | |||
0bfbe6dc79 | |||
ad0a9838bc | |||
81ec293e54 | |||
b8b3d76a1d | |||
805e641d40 | |||
18326f9df1 | |||
46dda84012 | |||
9979261cb6 | |||
e8887e2aa5 | |||
4a91fae984 | |||
0fe975f614 | |||
c7fd7b8a32 | |||
b7e3c3ae81 | |||
b2c3206185 | |||
b7d8d482fe | |||
8a9d14319b | |||
c396254e64 | |||
e4dbeca664 | |||
168540d6d2 | |||
c62cd6c023 | |||
033e0581f1 | |||
9f978d3362 | |||
841340a42d | |||
9595e9629f | |||
56ba543f8d | |||
1cead6c6cd | |||
f5f7ce4c42 | |||
b13075b8f2 | |||
c4db9e3227 | |||
f47bfb5439 | |||
cc4639cb23 | |||
69094f57fd | |||
ffe7b80888 | |||
fc846b808e | |||
1cbf6b67b2 | |||
286c02bdd9 | |||
5f1d76225b | |||
c05ea1b968 | |||
2d45ab2e88 | |||
ca9b1e25a7 | |||
2927875e16 | |||
486a97fa30 | |||
c22d434dff | |||
306cdeb68f | |||
7ee83dad06 | |||
d414313749 | |||
66d329f630 | |||
f524ffcb28 | |||
264b7e180b | |||
88dc7f4199 | |||
9652f75028 | |||
36c32db2d1 | |||
fd12bd557e | |||
7bd8ed4639 | |||
ca0e511efd | |||
e5f3fabcda | |||
efc9bac760 | |||
ce6327c3d5 | |||
f32d6bb331 | |||
e807aad814 | |||
b87754ca30 | |||
22dfb372ec | |||
674bbd728e | |||
68c09b8678 | |||
c83ab0886f | |||
999a0b3ede | |||
6daecd6466 | |||
7af2775972 | |||
4bb1acf493 | |||
c8cd3d3eb5 | |||
2360c4d6e4 | |||
36e9168eef | |||
fb79d189d7 | |||
12330d6d34 | |||
5efbcfd9c1 | |||
75240fc2e1 | |||
b6fabcc739 | |||
269ddae93a | |||
90c3f0e4e4 | |||
dd8c54aae3 | |||
aa3a46b941 | |||
744455f0df | |||
9aa25446d1 | |||
6199caea29 | |||
d6a68dd4d0 | |||
ee6e261c42 | |||
cabfd8a946 | |||
cf712636ed | |||
873c3d15a0 | |||
bc1bd3bad1 | |||
9f971632c9 | |||
91bc0505ac | |||
90c94624cc | |||
cd412894c6 | |||
ecf15d53d9 | |||
a593347336 | |||
22566869cb | |||
c959e7ec96 | |||
86a2846215 | |||
3b97a26a8a | |||
dc6c973574 | |||
2a3a561464 | |||
e5f45fb7ad | |||
f22cadd319 | |||
5ea25ec697 | |||
c0a250fc0f | |||
e69aa792c4 | |||
3b4ac4d2d2 | |||
781973777e | |||
8698d2c6ba | |||
47c15eca83 | |||
64f4bed080 | |||
fe47ba8a38 | |||
eb02adc7ba | |||
f257b503e9 | |||
bfdabe3554 | |||
77dd71935a | |||
4b418f041b | |||
c8a0e006a0 | |||
359119d896 | |||
1a3c767601 | |||
6a97e82d42 | |||
3edfd32879 | |||
33bdde1156 | |||
710cab64c3 | |||
ed707b1738 | |||
398903e8b8 | |||
d590f5ea98 | |||
d6cbe5aac8 | |||
08e6430c7d | |||
945fe66bbb | |||
8e3eb2b795 | |||
52fbc0ee8a | |||
a355228b93 | |||
2cb0b3b071 | |||
bc1fb235d3 | |||
713dda913e | |||
d182638971 | |||
a5c620acf3 | |||
c176ad1d16 | |||
14c2b4d90f | |||
03eb4ad0fc | |||
ba9cd15651 | |||
329ec63dfd | |||
4925c7868e | |||
13d28d0aa7 | |||
c7d3c79fe3 | |||
1e9da724ea | |||
645d4e15ab | |||
cad5b242b2 | |||
99a81042c1 | |||
61987a204e | |||
a208104fc8 | |||
00ccc8adf4 | |||
df0ed9ce53 | |||
26d9b915a2 | |||
16cb91990b | |||
9642d3e672 | |||
aed60e6905 | |||
da7615ba4c | |||
3eb6a21980 | |||
b4e371302c | |||
e6724b1d4a | |||
2b6e87c3a7 | |||
b01ee80ec2 | |||
5d48ecac80 | |||
ebdb826011 | |||
9dc725e34d | |||
f47c331a5b | |||
b45c70f32b | |||
cf33d6f066 | |||
8292e9a744 | |||
3c46a5b434 | |||
4a4c4e093a | |||
4fa8a650b8 | |||
da755b7902 | |||
ceebb18bdf | |||
d10a29598d | |||
8c56c8da5e | |||
c4ddb38d18 | |||
15a21e5745 | |||
7df1a856ea | |||
69381205a2 | |||
9e0d8056b3 | |||
4b85c57436 | |||
377498be1d | |||
142421ad48 | |||
768115b794 | |||
8b9d76db8a | |||
f17c78fda2 | |||
3d45a8b7d4 | |||
3888241cbd | |||
603b6749de | |||
22918ecfd1 | |||
70ded73b51 | |||
da147047ec | |||
0e24174373 | |||
bc9b4eeb19 | |||
c6b13c5175 | |||
f754b1d1b2 | |||
bd5300d69a | |||
9996f3ef41 | |||
0f95d7bc8a | |||
14098643ae | |||
7c2d5a45c5 | |||
9d5902e179 |
15
.circle_ci/apache/mailpoet.loc.conf
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
Listen 8080
|
||||||
|
|
||||||
|
<VirtualHost *:8080>
|
||||||
|
UseCanonicalName Off
|
||||||
|
ServerName mailpoet.loc
|
||||||
|
DocumentRoot /home/ubuntu/mailpoet/wordpress
|
||||||
|
DirectoryIndex index.php
|
||||||
|
LogLevel notice
|
||||||
|
|
||||||
|
<Directory /home/ubuntu/mailpoet/wordpress>
|
||||||
|
AllowOverride All
|
||||||
|
Allow from All
|
||||||
|
</Directory>
|
||||||
|
</VirtualHost>
|
||||||
|
|
3
.gitignore
vendored
@ -12,8 +12,9 @@ npm-debug.log
|
|||||||
/views/cache/**
|
/views/cache/**
|
||||||
temp
|
temp
|
||||||
.idea
|
.idea
|
||||||
wysija-newsletters.zip
|
mailpoet.zip
|
||||||
tests/javascript/testBundles
|
tests/javascript/testBundles
|
||||||
assets/css/*.css
|
assets/css/*.css
|
||||||
assets/js/*.js
|
assets/js/*.js
|
||||||
.vagrant
|
.vagrant
|
||||||
|
lang
|
67
RoboFile.php
@ -102,31 +102,51 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testUnit($file = null) {
|
function testUnit($opts=['file' => null, 'xml' => false]) {
|
||||||
$this->loadEnv();
|
$this->loadEnv();
|
||||||
$this->_exec('vendor/bin/codecept build');
|
$this->_exec('vendor/bin/codecept build');
|
||||||
$this->_exec('vendor/bin/codecept run unit -f '.(($file) ? $file : ''));
|
|
||||||
|
$command = 'vendor/bin/codecept run unit -f '.(($opts['file']) ? $opts['file'] : '');
|
||||||
|
|
||||||
|
if($opts['xml']) {
|
||||||
|
$command .= ' --xml';
|
||||||
|
}
|
||||||
|
return $this->_exec($command);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testCoverage($file = null) {
|
function testCoverage($opts=['file' => null, 'xml' => false]) {
|
||||||
$this->loadEnv();
|
$this->loadEnv();
|
||||||
$this->_exec('vendor/bin/codecept build');
|
$this->_exec('vendor/bin/codecept build');
|
||||||
$this->_exec(join(' ', array(
|
$command = join(' ', array(
|
||||||
'vendor/bin/codecept run',
|
'vendor/bin/codecept run',
|
||||||
(($file) ? $file : ''),
|
(($opts['file']) ? $opts['file'] : ''),
|
||||||
'--coverage',
|
'--coverage',
|
||||||
'--coverage-html'
|
($opts['xml']) ? '--coverage-xml' : '--coverage-html'
|
||||||
)));
|
));
|
||||||
|
|
||||||
|
if($opts['xml']) {
|
||||||
|
$command .= ' --xml';
|
||||||
|
}
|
||||||
|
return $this->_exec($command);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testJavascript() {
|
function testJavascript($xml_output_file = null) {
|
||||||
$this->compileJs();
|
$this->compileJs();
|
||||||
|
|
||||||
$this->_exec(join(' ', array(
|
$command = join(' ', array(
|
||||||
'./node_modules/.bin/mocha',
|
'./node_modules/.bin/mocha',
|
||||||
'-r tests/javascript/mochaTestHelper.js',
|
'-r tests/javascript/mochaTestHelper.js',
|
||||||
'tests/javascript/testBundles/**/*.js'
|
'tests/javascript/testBundles/**/*.js'
|
||||||
)));
|
));
|
||||||
|
|
||||||
|
if(!empty($xml_output_file)) {
|
||||||
|
$command .= sprintf(
|
||||||
|
' --reporter xunit --reporter-options output="%s"',
|
||||||
|
$xml_output_file
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->_exec($command);
|
||||||
}
|
}
|
||||||
|
|
||||||
function testDebug() {
|
function testDebug() {
|
||||||
@ -141,8 +161,33 @@ class RoboFile extends \Robo\Tasks {
|
|||||||
$this->_exec('vendor/bin/codecept run -g failed');
|
$this->_exec('vendor/bin/codecept run -g failed');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function qa() {
|
||||||
|
$this->qaLint();
|
||||||
|
$this->qaCodeSniffer('all');
|
||||||
|
}
|
||||||
|
|
||||||
|
function qaLint() {
|
||||||
|
$this->_exec('./tasks/php_lint.sh lib/ tests/ mailpoet.php');
|
||||||
|
}
|
||||||
|
|
||||||
|
function qaCodeSniffer($severity='errors') {
|
||||||
|
if ($severity === 'all') {
|
||||||
|
$severityFlag = '-w';
|
||||||
|
} else {
|
||||||
|
$severityFlag = '-n';
|
||||||
|
}
|
||||||
|
$this->_exec(
|
||||||
|
'./vendor/bin/phpcs '.
|
||||||
|
'--standard=./tasks/code_sniffer/MailPoet '.
|
||||||
|
'--ignore=./lib/Util/Sudzy/*,./lib/Util/CSS.php,./lib/Util/XLSXWriter.php,'.
|
||||||
|
'./lib/Config/PopulatorData/Templates/* '.
|
||||||
|
'lib/ '.
|
||||||
|
$severityFlag
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
protected function loadEnv() {
|
protected function loadEnv() {
|
||||||
$dotenv = new Dotenv\Dotenv(__DIR__);
|
$dotenv = new Dotenv\Dotenv(__DIR__);
|
||||||
$dotenv->load();
|
$dotenv->load();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
@require 'form_editor'
|
@require 'form_editor'
|
||||||
@require 'listing'
|
@require 'listing'
|
||||||
|
@require 'listing/newsletters'
|
||||||
|
|
||||||
@require 'box'
|
@require 'box'
|
||||||
@require 'breadcrumb'
|
@require 'breadcrumb'
|
||||||
|
|
||||||
|
@ -27,13 +27,12 @@
|
|||||||
|
|
||||||
img
|
img
|
||||||
min-width: 150px
|
min-width: 150px
|
||||||
min-height: 150px
|
|
||||||
height: auto
|
height: auto
|
||||||
width: 110%
|
width: 110%
|
||||||
position: relative
|
position: relative
|
||||||
top: 0
|
top: 50%
|
||||||
left: 50%
|
left: 50%
|
||||||
transform: translate(-50%, 0%)
|
transform: translate(-50%, -50%)
|
||||||
|
|
||||||
.mailpoet_overlay
|
.mailpoet_overlay
|
||||||
position: absolute
|
position: absolute
|
||||||
@ -61,16 +60,20 @@
|
|||||||
.mailpoet_boxes .mailpoet_description
|
.mailpoet_boxes .mailpoet_description
|
||||||
float:left
|
float:left
|
||||||
width: 245px
|
width: 245px
|
||||||
max-height: calc(110px - 2em)
|
max-height: calc(115px - 2em)
|
||||||
padding-bottom: 2em
|
padding-bottom: 2em
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
|
|
||||||
.mailpoet_boxes .mailpoet_description h3
|
h3
|
||||||
margin: 0 0 1em 0
|
margin: 0 0 0.7em 0
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
white-space: nowrap
|
max-width: 210px
|
||||||
text-overflow: ellipsis
|
line-height: 1.4em
|
||||||
max-width: 220px
|
|
||||||
|
p
|
||||||
|
font-size: 13px
|
||||||
|
line-height: 1.5
|
||||||
|
margin: 1em 0
|
||||||
|
|
||||||
.mailpoet_boxes .mailpoet_actions
|
.mailpoet_boxes .mailpoet_actions
|
||||||
position: absolute
|
position: absolute
|
||||||
|
3
assets/css/src/listing/newsletters.styl
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#newsletters_container
|
||||||
|
h2.nav-tab-wrapper
|
||||||
|
margin-bottom: 1rem
|
@ -1,6 +1,6 @@
|
|||||||
$tool-inactive-color = #bbbbbb
|
$tool-inactive-color = #333333
|
||||||
$tool-inactive-secondary-color = #ffffff
|
$tool-inactive-secondary-color = #ffffff
|
||||||
$tool-hover-color = #333333
|
$tool-hover-color = #bbbbbb
|
||||||
$tool-hover-secondary-color = #ffffff
|
$tool-hover-secondary-color = #ffffff
|
||||||
$tool-active-color = #d2d2d4
|
$tool-active-color = #d2d2d4
|
||||||
$tool-active-secondary-color = #ffffff
|
$tool-active-secondary-color = #ffffff
|
||||||
@ -12,21 +12,42 @@ $master-column-tool-width = 24px
|
|||||||
position: absolute
|
position: absolute
|
||||||
top: 0
|
top: 0
|
||||||
right: 0
|
right: 0
|
||||||
display: none
|
|
||||||
z-index: 20
|
z-index: 20
|
||||||
padding: 2px
|
padding: 2px
|
||||||
text-align: right
|
text-align: right
|
||||||
|
overflow: hidden
|
||||||
|
|
||||||
|
.mailpoet_tool_slider
|
||||||
|
position: relative
|
||||||
|
right: -100%
|
||||||
|
transition: all 250ms cubic-bezier(0.420, 0.000, 0.580, 1.000)
|
||||||
|
opacity: 0
|
||||||
|
|
||||||
|
&.mailpoet_display_tools
|
||||||
|
.mailpoet_tool_slider
|
||||||
|
right: 0
|
||||||
|
opacity: 1
|
||||||
|
|
||||||
a
|
a
|
||||||
vertical-align: top
|
vertical-align: top
|
||||||
|
|
||||||
.mailpoet_container_horizontal + &
|
.mailpoet_container_horizontal + &
|
||||||
left: 100%
|
left: 100%
|
||||||
|
right: initial
|
||||||
padding-left: 5px
|
padding-left: 5px
|
||||||
|
|
||||||
|
.mailpoet_tool_slider
|
||||||
|
left: -100%
|
||||||
|
right: initial
|
||||||
|
|
||||||
|
&.mailpoet_display_tools
|
||||||
|
.mailpoet_tool_slider
|
||||||
|
left: 0
|
||||||
|
|
||||||
.mailpoet_tool
|
.mailpoet_tool
|
||||||
width: $master-column-tool-width
|
width: $master-column-tool-width
|
||||||
height: $master-column-tool-width
|
height: $master-column-tool-width
|
||||||
|
display: block
|
||||||
|
|
||||||
.mailpoet_tool_icon
|
.mailpoet_tool_icon
|
||||||
width: $master-column-tool-width
|
width: $master-column-tool-width
|
||||||
@ -46,6 +67,7 @@ $master-column-tool-width = 24px
|
|||||||
opacity: 0
|
opacity: 0
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
display: block
|
display: block
|
||||||
|
margin: 0
|
||||||
|
|
||||||
.mailpoet_delete_block_activated
|
.mailpoet_delete_block_activated
|
||||||
width: auto
|
width: auto
|
||||||
@ -125,7 +147,6 @@ $master-column-tool-width = 24px
|
|||||||
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
|
|
||||||
|
|
||||||
.mailpoet_delete_block_activate
|
.mailpoet_delete_block_activate
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
.mailpoet_form_field_title
|
.mailpoet_form_field_title
|
||||||
clear: both
|
clear: both
|
||||||
font-size: 1.1em
|
|
||||||
margin-bottom: 5px
|
margin-bottom: 5px
|
||||||
|
|
||||||
.mailpoet_form_field_title_small
|
.mailpoet_form_field_title_small
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
.mailpoet_input_title,
|
.mailpoet_input_title,
|
||||||
.mailpoet_input_preheader
|
.mailpoet_input_preheader
|
||||||
width: 400px
|
width: 500px
|
||||||
padding: 3px
|
padding: 3px
|
||||||
line-height: normal
|
line-height: normal
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ $widget-icon-width = 30px
|
|||||||
border-left: $content-border-color
|
border-left: $content-border-color
|
||||||
border-bottom: $content-border-color
|
border-bottom: $content-border-color
|
||||||
color: $sidebar-text-color
|
color: $sidebar-text-color
|
||||||
|
font-size: $sidebar-text-size
|
||||||
|
|
||||||
.mailpoet_sidebar_region
|
.mailpoet_sidebar_region
|
||||||
margin-bottom: 0
|
margin-bottom: 0
|
||||||
|
@ -3,6 +3,7 @@ $sidepanel-active-heading-color = $primary-active-color
|
|||||||
/* Sidepanel */
|
/* Sidepanel */
|
||||||
.mailpoet_editor_settings
|
.mailpoet_editor_settings
|
||||||
color: $sidebar-text-color
|
color: $sidebar-text-color
|
||||||
|
font-size: $sidebar-text-size
|
||||||
|
|
||||||
p
|
p
|
||||||
font-size: 1em
|
font-size: 1em
|
||||||
@ -18,7 +19,6 @@ $sidepanel-active-heading-color = $primary-active-color
|
|||||||
|
|
||||||
.mailpoet_sidepanel_field_title
|
.mailpoet_sidepanel_field_title
|
||||||
clear: both
|
clear: both
|
||||||
font-size: 1.1em
|
|
||||||
margin-bottom: 5px
|
margin-bottom: 5px
|
||||||
|
|
||||||
.mailpoet_sidepanel_field_title_small
|
.mailpoet_sidepanel_field_title_small
|
||||||
|
@ -23,6 +23,7 @@ $block-text-line-height = $text-line-height
|
|||||||
border: 1px solid $transparent-color
|
border: 1px solid $transparent-color
|
||||||
|
|
||||||
&:hover > .mailpoet_block_highlight
|
&:hover > .mailpoet_block_highlight
|
||||||
|
&.mailpoet_highlight > .mailpoet_block_highlight
|
||||||
border: 1px dashed $block-hover-highlight-color
|
border: 1px dashed $block-hover-highlight-color
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ $three-column-width = ($newsletter-width / 3) - (2 * $column-margin)
|
|||||||
padding-left: 0
|
padding-left: 0
|
||||||
padding-right: 0
|
padding-right: 0
|
||||||
|
|
||||||
&:hover
|
&:hover > .mailpoet_block_highlight
|
||||||
border: 0
|
border: 0
|
||||||
|
|
||||||
.mailpoet_container_vertical > *
|
.mailpoet_container_vertical > *
|
||||||
|
@ -5,8 +5,8 @@ $active-social-icon-set-border-color = #adadad
|
|||||||
$active-social-icon-set-background-color = #daebf2
|
$active-social-icon-set-background-color = #daebf2
|
||||||
$social-icon-set-hover-border-color = $primary-active-color
|
$social-icon-set-hover-border-color = $primary-active-color
|
||||||
|
|
||||||
$tool-inactive-color = #bbbbbb
|
$tool-inactive-color = #333333
|
||||||
$tool-hover-color = #333333
|
$tool-hover-color = #bbbbbb
|
||||||
$tool-active-color = #d2d2d4
|
$tool-active-color = #d2d2d4
|
||||||
|
|
||||||
$tool-width = 16px
|
$tool-width = 16px
|
||||||
|
@ -31,7 +31,7 @@ div.mce-toolbar-grp.mce-container
|
|||||||
box-shadow(0px 0px 3px 1px rgba(0, 0, 0, 0.05))
|
box-shadow(0px 0px 3px 1px rgba(0, 0, 0, 0.05))
|
||||||
|
|
||||||
.mce-window
|
.mce-window
|
||||||
/* Fix TinyMCE mailpoet_custom_fields window lack of hiding overflow */
|
/* Fix TinyMCE mailpoet_shortcodes window lack of hiding overflow */
|
||||||
div.mce-container-body.mce-abs-layout
|
div.mce-container-body.mce-abs-layout
|
||||||
overflow: hidden
|
overflow: hidden
|
||||||
|
|
||||||
@ -40,8 +40,8 @@ div.mce-toolbar-grp.mce-container
|
|||||||
width: -webkit-calc( 100% - 36px )
|
width: -webkit-calc( 100% - 36px )
|
||||||
width: calc( 100% - 36px )
|
width: calc( 100% - 36px )
|
||||||
|
|
||||||
/* TinyMCE mailpoet_custom_fields toolbar icon */
|
/* TinyMCE mailpoet_shortcodes toolbar icon */
|
||||||
.mce-i-mailpoet_custom_fields:before
|
.mce-i-mailpoet_shortcodes:before
|
||||||
font: 400 20px/1 dashicons!important
|
font: 400 20px/1 dashicons!important
|
||||||
content: "\f307"
|
content: "\f307"
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ position: relative
|
|||||||
body
|
body
|
||||||
overflow-x: auto
|
overflow-x: auto
|
||||||
|
|
||||||
/* Hide the "Details" section of Wordpress Media manager */
|
/* Hide the "Details" section of WordPress Media manager */
|
||||||
.media-sidebar
|
.media-sidebar
|
||||||
display: none
|
display: none
|
||||||
|
|
||||||
@ -98,7 +98,7 @@ body
|
|||||||
.attachments-browser .uploader-inline
|
.attachments-browser .uploader-inline
|
||||||
right: 0
|
right: 0
|
||||||
|
|
||||||
/* Remove max width from date selector in Wordpress Media Manager */
|
/* Remove max width from date selector in WordPress Media Manager */
|
||||||
#media-attachment-date-filters
|
#media-attachment-date-filters
|
||||||
max-width: calc(100% - 12px)
|
max-width: calc(100% - 12px)
|
||||||
|
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
animation-slide-open-downwards()
|
animation-slide-open-downwards($max-height = 2000px)
|
||||||
transition: all 250ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
transition: all 250ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
||||||
max-height: 2000px
|
max-height: $max-height
|
||||||
opacity: 1
|
opacity: 1
|
||||||
|
overflow-y: hidden
|
||||||
|
|
||||||
&.mailpoet_closed
|
&.mailpoet_closed
|
||||||
max-height: 0
|
max-height: 0px
|
||||||
opacity: 0
|
opacity: 0
|
||||||
overflow-y: hidden
|
|
||||||
|
|
||||||
animation-background-color()
|
animation-background-color()
|
||||||
transition: background 250ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
transition: background 250ms cubic-bezier(0.420, 0.000, 0.580, 1.000) /* ease-in-out */
|
||||||
|
@ -26,3 +26,4 @@ $error-text-color = #d54e21
|
|||||||
$newsletter-width = 660px
|
$newsletter-width = 660px
|
||||||
|
|
||||||
$text-line-height = 1.6em
|
$text-line-height = 1.6em
|
||||||
|
$sidebar-text-size = 13px
|
||||||
|
@ -18,6 +18,7 @@ textarea.parsley-error
|
|||||||
list-style-type none
|
list-style-type none
|
||||||
font-size 0.9em
|
font-size 0.9em
|
||||||
line-height 0.9em
|
line-height 0.9em
|
||||||
|
color #B94A48
|
||||||
opacity 0
|
opacity 0
|
||||||
transition all .3s ease-in
|
transition all .3s ease-in
|
||||||
-o-transition all .3s ease-in
|
-o-transition all .3s ease-in
|
||||||
|
@ -1,14 +1,10 @@
|
|||||||
#mailpoet_settings
|
#mailpoet_settings
|
||||||
// common
|
// common
|
||||||
.mailpoet_panel
|
.mailpoet_panel
|
||||||
display: none
|
display none
|
||||||
|
|
||||||
.form-table th
|
.form-table th
|
||||||
width:20em
|
width 20em
|
||||||
|
|
||||||
// advanced
|
|
||||||
#mailpoet_role_permissions
|
|
||||||
margin-top: 20px;
|
|
||||||
|
|
||||||
// sending methods
|
// sending methods
|
||||||
.mailpoet_sending_methods
|
.mailpoet_sending_methods
|
||||||
@ -28,8 +24,7 @@
|
|||||||
line-height 54px
|
line-height 54px
|
||||||
font-size 1.5em
|
font-size 1.5em
|
||||||
.mailpoet_description
|
.mailpoet_description
|
||||||
line-height 1.5em
|
font-size 14px
|
||||||
font-size 1.1em
|
|
||||||
.mailpoet_status
|
.mailpoet_status
|
||||||
background-color #2f2f2f
|
background-color #2f2f2f
|
||||||
color #fff
|
color #fff
|
||||||
@ -60,11 +55,11 @@
|
|||||||
// responsive
|
// responsive
|
||||||
@media screen and (max-width: 782px)
|
@media screen and (max-width: 782px)
|
||||||
.form-table th
|
.form-table th
|
||||||
width: auto
|
width auto
|
||||||
|
|
||||||
.mailpoet_sending_methods
|
.mailpoet_sending_methods
|
||||||
li
|
li
|
||||||
float none
|
float none
|
||||||
width: auto
|
width auto
|
||||||
margin-right: 0
|
margin-right 0
|
||||||
|
|
||||||
|
BIN
assets/img/blank_templates/fake-logo.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 178 KiB After Width: | Height: | Size: 178 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 130 KiB |
Before Width: | Height: | Size: 63 KiB After Width: | Height: | Size: 63 KiB |
BIN
assets/img/sample_templates/discount/bicycle-header2.png
Normal file
After Width: | Height: | Size: 9.8 KiB |
BIN
assets/img/sample_templates/discount/bicycle-header3.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
assets/img/sample_templates/discount/orange-bicycle.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
assets/img/sample_templates/discount/red-icycle.jpg
Normal file
After Width: | Height: | Size: 70 KiB |
BIN
assets/img/sample_templates/restaurant/boyga-1329911-639x852.jpg
Normal file
After Width: | Height: | Size: 303 KiB |
BIN
assets/img/sample_templates/restaurant/burger.jpg
Normal file
After Width: | Height: | Size: 289 KiB |
BIN
assets/img/sample_templates/restaurant/header.jpg
Normal file
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 498 KiB |
BIN
assets/img/sample_templates/travel/gallery1.jpg
Normal file
After Width: | Height: | Size: 69 KiB |
BIN
assets/img/sample_templates/travel/gallery2.jpg
Normal file
After Width: | Height: | Size: 106 KiB |
BIN
assets/img/sample_templates/travel/gallery3.jpg
Normal file
After Width: | Height: | Size: 86 KiB |
BIN
assets/img/sample_templates/travel/gallery4.jpg
Normal file
After Width: | Height: | Size: 156 KiB |
BIN
assets/img/sample_templates/travel/glow-worms.jpg
Normal file
After Width: | Height: | Size: 145 KiB |
BIN
assets/img/sample_templates/travel/header.png
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
assets/img/sample_templates/travel/holiday-park.jpg
Normal file
After Width: | Height: | Size: 136 KiB |
BIN
assets/img/sample_templates/travel/luge.jpg
Normal file
After Width: | Height: | Size: 77 KiB |
BIN
assets/img/welcome_template/beacon.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 4.8 KiB |
BIN
assets/img/welcome_template/mailpoet-logo.png
Normal file
After Width: | Height: | Size: 6.2 KiB |
@ -1 +0,0 @@
|
|||||||
../src/newsletter_editor/tinymce/mailpoet_custom_fields
|
|
1
assets/js/lib/mailpoet_shortcodes
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../src/newsletter_editor/tinymce/mailpoet_shortcodes
|
@ -1,4 +1,4 @@
|
|||||||
define('ajax', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
|
define('ajax', ['mailpoet', 'jquery', 'underscore'], function(MailPoet, jQuery, _) {
|
||||||
'use strict';
|
'use strict';
|
||||||
MailPoet.Ajax = {
|
MailPoet.Ajax = {
|
||||||
version: 0.5,
|
version: 0.5,
|
||||||
@ -8,19 +8,11 @@ define('ajax', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
|
|||||||
endpoint: null,
|
endpoint: null,
|
||||||
action: null,
|
action: null,
|
||||||
token: null,
|
token: null,
|
||||||
data: {},
|
data: {}
|
||||||
onSuccess: function(data, textStatus, xhr) {},
|
|
||||||
onError: function(xhr, textStatus, errorThrown) {}
|
|
||||||
},
|
|
||||||
get: function(options) {
|
|
||||||
return this.request('get', options);
|
|
||||||
},
|
},
|
||||||
post: function(options) {
|
post: function(options) {
|
||||||
return this.request('post', options);
|
return this.request('post', options);
|
||||||
},
|
},
|
||||||
delete: function(options) {
|
|
||||||
return this.request('delete', options);
|
|
||||||
},
|
|
||||||
init: function(options) {
|
init: function(options) {
|
||||||
// merge options
|
// merge options
|
||||||
this.options = jQuery.extend({}, this.defaults, options);
|
this.options = jQuery.extend({}, this.defaults, options);
|
||||||
@ -50,31 +42,31 @@ define('ajax', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
|
|||||||
|
|
||||||
// set request params
|
// set request params
|
||||||
var params = this.getParams();
|
var params = this.getParams();
|
||||||
var jqXHR;
|
var deferred = jQuery.Deferred();
|
||||||
|
|
||||||
// make ajax request depending on method
|
// remove null values from the data object
|
||||||
if(method === 'get') {
|
if (_.isObject(params.data)) {
|
||||||
jqXHR = jQuery.get(
|
params.data = _.pick(params.data, function(value) {
|
||||||
this.options.url,
|
return (value !== null)
|
||||||
params,
|
})
|
||||||
this.options.onSuccess,
|
|
||||||
'json'
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
jqXHR = jQuery.ajax({
|
|
||||||
url: this.options.url,
|
|
||||||
type : 'post',
|
|
||||||
data: params,
|
|
||||||
dataType: 'json',
|
|
||||||
success : this.options.onSuccess,
|
|
||||||
error : this.options.onError
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ajax request
|
||||||
|
deferred = jQuery.post(
|
||||||
|
this.options.url,
|
||||||
|
params,
|
||||||
|
null,
|
||||||
|
'json'
|
||||||
|
).then(function(data) {
|
||||||
|
return data;
|
||||||
|
}, function(xhr) {
|
||||||
|
return xhr.responseJSON;
|
||||||
|
});
|
||||||
|
|
||||||
// clear options
|
// clear options
|
||||||
this.options = {};
|
this.options = {};
|
||||||
|
|
||||||
return jqXHR;
|
return deferred;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -1,100 +0,0 @@
|
|||||||
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(MailPoet.I18n.t('daemonControlError'));
|
|
||||||
}
|
|
||||||
}.bind(this));
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
if(this.state.status === 'loading') {
|
|
||||||
return(<div>{MailPoet.I18n.t('loadingDaemonStatus')}</div>);
|
|
||||||
}
|
|
||||||
switch(this.state.status) {
|
|
||||||
case 'started':
|
|
||||||
return(
|
|
||||||
<div>
|
|
||||||
{MailPoet.I18n.t('cronDaemonIsRunning')}
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
<a href="#" className="button-primary" onClick={this.controlCron.bind(null, 'stop')}>{MailPoet.I18n.t('stop')}</a>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'starting':
|
|
||||||
case 'stopping':
|
|
||||||
return(
|
|
||||||
<div>
|
|
||||||
{MailPoet.I18n.t('cronDaemonState').replace('%$1s', this.state.status)}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case 'stopped':
|
|
||||||
return(
|
|
||||||
<div>
|
|
||||||
{MailPoet.I18n.t('cronDaemonState').replace('%$1s', this.state.status)}
|
|
||||||
<br />
|
|
||||||
<br />
|
|
||||||
<a href="#" className="button-primary" onClick={this.controlCron.bind(null, 'start')}>{MailPoet.I18n.t('start')}</a>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const container = document.getElementById('cron_container');
|
|
||||||
|
|
||||||
if(container) {
|
|
||||||
ReactDOM.render(
|
|
||||||
<CronControl />,
|
|
||||||
container
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
@ -43,8 +43,9 @@ define('date',
|
|||||||
options = options || {};
|
options = options || {};
|
||||||
this.init(options);
|
this.init(options);
|
||||||
|
|
||||||
return Moment(date, this.convertFormat(options.parseFormat))
|
var date = Moment(date, this.convertFormat(options.parseFormat));
|
||||||
.format(this.convertFormat(this.options.format));
|
if (options.offset === 0) date = date.utc();
|
||||||
|
return date.format(this.convertFormat(this.options.format));
|
||||||
},
|
},
|
||||||
toDate: function(date, options) {
|
toDate: function(date, options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
@ -68,32 +69,45 @@ define('date',
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
convertFormat: function(format) {
|
convertFormat: function(format) {
|
||||||
const format_mappings = {
|
var format_mappings = {
|
||||||
date: {
|
date: {
|
||||||
D: 'ddd',
|
|
||||||
l: 'dddd',
|
|
||||||
d: 'DD',
|
d: 'DD',
|
||||||
|
D: 'ddd',
|
||||||
j: 'D',
|
j: 'D',
|
||||||
z: 'DDDD',
|
l: 'dddd',
|
||||||
N: 'E',
|
N: 'E',
|
||||||
S: '',
|
S: 'o',
|
||||||
M: 'MMM',
|
w: 'e',
|
||||||
|
z: 'DDD',
|
||||||
|
W: 'W',
|
||||||
F: 'MMMM',
|
F: 'MMMM',
|
||||||
m: 'MM',
|
m: 'MM',
|
||||||
n: '',
|
M: 'MMM',
|
||||||
t: '',
|
n: 'M',
|
||||||
y: 'YY',
|
t: '', // no equivalent
|
||||||
|
L: '', // no equivalent
|
||||||
|
o: 'YYYY',
|
||||||
Y: 'YYYY',
|
Y: 'YYYY',
|
||||||
H: 'HH',
|
y: 'YY',
|
||||||
h: 'hh',
|
a: 'a',
|
||||||
g: 'h',
|
|
||||||
A: 'A',
|
A: 'A',
|
||||||
|
B: '', // no equivalent
|
||||||
|
g: 'h',
|
||||||
|
G: 'H',
|
||||||
|
h: 'hh',
|
||||||
|
H: 'HH',
|
||||||
i: 'mm',
|
i: 'mm',
|
||||||
s: 'ss',
|
s: 'ss',
|
||||||
T: 'z',
|
u: 'SSS',
|
||||||
O: 'ZZ',
|
e: 'zz', // deprecated since version 1.6.0 of moment.js
|
||||||
w: 'd',
|
I: '', // no equivalent
|
||||||
W: 'WW'
|
O: '', // no equivalent
|
||||||
|
P: '', // no equivalent
|
||||||
|
T: '', // no equivalent
|
||||||
|
Z: '', // no equivalent
|
||||||
|
c: '', // no equivalent
|
||||||
|
r: '', // no equivalent
|
||||||
|
U: 'X'
|
||||||
},
|
},
|
||||||
strftime: {
|
strftime: {
|
||||||
a: 'ddd',
|
a: 'ddd',
|
||||||
@ -124,22 +138,31 @@ define('date',
|
|||||||
|
|
||||||
if (!format || format.length <= 0) return format;
|
if (!format || format.length <= 0) return format;
|
||||||
|
|
||||||
const replacements = format_mappings['date'];
|
var replacements = format_mappings['date'];
|
||||||
|
|
||||||
let outputFormat = '';
|
var convertedFormat = [];
|
||||||
|
var escapeToken = false;
|
||||||
|
|
||||||
Object.keys(replacements).forEach(function(key) {
|
for (var index in format) {
|
||||||
if (format.indexOf(key) !== -1) {
|
var token = format[index];
|
||||||
format = format.replace(key, '%'+key);
|
|
||||||
|
if (escapeToken === true) {
|
||||||
|
convertedFormat.push('['+token+']');
|
||||||
|
escapeToken = false;
|
||||||
|
} else {
|
||||||
|
if (token === '\\') {
|
||||||
|
// Slash escapes the next symbol to be treated as literal
|
||||||
|
escapeToken = true;
|
||||||
|
continue;
|
||||||
|
} else if (replacements[token] !== undefined) {
|
||||||
|
convertedFormat.push(replacements[token]);
|
||||||
|
} else {
|
||||||
|
convertedFormat.push('['+token+']');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
outputFormat = format;
|
|
||||||
Object.keys(replacements).forEach(function(key) {
|
return convertedFormat.join('');
|
||||||
if (outputFormat.indexOf('%'+key) !== -1) {
|
|
||||||
outputFormat = outputFormat.replace('%'+key, replacements[key]);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return outputFormat;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -6,7 +6,7 @@ function(
|
|||||||
) {
|
) {
|
||||||
const FormFieldCheckbox = React.createClass({
|
const FormFieldCheckbox = React.createClass({
|
||||||
onValueChange: function(e) {
|
onValueChange: function(e) {
|
||||||
e.target.value = this.refs.checkbox.checked ? '1' : '';
|
e.target.value = this.refs.checkbox.checked ? '1' : '0';
|
||||||
return this.props.onValueChange(e);
|
return this.props.onValueChange(e);
|
||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
@ -14,7 +14,9 @@ function(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isChecked = !!(this.props.item[this.props.field.name]);
|
// isChecked will be true only if the value is "1"
|
||||||
|
// it will be false in case value is "0" or empty
|
||||||
|
const isChecked = !!(~~(this.props.item[this.props.field.name]));
|
||||||
const options = Object.keys(this.props.field.values).map(
|
const options = Object.keys(this.props.field.values).map(
|
||||||
(value, index) => {
|
(value, index) => {
|
||||||
return (
|
return (
|
||||||
|
@ -27,7 +27,7 @@ define([
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<select
|
<select
|
||||||
name={ this.props.name + '[year]' }
|
name={ `${this.props.name}[year]` }
|
||||||
value={ this.props.year }
|
value={ this.props.year }
|
||||||
onChange={ this.props.onValueChange }
|
onChange={ this.props.onValueChange }
|
||||||
>
|
>
|
||||||
@ -57,7 +57,7 @@ define([
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<select
|
<select
|
||||||
name={ this.props.name + '[month]' }
|
name={ `${this.props.name}[month]` }
|
||||||
value={ this.props.month }
|
value={ this.props.month }
|
||||||
onChange={ this.props.onValueChange }
|
onChange={ this.props.onValueChange }
|
||||||
>
|
>
|
||||||
@ -88,7 +88,7 @@ define([
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<select
|
<select
|
||||||
name={ this.props.name + '[day]' }
|
name={ `${this.props.name}[day]` }
|
||||||
value={ this.props.day }
|
value={ this.props.day }
|
||||||
onChange={ this.props.onValueChange }
|
onChange={ this.props.onValueChange }
|
||||||
>
|
>
|
||||||
@ -102,46 +102,74 @@ define([
|
|||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
year: undefined,
|
year: '',
|
||||||
month: undefined,
|
month: '',
|
||||||
day: undefined
|
day: ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
|
this.extractDateParts();
|
||||||
}
|
}
|
||||||
componentDidUpdate(prevProps, prevState) {
|
componentDidUpdate(prevProps, prevState) {
|
||||||
if (
|
if (
|
||||||
(this.props.item !== undefined && prevProps.item !== undefined)
|
(this.props.item !== undefined && prevProps.item !== undefined)
|
||||||
&& (this.props.item.id !== prevProps.item.id)
|
&& (this.props.item.id !== prevProps.item.id)
|
||||||
) {
|
) {
|
||||||
this.extractTimeStamp();
|
this.extractDateParts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
extractTimeStamp() {
|
extractDateParts() {
|
||||||
const timeStamp = parseInt(this.props.item[this.props.field.name], 10);
|
const value = (this.props.item[this.props.field.name] !== undefined)
|
||||||
|
? this.props.item[this.props.field.name].trim()
|
||||||
|
: '';
|
||||||
|
|
||||||
|
if(value === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dateTime = Moment(value);
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
year: Moment.unix(timeStamp).year(),
|
year: dateTime.format('YYYY'),
|
||||||
// Moment returns the month as [0..11]
|
month: dateTime.format('M'),
|
||||||
// We increment it to match PHP's mktime() which expects [1..12]
|
day: dateTime.format('D')
|
||||||
month: Moment.unix(timeStamp).month() + 1,
|
|
||||||
day: Moment.unix(timeStamp).date()
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
updateTimeStamp(field) {
|
formatValue() {
|
||||||
let newTimeStamp = Moment(
|
const dateType = this.props.field.params.date_type;
|
||||||
`${this.state.month}/${this.state.day}/${this.state.year}`,
|
|
||||||
'M/D/YYYY'
|
let value;
|
||||||
).valueOf();
|
|
||||||
if (~~(newTimeStamp) > 0) {
|
switch(dateType) {
|
||||||
// convert milliseconds to seconds
|
case 'year_month_day':
|
||||||
newTimeStamp /= 1000;
|
value = {
|
||||||
return this.props.onValueChange({
|
'year': this.state.year,
|
||||||
target: {
|
'month': this.state.month,
|
||||||
name: field,
|
'day': this.state.day
|
||||||
value: newTimeStamp
|
};
|
||||||
}
|
break;
|
||||||
});
|
|
||||||
|
case 'year_month':
|
||||||
|
value = {
|
||||||
|
'year': this.state.year,
|
||||||
|
'month': this.state.month
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'month':
|
||||||
|
value = {
|
||||||
|
'month': this.state.month
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'year':
|
||||||
|
value = {
|
||||||
|
'year': this.state.year
|
||||||
|
};
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
onValueChange(e) {
|
onValueChange(e) {
|
||||||
// extract property from name
|
// extract property from name
|
||||||
@ -153,25 +181,29 @@ define([
|
|||||||
field = matches[1];
|
field = matches[1];
|
||||||
property = matches[2];
|
property = matches[2];
|
||||||
|
|
||||||
let value = parseInt(e.target.value, 10);
|
let value = ~~(e.target.value);
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
[`${property}`]: value
|
[`${property}`]: value
|
||||||
}, () => {
|
}, () => {
|
||||||
this.updateTimeStamp(field);
|
this.props.onValueChange({
|
||||||
|
target: {
|
||||||
|
name: field,
|
||||||
|
value: this.formatValue()
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
render() {
|
render() {
|
||||||
const monthNames = window.mailpoet_month_names || [];
|
const monthNames = window.mailpoet_month_names || [];
|
||||||
|
const dateFormats = window.mailpoet_date_formats || {};
|
||||||
const dateType = this.props.field.params.date_type;
|
const dateType = this.props.field.params.date_type;
|
||||||
|
const dateSelects = dateFormats[dateType][0].split('/');
|
||||||
const dateSelects = dateType.split('_');
|
|
||||||
|
|
||||||
const fields = dateSelects.map(type => {
|
const fields = dateSelects.map(type => {
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case 'year':
|
case 'YYYY':
|
||||||
return (<FormFieldDateYear
|
return (<FormFieldDateYear
|
||||||
onValueChange={ this.onValueChange.bind(this) }
|
onValueChange={ this.onValueChange.bind(this) }
|
||||||
ref={ 'year' }
|
ref={ 'year' }
|
||||||
@ -182,7 +214,7 @@ define([
|
|||||||
/>);
|
/>);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'month':
|
case 'MM':
|
||||||
return (<FormFieldDateMonth
|
return (<FormFieldDateMonth
|
||||||
onValueChange={ this.onValueChange.bind(this) }
|
onValueChange={ this.onValueChange.bind(this) }
|
||||||
ref={ 'month' }
|
ref={ 'month' }
|
||||||
@ -194,7 +226,7 @@ define([
|
|||||||
/>);
|
/>);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'day':
|
case 'DD':
|
||||||
return (<FormFieldDateDay
|
return (<FormFieldDateDay
|
||||||
onValueChange={ this.onValueChange.bind(this) }
|
onValueChange={ this.onValueChange.bind(this) }
|
||||||
ref={ 'day' }
|
ref={ 'day' }
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import _ from 'underscore'
|
||||||
|
|
||||||
const FormFieldSelect = React.createClass({
|
const FormFieldSelect = React.createClass({
|
||||||
render() {
|
render() {
|
||||||
@ -8,6 +9,7 @@ const FormFieldSelect = React.createClass({
|
|||||||
|
|
||||||
let filter = false;
|
let filter = false;
|
||||||
let placeholder = false;
|
let placeholder = false;
|
||||||
|
let sortBy = false;
|
||||||
|
|
||||||
if (this.props.field.placeholder !== undefined) {
|
if (this.props.field.placeholder !== undefined) {
|
||||||
placeholder = (
|
placeholder = (
|
||||||
@ -19,7 +21,27 @@ const FormFieldSelect = React.createClass({
|
|||||||
filter = this.props.field.filter;
|
filter = this.props.field.filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
const options = Object.keys(this.props.field.values).map(
|
if (_.isFunction(this.props.field.sortBy)) {
|
||||||
|
sortBy = this.props.field.sortBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
let keys;
|
||||||
|
if (sortBy) {
|
||||||
|
// Extract keys from sorted [key, value] select value pairs, sorted by
|
||||||
|
// provided sorting order.
|
||||||
|
keys =
|
||||||
|
_.map(
|
||||||
|
_.sortBy(
|
||||||
|
_.pairs(this.props.field.values),
|
||||||
|
(item) => sortBy(item[0], item[1])
|
||||||
|
),
|
||||||
|
(item) => item[0]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
keys = Object.keys(this.props.field.values)
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = keys.map(
|
||||||
(value, index) => {
|
(value, index) => {
|
||||||
|
|
||||||
if (filter !== false && filter(this.props.item, value) === false) {
|
if (filter !== false && filter(this.props.item, value) === false) {
|
||||||
@ -51,4 +73,4 @@ const FormFieldSelect = React.createClass({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = FormFieldSelect;
|
module.exports = FormFieldSelect;
|
||||||
|
@ -89,10 +89,17 @@ function(
|
|||||||
if(this.props.field['selected'] !== undefined) {
|
if(this.props.field['selected'] !== undefined) {
|
||||||
return this.props.field['selected'](this.props.item);
|
return this.props.field['selected'](this.props.item);
|
||||||
} else if(this.props.item !== undefined && this.props.field.name !== undefined) {
|
} else if(this.props.item !== undefined && this.props.field.name !== undefined) {
|
||||||
return this.props.item[this.props.field.name];
|
if (this.allowMultipleValues()) {
|
||||||
} else {
|
if (Array.isArray(this.props.item[this.props.field.name])) {
|
||||||
return null;
|
return this.props.item[this.props.field.name].map(function(item) {
|
||||||
|
return item.id;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return this.props.item[this.props.field.name];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
},
|
},
|
||||||
loadCachedItems: function() {
|
loadCachedItems: function() {
|
||||||
if(typeof(window['mailpoet_'+this.props.field.endpoint]) !== 'undefined') {
|
if(typeof(window['mailpoet_'+this.props.field.endpoint]) !== 'undefined') {
|
||||||
@ -115,9 +122,10 @@ function(
|
|||||||
} else {
|
} else {
|
||||||
value = e.target.value;
|
value = e.target.value;
|
||||||
}
|
}
|
||||||
|
var transformedValue = this.transformChangedValue(value);
|
||||||
this.props.onValueChange({
|
this.props.onValueChange({
|
||||||
target: {
|
target: {
|
||||||
value: value,
|
value: transformedValue,
|
||||||
name: this.props.field.name
|
name: this.props.field.name
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -141,6 +149,16 @@ function(
|
|||||||
}
|
}
|
||||||
return item.id;
|
return item.id;
|
||||||
},
|
},
|
||||||
|
// When it's impossible to represent the desired value in DOM,
|
||||||
|
// this function may be used to transform the placeholder value into
|
||||||
|
// desired value.
|
||||||
|
transformChangedValue: function(value) {
|
||||||
|
if(typeof this.props.field['transformChangedValue'] === 'function') {
|
||||||
|
return this.props.field.transformChangedValue.call(this, value);
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
const options = this.state.items.map((item, index) => {
|
const options = this.state.items.map((item, index) => {
|
||||||
let label = this.getLabel(item);
|
let label = this.getLabel(item);
|
||||||
|
@ -66,22 +66,22 @@ define(
|
|||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
endpoint: this.props.endpoint,
|
endpoint: this.props.endpoint,
|
||||||
action: 'get',
|
action: 'get',
|
||||||
data: id
|
data: {
|
||||||
}).done(function(response) {
|
id: id
|
||||||
if(response === false) {
|
|
||||||
this.setState({
|
|
||||||
loading: false,
|
|
||||||
item: {}
|
|
||||||
}, function() {
|
|
||||||
this.context.router.push('/new');
|
|
||||||
}.bind(this));
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
loading: false,
|
|
||||||
item: response
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}.bind(this));
|
}).done((response) => {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
item: response.data
|
||||||
|
});
|
||||||
|
}).fail((response) => {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
item: {}
|
||||||
|
}, function() {
|
||||||
|
this.context.router.push('/new');
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
handleSubmit: function(e) {
|
handleSubmit: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@ -115,29 +115,25 @@ define(
|
|||||||
endpoint: this.props.endpoint,
|
endpoint: this.props.endpoint,
|
||||||
action: 'save',
|
action: 'save',
|
||||||
data: item
|
data: item
|
||||||
}).done(function(response) {
|
}).always(() => {
|
||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
|
}).done((response) => {
|
||||||
if(response.result === true) {
|
if(this.props.onSuccess !== undefined) {
|
||||||
if(this.props.onSuccess !== undefined) {
|
this.props.onSuccess();
|
||||||
this.props.onSuccess();
|
|
||||||
} else {
|
|
||||||
this.context.router.push('/');
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this.props.params.id !== undefined) {
|
|
||||||
this.props.messages.onUpdate();
|
|
||||||
} else {
|
|
||||||
this.props.messages.onCreate();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if(response.result === false) {
|
this.context.router.push('/');
|
||||||
if(response.errors.length > 0) {
|
|
||||||
this.setState({ errors: response.errors });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}.bind(this));
|
|
||||||
|
if(this.props.params.id !== undefined) {
|
||||||
|
this.props.messages.onUpdate();
|
||||||
|
} else {
|
||||||
|
this.props.messages.onCreate();
|
||||||
|
}
|
||||||
|
}).fail((response) => {
|
||||||
|
if(response.errors.length > 0) {
|
||||||
|
this.setState({ errors: response.errors });
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
handleValueChange: function(e) {
|
handleValueChange: function(e) {
|
||||||
if (this.props.onChange) {
|
if (this.props.onChange) {
|
||||||
@ -159,7 +155,7 @@ define(
|
|||||||
var errors = this.getErrors().map(function(error, index) {
|
var errors = this.getErrors().map(function(error, index) {
|
||||||
return (
|
return (
|
||||||
<p key={ 'error-'+index } className="mailpoet_error">
|
<p key={ 'error-'+index } className="mailpoet_error">
|
||||||
{ error }
|
{ error.message }
|
||||||
</p>
|
</p>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -13,8 +13,11 @@ const columns = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'segments',
|
name: 'segments',
|
||||||
label: MailPoet.I18n.t('segments'),
|
label: MailPoet.I18n.t('segments')
|
||||||
sortable: false
|
},
|
||||||
|
{
|
||||||
|
name: 'signups',
|
||||||
|
label: MailPoet.I18n.t('signups')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'created_at',
|
name: 'created_at',
|
||||||
@ -24,48 +27,48 @@ const columns = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
const messages = {
|
const messages = {
|
||||||
onTrash: function(response) {
|
onTrash: (response) => {
|
||||||
var count = ~~response;
|
const count = ~~response.meta.count;
|
||||||
var message = null;
|
let message = null;
|
||||||
|
|
||||||
if(count === 1) {
|
if (count === 1) {
|
||||||
message = (
|
message = (
|
||||||
MailPoet.I18n.t('oneFormTrashed')
|
MailPoet.I18n.t('oneFormTrashed')
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
message = (
|
message = (
|
||||||
MailPoet.I18n.t('multipleFormsTrashed')
|
MailPoet.I18n.t('multipleFormsTrashed')
|
||||||
).replace('%$1d', count);
|
).replace('%$1d', count.toLocaleString());
|
||||||
}
|
}
|
||||||
MailPoet.Notice.success(message);
|
MailPoet.Notice.success(message);
|
||||||
},
|
},
|
||||||
onDelete: function(response) {
|
onDelete: (response) => {
|
||||||
var count = ~~response;
|
const count = ~~response.meta.count;
|
||||||
var message = null;
|
let message = null;
|
||||||
|
|
||||||
if(count === 1) {
|
if (count === 1) {
|
||||||
message = (
|
message = (
|
||||||
MailPoet.I18n.t('oneFormDeleted')
|
MailPoet.I18n.t('oneFormDeleted')
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
message = (
|
message = (
|
||||||
MailPoet.I18n.t('multipleFormsDeleted')
|
MailPoet.I18n.t('multipleFormsDeleted')
|
||||||
).replace('%$1d', count);
|
).replace('%$1d', count.toLocaleString());
|
||||||
}
|
}
|
||||||
MailPoet.Notice.success(message);
|
MailPoet.Notice.success(message);
|
||||||
},
|
},
|
||||||
onRestore: function(response) {
|
onRestore: (response) => {
|
||||||
var count = ~~response;
|
const count = ~~response.meta.count;
|
||||||
var message = null;
|
let message = null;
|
||||||
|
|
||||||
if(count === 1) {
|
if (count === 1) {
|
||||||
message = (
|
message = (
|
||||||
MailPoet.I18n.t('oneFormRestored')
|
MailPoet.I18n.t('oneFormRestored')
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
message = (
|
message = (
|
||||||
MailPoet.I18n.t('multipleFormsRestored')
|
MailPoet.I18n.t('multipleFormsRestored')
|
||||||
).replace('%$1d', count);
|
).replace('%$1d', count.toLocaleString());
|
||||||
}
|
}
|
||||||
MailPoet.Notice.success(message);
|
MailPoet.Notice.success(message);
|
||||||
}
|
}
|
||||||
@ -90,18 +93,27 @@ const item_actions = [
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'duplicate_form',
|
name: 'duplicate',
|
||||||
label: MailPoet.I18n.t('duplicate'),
|
label: MailPoet.I18n.t('duplicate'),
|
||||||
onClick: function(item, refresh) {
|
onClick: function(item, refresh) {
|
||||||
return MailPoet.Ajax.post({
|
return MailPoet.Ajax.post({
|
||||||
endpoint: 'forms',
|
endpoint: 'forms',
|
||||||
action: 'duplicate',
|
action: 'duplicate',
|
||||||
data: item.id
|
data: {
|
||||||
}).done(function(response) {
|
id: item.id
|
||||||
|
}
|
||||||
|
}).done((response) => {
|
||||||
MailPoet.Notice.success(
|
MailPoet.Notice.success(
|
||||||
(MailPoet.I18n.t('formDuplicated')).replace('%$1s', response.name)
|
(MailPoet.I18n.t('formDuplicated')).replace('%$1s', response.data.name)
|
||||||
);
|
);
|
||||||
refresh();
|
refresh();
|
||||||
|
}).fail((response) => {
|
||||||
|
if (response.errors.length > 0) {
|
||||||
|
MailPoet.Notice.error(
|
||||||
|
response.errors.map(function(error) { return error.message; }),
|
||||||
|
{ scroll: true }
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -115,9 +127,14 @@ const FormList = React.createClass({
|
|||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
endpoint: 'forms',
|
endpoint: 'forms',
|
||||||
action: 'create'
|
action: 'create'
|
||||||
}).done(function(response) {
|
}).done((response) => {
|
||||||
if(response.result && response.form_id) {
|
window.location = mailpoet_form_edit_url + response.data.id;
|
||||||
window.location = mailpoet_form_edit_url + response.form_id;
|
}).fail((response) => {
|
||||||
|
if (response.errors.length > 0) {
|
||||||
|
MailPoet.Notice.error(
|
||||||
|
response.errors.map(function(error) { return error.message; }),
|
||||||
|
{ scroll: true }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@ -134,6 +151,10 @@ const FormList = React.createClass({
|
|||||||
return segment.name;
|
return segment.name;
|
||||||
}).join(', ');
|
}).join(', ');
|
||||||
|
|
||||||
|
if (form.settings.segments_selected_by === 'user') {
|
||||||
|
segments = MailPoet.I18n.t('userChoice') + ' ' + segments;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<td className={ row_classes }>
|
<td className={ row_classes }>
|
||||||
@ -145,9 +166,12 @@ const FormList = React.createClass({
|
|||||||
</strong>
|
</strong>
|
||||||
{ actions }
|
{ actions }
|
||||||
</td>
|
</td>
|
||||||
<td className="column-format" data-colname={MailPoet.I18n.t('segments')}>
|
<td className="column" data-colname={MailPoet.I18n.t('segments')}>
|
||||||
{ segments }
|
{ segments }
|
||||||
</td>
|
</td>
|
||||||
|
<td className="column" data-colname={MailPoet.I18n.t('signups')}>
|
||||||
|
{ form.signups }
|
||||||
|
</td>
|
||||||
<td className="column-date" data-colname={MailPoet.I18n.t('createdOn')}>
|
<td className="column-date" data-colname={MailPoet.I18n.t('createdOn')}>
|
||||||
<abbr>{ MailPoet.Date.format(form.created_at) }</abbr>
|
<abbr>{ MailPoet.Date.format(form.created_at) }</abbr>
|
||||||
</td>
|
</td>
|
||||||
|
@ -47,13 +47,16 @@ function(
|
|||||||
|
|
||||||
data.action = this.state.action;
|
data.action = this.state.action;
|
||||||
|
|
||||||
var callback = function() {};
|
var onSuccess = function() {};
|
||||||
if(action['onSuccess'] !== undefined) {
|
if(action['onSuccess'] !== undefined) {
|
||||||
callback = action.onSuccess;
|
onSuccess = action.onSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data.action) {
|
if(data.action) {
|
||||||
this.props.onBulkAction(selected_ids, data, callback);
|
const promise = this.props.onBulkAction(selected_ids, data);
|
||||||
|
if (promise !== false) {
|
||||||
|
promise.then(onSuccess);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
|
@ -10,10 +10,10 @@ function(
|
|||||||
) {
|
) {
|
||||||
var ListingFilters = React.createClass({
|
var ListingFilters = React.createClass({
|
||||||
handleFilterAction: function() {
|
handleFilterAction: function() {
|
||||||
let filters = {}
|
let filters = {};
|
||||||
this.getAvailableFilters().map((filter, i) => {
|
this.getAvailableFilters().map((filter, i) => {
|
||||||
filters[this.refs['filter-'+i].name] = this.refs['filter-'+i].value
|
filters[this.refs['filter-'+i].name] = this.refs['filter-'+i].value
|
||||||
})
|
});
|
||||||
return this.props.onSelectFilter(filters);
|
return this.props.onSelectFilter(filters);
|
||||||
},
|
},
|
||||||
handleEmptyTrash: function() {
|
handleEmptyTrash: function() {
|
||||||
@ -21,7 +21,6 @@ function(
|
|||||||
},
|
},
|
||||||
getAvailableFilters: function() {
|
getAvailableFilters: function() {
|
||||||
let filters = this.props.filters;
|
let filters = this.props.filters;
|
||||||
|
|
||||||
return Object.keys(filters).filter(function(filter) {
|
return Object.keys(filters).filter(function(filter) {
|
||||||
return !(
|
return !(
|
||||||
filters[filter].length === 0
|
filters[filter].length === 0
|
||||||
@ -30,26 +29,29 @@ function(
|
|||||||
&& !filters[filter][0].value
|
&& !filters[filter][0].value
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
})
|
});
|
||||||
|
},
|
||||||
|
componentDidUpdate: function() {
|
||||||
|
const selected_filters = this.props.filter;
|
||||||
|
const available_filters = this.getAvailableFilters().map(
|
||||||
|
function(filter, i) {
|
||||||
|
if (selected_filters[filter] !== undefined && selected_filters[filter]) {
|
||||||
|
jQuery(this.refs['filter-'+i])
|
||||||
|
.val(selected_filters[filter])
|
||||||
|
.trigger('change');
|
||||||
|
}
|
||||||
|
}.bind(this)
|
||||||
|
);
|
||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
const filters = this.props.filters;
|
const filters = this.props.filters;
|
||||||
const selected_filters = this.props.filter;
|
|
||||||
|
|
||||||
const available_filters = this.getAvailableFilters()
|
const available_filters = this.getAvailableFilters()
|
||||||
.map(function(filter, i) {
|
.map(function(filter, i) {
|
||||||
let default_value = false;
|
|
||||||
if (selected_filters[filter] !== undefined && selected_filters[filter]) {
|
|
||||||
default_value = selected_filters[filter]
|
|
||||||
} else {
|
|
||||||
jQuery(`select[name="${filter}"]`).val('');
|
|
||||||
}
|
|
||||||
return (
|
return (
|
||||||
<select
|
<select
|
||||||
ref={ `filter-${i}` }
|
ref={ `filter-${i}` }
|
||||||
key={ `filter-${i}` }
|
key={ `filter-${i}` }
|
||||||
name={ filter }
|
name={ filter }
|
||||||
defaultValue={ default_value }
|
|
||||||
>
|
>
|
||||||
{ filters[filter].map(function(option, j) {
|
{ filters[filter].map(function(option, j) {
|
||||||
return (
|
return (
|
||||||
@ -63,7 +65,7 @@ function(
|
|||||||
);
|
);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
let button = false;
|
let button;
|
||||||
|
|
||||||
if (available_filters.length > 0) {
|
if (available_filters.length > 0) {
|
||||||
button = (
|
button = (
|
||||||
@ -76,7 +78,7 @@ function(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let empty_trash = false;
|
let empty_trash;
|
||||||
if (this.props.group === 'trash') {
|
if (this.props.group === 'trash') {
|
||||||
empty_trash = (
|
empty_trash = (
|
||||||
<input
|
<input
|
||||||
|
@ -1,98 +1,91 @@
|
|||||||
define([
|
import MailPoet from 'mailpoet'
|
||||||
'react',
|
import React from 'react'
|
||||||
'classnames',
|
import classNames from 'classnames'
|
||||||
'mailpoet'
|
|
||||||
], function(
|
|
||||||
React,
|
|
||||||
classNames,
|
|
||||||
MailPoet
|
|
||||||
) {
|
|
||||||
|
|
||||||
var ListingHeader = React.createClass({
|
|
||||||
handleSelectItems: function() {
|
|
||||||
return this.props.onSelectItems(
|
|
||||||
this.refs.toggle.checked
|
|
||||||
);
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
var columns = this.props.columns.map(function(column, index) {
|
|
||||||
column.is_primary = (index === 0);
|
|
||||||
column.sorted = (this.props.sort_by === column.name)
|
|
||||||
? this.props.sort_order
|
|
||||||
: 'desc';
|
|
||||||
return (
|
|
||||||
<ListingColumn
|
|
||||||
onSort={this.props.onSort}
|
|
||||||
sort_by={this.props.sort_by}
|
|
||||||
key={ 'column-' + index }
|
|
||||||
column={column} />
|
|
||||||
);
|
|
||||||
}.bind(this));
|
|
||||||
|
|
||||||
var checkbox = false;
|
|
||||||
|
|
||||||
if(this.props.is_selectable === true) {
|
|
||||||
checkbox = (
|
|
||||||
<th
|
|
||||||
className="manage-column column-cb check-column">
|
|
||||||
<label className="screen-reader-text">
|
|
||||||
{MailPoet.I18n.t('selectAll')}
|
|
||||||
</label>
|
|
||||||
<input
|
|
||||||
type="checkbox"
|
|
||||||
name="select_all"
|
|
||||||
ref="toggle"
|
|
||||||
checked={ this.props.selection }
|
|
||||||
onChange={ this.handleSelectItems } />
|
|
||||||
</th>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const ListingHeader = React.createClass({
|
||||||
|
handleSelectItems: function() {
|
||||||
|
return this.props.onSelectItems(
|
||||||
|
this.refs.toggle.checked
|
||||||
|
);
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
const columns = this.props.columns.map(function(column, index) {
|
||||||
|
column.is_primary = (index === 0);
|
||||||
|
column.sorted = (this.props.sort_by === column.name)
|
||||||
|
? this.props.sort_order
|
||||||
|
: 'desc';
|
||||||
return (
|
return (
|
||||||
<tr>
|
<ListingColumn
|
||||||
{checkbox}
|
onSort={this.props.onSort}
|
||||||
{columns}
|
sort_by={this.props.sort_by}
|
||||||
</tr>
|
key={ 'column-' + index }
|
||||||
|
column={column} />
|
||||||
);
|
);
|
||||||
}
|
}.bind(this));
|
||||||
});
|
|
||||||
|
|
||||||
var ListingColumn = React.createClass({
|
let checkbox;
|
||||||
handleSort: function() {
|
|
||||||
var sort_by = this.props.column.name,
|
|
||||||
sort_order = (this.props.column.sorted === 'asc') ? 'desc' : 'asc';
|
|
||||||
this.props.onSort(sort_by, sort_order);
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
var classes = classNames(
|
|
||||||
'manage-column',
|
|
||||||
{ 'column-primary': this.props.column.is_primary },
|
|
||||||
{ 'sortable': this.props.column.sortable },
|
|
||||||
this.props.column.sorted,
|
|
||||||
{ 'sorted': (this.props.sort_by === this.props.column.name) }
|
|
||||||
);
|
|
||||||
var label;
|
|
||||||
|
|
||||||
if(this.props.column.sortable === true) {
|
if(this.props.is_selectable === true) {
|
||||||
label = (
|
checkbox = (
|
||||||
<a onClick={this.handleSort}>
|
|
||||||
<span>{ this.props.column.label }</span>
|
|
||||||
<span className="sorting-indicator"></span>
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
label = this.props.column.label;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<th
|
<th
|
||||||
className={ classes }
|
className="manage-column column-cb check-column">
|
||||||
id={this.props.column.name }
|
<label className="screen-reader-text">
|
||||||
scope="col">
|
{MailPoet.I18n.t('selectAll')}
|
||||||
{label}
|
</label>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
name="select_all"
|
||||||
|
ref="toggle"
|
||||||
|
checked={ this.props.selection }
|
||||||
|
onChange={ this.handleSelectItems } />
|
||||||
</th>
|
</th>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
return ListingHeader;
|
return (
|
||||||
|
<tr>
|
||||||
|
{checkbox}
|
||||||
|
{columns}
|
||||||
|
</tr>
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const ListingColumn = React.createClass({
|
||||||
|
handleSort: function() {
|
||||||
|
const sort_by = this.props.column.name;
|
||||||
|
const sort_order = (this.props.column.sorted === 'asc') ? 'desc' : 'asc';
|
||||||
|
this.props.onSort(sort_by, sort_order);
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
const classes = classNames(
|
||||||
|
'manage-column',
|
||||||
|
{ 'column-primary': this.props.column.is_primary },
|
||||||
|
{ 'sortable': this.props.column.sortable },
|
||||||
|
this.props.column.sorted,
|
||||||
|
{ 'sorted': (this.props.sort_by === this.props.column.name) }
|
||||||
|
);
|
||||||
|
let label;
|
||||||
|
|
||||||
|
if(this.props.column.sortable === true) {
|
||||||
|
label = (
|
||||||
|
<a onClick={ this.handleSort }>
|
||||||
|
<span>{ this.props.column.label }</span>
|
||||||
|
<span className="sorting-indicator"></span>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
label = this.props.column.label;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<th
|
||||||
|
className={ classes }
|
||||||
|
id={this.props.column.name }
|
||||||
|
scope="col"
|
||||||
|
width={ this.props.column.width || null }
|
||||||
|
>{label}</th>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = ListingHeader;
|
@ -112,7 +112,16 @@ define([
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}).preventDefault('auto');
|
})
|
||||||
|
.preventDefault('auto')
|
||||||
|
.actionChecker(function (pointer, event, action) {
|
||||||
|
// Disable dragging with right click
|
||||||
|
if (event.button !== 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return action;
|
||||||
|
});
|
||||||
|
|
||||||
if (this.options.drop !== undefined) {
|
if (this.options.drop !== undefined) {
|
||||||
interactable.getDropModel = this.options.drop;
|
interactable.getDropModel = this.options.drop;
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* Highlight Editing Behavior
|
||||||
|
*
|
||||||
|
* Highlights a block that is being edited
|
||||||
|
*/
|
||||||
|
define([
|
||||||
|
'backbone.marionette',
|
||||||
|
'newsletter_editor/behaviors/BehaviorsLookup',
|
||||||
|
], function(Marionette, BehaviorsLookup) {
|
||||||
|
|
||||||
|
BehaviorsLookup.HighlightEditingBehavior = Marionette.Behavior.extend({
|
||||||
|
modelEvents: {
|
||||||
|
'startEditing': 'enableHighlight',
|
||||||
|
'stopEditing': 'disableHighlight',
|
||||||
|
},
|
||||||
|
enableHighlight: function() {
|
||||||
|
this.$el.addClass('mailpoet_highlight');
|
||||||
|
},
|
||||||
|
disableHighlight: function() {
|
||||||
|
this.$el.removeClass('mailpoet_highlight');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Show Settings Behavior
|
||||||
|
*
|
||||||
|
* Opens up settings of a BlockView if contents are clicked upon
|
||||||
|
*/
|
||||||
|
define([
|
||||||
|
'backbone.marionette',
|
||||||
|
'jquery',
|
||||||
|
'newsletter_editor/behaviors/BehaviorsLookup',
|
||||||
|
], function(Marionette, jQuery, BehaviorsLookup) {
|
||||||
|
|
||||||
|
BehaviorsLookup.ShowSettingsBehavior = Marionette.Behavior.extend({
|
||||||
|
defaults: {
|
||||||
|
ignoreFrom: '', // selector
|
||||||
|
},
|
||||||
|
events: {
|
||||||
|
'click .mailpoet_content': 'showSettings',
|
||||||
|
},
|
||||||
|
showSettings: function(event) {
|
||||||
|
if(!this.isIgnoredElement(event.target)) {
|
||||||
|
this.view.triggerMethod('showSettings');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isIgnoredElement: function(element) {
|
||||||
|
return this.options.ignoreFrom
|
||||||
|
&& this.options.ignoreFrom.length > 0
|
||||||
|
&& jQuery(element).is(this.options.ignoreFrom);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -13,6 +13,7 @@ define([
|
|||||||
'newsletter_editor/blocks/divider',
|
'newsletter_editor/blocks/divider',
|
||||||
'newsletter_editor/components/communication',
|
'newsletter_editor/components/communication',
|
||||||
'mailpoet',
|
'mailpoet',
|
||||||
|
'backbone.supermodel',
|
||||||
'underscore',
|
'underscore',
|
||||||
'jquery'
|
'jquery'
|
||||||
], function(
|
], function(
|
||||||
@ -22,6 +23,7 @@ define([
|
|||||||
DividerBlock,
|
DividerBlock,
|
||||||
CommunicationComponent,
|
CommunicationComponent,
|
||||||
MailPoet,
|
MailPoet,
|
||||||
|
SuperModel,
|
||||||
_,
|
_,
|
||||||
jQuery
|
jQuery
|
||||||
) {
|
) {
|
||||||
@ -31,6 +33,41 @@ define([
|
|||||||
var Module = {},
|
var Module = {},
|
||||||
base = BaseBlock;
|
base = BaseBlock;
|
||||||
|
|
||||||
|
Module.ALCSupervisor = SuperModel.extend({
|
||||||
|
initialize: function() {
|
||||||
|
var DELAY_REFRESH_FOR_MS = 500;
|
||||||
|
this.listenTo(
|
||||||
|
App.getChannel(),
|
||||||
|
'automatedLatestContentRefresh',
|
||||||
|
_.debounce(this.refresh, DELAY_REFRESH_FOR_MS)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
refresh: function() {
|
||||||
|
var models = App.findModels(function(model) {
|
||||||
|
return model.get('type') === 'automatedLatestContent';
|
||||||
|
}) || [];
|
||||||
|
|
||||||
|
if (models.length === 0) return;
|
||||||
|
var blocks = _.map(models, function(model) {
|
||||||
|
return model.toJSON();
|
||||||
|
});
|
||||||
|
|
||||||
|
CommunicationComponent.getBulkTransformedPosts({
|
||||||
|
blocks: blocks,
|
||||||
|
}).then(_.partial(this.refreshBlocks, models));
|
||||||
|
},
|
||||||
|
refreshBlocks: function(models, renderedBlocks) {
|
||||||
|
_.each(
|
||||||
|
_.zip(models, renderedBlocks),
|
||||||
|
function(args) {
|
||||||
|
var model = args[0],
|
||||||
|
contents = args[1];
|
||||||
|
model.trigger('refreshPosts', contents);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
Module.AutomatedLatestContentBlockModel = base.BlockModel.extend({
|
Module.AutomatedLatestContentBlockModel = base.BlockModel.extend({
|
||||||
stale: ['_container'],
|
stale: ['_container'],
|
||||||
defaults: function() {
|
defaults: function() {
|
||||||
@ -72,34 +109,21 @@ define([
|
|||||||
},
|
},
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
base.BlockView.prototype.initialize.apply(this, arguments);
|
base.BlockView.prototype.initialize.apply(this, arguments);
|
||||||
this.fetchPosts();
|
|
||||||
this.on('change:amount change:contentType change:terms change:inclusionType change:displayType change:titleFormat change:featuredImagePosition change:titleAlignment change:titleIsLink change:imageFullWidth change:showAuthor change:authorPrecededBy change:showCategories change:categoriesPrecededBy change:readMoreType change:readMoreText change:sortBy change:showDivider', this._scheduleFetchPosts, this);
|
this.on('change:amount change:contentType change:terms change:inclusionType change:displayType change:titleFormat change:featuredImagePosition change:titleAlignment change:titleIsLink change:imageFullWidth change:showAuthor change:authorPrecededBy change:showCategories change:categoriesPrecededBy change:readMoreType change:readMoreText change: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);
|
||||||
|
this.on('add remove update reset', this._scheduleFetchPosts);
|
||||||
|
this.on('refreshPosts', this.updatePosts, this);
|
||||||
},
|
},
|
||||||
fetchPosts: function() {
|
updatePosts: function(posts) {
|
||||||
var that = this;
|
this.get('_container.blocks').reset(posts, {parse: true});
|
||||||
CommunicationComponent.getTransformedPosts(this.toJSON()).done(function(content) {
|
|
||||||
that.get('_container').get('blocks').reset(content, {parse: true});
|
|
||||||
that.trigger('postsChanged');
|
|
||||||
}).fail(function(error) {
|
|
||||||
MailPoet.Notice.error(MailPoet.I18n.t('failedToFetchRenderedPosts'));
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
* Batch more changes during a specific time, instead of fetching
|
* Batch more changes during a specific time, instead of fetching
|
||||||
* ALC posts on each model change
|
* ALC posts on each model change
|
||||||
*/
|
*/
|
||||||
_scheduleFetchPosts: function() {
|
_scheduleFetchPosts: function() {
|
||||||
var timeout = 500,
|
App.getChannel().trigger('automatedLatestContentRefresh');
|
||||||
that = this;
|
|
||||||
if (this._fetchPostsTimer !== undefined) {
|
|
||||||
clearTimeout(this._fetchPostsTimer);
|
|
||||||
}
|
|
||||||
this._fetchPostsTimer = setTimeout(function() {
|
|
||||||
that.fetchPosts();
|
|
||||||
that._fetchPostsTimer = undefined;
|
|
||||||
}, timeout);
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -124,6 +148,7 @@ define([
|
|||||||
renderOptions = {
|
renderOptions = {
|
||||||
disableTextEditor: true,
|
disableTextEditor: true,
|
||||||
disableDragAndDrop: true,
|
disableDragAndDrop: true,
|
||||||
|
emptyContainerMessage: MailPoet.I18n.t('noPostsToDisplay'),
|
||||||
};
|
};
|
||||||
this.toolsView = new Module.AutomatedLatestContentBlockToolsView({ model: this.model });
|
this.toolsView = new Module.AutomatedLatestContentBlockToolsView({ model: this.model });
|
||||||
this.toolsRegion.show(this.toolsView);
|
this.toolsRegion.show(this.toolsView);
|
||||||
@ -149,24 +174,21 @@ define([
|
|||||||
"change .mailpoet_automated_latest_content_title_format": 'changeTitleFormat',
|
"change .mailpoet_automated_latest_content_title_format": 'changeTitleFormat',
|
||||||
"change .mailpoet_automated_latest_content_title_as_links": _.partial(this.changeBoolField, 'titleIsLink'),
|
"change .mailpoet_automated_latest_content_title_as_links": _.partial(this.changeBoolField, 'titleIsLink'),
|
||||||
"change .mailpoet_automated_latest_content_show_divider": _.partial(this.changeBoolField, 'showDivider'),
|
"change .mailpoet_automated_latest_content_show_divider": _.partial(this.changeBoolField, 'showDivider'),
|
||||||
"keyup .mailpoet_automated_latest_content_show_amount": _.partial(this.changeField, "amount"),
|
"input .mailpoet_automated_latest_content_show_amount": _.partial(this.changeField, "amount"),
|
||||||
"change .mailpoet_automated_latest_content_content_type": _.partial(this.changeField, "contentType"),
|
"change .mailpoet_automated_latest_content_content_type": _.partial(this.changeField, "contentType"),
|
||||||
"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_alignment": _.partial(this.changeField, "titleAlignment"),
|
"change .mailpoet_automated_latest_content_title_alignment": _.partial(this.changeField, "titleAlignment"),
|
||||||
"change .mailpoet_automated_latest_content_image_full_width": _.partial(this.changeBoolField, "imageFullWidth"),
|
"change .mailpoet_automated_latest_content_image_full_width": _.partial(this.changeBoolField, "imageFullWidth"),
|
||||||
"change .mailpoet_automated_latest_content_featured_image_position": _.partial(this.changeField, "featuredImagePosition"),
|
"change .mailpoet_automated_latest_content_featured_image_position": _.partial(this.changeField, "featuredImagePosition"),
|
||||||
"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"),
|
"input .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"),
|
||||||
"keyup .mailpoet_automated_latest_content_categories": _.partial(this.changeField, "categoriesPrecededBy"),
|
"input .mailpoet_automated_latest_content_categories": _.partial(this.changeField, "categoriesPrecededBy"),
|
||||||
"keyup .mailpoet_automated_latest_content_read_more_text": _.partial(this.changeField, "readMoreText"),
|
"input .mailpoet_automated_latest_content_read_more_text": _.partial(this.changeField, "readMoreText"),
|
||||||
"change .mailpoet_automated_latest_content_sort_by": _.partial(this.changeField, "sortBy"),
|
"change .mailpoet_automated_latest_content_sort_by": _.partial(this.changeField, "sortBy"),
|
||||||
"click .mailpoet_done_editing": "close",
|
"click .mailpoet_done_editing": "close",
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
behaviors: {
|
|
||||||
ColorPickerBehavior: {},
|
|
||||||
},
|
|
||||||
templateHelpers: function() {
|
templateHelpers: function() {
|
||||||
return {
|
return {
|
||||||
model: this.model.toJSON(),
|
model: this.model.toJSON(),
|
||||||
@ -181,6 +203,7 @@ define([
|
|||||||
this.$('.mailpoet_automated_latest_content_categories_and_tags').select2({
|
this.$('.mailpoet_automated_latest_content_categories_and_tags').select2({
|
||||||
multiple: true,
|
multiple: true,
|
||||||
allowClear: true,
|
allowClear: true,
|
||||||
|
placeholder: MailPoet.I18n.t('categoriesAndTags'),
|
||||||
ajax: {
|
ajax: {
|
||||||
data: function (params) {
|
data: function (params) {
|
||||||
return {
|
return {
|
||||||
@ -188,8 +211,10 @@ define([
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
transport: function(options, success, failure) {
|
transport: function(options, success, failure) {
|
||||||
var taxonomies,
|
var taxonomies;
|
||||||
promise = CommunicationComponent.getTaxonomies(that.model.get('contentType')).then(function(tax) {
|
var 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 = CommunicationComponent.getTerms({
|
var promise = CommunicationComponent.getTerms({
|
||||||
@ -198,7 +223,7 @@ define([
|
|||||||
}).then(function(terms) {
|
}).then(function(terms) {
|
||||||
return {
|
return {
|
||||||
taxonomies: taxonomies,
|
taxonomies: taxonomies,
|
||||||
terms: terms,
|
terms: terms
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
return promise;
|
return promise;
|
||||||
@ -287,9 +312,11 @@ define([
|
|||||||
if (value == 'titleOnly') {
|
if (value == 'titleOnly') {
|
||||||
this.$('.mailpoet_automated_latest_content_title_as_list').removeClass('mailpoet_hidden');
|
this.$('.mailpoet_automated_latest_content_title_as_list').removeClass('mailpoet_hidden');
|
||||||
this.$('.mailpoet_automated_latest_content_image_full_width_option').addClass('mailpoet_hidden');
|
this.$('.mailpoet_automated_latest_content_image_full_width_option').addClass('mailpoet_hidden');
|
||||||
|
this.$('.mailpoet_automated_latest_content_image_separator').addClass('mailpoet_hidden');
|
||||||
} else {
|
} else {
|
||||||
this.$('.mailpoet_automated_latest_content_title_as_list').addClass('mailpoet_hidden');
|
this.$('.mailpoet_automated_latest_content_title_as_list').addClass('mailpoet_hidden');
|
||||||
this.$('.mailpoet_automated_latest_content_image_full_width_option').removeClass('mailpoet_hidden');
|
this.$('.mailpoet_automated_latest_content_image_full_width_option').removeClass('mailpoet_hidden');
|
||||||
|
this.$('.mailpoet_automated_latest_content_image_separator').removeClass('mailpoet_hidden');
|
||||||
|
|
||||||
// Reset titleFormat if it was set to List when switching away from displayType=titleOnly
|
// Reset titleFormat if it was set to List when switching away from displayType=titleOnly
|
||||||
if (this.model.get('titleFormat') === 'ul') {
|
if (this.model.get('titleFormat') === 'ul') {
|
||||||
@ -363,5 +390,10 @@ define([
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
App.on('start', function() {
|
||||||
|
App._ALCSupervisor = new Module.ALCSupervisor();
|
||||||
|
App._ALCSupervisor.refresh();
|
||||||
|
});
|
||||||
|
|
||||||
return Module;
|
return Module;
|
||||||
});
|
});
|
||||||
|
@ -40,6 +40,9 @@ define([
|
|||||||
// Remove stale attributes from resulting JSON object
|
// Remove stale attributes from resulting JSON object
|
||||||
return _.omit(SuperModel.prototype.toJSON.call(this), this.stale);
|
return _.omit(SuperModel.prototype.toJSON.call(this), this.stale);
|
||||||
},
|
},
|
||||||
|
getChildren: function() {
|
||||||
|
return [];
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Module.BlockView = AugmentedView.extend({
|
Module.BlockView = AugmentedView.extend({
|
||||||
@ -77,6 +80,7 @@ define([
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
HighlightEditingBehavior: {},
|
||||||
},
|
},
|
||||||
templateHelpers: function() {
|
templateHelpers: function() {
|
||||||
return {
|
return {
|
||||||
@ -95,12 +99,12 @@ define([
|
|||||||
},
|
},
|
||||||
showTools: function(_event) {
|
showTools: function(_event) {
|
||||||
if (!this.showingToolsDisabled) {
|
if (!this.showingToolsDisabled) {
|
||||||
this.$('> .mailpoet_tools').show();
|
this.$('> .mailpoet_tools').addClass('mailpoet_display_tools');
|
||||||
this.toolsView.triggerMethod('showTools');
|
this.toolsView.triggerMethod('showTools');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hideTools: function(e) {
|
hideTools: function(e) {
|
||||||
this.$('> .mailpoet_tools').hide();
|
this.$('> .mailpoet_tools').removeClass('mailpoet_display_tools');
|
||||||
this.toolsView.triggerMethod('hideTools');
|
this.toolsView.triggerMethod('hideTools');
|
||||||
},
|
},
|
||||||
enableShowingTools: function() {
|
enableShowingTools: function() {
|
||||||
@ -215,8 +219,12 @@ define([
|
|||||||
|
|
||||||
Module.BlockSettingsView = Marionette.LayoutView.extend({
|
Module.BlockSettingsView = Marionette.LayoutView.extend({
|
||||||
className: 'mailpoet_editor_settings',
|
className: 'mailpoet_editor_settings',
|
||||||
initialize: function() {
|
behaviors: {
|
||||||
MailPoet.Modal.panel({
|
ColorPickerBehavior: {},
|
||||||
|
},
|
||||||
|
initialize: function(params) {
|
||||||
|
this.model.trigger('startEditing');
|
||||||
|
var panelParams = {
|
||||||
element: this.$el,
|
element: this.$el,
|
||||||
template: '',
|
template: '',
|
||||||
position: 'right',
|
position: 'right',
|
||||||
@ -224,7 +232,13 @@ define([
|
|||||||
onCancel: function() {
|
onCancel: function() {
|
||||||
this.destroy();
|
this.destroy();
|
||||||
}.bind(this),
|
}.bind(this),
|
||||||
});
|
};
|
||||||
|
this.renderOptions = params.renderOptions || {};
|
||||||
|
if (this.renderOptions.displayFormat === 'subpanel') {
|
||||||
|
MailPoet.Modal.subpanel(panelParams);
|
||||||
|
} else {
|
||||||
|
MailPoet.Modal.panel(panelParams);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
close: function(event) {
|
close: function(event) {
|
||||||
this.destroy();
|
this.destroy();
|
||||||
@ -253,6 +267,7 @@ define([
|
|||||||
},
|
},
|
||||||
onBeforeDestroy: function() {
|
onBeforeDestroy: function() {
|
||||||
MailPoet.Modal.close();
|
MailPoet.Modal.close();
|
||||||
|
this.model.trigger('stopEditing');
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ define([
|
|||||||
return this._getDefaults({
|
return this._getDefaults({
|
||||||
type: 'button',
|
type: 'button',
|
||||||
text: 'Button',
|
text: 'Button',
|
||||||
url: 'http://google.com',
|
url: '',
|
||||||
styles: {
|
styles: {
|
||||||
block: {
|
block: {
|
||||||
backgroundColor: '#ff0000',
|
backgroundColor: '#ff0000',
|
||||||
@ -44,6 +44,9 @@ define([
|
|||||||
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; },
|
||||||
onDragSubstituteBy: function() { return Module.ButtonWidgetView; },
|
onDragSubstituteBy: function() { return Module.ButtonWidgetView; },
|
||||||
|
behaviors: _.extend({}, base.BlockView.prototype.behaviors, {
|
||||||
|
ShowSettingsBehavior: {},
|
||||||
|
}),
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
base.BlockView.prototype.initialize.apply(this, arguments);
|
base.BlockView.prototype.initialize.apply(this, arguments);
|
||||||
|
|
||||||
@ -65,8 +68,8 @@ define([
|
|||||||
getTemplate: function() { return templates.buttonBlockSettings; },
|
getTemplate: function() { return templates.buttonBlockSettings; },
|
||||||
events: function() {
|
events: function() {
|
||||||
return {
|
return {
|
||||||
"keyup .mailpoet_field_button_text": _.partial(this.changeField, "text"),
|
"input .mailpoet_field_button_text": _.partial(this.changeField, "text"),
|
||||||
"keyup .mailpoet_field_button_url": _.partial(this.changeField, "url"),
|
"input .mailpoet_field_button_url": _.partial(this.changeField, "url"),
|
||||||
"change .mailpoet_field_button_alignment": _.partial(this.changeField, "styles.block.textAlign"),
|
"change .mailpoet_field_button_alignment": _.partial(this.changeField, "styles.block.textAlign"),
|
||||||
"change .mailpoet_field_button_font_color": _.partial(this.changeColorField, "styles.block.fontColor"),
|
"change .mailpoet_field_button_font_color": _.partial(this.changeColorField, "styles.block.fontColor"),
|
||||||
"change .mailpoet_field_button_font_family": _.partial(this.changeField, "styles.block.fontFamily"),
|
"change .mailpoet_field_button_font_family": _.partial(this.changeField, "styles.block.fontFamily"),
|
||||||
@ -77,45 +80,24 @@ define([
|
|||||||
|
|
||||||
"input .mailpoet_field_button_border_width": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_width_input', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
"input .mailpoet_field_button_border_width": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_width_input', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||||
"change .mailpoet_field_button_border_width": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_width_input', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
"change .mailpoet_field_button_border_width": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_width_input', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||||
"change .mailpoet_field_button_border_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_width', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
"input .mailpoet_field_button_border_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_width', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||||
"keyup .mailpoet_field_button_border_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_width', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
|
||||||
|
|
||||||
"input .mailpoet_field_button_border_radius": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_radius_input', _.partial(this.changePixelField, "styles.block.borderRadius").bind(this)),
|
"input .mailpoet_field_button_border_radius": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_radius_input', _.partial(this.changePixelField, "styles.block.borderRadius").bind(this)),
|
||||||
"change .mailpoet_field_button_border_radius": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_radius_input', _.partial(this.changePixelField, "styles.block.borderRadius").bind(this)),
|
"change .mailpoet_field_button_border_radius": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_radius_input', _.partial(this.changePixelField, "styles.block.borderRadius").bind(this)),
|
||||||
"change .mailpoet_field_button_border_radius_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_radius', _.partial(this.changePixelField, "styles.block.borderRadius").bind(this)),
|
"input .mailpoet_field_button_border_radius_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_radius', _.partial(this.changePixelField, "styles.block.borderRadius").bind(this)),
|
||||||
"keyup .mailpoet_field_button_border_radius_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_border_radius', _.partial(this.changePixelField, "styles.block.borderRadius").bind(this)),
|
|
||||||
|
|
||||||
"input .mailpoet_field_button_width": _.partial(this.updateValueAndCall, '.mailpoet_field_button_width_input', _.partial(this.changePixelField, "styles.block.width").bind(this)),
|
"input .mailpoet_field_button_width": _.partial(this.updateValueAndCall, '.mailpoet_field_button_width_input', _.partial(this.changePixelField, "styles.block.width").bind(this)),
|
||||||
"change .mailpoet_field_button_width": _.partial(this.updateValueAndCall, '.mailpoet_field_button_width_input', _.partial(this.changePixelField, "styles.block.width").bind(this)),
|
"change .mailpoet_field_button_width": _.partial(this.updateValueAndCall, '.mailpoet_field_button_width_input', _.partial(this.changePixelField, "styles.block.width").bind(this)),
|
||||||
"change .mailpoet_field_button_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_width', _.partial(this.changePixelField, "styles.block.width").bind(this)),
|
"input .mailpoet_field_button_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_width', _.partial(this.changePixelField, "styles.block.width").bind(this)),
|
||||||
"keyup .mailpoet_field_button_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_width', _.partial(this.changePixelField, "styles.block.width").bind(this)),
|
|
||||||
|
|
||||||
"input .mailpoet_field_button_line_height": _.partial(this.updateValueAndCall, '.mailpoet_field_button_line_height_input', _.partial(this.changePixelField, "styles.block.lineHeight").bind(this)),
|
"input .mailpoet_field_button_line_height": _.partial(this.updateValueAndCall, '.mailpoet_field_button_line_height_input', _.partial(this.changePixelField, "styles.block.lineHeight").bind(this)),
|
||||||
"change .mailpoet_field_button_line_height": _.partial(this.updateValueAndCall, '.mailpoet_field_button_line_height_input', _.partial(this.changePixelField, "styles.block.lineHeight").bind(this)),
|
"change .mailpoet_field_button_line_height": _.partial(this.updateValueAndCall, '.mailpoet_field_button_line_height_input', _.partial(this.changePixelField, "styles.block.lineHeight").bind(this)),
|
||||||
"change .mailpoet_field_button_line_height_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_line_height', _.partial(this.changePixelField, "styles.block.lineHeight").bind(this)),
|
"input .mailpoet_field_button_line_height_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_line_height', _.partial(this.changePixelField, "styles.block.lineHeight").bind(this)),
|
||||||
"keyup .mailpoet_field_button_line_height_input": _.partial(this.updateValueAndCall, '.mailpoet_field_button_line_height', _.partial(this.changePixelField, "styles.block.lineHeight").bind(this)),
|
|
||||||
|
|
||||||
"click .mailpoet_field_button_replace_all_styles": "applyToAll",
|
"click .mailpoet_field_button_replace_all_styles": "applyToAll",
|
||||||
"click .mailpoet_done_editing": "close",
|
"click .mailpoet_done_editing": "close",
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
behaviors: {
|
|
||||||
ColorPickerBehavior: {},
|
|
||||||
},
|
|
||||||
initialize: function(params) {
|
|
||||||
var panelParams = {
|
|
||||||
element: this.$el,
|
|
||||||
template: '',
|
|
||||||
position: 'right',
|
|
||||||
width: App.getConfig().get('sidepanelWidth'),
|
|
||||||
};
|
|
||||||
this.renderOptions = params.renderOptions || {};
|
|
||||||
if (this.renderOptions.displayFormat === 'subpanel') {
|
|
||||||
MailPoet.Modal.subpanel(panelParams);
|
|
||||||
} else {
|
|
||||||
MailPoet.Modal.panel(panelParams);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
templateHelpers: function() {
|
templateHelpers: function() {
|
||||||
return {
|
return {
|
||||||
model: this.model.toJSON(),
|
model: this.model.toJSON(),
|
||||||
|
@ -65,6 +65,13 @@ define([
|
|||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
},
|
},
|
||||||
|
getChildren: function() {
|
||||||
|
var models = this.get('blocks').map(function(model, index, list) {
|
||||||
|
return [model, model.getChildren()];
|
||||||
|
});
|
||||||
|
|
||||||
|
return _.flatten(models);
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Module.ContainerBlockView = Marionette.CompositeView.extend({
|
Module.ContainerBlockView = Marionette.CompositeView.extend({
|
||||||
@ -118,6 +125,7 @@ define([
|
|||||||
return view.renderOptions.depth === 1;
|
return view.renderOptions.depth === 1;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
HighlightEditingBehavior: {}
|
||||||
},
|
},
|
||||||
onDragSubstituteBy: function() {
|
onDragSubstituteBy: function() {
|
||||||
// For two and three column layouts display their respective widgets,
|
// For two and three column layouts display their respective widgets,
|
||||||
@ -178,13 +186,13 @@ define([
|
|||||||
},
|
},
|
||||||
showTools: function() {
|
showTools: function() {
|
||||||
if (this.renderOptions.depth === 1 && !this.$el.hasClass('mailpoet_container_layer_active')) {
|
if (this.renderOptions.depth === 1 && !this.$el.hasClass('mailpoet_container_layer_active')) {
|
||||||
this.$(this.ui.tools).show();
|
this.$(this.ui.tools).addClass('mailpoet_display_tools');
|
||||||
this.toolsView.triggerMethod('showTools');
|
this.toolsView.triggerMethod('showTools');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hideTools: function() {
|
hideTools: function() {
|
||||||
if (this.renderOptions.depth === 1 && !this.$el.hasClass('mailpoet_container_layer_active')) {
|
if (this.renderOptions.depth === 1 && !this.$el.hasClass('mailpoet_container_layer_active')) {
|
||||||
this.$(this.ui.tools).hide();
|
this.$(this.ui.tools).removeClass('mailpoet_display_tools');
|
||||||
this.toolsView.triggerMethod('hideTools');
|
this.toolsView.triggerMethod('hideTools');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -286,6 +294,7 @@ define([
|
|||||||
templateHelpers: function() {
|
templateHelpers: function() {
|
||||||
return {
|
return {
|
||||||
isRoot: this.renderOptions.depth === 0,
|
isRoot: this.renderOptions.depth === 0,
|
||||||
|
emptyContainerMessage: this.renderOptions.emptyContainerMessage || '',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -302,9 +311,6 @@ define([
|
|||||||
"click .mailpoet_done_editing": "close",
|
"click .mailpoet_done_editing": "close",
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
behaviors: {
|
|
||||||
ColorPickerBehavior: {},
|
|
||||||
},
|
|
||||||
regions: {
|
regions: {
|
||||||
columnsSettingsRegion: '.mailpoet_container_columns_settings',
|
columnsSettingsRegion: '.mailpoet_container_columns_settings',
|
||||||
},
|
},
|
||||||
|
@ -43,6 +43,9 @@ define([
|
|||||||
minLength: 0, // TODO: Move this number to editor configuration
|
minLength: 0, // TODO: Move this number to editor configuration
|
||||||
modelField: 'styles.block.padding',
|
modelField: 'styles.block.padding',
|
||||||
},
|
},
|
||||||
|
ShowSettingsBehavior: {
|
||||||
|
ignoreFrom: '.mailpoet_resize_handle'
|
||||||
|
},
|
||||||
}, base.BlockView.prototype.behaviors),
|
}, base.BlockView.prototype.behaviors),
|
||||||
onDragSubstituteBy: function() { return Module.DividerWidgetView; },
|
onDragSubstituteBy: function() { return Module.DividerWidgetView; },
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
@ -88,8 +91,7 @@ define([
|
|||||||
|
|
||||||
"input .mailpoet_field_divider_border_width": _.partial(this.updateValueAndCall, '.mailpoet_field_divider_border_width_input', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
"input .mailpoet_field_divider_border_width": _.partial(this.updateValueAndCall, '.mailpoet_field_divider_border_width_input', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||||
"change .mailpoet_field_divider_border_width": _.partial(this.updateValueAndCall, '.mailpoet_field_divider_border_width_input', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
"change .mailpoet_field_divider_border_width": _.partial(this.updateValueAndCall, '.mailpoet_field_divider_border_width_input', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||||
"change .mailpoet_field_divider_border_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_divider_border_width', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
"input .mailpoet_field_divider_border_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_divider_border_width', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
||||||
"keyup .mailpoet_field_divider_border_width_input": _.partial(this.updateValueAndCall, '.mailpoet_field_divider_border_width', _.partial(this.changePixelField, "styles.block.borderWidth").bind(this)),
|
|
||||||
|
|
||||||
"change .mailpoet_field_divider_border_color": _.partial(this.changeColorField, "styles.block.borderColor"),
|
"change .mailpoet_field_divider_border_color": _.partial(this.changeColorField, "styles.block.borderColor"),
|
||||||
"change .mailpoet_field_divider_background_color": _.partial(this.changeColorField, "styles.block.backgroundColor"),
|
"change .mailpoet_field_divider_background_color": _.partial(this.changeColorField, "styles.block.backgroundColor"),
|
||||||
@ -102,23 +104,6 @@ define([
|
|||||||
'change:styles.block.borderColor': 'repaintDividerStyleOptions',
|
'change:styles.block.borderColor': 'repaintDividerStyleOptions',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
behaviors: {
|
|
||||||
ColorPickerBehavior: {},
|
|
||||||
},
|
|
||||||
initialize: function(params) {
|
|
||||||
var panelParams = {
|
|
||||||
element: this.$el,
|
|
||||||
template: '',
|
|
||||||
position: 'right',
|
|
||||||
width: App.getConfig().get('sidepanelWidth'),
|
|
||||||
};
|
|
||||||
this.renderOptions = params.renderOptions || {};
|
|
||||||
if (this.renderOptions.displayFormat === 'subpanel') {
|
|
||||||
MailPoet.Modal.subpanel(panelParams);
|
|
||||||
} else {
|
|
||||||
MailPoet.Modal.panel(panelParams);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
templateHelpers: function() {
|
templateHelpers: function() {
|
||||||
return {
|
return {
|
||||||
model: this.model.toJSON(),
|
model: this.model.toJSON(),
|
||||||
|
@ -56,32 +56,46 @@ define([
|
|||||||
inline: true,
|
inline: true,
|
||||||
|
|
||||||
menubar: false,
|
menubar: false,
|
||||||
toolbar: "bold italic link unlink forecolor mailpoet_custom_fields",
|
toolbar: "bold italic link unlink forecolor mailpoet_shortcodes",
|
||||||
|
|
||||||
valid_elements: "p[class|style],span[class|style],a[href|class|title|target|style],strong[class|style],em[class|style],strike,br",
|
valid_elements: "p[class|style],span[class|style],a[href|class|title|target|style],strong[class|style],em[class|style],strike,br",
|
||||||
invalid_elements: "script",
|
invalid_elements: "script",
|
||||||
block_formats: 'Paragraph=p',
|
block_formats: 'Paragraph=p',
|
||||||
|
relative_urls: false,
|
||||||
|
remove_script_host: false,
|
||||||
|
|
||||||
plugins: "link textcolor colorpicker mailpoet_custom_fields",
|
plugins: "link textcolor colorpicker mailpoet_shortcodes",
|
||||||
|
|
||||||
setup: function(editor) {
|
setup: function(editor) {
|
||||||
editor.on('change', function(e) {
|
editor.on('change', function(e) {
|
||||||
that.model.set('text', editor.getContent());
|
that.model.set('text', editor.getContent());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
editor.on('click', function(e) {
|
||||||
|
editor.focus();
|
||||||
|
});
|
||||||
|
|
||||||
editor.on('focus', function(e) {
|
editor.on('focus', function(e) {
|
||||||
|
that.disableDragging();
|
||||||
that.disableShowingTools();
|
that.disableShowingTools();
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.on('blur', function(e) {
|
editor.on('blur', function(e) {
|
||||||
|
that.enableDragging();
|
||||||
that.enableShowingTools();
|
that.enableShowingTools();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
mailpoet_custom_fields: App.getConfig().get('customFields').toJSON(),
|
mailpoet_shortcodes: App.getConfig().get('shortcodes').toJSON(),
|
||||||
mailpoet_custom_fields_window_title: MailPoet.I18n.t('customFieldsWindowTitle'),
|
mailpoet_shortcodes_window_title: MailPoet.I18n.t('shortcodesWindowTitle'),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
disableDragging: function() {
|
||||||
|
this.$('.mailpoet_content').addClass('mailpoet_ignore_drag');
|
||||||
|
},
|
||||||
|
enableDragging: function() {
|
||||||
|
this.$('.mailpoet_content').removeClass('mailpoet_ignore_drag');
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Module.FooterBlockToolsView = base.BlockToolsView.extend({
|
Module.FooterBlockToolsView = base.BlockToolsView.extend({
|
||||||
@ -104,9 +118,6 @@ define([
|
|||||||
"click .mailpoet_done_editing": "close",
|
"click .mailpoet_done_editing": "close",
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
behaviors: {
|
|
||||||
ColorPickerBehavior: {},
|
|
||||||
},
|
|
||||||
templateHelpers: function() {
|
templateHelpers: function() {
|
||||||
return {
|
return {
|
||||||
model: this.model.toJSON(),
|
model: this.model.toJSON(),
|
||||||
|
@ -56,32 +56,46 @@ define([
|
|||||||
inline: true,
|
inline: true,
|
||||||
|
|
||||||
menubar: false,
|
menubar: false,
|
||||||
toolbar: "bold italic link unlink forecolor mailpoet_custom_fields",
|
toolbar: "bold italic link unlink forecolor mailpoet_shortcodes",
|
||||||
|
|
||||||
valid_elements: "p[class|style],span[class|style],a[href|class|title|target|style],strong[class|style],em[class|style],strike,br",
|
valid_elements: "p[class|style],span[class|style],a[href|class|title|target|style],strong[class|style],em[class|style],strike,br",
|
||||||
invalid_elements: "script",
|
invalid_elements: "script",
|
||||||
block_formats: 'Paragraph=p',
|
block_formats: 'Paragraph=p',
|
||||||
|
relative_urls: false,
|
||||||
|
remove_script_host: false,
|
||||||
|
|
||||||
plugins: "link textcolor colorpicker mailpoet_custom_fields",
|
plugins: "link textcolor colorpicker mailpoet_shortcodes",
|
||||||
|
|
||||||
setup: function(editor) {
|
setup: function(editor) {
|
||||||
editor.on('change', function(e) {
|
editor.on('change', function(e) {
|
||||||
that.model.set('text', editor.getContent());
|
that.model.set('text', editor.getContent());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
editor.on('click', function(e) {
|
||||||
|
editor.focus();
|
||||||
|
});
|
||||||
|
|
||||||
editor.on('focus', function(e) {
|
editor.on('focus', function(e) {
|
||||||
|
that.disableDragging();
|
||||||
that.disableShowingTools();
|
that.disableShowingTools();
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.on('blur', function(e) {
|
editor.on('blur', function(e) {
|
||||||
|
that.enableDragging();
|
||||||
that.enableShowingTools();
|
that.enableShowingTools();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
mailpoet_custom_fields: App.getConfig().get('customFields').toJSON(),
|
mailpoet_shortcodes: App.getConfig().get('shortcodes').toJSON(),
|
||||||
mailpoet_custom_fields_window_title: MailPoet.I18n.t('customFieldsWindowTitle'),
|
mailpoet_shortcodes_window_title: MailPoet.I18n.t('shortcodesWindowTitle'),
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
disableDragging: function() {
|
||||||
|
this.$('.mailpoet_content').addClass('mailpoet_ignore_drag');
|
||||||
|
},
|
||||||
|
enableDragging: function() {
|
||||||
|
this.$('.mailpoet_content').removeClass('mailpoet_ignore_drag');
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Module.HeaderBlockToolsView = base.BlockToolsView.extend({
|
Module.HeaderBlockToolsView = base.BlockToolsView.extend({
|
||||||
@ -104,9 +118,6 @@ define([
|
|||||||
"click .mailpoet_done_editing": "close",
|
"click .mailpoet_done_editing": "close",
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
behaviors: {
|
|
||||||
ColorPickerBehavior: {},
|
|
||||||
},
|
|
||||||
templateHelpers: function() {
|
templateHelpers: function() {
|
||||||
return {
|
return {
|
||||||
model: this.model.toJSON(),
|
model: this.model.toJSON(),
|
||||||
|
@ -17,8 +17,8 @@ define([
|
|||||||
defaults: function() {
|
defaults: function() {
|
||||||
return this._getDefaults({
|
return this._getDefaults({
|
||||||
type: 'image',
|
type: 'image',
|
||||||
link: 'http://example.org',
|
link: '',
|
||||||
src: 'no-image.png',
|
src: '',
|
||||||
alt: 'An image of...',
|
alt: 'An image of...',
|
||||||
fullWidth: true, // true | false
|
fullWidth: true, // true | false
|
||||||
width: '64px',
|
width: '64px',
|
||||||
@ -41,6 +41,9 @@ define([
|
|||||||
imageMissingSrc: App.getConfig().get('urls.imageMissing'),
|
imageMissingSrc: App.getConfig().get('urls.imageMissing'),
|
||||||
}, base.BlockView.prototype.templateHelpers.apply(this));
|
}, base.BlockView.prototype.templateHelpers.apply(this));
|
||||||
},
|
},
|
||||||
|
behaviors: _.extend({}, base.BlockView.prototype.behaviors, {
|
||||||
|
ShowSettingsBehavior: {},
|
||||||
|
}),
|
||||||
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);
|
||||||
@ -61,9 +64,9 @@ define([
|
|||||||
getTemplate: function() { return templates.imageBlockSettings; },
|
getTemplate: function() { return templates.imageBlockSettings; },
|
||||||
events: function() {
|
events: function() {
|
||||||
return {
|
return {
|
||||||
"keyup .mailpoet_field_image_link": _.partial(this.changeField, "link"),
|
"input .mailpoet_field_image_link": _.partial(this.changeField, "link"),
|
||||||
"keyup .mailpoet_field_image_address": _.partial(this.changeField, "src"),
|
"input .mailpoet_field_image_address": _.partial(this.changeField, "src"),
|
||||||
"keyup .mailpoet_field_image_alt_text": _.partial(this.changeField, "alt"),
|
"input .mailpoet_field_image_alt_text": _.partial(this.changeField, "alt"),
|
||||||
"change .mailpoet_field_image_full_width": _.partial(this.changeBoolCheckboxField, "fullWidth"),
|
"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",
|
||||||
|
@ -23,7 +23,19 @@ define([
|
|||||||
'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, CommunicationComponent, BaseBlock, ButtonBlock, DividerBlock) {
|
], function(
|
||||||
|
Backbone,
|
||||||
|
Marionette,
|
||||||
|
Radio,
|
||||||
|
_,
|
||||||
|
jQuery,
|
||||||
|
MailPoet,
|
||||||
|
App,
|
||||||
|
CommunicationComponent,
|
||||||
|
BaseBlock,
|
||||||
|
ButtonBlock,
|
||||||
|
DividerBlock
|
||||||
|
) {
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
@ -163,6 +175,7 @@ define([
|
|||||||
renderOptions = {
|
renderOptions = {
|
||||||
disableTextEditor: true,
|
disableTextEditor: true,
|
||||||
disableDragAndDrop: true,
|
disableDragAndDrop: true,
|
||||||
|
emptyContainerMessage: MailPoet.I18n.t('noPostsToDisplay'),
|
||||||
};
|
};
|
||||||
this.postsRegion.show(new ContainerView({ model: this.model.get('_transformedPosts'), renderOptions: renderOptions }));
|
this.postsRegion.show(new ContainerView({ model: this.model.get('_transformedPosts'), renderOptions: renderOptions }));
|
||||||
},
|
},
|
||||||
@ -195,6 +208,7 @@ define([
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
|
this.model.trigger('startEditing');
|
||||||
this.selectionView = new PostSelectionSettingsView({ model: this.model });
|
this.selectionView = new PostSelectionSettingsView({ model: this.model });
|
||||||
this.displayOptionsView = new PostsDisplayOptionsSettingsView({ model: this.model });
|
this.displayOptionsView = new PostsDisplayOptionsSettingsView({ model: this.model });
|
||||||
},
|
},
|
||||||
@ -202,21 +216,23 @@ define([
|
|||||||
var that = this,
|
var that = this,
|
||||||
blockView = this.model.request('blockView');
|
blockView = this.model.request('blockView');
|
||||||
|
|
||||||
this.selectionRegion.show(this.selectionView);
|
this.showChildView('selectionRegion', this.selectionView);
|
||||||
this.displayOptionsRegion.show(this.displayOptionsView);
|
this.showChildView('displayOptionsRegion', this.displayOptionsView);
|
||||||
|
|
||||||
MailPoet.Modal.panel({
|
MailPoet.Modal.panel({
|
||||||
element: this.$el,
|
element: this.$el,
|
||||||
template: '',
|
template: '',
|
||||||
position: 'right',
|
position: 'right',
|
||||||
overlay: true,
|
|
||||||
highlight: blockView.$el,
|
|
||||||
width: App.getConfig().get('sidepanelWidth'),
|
width: App.getConfig().get('sidepanelWidth'),
|
||||||
onCancel: function() {
|
onCancel: function() {
|
||||||
// Self destroy the block if the user closes settings modal
|
// Self destroy the block if the user closes settings modal
|
||||||
that.model.destroy();
|
that.model.destroy();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Inform child views that they have been attached to document
|
||||||
|
this.selectionView.triggerMethod('attach');
|
||||||
|
this.displayOptionsView.triggerMethod('attach');
|
||||||
},
|
},
|
||||||
switchToDisplayOptions: function() {
|
switchToDisplayOptions: function() {
|
||||||
// Switch content view
|
// Switch content view
|
||||||
@ -257,7 +273,7 @@ define([
|
|||||||
return {
|
return {
|
||||||
'change .mailpoet_settings_posts_content_type': _.partial(this.changeField, 'contentType'),
|
'change .mailpoet_settings_posts_content_type': _.partial(this.changeField, 'contentType'),
|
||||||
'change .mailpoet_posts_post_status': _.partial(this.changeField, 'postStatus'),
|
'change .mailpoet_posts_post_status': _.partial(this.changeField, 'postStatus'),
|
||||||
'keyup .mailpoet_posts_search_term': _.partial(this.changeField, 'search'),
|
'input .mailpoet_posts_search_term': _.partial(this.changeField, 'search'),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
constructor: function() {
|
constructor: function() {
|
||||||
@ -266,14 +282,19 @@ define([
|
|||||||
Marionette.CompositeView.apply(this, arguments);
|
Marionette.CompositeView.apply(this, arguments);
|
||||||
},
|
},
|
||||||
onRender: function() {
|
onRender: function() {
|
||||||
|
// Dynamically update available post types
|
||||||
|
CommunicationComponent.getPostTypes().done(_.bind(this._updateContentTypes, this));
|
||||||
|
},
|
||||||
|
onAttach: function() {
|
||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
// Dynamically update available post types
|
// Dynamically update available post types
|
||||||
CommunicationComponent.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,
|
||||||
allowClear: true,
|
allowClear: true,
|
||||||
|
placeholder: MailPoet.I18n.t('categoriesAndTags'),
|
||||||
ajax: {
|
ajax: {
|
||||||
data: function (params) {
|
data: function (params) {
|
||||||
return {
|
return {
|
||||||
@ -281,8 +302,10 @@ define([
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
transport: function(options, success, failure) {
|
transport: function(options, success, failure) {
|
||||||
var taxonomies,
|
var taxonomies;
|
||||||
promise = CommunicationComponent.getTaxonomies(that.model.get('contentType')).then(function(tax) {
|
var 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 = CommunicationComponent.getTerms({
|
var promise = CommunicationComponent.getTerms({
|
||||||
@ -291,7 +314,7 @@ define([
|
|||||||
}).then(function(terms) {
|
}).then(function(terms) {
|
||||||
return {
|
return {
|
||||||
taxonomies: taxonomies,
|
taxonomies: taxonomies,
|
||||||
terms: terms,
|
terms: terms
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
return promise;
|
return promise;
|
||||||
@ -391,23 +414,20 @@ define([
|
|||||||
"change .mailpoet_posts_title_format": 'changeTitleFormat',
|
"change .mailpoet_posts_title_format": 'changeTitleFormat',
|
||||||
"change .mailpoet_posts_title_as_links": _.partial(this.changeBoolField, 'titleIsLink'),
|
"change .mailpoet_posts_title_as_links": _.partial(this.changeBoolField, 'titleIsLink'),
|
||||||
"change .mailpoet_posts_show_divider": _.partial(this.changeBoolField, 'showDivider'),
|
"change .mailpoet_posts_show_divider": _.partial(this.changeBoolField, 'showDivider'),
|
||||||
"keyup .mailpoet_posts_show_amount": _.partial(this.changeField, "amount"),
|
"input .mailpoet_posts_show_amount": _.partial(this.changeField, "amount"),
|
||||||
"change .mailpoet_posts_content_type": _.partial(this.changeField, "contentType"),
|
"change .mailpoet_posts_content_type": _.partial(this.changeField, "contentType"),
|
||||||
"change .mailpoet_posts_include_or_exclude": _.partial(this.changeField, "inclusionType"),
|
"change .mailpoet_posts_include_or_exclude": _.partial(this.changeField, "inclusionType"),
|
||||||
"change .mailpoet_posts_title_alignment": _.partial(this.changeField, "titleAlignment"),
|
"change .mailpoet_posts_title_alignment": _.partial(this.changeField, "titleAlignment"),
|
||||||
"change .mailpoet_posts_image_full_width": _.partial(this.changeBoolField, "imageFullWidth"),
|
"change .mailpoet_posts_image_full_width": _.partial(this.changeBoolField, "imageFullWidth"),
|
||||||
"change .mailpoet_posts_featured_image_position": _.partial(this.changeField, "featuredImagePosition"),
|
"change .mailpoet_posts_featured_image_position": _.partial(this.changeField, "featuredImagePosition"),
|
||||||
"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"),
|
"input .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"),
|
||||||
"keyup .mailpoet_posts_categories": _.partial(this.changeField, "categoriesPrecededBy"),
|
"input .mailpoet_posts_categories": _.partial(this.changeField, "categoriesPrecededBy"),
|
||||||
"keyup .mailpoet_posts_read_more_text": _.partial(this.changeField, "readMoreText"),
|
"input .mailpoet_posts_read_more_text": _.partial(this.changeField, "readMoreText"),
|
||||||
"change .mailpoet_posts_sort_by": _.partial(this.changeField, "sortBy"),
|
"change .mailpoet_posts_sort_by": _.partial(this.changeField, "sortBy"),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
behaviors: {
|
|
||||||
ColorPickerBehavior: {},
|
|
||||||
},
|
|
||||||
templateHelpers: function() {
|
templateHelpers: function() {
|
||||||
return {
|
return {
|
||||||
model: this.model.toJSON(),
|
model: this.model.toJSON(),
|
||||||
@ -450,9 +470,11 @@ define([
|
|||||||
if (value == 'titleOnly') {
|
if (value == 'titleOnly') {
|
||||||
this.$('.mailpoet_posts_title_as_list').removeClass('mailpoet_hidden');
|
this.$('.mailpoet_posts_title_as_list').removeClass('mailpoet_hidden');
|
||||||
this.$('.mailpoet_posts_image_full_width_option').addClass('mailpoet_hidden');
|
this.$('.mailpoet_posts_image_full_width_option').addClass('mailpoet_hidden');
|
||||||
|
this.$('.mailpoet_posts_image_separator').addClass('mailpoet_hidden');
|
||||||
} else {
|
} else {
|
||||||
this.$('.mailpoet_posts_title_as_list').addClass('mailpoet_hidden');
|
this.$('.mailpoet_posts_title_as_list').addClass('mailpoet_hidden');
|
||||||
this.$('.mailpoet_posts_image_full_width_option').removeClass('mailpoet_hidden');
|
this.$('.mailpoet_posts_image_full_width_option').removeClass('mailpoet_hidden');
|
||||||
|
this.$('.mailpoet_posts_image_separator').removeClass('mailpoet_hidden');
|
||||||
|
|
||||||
// Reset titleFormat if it was set to List when switching away from displayType=titleOnly
|
// Reset titleFormat if it was set to List when switching away from displayType=titleOnly
|
||||||
if (this.model.get('titleFormat') === 'ul') {
|
if (this.model.get('titleFormat') === 'ul') {
|
||||||
|
@ -93,6 +93,7 @@ define([
|
|||||||
return {
|
return {
|
||||||
model: this.model.toJSON(),
|
model: this.model.toJSON(),
|
||||||
allIconSets: allIconSets.toJSON(),
|
allIconSets: allIconSets.toJSON(),
|
||||||
|
imageMissingSrc: App.getConfig().get('urls.imageMissing'),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -139,6 +140,8 @@ define([
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
HighlightEditingBehavior: {},
|
||||||
|
ShowSettingsBehavior: {},
|
||||||
},
|
},
|
||||||
onDragSubstituteBy: function() { return Module.SocialWidgetView; },
|
onDragSubstituteBy: function() { return Module.SocialWidgetView; },
|
||||||
constructor: function() {
|
constructor: function() {
|
||||||
@ -147,6 +150,7 @@ define([
|
|||||||
Marionette.CompositeView.apply(this, arguments);
|
Marionette.CompositeView.apply(this, arguments);
|
||||||
},
|
},
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
|
this.on('showSettings', this.showSettings, this);
|
||||||
this.on('dom:refresh', this.showBlock, this);
|
this.on('dom:refresh', this.showBlock, this);
|
||||||
this._isFirstRender = true;
|
this._isFirstRender = true;
|
||||||
},
|
},
|
||||||
@ -167,13 +171,16 @@ define([
|
|||||||
this.regionManager.destroy();
|
this.regionManager.destroy();
|
||||||
},
|
},
|
||||||
showTools: function(_event) {
|
showTools: function(_event) {
|
||||||
this.$(this.ui.tools).show();
|
this.$(this.ui.tools).addClass('mailpoet_display_tools');
|
||||||
_event.stopPropagation();
|
_event.stopPropagation();
|
||||||
},
|
},
|
||||||
hideTools: function(_event) {
|
hideTools: function(_event) {
|
||||||
this.$(this.ui.tools).hide();
|
this.$(this.ui.tools).removeClass('mailpoet_display_tools');
|
||||||
_event.stopPropagation();
|
_event.stopPropagation();
|
||||||
},
|
},
|
||||||
|
showSettings: function(options) {
|
||||||
|
this.toolsView.triggerMethod('showSettings', options);
|
||||||
|
},
|
||||||
getDropFunc: function() {
|
getDropFunc: function() {
|
||||||
return function() {
|
return function() {
|
||||||
return this.model.clone();
|
return this.model.clone();
|
||||||
@ -273,9 +280,9 @@ define([
|
|||||||
return {
|
return {
|
||||||
"click .mailpoet_delete_block": "deleteIcon",
|
"click .mailpoet_delete_block": "deleteIcon",
|
||||||
"change .mailpoet_social_icon_field_type": _.partial(this.changeField, "iconType"),
|
"change .mailpoet_social_icon_field_type": _.partial(this.changeField, "iconType"),
|
||||||
"keyup .mailpoet_social_icon_field_image": _.partial(this.changeField, "image"),
|
"input .mailpoet_social_icon_field_image": _.partial(this.changeField, "image"),
|
||||||
"keyup .mailpoet_social_icon_field_link": this.changeLink,
|
"input .mailpoet_social_icon_field_link": this.changeLink,
|
||||||
"keyup .mailpoet_social_icon_field_text": _.partial(this.changeField, "text"),
|
"input .mailpoet_social_icon_field_text": _.partial(this.changeField, "text"),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
modelEvents: {
|
modelEvents: {
|
||||||
@ -382,7 +389,7 @@ define([
|
|||||||
{
|
{
|
||||||
type: 'socialIcon',
|
type: 'socialIcon',
|
||||||
iconType: 'facebook',
|
iconType: 'facebook',
|
||||||
link: 'http://example.com',
|
link: 'http://www.facebook.com',
|
||||||
image: App.getAvailableStyles().get('socialIconSets.default.facebook'),
|
image: App.getAvailableStyles().get('socialIconSets.default.facebook'),
|
||||||
height: '32px',
|
height: '32px',
|
||||||
width: '32px',
|
width: '32px',
|
||||||
@ -391,7 +398,7 @@ define([
|
|||||||
{
|
{
|
||||||
type: 'socialIcon',
|
type: 'socialIcon',
|
||||||
iconType: 'twitter',
|
iconType: 'twitter',
|
||||||
link: 'http://example.com',
|
link: 'http://www.twitter.com',
|
||||||
image: App.getAvailableStyles().get('socialIconSets.default.twitter'),
|
image: App.getAvailableStyles().get('socialIconSets.default.twitter'),
|
||||||
height: '32px',
|
height: '32px',
|
||||||
width: '32px',
|
width: '32px',
|
||||||
|
@ -36,6 +36,9 @@ define([
|
|||||||
minLength: 20, // TODO: Move this number to editor configuration
|
minLength: 20, // TODO: Move this number to editor configuration
|
||||||
modelField: 'styles.block.height',
|
modelField: 'styles.block.height',
|
||||||
},
|
},
|
||||||
|
ShowSettingsBehavior: {
|
||||||
|
ignoreFrom: '.mailpoet_resize_handle'
|
||||||
|
},
|
||||||
}, base.BlockView.prototype.behaviors),
|
}, base.BlockView.prototype.behaviors),
|
||||||
modelEvents: _.omit(base.BlockView.prototype.modelEvents, 'change'),
|
modelEvents: _.omit(base.BlockView.prototype.modelEvents, 'change'),
|
||||||
onDragSubstituteBy: function() { return Module.SpacerWidgetView; },
|
onDragSubstituteBy: function() { return Module.SpacerWidgetView; },
|
||||||
@ -70,9 +73,6 @@ define([
|
|||||||
"click .mailpoet_done_editing": "close",
|
"click .mailpoet_done_editing": "close",
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
behaviors: {
|
|
||||||
ColorPickerBehavior: {},
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Module.SpacerWidgetView = base.WidgetView.extend({
|
Module.SpacerWidgetView = base.WidgetView.extend({
|
||||||
|
@ -53,34 +53,48 @@ define([
|
|||||||
|
|
||||||
menubar: false,
|
menubar: false,
|
||||||
toolbar1: "formatselect bold italic forecolor | link unlink",
|
toolbar1: "formatselect bold italic forecolor | link unlink",
|
||||||
toolbar2: "alignleft aligncenter alignright alignjustify | bullist numlist blockquote | code mailpoet_custom_fields",
|
toolbar2: "alignleft aligncenter alignright alignjustify | bullist numlist blockquote | code mailpoet_shortcodes",
|
||||||
|
|
||||||
//forced_root_block: 'p',
|
//forced_root_block: 'p',
|
||||||
valid_elements: "p[class|style],span[class|style],a[href|class|title|target|style],h1[class|style],h2[class|style],h3[class|style],ol[class|style],ul[class|style],li[class|style],strong[class|style],em[class|style],strike,br,blockquote[class|style],table[class|style],tr[class|style],th[class|style],td[class|style]",
|
valid_elements: "p[class|style],span[class|style],a[href|class|title|target|style],h1[class|style],h2[class|style],h3[class|style],ol[class|style],ul[class|style],li[class|style],strong[class|style],em[class|style],strike,br,blockquote[class|style],table[class|style],tr[class|style],th[class|style],td[class|style]",
|
||||||
invalid_elements: "script",
|
invalid_elements: "script",
|
||||||
block_formats: 'Heading 1=h1;Heading 2=h2;Heading 3=h3;Paragraph=p',
|
block_formats: 'Heading 1=h1;Heading 2=h2;Heading 3=h3;Paragraph=p',
|
||||||
|
relative_urls: false,
|
||||||
|
remove_script_host: false,
|
||||||
|
|
||||||
plugins: "link code textcolor colorpicker mailpoet_custom_fields",
|
plugins: "link code textcolor colorpicker mailpoet_shortcodes",
|
||||||
|
|
||||||
setup: function(editor) {
|
setup: function(editor) {
|
||||||
editor.on('change', function(e) {
|
editor.on('change', function(e) {
|
||||||
that.model.set('text', editor.getContent());
|
that.model.set('text', editor.getContent());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
editor.on('click', function(e) {
|
||||||
|
editor.focus();
|
||||||
|
});
|
||||||
|
|
||||||
editor.on('focus', function(e) {
|
editor.on('focus', function(e) {
|
||||||
|
that.disableDragging();
|
||||||
that.disableShowingTools();
|
that.disableShowingTools();
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.on('blur', function(e) {
|
editor.on('blur', function(e) {
|
||||||
|
that.enableDragging();
|
||||||
that.enableShowingTools();
|
that.enableShowingTools();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
mailpoet_custom_fields: App.getConfig().get('customFields').toJSON(),
|
mailpoet_shortcodes: App.getConfig().get('shortcodes').toJSON(),
|
||||||
mailpoet_custom_fields_window_title: MailPoet.I18n.t('customFieldsWindowTitle'),
|
mailpoet_shortcodes_window_title: MailPoet.I18n.t('shortcodesWindowTitle'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
disableDragging: function() {
|
||||||
|
this.$('.mailpoet_content').addClass('mailpoet_ignore_drag');
|
||||||
|
},
|
||||||
|
enableDragging: function() {
|
||||||
|
this.$('.mailpoet_content').removeClass('mailpoet_ignore_drag');
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
Module.TextBlockToolsView = base.BlockToolsView.extend({
|
Module.TextBlockToolsView = base.BlockToolsView.extend({
|
||||||
|
@ -11,7 +11,7 @@ define([
|
|||||||
return MailPoet.Ajax.post({
|
return MailPoet.Ajax.post({
|
||||||
endpoint: 'automatedLatestContent',
|
endpoint: 'automatedLatestContent',
|
||||||
action: args.action,
|
action: args.action,
|
||||||
data: args.options || {},
|
data: args.options || {}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
Module._cachedQuery = _.memoize(Module._query, JSON.stringify);
|
Module._cachedQuery = _.memoize(Module._query, JSON.stringify);
|
||||||
@ -19,16 +19,16 @@ define([
|
|||||||
Module.getNewsletter = function(options) {
|
Module.getNewsletter = function(options) {
|
||||||
return Module._query({
|
return Module._query({
|
||||||
action: 'get',
|
action: 'get',
|
||||||
options: options,
|
options: options
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Module.getPostTypes = function() {
|
Module.getPostTypes = function() {
|
||||||
return Module._cachedQuery({
|
return Module._cachedQuery({
|
||||||
action: 'getPostTypes',
|
action: 'getPostTypes',
|
||||||
options: {},
|
options: {}
|
||||||
}).then(function(types) {
|
}).then(function(response) {
|
||||||
return _.values(types);
|
return _.values(response.data);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -36,29 +36,46 @@ define([
|
|||||||
return Module._cachedQuery({
|
return Module._cachedQuery({
|
||||||
action: 'getTaxonomies',
|
action: 'getTaxonomies',
|
||||||
options: {
|
options: {
|
||||||
postType: postType,
|
postType: postType
|
||||||
},
|
}
|
||||||
|
}).then(function(response) {
|
||||||
|
return response.data;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Module.getTerms = function(options) {
|
Module.getTerms = function(options) {
|
||||||
return Module._cachedQuery({
|
return Module._cachedQuery({
|
||||||
action: 'getTerms',
|
action: 'getTerms',
|
||||||
options: options,
|
options: options
|
||||||
|
}).then(function(response) {
|
||||||
|
return response.data;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Module.getPosts = function(options) {
|
Module.getPosts = function(options) {
|
||||||
return Module._cachedQuery({
|
return Module._cachedQuery({
|
||||||
action: 'getPosts',
|
action: 'getPosts',
|
||||||
options: options,
|
options: options
|
||||||
|
}).then(function(response) {
|
||||||
|
return response.data;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Module.getTransformedPosts = function(options) {
|
Module.getTransformedPosts = function(options) {
|
||||||
return Module._cachedQuery({
|
return Module._cachedQuery({
|
||||||
action: 'getTransformedPosts',
|
action: 'getTransformedPosts',
|
||||||
options: options,
|
options: options
|
||||||
|
}).then(function(response) {
|
||||||
|
return response.data;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Module.getBulkTransformedPosts = function(options) {
|
||||||
|
return Module._query({
|
||||||
|
action: 'getBulkTransformedPosts',
|
||||||
|
options: options
|
||||||
|
}).then(function(response) {
|
||||||
|
return response.data;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -66,7 +83,7 @@ define([
|
|||||||
return MailPoet.Ajax.post({
|
return MailPoet.Ajax.post({
|
||||||
endpoint: 'newsletters',
|
endpoint: 'newsletters',
|
||||||
action: 'save',
|
action: 'save',
|
||||||
data: options || {},
|
data: options || {}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -74,7 +91,7 @@ define([
|
|||||||
return MailPoet.Ajax.post({
|
return MailPoet.Ajax.post({
|
||||||
endpoint: 'newsletters',
|
endpoint: 'newsletters',
|
||||||
action: 'sendPreview',
|
action: 'sendPreview',
|
||||||
data: options || {},
|
data: options || {}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,15 +11,16 @@ 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', 'created_at', 'deleted_at', 'updated_at'],
|
whitelisted: ['id', 'subject', 'preheader'],
|
||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
this.on('change', function() {
|
this.on('change', function() {
|
||||||
App.getChannel().trigger('autoSave');
|
App.getChannel().trigger('autoSave');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
toJSON: function() {
|
toJSON: function() {
|
||||||
// Remove stale attributes from resulting JSON object
|
// Use only whitelisted properties to ensure properties editor
|
||||||
return _.omit(SuperModel.prototype.toJSON.call(this), this.stale);
|
// doesn't control don't change.
|
||||||
|
return _.pick(SuperModel.prototype.toJSON.call(this), this.whitelisted);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -60,6 +61,11 @@ define([
|
|||||||
return Module.newsletter;
|
return Module.newsletter;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Module.findModels = function(predicate) {
|
||||||
|
var blocks = App._contentContainer.getChildren();
|
||||||
|
return _.filter(blocks, predicate);
|
||||||
|
};
|
||||||
|
|
||||||
App.on('before:start', function(options) {
|
App.on('before:start', function(options) {
|
||||||
// Expose block methods globally
|
// Expose block methods globally
|
||||||
App.registerBlockType = Module.registerBlockType;
|
App.registerBlockType = Module.registerBlockType;
|
||||||
@ -68,6 +74,7 @@ define([
|
|||||||
App.toJSON = Module.toJSON;
|
App.toJSON = Module.toJSON;
|
||||||
App.getBody = Module.getBody;
|
App.getBody = Module.getBody;
|
||||||
App.getNewsletter = Module.getNewsletter;
|
App.getNewsletter = Module.getNewsletter;
|
||||||
|
App.findModels = Module.findModels;
|
||||||
|
|
||||||
Module.newsletter = new Module.NewsletterModel(_.omit(_.clone(options.newsletter), ['body']));
|
Module.newsletter = new Module.NewsletterModel(_.omit(_.clone(options.newsletter), ['body']));
|
||||||
});
|
});
|
||||||
|
@ -104,7 +104,7 @@ define([
|
|||||||
return MailPoet.Ajax.post({
|
return MailPoet.Ajax.post({
|
||||||
endpoint: 'newsletterTemplates',
|
endpoint: 'newsletterTemplates',
|
||||||
action: 'save',
|
action: 'save',
|
||||||
data: data,
|
data: data
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -283,8 +283,10 @@ define([
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var contents = JSON.stringify(jsonObject);
|
||||||
if (App.getConfig().get('validation.validateUnsubscribeLinkPresent') &&
|
if (App.getConfig().get('validation.validateUnsubscribeLinkPresent') &&
|
||||||
JSON.stringify(jsonObject).indexOf("[link:subscription_unsubscribe_url]") < 0) {
|
contents.indexOf("[link:subscription_unsubscribe_url]") < 0 &&
|
||||||
|
contents.indexOf("[link:subscription_unsubscribe]") < 0) {
|
||||||
this.showValidationError(MailPoet.I18n.t('unsubscribeLinkMissing'));
|
this.showValidationError(MailPoet.I18n.t('unsubscribeLinkMissing'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -65,10 +65,6 @@ define([
|
|||||||
var $openRegion = this.$el.find('.mailpoet_sidebar_region:not(.closed)'),
|
var $openRegion = this.$el.find('.mailpoet_sidebar_region:not(.closed)'),
|
||||||
$targetRegion = this.$el.find(event.target).closest('.mailpoet_sidebar_region');
|
$targetRegion = this.$el.find(event.target).closest('.mailpoet_sidebar_region');
|
||||||
|
|
||||||
if ($openRegion.get(0) === $targetRegion.get(0)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$openRegion.find('.mailpoet_region_content').velocity(
|
$openRegion.find('.mailpoet_region_content').velocity(
|
||||||
'slideUp',
|
'slideUp',
|
||||||
{
|
{
|
||||||
@ -79,16 +75,19 @@ define([
|
|||||||
}.bind(this)
|
}.bind(this)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
$targetRegion.find('.mailpoet_region_content').velocity(
|
|
||||||
'slideDown',
|
if ($openRegion.get(0) !== $targetRegion.get(0)) {
|
||||||
{
|
$targetRegion.find('.mailpoet_region_content').velocity(
|
||||||
duration: 250,
|
'slideDown',
|
||||||
easing: "easeIn",
|
{
|
||||||
complete: function() {
|
duration: 250,
|
||||||
$targetRegion.removeClass('closed');
|
easing: "easeIn",
|
||||||
},
|
complete: function() {
|
||||||
}
|
$targetRegion.removeClass('closed');
|
||||||
);
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
initialize: function(options) {
|
initialize: function(options) {
|
||||||
@ -233,6 +232,12 @@ define([
|
|||||||
'click .mailpoet_show_preview': 'showPreview',
|
'click .mailpoet_show_preview': 'showPreview',
|
||||||
'click #mailpoet_send_preview': 'sendPreview',
|
'click #mailpoet_send_preview': 'sendPreview',
|
||||||
},
|
},
|
||||||
|
onBeforeDestroy: function() {
|
||||||
|
if (this.previewView) {
|
||||||
|
this.previewView.destroy();
|
||||||
|
this.previewView = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
showPreview: function() {
|
showPreview: function() {
|
||||||
var json = App.toJSON();
|
var json = App.toJSON();
|
||||||
|
|
||||||
@ -247,18 +252,31 @@ define([
|
|||||||
endpoint: 'newsletters',
|
endpoint: 'newsletters',
|
||||||
action: 'showPreview',
|
action: 'showPreview',
|
||||||
data: json,
|
data: json,
|
||||||
}).done(function(response){
|
}).always(function() {
|
||||||
MailPoet.Modal.loading(false);
|
MailPoet.Modal.loading(false);
|
||||||
|
}).done(function(response) {
|
||||||
|
this.previewView = new Module.NewsletterPreviewView({
|
||||||
|
previewUrl: response.meta.preview_url
|
||||||
|
});
|
||||||
|
|
||||||
if (response.result === true) {
|
var view = this.previewView.render();
|
||||||
window.open(response.data.url, '_blank')
|
|
||||||
|
MailPoet.Modal.popup({
|
||||||
|
template: '',
|
||||||
|
element: this.previewView.$el,
|
||||||
|
title: MailPoet.I18n.t('newsletterPreview'),
|
||||||
|
onCancel: function() {
|
||||||
|
this.previewView.destroy();
|
||||||
|
this.previewView = null;
|
||||||
|
}.bind(this)
|
||||||
|
});
|
||||||
|
}.bind(this)).fail(function(response) {
|
||||||
|
if (response.errors.length > 0) {
|
||||||
|
MailPoet.Notice.error(
|
||||||
|
response.errors.map(function(error) { return error.message; }),
|
||||||
|
{ scroll: true }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
MailPoet.Notice.error(response.errors);
|
|
||||||
}).fail(function(error) {
|
|
||||||
MailPoet.Modal.loading(false);
|
|
||||||
MailPoet.Notice.error(
|
|
||||||
MailPoet.I18n.t('newsletterPreviewFailed')
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
sendPreview: function() {
|
sendPreview: function() {
|
||||||
@ -283,32 +301,39 @@ define([
|
|||||||
// send test email
|
// send test email
|
||||||
MailPoet.Modal.loading(true);
|
MailPoet.Modal.loading(true);
|
||||||
|
|
||||||
CommunicationComponent.previewNewsletter(data).done(function(response) {
|
CommunicationComponent.previewNewsletter(data).always(function() {
|
||||||
if(response.result !== undefined && response.result === true) {
|
|
||||||
MailPoet.Notice.success(MailPoet.I18n.t('newsletterPreviewSent'), { scroll: true });
|
|
||||||
} else {
|
|
||||||
if (_.isArray(response.errors)) {
|
|
||||||
response.errors.map(function(error) {
|
|
||||||
MailPoet.Notice.error(error, { scroll: true });
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
MailPoet.Notice.error(
|
|
||||||
MailPoet.I18n.t('newsletterPreviewFailedToSend'),
|
|
||||||
{
|
|
||||||
scroll: true,
|
|
||||||
static: true,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MailPoet.Modal.loading(false);
|
MailPoet.Modal.loading(false);
|
||||||
|
}).done(function(response) {
|
||||||
|
MailPoet.Notice.success(
|
||||||
|
MailPoet.I18n.t('newsletterPreviewSent'),
|
||||||
|
{ scroll: true });
|
||||||
}).fail(function(response) {
|
}).fail(function(response) {
|
||||||
// an error occurred
|
if (response.errors.length > 0) {
|
||||||
MailPoet.Modal.loading(false);
|
MailPoet.Notice.error(
|
||||||
|
response.errors.map(function(error) { return error.message; }),
|
||||||
|
{ scroll: true, static: true }
|
||||||
|
);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Module.NewsletterPreviewView = Marionette.ItemView.extend({
|
||||||
|
getTemplate: function() { return templates.newsletterPreview; },
|
||||||
|
initialize: function(options) {
|
||||||
|
this.previewUrl = options.previewUrl;
|
||||||
|
this.width = App.getConfig().get('newsletterPreview.width');
|
||||||
|
this.height = App.getConfig().get('newsletterPreview.height')
|
||||||
|
},
|
||||||
|
templateHelpers: function() {
|
||||||
|
return {
|
||||||
|
previewUrl: this.previewUrl,
|
||||||
|
width: this.width,
|
||||||
|
height: this.height,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
App.on('before:start', function(options) {
|
App.on('before:start', function(options) {
|
||||||
App.registerWidget = Module.registerWidget;
|
App.registerWidget = Module.registerWidget;
|
||||||
App.getWidgets = Module.getWidgets;
|
App.getWidgets = Module.getWidgets;
|
||||||
|
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 26 KiB |
@ -1,58 +0,0 @@
|
|||||||
/**
|
|
||||||
* wysija_custom_fields/plugin.js
|
|
||||||
*
|
|
||||||
* TinyMCE plugin for adding dynamic data placeholders to newsletters.
|
|
||||||
*
|
|
||||||
* This adds a button to the editor toolbar which displays a modal window of
|
|
||||||
* available dynamic data placeholder buttons. On click each button inserts
|
|
||||||
* its placeholder into editor text.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*jshint unused:false */
|
|
||||||
/*global tinymce:true */
|
|
||||||
tinymce.PluginManager.add('mailpoet_custom_fields', function(editor, url) {
|
|
||||||
var appendLabelAndClose = function(text) {
|
|
||||||
editor.insertContent('[' + text + ']');
|
|
||||||
editor.windowManager.close();
|
|
||||||
},
|
|
||||||
generateOnClickFunc = function(id) {
|
|
||||||
return function() {
|
|
||||||
appendLabelAndClose(id);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
editor.addButton('mailpoet_custom_fields', {
|
|
||||||
icon: 'mailpoet_custom_fields',
|
|
||||||
onclick: function() {
|
|
||||||
var customFields = [],
|
|
||||||
configCustomFields = editor.settings.mailpoet_custom_fields;
|
|
||||||
|
|
||||||
for (var segment in configCustomFields) {
|
|
||||||
if (configCustomFields.hasOwnProperty(segment)) {
|
|
||||||
customFields.push({
|
|
||||||
type: 'label',
|
|
||||||
text: segment,
|
|
||||||
});
|
|
||||||
|
|
||||||
for (var i = 0; i < configCustomFields[segment].length; i += 1) {
|
|
||||||
customFields.push({
|
|
||||||
type: 'button',
|
|
||||||
text: configCustomFields[segment][i].text,
|
|
||||||
onClick: generateOnClickFunc(configCustomFields[segment][i].shortcode)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open window
|
|
||||||
editor.windowManager.open({
|
|
||||||
height: parseInt(editor.getParam("plugin_mailpoet_custom_fields_height", 400)),
|
|
||||||
width: parseInt(editor.getParam("plugin_mailpoet_custom_fields_width", 450)),
|
|
||||||
autoScroll: true,
|
|
||||||
title: editor.settings.mailpoet_custom_fields_window_title,
|
|
||||||
body: customFields,
|
|
||||||
buttons: [],
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* wysija_shortcodes/plugin.js
|
||||||
|
*
|
||||||
|
* TinyMCE plugin for adding dynamic data placeholders to newsletters.
|
||||||
|
*
|
||||||
|
* This adds a button to the editor toolbar which displays a modal window of
|
||||||
|
* available dynamic data placeholder buttons. On click each button inserts
|
||||||
|
* its placeholder into editor text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*jshint unused:false */
|
||||||
|
/*global tinymce:true */
|
||||||
|
tinymce.PluginManager.add('mailpoet_shortcodes', function(editor, url) {
|
||||||
|
var appendLabelAndClose = function(text) {
|
||||||
|
editor.insertContent('[' + text + ']');
|
||||||
|
editor.windowManager.close();
|
||||||
|
},
|
||||||
|
generateOnClickFunc = function(id) {
|
||||||
|
return function() {
|
||||||
|
appendLabelAndClose(id);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
editor.addButton('mailpoet_shortcodes', {
|
||||||
|
icon: 'mailpoet_shortcodes',
|
||||||
|
onclick: function() {
|
||||||
|
var shortcodes = [],
|
||||||
|
configShortcodes = editor.settings.mailpoet_shortcodes;
|
||||||
|
|
||||||
|
for (var segment in configShortcodes) {
|
||||||
|
if (configShortcodes.hasOwnProperty(segment)) {
|
||||||
|
shortcodes.push({
|
||||||
|
type: 'label',
|
||||||
|
text: segment,
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var i = 0; i < configShortcodes[segment].length; i += 1) {
|
||||||
|
shortcodes.push({
|
||||||
|
type: 'button',
|
||||||
|
text: configShortcodes[segment][i].text,
|
||||||
|
onClick: generateOnClickFunc(configShortcodes[segment][i].shortcode)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open window
|
||||||
|
editor.windowManager.open({
|
||||||
|
height: parseInt(editor.getParam("plugin_mailpoet_shortcodes_height", 400)),
|
||||||
|
width: parseInt(editor.getParam("plugin_mailpoet_shortcodes_width", 450)),
|
||||||
|
autoScroll: true,
|
||||||
|
title: editor.settings.mailpoet_shortcodes_window_title,
|
||||||
|
body: shortcodes,
|
||||||
|
buttons: [],
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
@ -1,311 +0,0 @@
|
|||||||
define(
|
|
||||||
[
|
|
||||||
'react',
|
|
||||||
'react-router',
|
|
||||||
'listing/listing.jsx',
|
|
||||||
'classnames',
|
|
||||||
'jquery',
|
|
||||||
'mailpoet'
|
|
||||||
],
|
|
||||||
function(
|
|
||||||
React,
|
|
||||||
Router,
|
|
||||||
Listing,
|
|
||||||
classNames,
|
|
||||||
jQuery,
|
|
||||||
MailPoet
|
|
||||||
) {
|
|
||||||
var Link = Router.Link;
|
|
||||||
|
|
||||||
var columns = [
|
|
||||||
{
|
|
||||||
name: 'subject',
|
|
||||||
label: MailPoet.I18n.t('subject'),
|
|
||||||
sortable: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'status',
|
|
||||||
label: MailPoet.I18n.t('status')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'segments',
|
|
||||||
label: MailPoet.I18n.t('lists')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'statistics',
|
|
||||||
label: MailPoet.I18n.t('statistics')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'created_at',
|
|
||||||
label: MailPoet.I18n.t('createdOn'),
|
|
||||||
sortable: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'updated_at',
|
|
||||||
label: MailPoet.I18n.t('lastModifiedOn'),
|
|
||||||
sortable: true
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
var messages = {
|
|
||||||
onTrash: function(response) {
|
|
||||||
var count = ~~response;
|
|
||||||
var message = null;
|
|
||||||
|
|
||||||
if(count === 1) {
|
|
||||||
message = (
|
|
||||||
MailPoet.I18n.t('oneNewsletterTrashed')
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
message = (
|
|
||||||
MailPoet.I18n.t('multipleNewslettersTrashed')
|
|
||||||
).replace('%$1d', count);
|
|
||||||
}
|
|
||||||
MailPoet.Notice.success(message);
|
|
||||||
},
|
|
||||||
onDelete: function(response) {
|
|
||||||
var count = ~~response;
|
|
||||||
var message = null;
|
|
||||||
|
|
||||||
if(count === 1) {
|
|
||||||
message = (
|
|
||||||
MailPoet.I18n.t('oneNewsletterDeleted')
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
message = (
|
|
||||||
MailPoet.I18n.t('multipleNewslettersDeleted')
|
|
||||||
).replace('%$1d', count);
|
|
||||||
}
|
|
||||||
MailPoet.Notice.success(message);
|
|
||||||
},
|
|
||||||
onRestore: function(response) {
|
|
||||||
var count = ~~response;
|
|
||||||
var message = null;
|
|
||||||
|
|
||||||
if(count === 1) {
|
|
||||||
message = (
|
|
||||||
MailPoet.I18n.t('oneNewsletterRestored')
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
message = (
|
|
||||||
MailPoet.I18n.t('multipleNewslettersRestored')
|
|
||||||
).replace('%$1d', count);
|
|
||||||
}
|
|
||||||
MailPoet.Notice.success(message);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var bulk_actions = [
|
|
||||||
{
|
|
||||||
name: 'trash',
|
|
||||||
label: MailPoet.I18n.t('trash'),
|
|
||||||
onSuccess: messages.onTrash
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
var item_actions = [
|
|
||||||
{
|
|
||||||
name: 'edit',
|
|
||||||
link: function(item) {
|
|
||||||
return (
|
|
||||||
<a href={ `?page=mailpoet-newsletter-editor&id=${ item.id }` }>
|
|
||||||
{MailPoet.I18n.t('edit')}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'trash'
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
var NewsletterList = React.createClass({
|
|
||||||
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) {
|
|
||||||
return (
|
|
||||||
<span>{MailPoet.I18n.t('notSentYet')}</span>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
if (item.queue.status === 'scheduled') {
|
|
||||||
return (
|
|
||||||
<span>{MailPoet.I18n.t('scheduledFor')} { MailPoet.Date.format(item.queue.scheduled_at) } </span>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
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>
|
|
||||||
{
|
|
||||||
MailPoet.I18n.t('newsletterQueueCompleted')
|
|
||||||
.replace("%$1d", item.queue.count_processed - item.queue.count_failed)
|
|
||||||
.replace("%$2d", 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) }
|
|
||||||
>{MailPoet.I18n.t('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) }
|
|
||||||
>{MailPoet.I18n.t('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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
renderStatistics: function(item) {
|
|
||||||
if(!item.statistics || !item.queue || item.queue.count_processed == 0 || item.queue.status === 'scheduled') {
|
|
||||||
return (
|
|
||||||
<span>
|
|
||||||
{MailPoet.I18n.t('notSentYet')}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
var percentage_clicked = Math.round(
|
|
||||||
(item.statistics.clicked * 100) / (item.queue.count_processed)
|
|
||||||
);
|
|
||||||
var percentage_opened = Math.round(
|
|
||||||
(item.statistics.opened * 100) / (item.queue.count_processed)
|
|
||||||
);
|
|
||||||
var percentage_unsubscribed = Math.round(
|
|
||||||
(item.statistics.unsubscribed * 100) / (item.queue.count_processed)
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<span>
|
|
||||||
{ percentage_opened }%, { percentage_clicked }%, { percentage_unsubscribed }%
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
renderItem: function(newsletter, actions) {
|
|
||||||
var rowClasses = classNames(
|
|
||||||
'manage-column',
|
|
||||||
'column-primary',
|
|
||||||
'has-row-actions'
|
|
||||||
);
|
|
||||||
|
|
||||||
var segments = newsletter.segments.map(function(segment) {
|
|
||||||
return segment.name
|
|
||||||
}).join(', ');
|
|
||||||
|
|
||||||
var statistics_column =
|
|
||||||
(!mailpoet_settings.tracking || !mailpoet_settings.tracking.enabled) ?
|
|
||||||
false :
|
|
||||||
<td className="column {statistics_class}" data-colname={ MailPoet.I18n.t('statistics') }>
|
|
||||||
{ this.renderStatistics(newsletter) }
|
|
||||||
</td>;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<td className={ rowClasses }>
|
|
||||||
<strong>
|
|
||||||
<a>{ newsletter.subject }</a>
|
|
||||||
</strong>
|
|
||||||
{ actions }
|
|
||||||
</td>
|
|
||||||
<td className="column" data-colname={ MailPoet.I18n.t('status') }>
|
|
||||||
{ this.renderStatus(newsletter) }
|
|
||||||
</td>
|
|
||||||
<td className="column" data-colname={ MailPoet.I18n.t('lists') }>
|
|
||||||
{ segments }
|
|
||||||
</td>
|
|
||||||
{ statistics_column }
|
|
||||||
<td className="column-date" data-colname={ MailPoet.I18n.t('createdOn') }>
|
|
||||||
<abbr>{ MailPoet.Date.format(newsletter.created_at) }</abbr>
|
|
||||||
</td>
|
|
||||||
<td className="column-date" data-colname={ MailPoet.I18n.t('lastModifiedOn') }>
|
|
||||||
<abbr>{ MailPoet.Date.format(newsletter.updated_at) }</abbr>
|
|
||||||
</td>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
if (!mailpoet_settings.tracking || !mailpoet_settings.tracking.enabled) {
|
|
||||||
columns = _.without(columns, _.findWhere(columns, {name: 'statistics'}));
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<h1 className="title">
|
|
||||||
{MailPoet.I18n.t('pageTitle')} <Link className="page-title-action" to="/new">{MailPoet.I18n.t('new')}</Link>
|
|
||||||
</h1>
|
|
||||||
|
|
||||||
<Listing
|
|
||||||
limit={ mailpoet_listing_per_page }
|
|
||||||
params={ this.props.params }
|
|
||||||
endpoint="newsletters"
|
|
||||||
onRenderItem={this.renderItem}
|
|
||||||
columns={columns}
|
|
||||||
bulk_actions={ bulk_actions }
|
|
||||||
item_actions={ item_actions }
|
|
||||||
messages={ messages }
|
|
||||||
auto_refresh={ true } />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return NewsletterList;
|
|
||||||
}
|
|
||||||
);
|
|
170
assets/js/src/newsletters/listings/mixins.jsx
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import MailPoet from 'mailpoet'
|
||||||
|
import classNames from 'classnames'
|
||||||
|
import jQuery from 'jquery'
|
||||||
|
|
||||||
|
const _QueueMixin = {
|
||||||
|
pauseSending: function(newsletter) {
|
||||||
|
MailPoet.Ajax.post({
|
||||||
|
endpoint: 'sendingQueue',
|
||||||
|
action: 'pause',
|
||||||
|
data: {
|
||||||
|
newsletter_id: newsletter.id
|
||||||
|
}
|
||||||
|
}).done(function() {
|
||||||
|
jQuery('#resume_'+newsletter.id).show();
|
||||||
|
jQuery('#pause_'+newsletter.id).hide();
|
||||||
|
}).fail((response) => {
|
||||||
|
if (response.errors.length > 0) {
|
||||||
|
MailPoet.Notice.error(
|
||||||
|
response.errors.map(function(error) { return error.message; }),
|
||||||
|
{ scroll: true }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
resumeSending: function(newsletter) {
|
||||||
|
MailPoet.Ajax.post({
|
||||||
|
endpoint: 'sendingQueue',
|
||||||
|
action: 'resume',
|
||||||
|
data: {
|
||||||
|
newsletter_id: newsletter.id
|
||||||
|
}
|
||||||
|
}).done(function() {
|
||||||
|
jQuery('#pause_'+newsletter.id).show();
|
||||||
|
jQuery('#resume_'+newsletter.id).hide();
|
||||||
|
}).fail((response) => {
|
||||||
|
if (response.errors.length > 0) {
|
||||||
|
MailPoet.Notice.error(
|
||||||
|
response.errors.map(function(error) { return error.message; }),
|
||||||
|
{ scroll: true }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
renderQueueStatus: function(newsletter) {
|
||||||
|
if (!newsletter.queue) {
|
||||||
|
return (
|
||||||
|
<span>{MailPoet.I18n.t('notSentYet')}</span>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
if (newsletter.queue.status === 'scheduled') {
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
{ MailPoet.I18n.t('scheduledFor') } { MailPoet.Date.format(newsletter.queue.scheduled_at) }
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const progressClasses = classNames(
|
||||||
|
'mailpoet_progress',
|
||||||
|
{ 'mailpoet_progress_complete': newsletter.queue.status === 'completed'}
|
||||||
|
);
|
||||||
|
|
||||||
|
// calculate percentage done
|
||||||
|
const percentage = Math.round(
|
||||||
|
(newsletter.queue.count_processed * 100) / (newsletter.queue.count_total)
|
||||||
|
);
|
||||||
|
|
||||||
|
let label;
|
||||||
|
|
||||||
|
if (newsletter.queue.status === 'completed') {
|
||||||
|
label = (
|
||||||
|
<span>
|
||||||
|
{
|
||||||
|
MailPoet.I18n.t('newsletterQueueCompleted')
|
||||||
|
.replace(
|
||||||
|
"%$1d",
|
||||||
|
newsletter.queue.count_processed - newsletter.queue.count_failed
|
||||||
|
)
|
||||||
|
.replace(
|
||||||
|
"%$2d",
|
||||||
|
newsletter.queue.count_total
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
label = (
|
||||||
|
<span>
|
||||||
|
{ newsletter.queue.count_processed } / { newsletter.queue.count_total }
|
||||||
|
|
||||||
|
<a
|
||||||
|
id={ 'resume_'+newsletter.id }
|
||||||
|
className="button"
|
||||||
|
style={{ display: (newsletter.queue.status === 'paused')
|
||||||
|
? 'inline-block': 'none' }}
|
||||||
|
href="javascript:;"
|
||||||
|
onClick={ this.resumeSending.bind(null, newsletter) }
|
||||||
|
>{MailPoet.I18n.t('resume')}</a>
|
||||||
|
<a
|
||||||
|
id={ 'pause_'+newsletter.id }
|
||||||
|
className="button mailpoet_pause"
|
||||||
|
style={{ display: (newsletter.queue.status === null)
|
||||||
|
? 'inline-block': 'none' }}
|
||||||
|
href="javascript:;"
|
||||||
|
onClick={ this.pauseSending.bind(null, newsletter) }
|
||||||
|
>{MailPoet.I18n.t('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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const _StatisticsMixin = {
|
||||||
|
renderStatistics: function(newsletter) {
|
||||||
|
if (
|
||||||
|
newsletter.statistics
|
||||||
|
&& newsletter.queue
|
||||||
|
&& newsletter.queue.status !== 'scheduled'
|
||||||
|
) {
|
||||||
|
const total_sent = ~~(newsletter.queue.count_processed);
|
||||||
|
|
||||||
|
let percentage_clicked = 0;
|
||||||
|
let percentage_opened = 0;
|
||||||
|
let percentage_unsubscribed = 0;
|
||||||
|
|
||||||
|
if (total_sent > 0) {
|
||||||
|
percentage_clicked = Math.round(
|
||||||
|
(~~(newsletter.statistics.clicked) * 100) / total_sent
|
||||||
|
);
|
||||||
|
percentage_opened = Math.round(
|
||||||
|
(~~(newsletter.statistics.opened) * 100) / total_sent
|
||||||
|
);
|
||||||
|
percentage_unsubscribed = Math.round(
|
||||||
|
(~~(newsletter.statistics.unsubscribed) * 100) / total_sent
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
{ percentage_opened }%, { percentage_clicked }%, { percentage_unsubscribed }%
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<span>{MailPoet.I18n.t('notSentYet')}</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { _QueueMixin as QueueMixin };
|
||||||
|
export { _StatisticsMixin as StatisticsMixin };
|
337
assets/js/src/newsletters/listings/notification.jsx
Normal file
@ -0,0 +1,337 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { Router, Route, IndexRoute, Link, useRouterHistory } from 'react-router'
|
||||||
|
import { createHashHistory } from 'history'
|
||||||
|
|
||||||
|
import Listing from 'listing/listing.jsx'
|
||||||
|
import ListingTabs from 'newsletters/listings/tabs.jsx'
|
||||||
|
|
||||||
|
import classNames from 'classnames'
|
||||||
|
import jQuery from 'jquery'
|
||||||
|
import MailPoet from 'mailpoet'
|
||||||
|
|
||||||
|
import {
|
||||||
|
timeOfDayValues,
|
||||||
|
weekDayValues,
|
||||||
|
monthDayValues,
|
||||||
|
nthWeekDayValues
|
||||||
|
} from 'newsletters/scheduling/common.jsx'
|
||||||
|
|
||||||
|
const messages = {
|
||||||
|
onTrash: (response) => {
|
||||||
|
const count = ~~response.meta.count;
|
||||||
|
let message = null;
|
||||||
|
|
||||||
|
if (count === 1) {
|
||||||
|
message = (
|
||||||
|
MailPoet.I18n.t('oneNewsletterTrashed')
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
MailPoet.I18n.t('multipleNewslettersTrashed')
|
||||||
|
).replace('%$1d', count.toLocaleString());
|
||||||
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
|
},
|
||||||
|
onDelete: (response) => {
|
||||||
|
const count = ~~response.meta.count;
|
||||||
|
let message = null;
|
||||||
|
|
||||||
|
if (count === 1) {
|
||||||
|
message = (
|
||||||
|
MailPoet.I18n.t('oneNewsletterDeleted')
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
MailPoet.I18n.t('multipleNewslettersDeleted')
|
||||||
|
).replace('%$1d', count.toLocaleString());
|
||||||
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
|
},
|
||||||
|
onRestore: (response) => {
|
||||||
|
const count = ~~response.meta.count;
|
||||||
|
let message = null;
|
||||||
|
|
||||||
|
if (count === 1) {
|
||||||
|
message = (
|
||||||
|
MailPoet.I18n.t('oneNewsletterRestored')
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
MailPoet.I18n.t('multipleNewslettersRestored')
|
||||||
|
).replace('%$1d', count.toLocaleString());
|
||||||
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
name: 'subject',
|
||||||
|
label: MailPoet.I18n.t('subject'),
|
||||||
|
sortable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'status',
|
||||||
|
label: MailPoet.I18n.t('status'),
|
||||||
|
width: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'settings',
|
||||||
|
label: MailPoet.I18n.t('settings')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'history',
|
||||||
|
label: MailPoet.I18n.t('history'),
|
||||||
|
width: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'updated_at',
|
||||||
|
label: MailPoet.I18n.t('lastModifiedOn'),
|
||||||
|
sortable: true
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const bulk_actions = [
|
||||||
|
{
|
||||||
|
name: 'trash',
|
||||||
|
label: MailPoet.I18n.t('trash'),
|
||||||
|
onSuccess: messages.onTrash
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const newsletter_actions = [
|
||||||
|
{
|
||||||
|
name: 'view',
|
||||||
|
link: function(newsletter) {
|
||||||
|
return (
|
||||||
|
<a href={ newsletter.preview_url } target="_blank">
|
||||||
|
{MailPoet.I18n.t('preview')}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'edit',
|
||||||
|
link: function(newsletter) {
|
||||||
|
return (
|
||||||
|
<a href={ `?page=mailpoet-newsletter-editor&id=${ newsletter.id }` }>
|
||||||
|
{MailPoet.I18n.t('edit')}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'duplicate',
|
||||||
|
label: MailPoet.I18n.t('duplicate'),
|
||||||
|
onClick: function(newsletter, refresh) {
|
||||||
|
return MailPoet.Ajax.post({
|
||||||
|
endpoint: 'newsletters',
|
||||||
|
action: 'duplicate',
|
||||||
|
data: {
|
||||||
|
id: newsletter.id
|
||||||
|
}
|
||||||
|
}).done((response) => {
|
||||||
|
MailPoet.Notice.success(
|
||||||
|
(MailPoet.I18n.t('newsletterDuplicated')).replace(
|
||||||
|
'%$1s', response.data.subject
|
||||||
|
)
|
||||||
|
);
|
||||||
|
refresh();
|
||||||
|
}).fail((response) => {
|
||||||
|
if (response.errors.length > 0) {
|
||||||
|
MailPoet.Notice.error(
|
||||||
|
response.errors.map(function(error) { return error.message; }),
|
||||||
|
{ scroll: true }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'trash'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const NewsletterListNotification = React.createClass({
|
||||||
|
updateStatus: function(e) {
|
||||||
|
// make the event persist so that we can still override the selected value
|
||||||
|
// in the ajax callback
|
||||||
|
e.persist();
|
||||||
|
|
||||||
|
MailPoet.Ajax.post({
|
||||||
|
endpoint: 'newsletters',
|
||||||
|
action: 'setStatus',
|
||||||
|
data: {
|
||||||
|
id: ~~(e.target.getAttribute('data-id')),
|
||||||
|
status: e.target.value
|
||||||
|
}
|
||||||
|
}).done((response) => {
|
||||||
|
if (response.data.status === 'active') {
|
||||||
|
MailPoet.Notice.success(MailPoet.I18n.t('postNotificationActivated'));
|
||||||
|
}
|
||||||
|
// force refresh of listing so that groups are updated
|
||||||
|
this.forceUpdate();
|
||||||
|
}).fail((response) => {
|
||||||
|
MailPoet.Notice.error(MailPoet.I18n.t('postNotificationActivationFailed'));
|
||||||
|
|
||||||
|
// reset value to actual newsletter's status
|
||||||
|
e.target.value = response.status;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
renderStatus: function(newsletter) {
|
||||||
|
return (
|
||||||
|
<select
|
||||||
|
data-id={ newsletter.id }
|
||||||
|
defaultValue={ newsletter.status }
|
||||||
|
onChange={ this.updateStatus }
|
||||||
|
>
|
||||||
|
<option value="active">{ MailPoet.I18n.t('active') }</option>
|
||||||
|
<option value="draft">{ MailPoet.I18n.t('inactive') }</option>
|
||||||
|
</select>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
renderSettings: function(newsletter) {
|
||||||
|
let sendingFrequency;
|
||||||
|
let sendingToSegments;
|
||||||
|
|
||||||
|
// get list of segments' name
|
||||||
|
const segments = newsletter.segments.map(function(segment) {
|
||||||
|
return segment.name
|
||||||
|
});
|
||||||
|
|
||||||
|
// check if the user has specified segments to send to
|
||||||
|
if(segments.length === 0) {
|
||||||
|
return (
|
||||||
|
<span className="mailpoet_error">
|
||||||
|
{ MailPoet.I18n.t('sendingToSegmentsNotSpecified') }
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
sendingToSegments = MailPoet.I18n.t('ifNewContentToSegments').replace(
|
||||||
|
'%$1s', segments.join(', ')
|
||||||
|
);
|
||||||
|
|
||||||
|
// set sending frequency
|
||||||
|
switch (newsletter.options.intervalType) {
|
||||||
|
case 'daily':
|
||||||
|
sendingFrequency = MailPoet.I18n.t('sendDaily').replace(
|
||||||
|
'%$1s', timeOfDayValues[newsletter.options.timeOfDay]
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'weekly':
|
||||||
|
sendingFrequency = MailPoet.I18n.t('sendWeekly').replace(
|
||||||
|
'%$1s', weekDayValues[newsletter.options.weekDay]
|
||||||
|
).replace(
|
||||||
|
'%$2s', timeOfDayValues[newsletter.options.timeOfDay]
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'monthly':
|
||||||
|
sendingFrequency = MailPoet.I18n.t('sendMonthly').replace(
|
||||||
|
'%$1s', monthDayValues[newsletter.options.monthDay]
|
||||||
|
).replace(
|
||||||
|
'%$2s', timeOfDayValues[newsletter.options.timeOfDay]
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'nthWeekDay':
|
||||||
|
sendingFrequency = MailPoet.I18n.t('sendNthWeekDay').replace(
|
||||||
|
'%$1s', nthWeekDayValues[newsletter.options.nthWeekDay]
|
||||||
|
).replace(
|
||||||
|
'%$2s', weekDayValues[newsletter.options.weekDay]
|
||||||
|
).replace(
|
||||||
|
'%$3s', timeOfDayValues[newsletter.options.timeOfDay]
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'immediately':
|
||||||
|
sendingFrequency = MailPoet.I18n.t('sendImmediately');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
{ sendingFrequency } { sendingToSegments }
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
renderHistoryLink: function(newsletter) {
|
||||||
|
const childrenCount = ~~(newsletter.children_count);
|
||||||
|
if (childrenCount === 0) {
|
||||||
|
return (
|
||||||
|
MailPoet.I18n.t('notSentYet')
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
to={ `/notification/history/${ newsletter.id }` }
|
||||||
|
>{ MailPoet.I18n.t('viewHistory') }</Link>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
renderItem: function(newsletter, actions) {
|
||||||
|
const rowClasses = classNames(
|
||||||
|
'manage-column',
|
||||||
|
'column-primary',
|
||||||
|
'has-row-actions'
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<td className={ rowClasses }>
|
||||||
|
<strong>
|
||||||
|
<a
|
||||||
|
className="row-title"
|
||||||
|
href={ `?page=mailpoet-newsletter-editor&id=${ newsletter.id }` }
|
||||||
|
>{ newsletter.subject }</a>
|
||||||
|
</strong>
|
||||||
|
{ actions }
|
||||||
|
</td>
|
||||||
|
<td className="column" data-colname={ MailPoet.I18n.t('status') }>
|
||||||
|
{ this.renderStatus(newsletter) }
|
||||||
|
</td>
|
||||||
|
<td className="column" data-colname={ MailPoet.I18n.t('settings') }>
|
||||||
|
{ this.renderSettings(newsletter) }
|
||||||
|
</td>
|
||||||
|
<td className="column" data-colname={ MailPoet.I18n.t('history') }>
|
||||||
|
{ this.renderHistoryLink(newsletter) }
|
||||||
|
</td>
|
||||||
|
<td className="column-date" data-colname={ MailPoet.I18n.t('lastModifiedOn') }>
|
||||||
|
<abbr>{ MailPoet.Date.format(newsletter.updated_at) }</abbr>
|
||||||
|
</td>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1 className="title">
|
||||||
|
{MailPoet.I18n.t('pageTitle')} <Link className="page-title-action" to="/new">{MailPoet.I18n.t('new')}</Link>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<ListingTabs tab="notification" />
|
||||||
|
|
||||||
|
<Listing
|
||||||
|
limit={ mailpoet_listing_per_page }
|
||||||
|
location={ this.props.location }
|
||||||
|
params={ this.props.params }
|
||||||
|
endpoint="newsletters"
|
||||||
|
type="notification"
|
||||||
|
base_url="notification"
|
||||||
|
onRenderItem={ this.renderItem }
|
||||||
|
columns={ columns }
|
||||||
|
bulk_actions={ bulk_actions }
|
||||||
|
item_actions={ newsletter_actions }
|
||||||
|
messages={ messages }
|
||||||
|
auto_refresh={ true }
|
||||||
|
sort_by="updated_at"
|
||||||
|
sort_order="desc"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = NewsletterListNotification;
|
125
assets/js/src/newsletters/listings/notification_history.jsx
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { Router, Link } from 'react-router'
|
||||||
|
import classNames from 'classnames'
|
||||||
|
import jQuery from 'jquery'
|
||||||
|
import MailPoet from 'mailpoet'
|
||||||
|
|
||||||
|
import Listing from 'listing/listing.jsx'
|
||||||
|
import ListingTabs from 'newsletters/listings/tabs.jsx'
|
||||||
|
|
||||||
|
import { QueueMixin, StatisticsMixin } from 'newsletters/listings/mixins.jsx'
|
||||||
|
|
||||||
|
const mailpoet_tracking_enabled = (!!(window['mailpoet_tracking_enabled']));
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
name: 'subject',
|
||||||
|
label: MailPoet.I18n.t('subject'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'status',
|
||||||
|
label: MailPoet.I18n.t('status')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'segments',
|
||||||
|
label: MailPoet.I18n.t('lists')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'statistics',
|
||||||
|
label: MailPoet.I18n.t('statistics'),
|
||||||
|
display: mailpoet_tracking_enabled
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'processed_at',
|
||||||
|
label: MailPoet.I18n.t('sentOn'),
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const newsletter_actions = [
|
||||||
|
{
|
||||||
|
name: 'view',
|
||||||
|
link: function(newsletter) {
|
||||||
|
return (
|
||||||
|
<a href={ newsletter.preview_url } target="_blank">
|
||||||
|
{MailPoet.I18n.t('preview')}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const NewsletterListNotificationHistory = React.createClass({
|
||||||
|
mixins: [QueueMixin, StatisticsMixin],
|
||||||
|
renderItem: function(newsletter, actions) {
|
||||||
|
const rowClasses = classNames(
|
||||||
|
'manage-column',
|
||||||
|
'column-primary',
|
||||||
|
'has-row-actions'
|
||||||
|
);
|
||||||
|
|
||||||
|
const segments = newsletter.segments.map(function(segment) {
|
||||||
|
return segment.name
|
||||||
|
}).join(', ');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<td className={ rowClasses }>
|
||||||
|
<strong>
|
||||||
|
<a
|
||||||
|
href={ newsletter.preview_url }
|
||||||
|
target="_blank"
|
||||||
|
>{ newsletter.subject }</a>
|
||||||
|
</strong>
|
||||||
|
{ actions }
|
||||||
|
</td>
|
||||||
|
<td className="column" data-colname={ MailPoet.I18n.t('status') }>
|
||||||
|
{ this.renderQueueStatus(newsletter) }
|
||||||
|
</td>
|
||||||
|
<td className="column" data-colname={ MailPoet.I18n.t('lists') }>
|
||||||
|
{ segments }
|
||||||
|
</td>
|
||||||
|
{ (mailpoet_tracking_enabled === true) ? (
|
||||||
|
<td className="column" data-colname={ MailPoet.I18n.t('statistics') }>
|
||||||
|
{ this.renderStatistics(newsletter) }
|
||||||
|
</td>
|
||||||
|
) : null }
|
||||||
|
<td className="column-date" data-colname={ MailPoet.I18n.t('lastModifiedOn') }>
|
||||||
|
<abbr>{ MailPoet.Date.format(newsletter.updated_at) }</abbr>
|
||||||
|
</td>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1 className="title">
|
||||||
|
{MailPoet.I18n.t('pageTitle')} <Link className="page-title-action" to="/new">{MailPoet.I18n.t('new')}</Link>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<ListingTabs tab="notification" />
|
||||||
|
|
||||||
|
<Link
|
||||||
|
className="page-title-action"
|
||||||
|
to="/notification"
|
||||||
|
>{MailPoet.I18n.t('backToPostNotifications')}</Link>
|
||||||
|
|
||||||
|
<Listing
|
||||||
|
limit={ mailpoet_listing_per_page }
|
||||||
|
location={ this.props.location }
|
||||||
|
params={ this.props.params }
|
||||||
|
endpoint="newsletters"
|
||||||
|
type="notification_history"
|
||||||
|
base_url="notification/history/:parent_id"
|
||||||
|
onRenderItem={ this.renderItem }
|
||||||
|
columns={columns}
|
||||||
|
item_actions={ newsletter_actions }
|
||||||
|
auto_refresh={ true }
|
||||||
|
sort_by="updated_at"
|
||||||
|
sort_order="desc"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = NewsletterListNotificationHistory;
|
221
assets/js/src/newsletters/listings/standard.jsx
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { Router, Link } from 'react-router'
|
||||||
|
import classNames from 'classnames'
|
||||||
|
import jQuery from 'jquery'
|
||||||
|
import MailPoet from 'mailpoet'
|
||||||
|
|
||||||
|
import Listing from 'listing/listing.jsx'
|
||||||
|
import ListingTabs from 'newsletters/listings/tabs.jsx'
|
||||||
|
|
||||||
|
import { QueueMixin, StatisticsMixin } from 'newsletters/listings/mixins.jsx'
|
||||||
|
|
||||||
|
const mailpoet_tracking_enabled = (!!(window['mailpoet_tracking_enabled']));
|
||||||
|
|
||||||
|
const messages = {
|
||||||
|
onTrash: (response) => {
|
||||||
|
const count = ~~response.meta.count;
|
||||||
|
let message = null;
|
||||||
|
|
||||||
|
if (count === 1) {
|
||||||
|
message = (
|
||||||
|
MailPoet.I18n.t('oneNewsletterTrashed')
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
MailPoet.I18n.t('multipleNewslettersTrashed')
|
||||||
|
).replace('%$1d', count.toLocaleString());
|
||||||
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
|
},
|
||||||
|
onDelete: (response) => {
|
||||||
|
const count = ~~response.meta.count;
|
||||||
|
let message = null;
|
||||||
|
|
||||||
|
if (count === 1) {
|
||||||
|
message = (
|
||||||
|
MailPoet.I18n.t('oneNewsletterDeleted')
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
MailPoet.I18n.t('multipleNewslettersDeleted')
|
||||||
|
).replace('%$1d', count.toLocaleString());
|
||||||
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
|
},
|
||||||
|
onRestore: (response) => {
|
||||||
|
const count = ~~response.meta.count;
|
||||||
|
let message = null;
|
||||||
|
|
||||||
|
if (count === 1) {
|
||||||
|
message = (
|
||||||
|
MailPoet.I18n.t('oneNewsletterRestored')
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
MailPoet.I18n.t('multipleNewslettersRestored')
|
||||||
|
).replace('%$1d', count.toLocaleString());
|
||||||
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
name: 'subject',
|
||||||
|
label: MailPoet.I18n.t('subject'),
|
||||||
|
sortable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'status',
|
||||||
|
label: MailPoet.I18n.t('status')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'segments',
|
||||||
|
label: MailPoet.I18n.t('lists')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'statistics',
|
||||||
|
label: MailPoet.I18n.t('statistics'),
|
||||||
|
display: mailpoet_tracking_enabled
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'updated_at',
|
||||||
|
label: MailPoet.I18n.t('lastModifiedOn'),
|
||||||
|
sortable: true
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
const bulk_actions = [
|
||||||
|
{
|
||||||
|
name: 'trash',
|
||||||
|
label: MailPoet.I18n.t('trash'),
|
||||||
|
onSuccess: messages.onTrash
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const newsletter_actions = [
|
||||||
|
{
|
||||||
|
name: 'view',
|
||||||
|
link: function(newsletter) {
|
||||||
|
return (
|
||||||
|
<a href={ newsletter.preview_url } target="_blank">
|
||||||
|
{MailPoet.I18n.t('preview')}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'edit',
|
||||||
|
link: function(newsletter) {
|
||||||
|
return (
|
||||||
|
<a href={ `?page=mailpoet-newsletter-editor&id=${ newsletter.id }` }>
|
||||||
|
{MailPoet.I18n.t('edit')}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'duplicate',
|
||||||
|
label: MailPoet.I18n.t('duplicate'),
|
||||||
|
onClick: function(newsletter, refresh) {
|
||||||
|
return MailPoet.Ajax.post({
|
||||||
|
endpoint: 'newsletters',
|
||||||
|
action: 'duplicate',
|
||||||
|
data: {
|
||||||
|
id: newsletter.id
|
||||||
|
}
|
||||||
|
}).done((response) => {
|
||||||
|
MailPoet.Notice.success(
|
||||||
|
(MailPoet.I18n.t('newsletterDuplicated')).replace(
|
||||||
|
'%$1s', response.data.subject
|
||||||
|
)
|
||||||
|
);
|
||||||
|
refresh();
|
||||||
|
}).fail((response) => {
|
||||||
|
if (response.errors.length > 0) {
|
||||||
|
MailPoet.Notice.error(
|
||||||
|
response.errors.map(function(error) { return error.message; }),
|
||||||
|
{ scroll: true }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'trash'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const NewsletterListStandard = React.createClass({
|
||||||
|
mixins: [QueueMixin, StatisticsMixin],
|
||||||
|
renderItem: function(newsletter, actions) {
|
||||||
|
const rowClasses = classNames(
|
||||||
|
'manage-column',
|
||||||
|
'column-primary',
|
||||||
|
'has-row-actions'
|
||||||
|
);
|
||||||
|
|
||||||
|
const segments = newsletter.segments.map(function(segment) {
|
||||||
|
return segment.name
|
||||||
|
}).join(', ');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<td className={ rowClasses }>
|
||||||
|
<strong>
|
||||||
|
<a
|
||||||
|
className="row-title"
|
||||||
|
href={ `?page=mailpoet-newsletter-editor&id=${ newsletter.id }` }
|
||||||
|
>{ newsletter.subject }</a>
|
||||||
|
</strong>
|
||||||
|
{ actions }
|
||||||
|
</td>
|
||||||
|
<td className="column" data-colname={ MailPoet.I18n.t('status') }>
|
||||||
|
{ this.renderQueueStatus(newsletter) }
|
||||||
|
</td>
|
||||||
|
<td className="column" data-colname={ MailPoet.I18n.t('lists') }>
|
||||||
|
{ segments }
|
||||||
|
</td>
|
||||||
|
{ (mailpoet_tracking_enabled === true) ? (
|
||||||
|
<td className="column" data-colname={ MailPoet.I18n.t('statistics') }>
|
||||||
|
{ this.renderStatistics(newsletter) }
|
||||||
|
</td>
|
||||||
|
) : null }
|
||||||
|
<td className="column-date" data-colname={ MailPoet.I18n.t('lastModifiedOn') }>
|
||||||
|
<abbr>{ MailPoet.Date.format(newsletter.updated_at) }</abbr>
|
||||||
|
</td>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1 className="title">
|
||||||
|
{MailPoet.I18n.t('pageTitle')} <Link className="page-title-action" to="/new">{MailPoet.I18n.t('new')}</Link>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<ListingTabs tab="standard" />
|
||||||
|
|
||||||
|
<Listing
|
||||||
|
limit={ mailpoet_listing_per_page }
|
||||||
|
location={ this.props.location }
|
||||||
|
params={ this.props.params }
|
||||||
|
endpoint="newsletters"
|
||||||
|
type="standard"
|
||||||
|
base_url="standard"
|
||||||
|
onRenderItem={this.renderItem}
|
||||||
|
columns={columns}
|
||||||
|
bulk_actions={ bulk_actions }
|
||||||
|
item_actions={ newsletter_actions }
|
||||||
|
messages={ messages }
|
||||||
|
auto_refresh={ true }
|
||||||
|
sort_by="updated_at"
|
||||||
|
sort_order="desc"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = NewsletterListStandard;
|
53
assets/js/src/newsletters/listings/tabs.jsx
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { Link } from 'react-router'
|
||||||
|
import classNames from 'classnames'
|
||||||
|
import MailPoet from 'mailpoet'
|
||||||
|
|
||||||
|
const ListingTabs = React.createClass({
|
||||||
|
getInitialState() {
|
||||||
|
return {
|
||||||
|
tab: null,
|
||||||
|
tabs: [
|
||||||
|
{
|
||||||
|
name: 'standard',
|
||||||
|
label: MailPoet.I18n.t('tabStandardTitle'),
|
||||||
|
link: '/standard'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'welcome',
|
||||||
|
label: MailPoet.I18n.t('tabWelcomeTitle'),
|
||||||
|
link: '/welcome'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'notification',
|
||||||
|
label: MailPoet.I18n.t('tabNotificationTitle'),
|
||||||
|
link: '/notification'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
const tabs = this.state.tabs.map((tab, index) => {
|
||||||
|
const tabClasses = classNames(
|
||||||
|
'nav-tab',
|
||||||
|
{ 'nav-tab-active': (this.props.tab === tab.name) }
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
key={ 'tab-'+index }
|
||||||
|
className={ tabClasses }
|
||||||
|
to={ tab.link }
|
||||||
|
>{ tab.label }</Link>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<h2 className="nav-tab-wrapper">
|
||||||
|
{ tabs }
|
||||||
|
</h2>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = ListingTabs;
|
367
assets/js/src/newsletters/listings/welcome.jsx
Normal file
@ -0,0 +1,367 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { Router, Route, IndexRoute, Link, useRouterHistory } from 'react-router'
|
||||||
|
import { createHashHistory } from 'history'
|
||||||
|
|
||||||
|
import Listing from 'listing/listing.jsx'
|
||||||
|
import ListingTabs from 'newsletters/listings/tabs.jsx'
|
||||||
|
|
||||||
|
import classNames from 'classnames'
|
||||||
|
import jQuery from 'jquery'
|
||||||
|
import MailPoet from 'mailpoet'
|
||||||
|
import _ from 'underscore'
|
||||||
|
|
||||||
|
const mailpoet_roles = window.mailpoet_roles || {};
|
||||||
|
const mailpoet_segments = window.mailpoet_segments || {};
|
||||||
|
const mailpoet_tracking_enabled = (!!(window['mailpoet_tracking_enabled']));
|
||||||
|
|
||||||
|
const messages = {
|
||||||
|
onTrash: (response) => {
|
||||||
|
const count = ~~response.meta.count;
|
||||||
|
let message = null;
|
||||||
|
|
||||||
|
if (count === 1) {
|
||||||
|
message = (
|
||||||
|
MailPoet.I18n.t('oneNewsletterTrashed')
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
MailPoet.I18n.t('multipleNewslettersTrashed')
|
||||||
|
).replace('%$1d', count.toLocaleString());
|
||||||
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
|
},
|
||||||
|
onDelete: (response) => {
|
||||||
|
const count = ~~response.meta.count;
|
||||||
|
let message = null;
|
||||||
|
|
||||||
|
if (count === 1) {
|
||||||
|
message = (
|
||||||
|
MailPoet.I18n.t('oneNewsletterDeleted')
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
MailPoet.I18n.t('multipleNewslettersDeleted')
|
||||||
|
).replace('%$1d', count.toLocaleString());
|
||||||
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
|
},
|
||||||
|
onRestore: (response) => {
|
||||||
|
const count = ~~response.meta.count;
|
||||||
|
let message = null;
|
||||||
|
|
||||||
|
if (count === 1) {
|
||||||
|
message = (
|
||||||
|
MailPoet.I18n.t('oneNewsletterRestored')
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
message = (
|
||||||
|
MailPoet.I18n.t('multipleNewslettersRestored')
|
||||||
|
).replace('%$1d', count.toLocaleString());
|
||||||
|
}
|
||||||
|
MailPoet.Notice.success(message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
name: 'subject',
|
||||||
|
label: MailPoet.I18n.t('subject'),
|
||||||
|
sortable: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'status',
|
||||||
|
label: MailPoet.I18n.t('status'),
|
||||||
|
width: 145
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'settings',
|
||||||
|
label: MailPoet.I18n.t('settings')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'statistics',
|
||||||
|
label: MailPoet.I18n.t('statistics'),
|
||||||
|
display: mailpoet_tracking_enabled
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'updated_at',
|
||||||
|
label: MailPoet.I18n.t('lastModifiedOn'),
|
||||||
|
sortable: true
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const bulk_actions = [
|
||||||
|
{
|
||||||
|
name: 'trash',
|
||||||
|
label: MailPoet.I18n.t('trash'),
|
||||||
|
onSuccess: messages.onTrash
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const newsletter_actions = [
|
||||||
|
{
|
||||||
|
name: 'view',
|
||||||
|
link: function(newsletter) {
|
||||||
|
return (
|
||||||
|
<a href={ newsletter.preview_url } target="_blank">
|
||||||
|
{MailPoet.I18n.t('preview')}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'edit',
|
||||||
|
link: function(newsletter) {
|
||||||
|
return (
|
||||||
|
<a href={ `?page=mailpoet-newsletter-editor&id=${ newsletter.id }` }>
|
||||||
|
{MailPoet.I18n.t('edit')}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'duplicate',
|
||||||
|
label: MailPoet.I18n.t('duplicate'),
|
||||||
|
onClick: function(newsletter, refresh) {
|
||||||
|
return MailPoet.Ajax.post({
|
||||||
|
endpoint: 'newsletters',
|
||||||
|
action: 'duplicate',
|
||||||
|
data: {
|
||||||
|
id: newsletter.id
|
||||||
|
}
|
||||||
|
}).done((response) => {
|
||||||
|
MailPoet.Notice.success(
|
||||||
|
(MailPoet.I18n.t('newsletterDuplicated')).replace(
|
||||||
|
'%$1s', response.data.subject
|
||||||
|
)
|
||||||
|
);
|
||||||
|
refresh();
|
||||||
|
}).fail((response) => {
|
||||||
|
if (response.errors.length > 0) {
|
||||||
|
MailPoet.Notice.error(
|
||||||
|
response.errors.map(function(error) { return error.message; }),
|
||||||
|
{ scroll: true }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'trash'
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const NewsletterListWelcome = React.createClass({
|
||||||
|
updateStatus: function(e) {
|
||||||
|
// make the event persist so that we can still override the selected value
|
||||||
|
// in the ajax callback
|
||||||
|
e.persist();
|
||||||
|
|
||||||
|
MailPoet.Ajax.post({
|
||||||
|
endpoint: 'newsletters',
|
||||||
|
action: 'setStatus',
|
||||||
|
data: {
|
||||||
|
id: ~~(e.target.getAttribute('data-id')),
|
||||||
|
status: e.target.value
|
||||||
|
}
|
||||||
|
}).done((response) => {
|
||||||
|
if (response.data.status === 'active') {
|
||||||
|
MailPoet.Notice.success(MailPoet.I18n.t('welcomeEmailActivated'));
|
||||||
|
}
|
||||||
|
// force refresh of listing so that groups are updated
|
||||||
|
this.forceUpdate();
|
||||||
|
}).fail((response) => {
|
||||||
|
MailPoet.Notice.error(MailPoet.I18n.t('welcomeEmailActivationFailed'));
|
||||||
|
|
||||||
|
// reset value to actual newsletter's status
|
||||||
|
e.target.value = response.status;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
renderStatus: function(newsletter) {
|
||||||
|
let total_sent;
|
||||||
|
total_sent = (
|
||||||
|
MailPoet.I18n.t('sentToXSubscribers')
|
||||||
|
.replace('%$1d', newsletter.total_sent.toLocaleString())
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
<select
|
||||||
|
data-id={ newsletter.id }
|
||||||
|
defaultValue={ newsletter.status }
|
||||||
|
onChange={ this.updateStatus }
|
||||||
|
>
|
||||||
|
<option value="active">{ MailPoet.I18n.t('active') }</option>
|
||||||
|
<option value="draft">{ MailPoet.I18n.t('inactive') }</option>
|
||||||
|
</select>
|
||||||
|
</p>
|
||||||
|
<p>{ total_sent }</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
renderSettings: function(newsletter) {
|
||||||
|
let sendingEvent;
|
||||||
|
let sendingDelay;
|
||||||
|
|
||||||
|
// set sending event
|
||||||
|
switch (newsletter.options.event) {
|
||||||
|
case 'user':
|
||||||
|
// WP User
|
||||||
|
if (newsletter.options.role === 'mailpoet_all') {
|
||||||
|
sendingEvent = MailPoet.I18n.t('welcomeEventWPUserAnyRole');
|
||||||
|
} else {
|
||||||
|
sendingEvent = MailPoet.I18n.t('welcomeEventWPUserWithRole').replace(
|
||||||
|
'%$1s', mailpoet_roles[newsletter.options.role]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'segment':
|
||||||
|
// get segment
|
||||||
|
const segment = _.find(mailpoet_segments, function(segment) {
|
||||||
|
return (~~(segment.id) === ~~(newsletter.options.segment));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (segment === undefined) {
|
||||||
|
return (
|
||||||
|
<span className="mailpoet_error">
|
||||||
|
{ MailPoet.I18n.t('sendingToSegmentsNotSpecified') }
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
sendingEvent = MailPoet.I18n.t('welcomeEventSegment').replace(
|
||||||
|
'%$1s', segment.name
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set sending delay
|
||||||
|
if (sendingEvent) {
|
||||||
|
if (newsletter.options.afterTimeType !== 'immediate') {
|
||||||
|
switch (newsletter.options.afterTimeType) {
|
||||||
|
case 'hours':
|
||||||
|
sendingDelay = MailPoet.I18n.t('sendingDelayHours').replace(
|
||||||
|
'%$1d', newsletter.options.afterTimeNumber
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'days':
|
||||||
|
sendingDelay = MailPoet.I18n.t('sendingDelayDays').replace(
|
||||||
|
'%$1d', newsletter.options.afterTimeNumber
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'weeks':
|
||||||
|
sendingDelay = MailPoet.I18n.t('sendingDelayWeeks').replace(
|
||||||
|
'%$1d', newsletter.options.afterTimeNumber
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sendingEvent += ' [' + sendingDelay + ']';
|
||||||
|
}
|
||||||
|
// add a "period" at the end if we do have a sendingEvent
|
||||||
|
sendingEvent += '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
{ sendingEvent }
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
renderStatistics: function(newsletter) {
|
||||||
|
if (mailpoet_tracking_enabled === false) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newsletter.total_sent > 0 && newsletter.statistics) {
|
||||||
|
const total_sent = ~~(newsletter.total_sent);
|
||||||
|
|
||||||
|
const percentage_clicked = Math.round(
|
||||||
|
(~~(newsletter.statistics.clicked) * 100) / total_sent
|
||||||
|
);
|
||||||
|
const percentage_opened = Math.round(
|
||||||
|
(~~(newsletter.statistics.opened) * 100) / total_sent
|
||||||
|
);
|
||||||
|
const percentage_unsubscribed = Math.round(
|
||||||
|
(~~(newsletter.statistics.unsubscribed) * 100) / total_sent
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
{ percentage_opened }%, { percentage_clicked }%, { percentage_unsubscribed }%
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
<span>{MailPoet.I18n.t('notSentYet')}</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
renderItem: function(newsletter, actions) {
|
||||||
|
const rowClasses = classNames(
|
||||||
|
'manage-column',
|
||||||
|
'column-primary',
|
||||||
|
'has-row-actions'
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<td className={ rowClasses }>
|
||||||
|
<strong>
|
||||||
|
<a
|
||||||
|
className="row-title"
|
||||||
|
href={ `?page=mailpoet-newsletter-editor&id=${ newsletter.id }` }
|
||||||
|
>{ newsletter.subject }</a>
|
||||||
|
</strong>
|
||||||
|
{ actions }
|
||||||
|
</td>
|
||||||
|
<td className="column" data-colname={ MailPoet.I18n.t('status') }>
|
||||||
|
{ this.renderStatus(newsletter) }
|
||||||
|
</td>
|
||||||
|
<td className="column" data-colname={ MailPoet.I18n.t('settings') }>
|
||||||
|
{ this.renderSettings(newsletter) }
|
||||||
|
</td>
|
||||||
|
{ (mailpoet_tracking_enabled === true) ? (
|
||||||
|
<td className="column" data-colname={ MailPoet.I18n.t('statistics') }>
|
||||||
|
{ this.renderStatistics(newsletter) }
|
||||||
|
</td>
|
||||||
|
) : null }
|
||||||
|
<td className="column-date" data-colname={ MailPoet.I18n.t('lastModifiedOn') }>
|
||||||
|
<abbr>{ MailPoet.Date.format(newsletter.updated_at) }</abbr>
|
||||||
|
</td>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h1 className="title">
|
||||||
|
{ MailPoet.I18n.t('pageTitle') } <Link className="page-title-action" to="/new">{ MailPoet.I18n.t('new') }</Link>
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<ListingTabs tab="welcome" />
|
||||||
|
|
||||||
|
<Listing
|
||||||
|
limit={ mailpoet_listing_per_page }
|
||||||
|
location={ this.props.location }
|
||||||
|
params={ this.props.params }
|
||||||
|
endpoint="newsletters"
|
||||||
|
type="welcome"
|
||||||
|
base_url="welcome"
|
||||||
|
onRenderItem={ this.renderItem }
|
||||||
|
columns={ columns }
|
||||||
|
bulk_actions={ bulk_actions }
|
||||||
|
item_actions={ newsletter_actions }
|
||||||
|
messages={ messages }
|
||||||
|
auto_refresh={ true }
|
||||||
|
sort_by="updated_at"
|
||||||
|
sort_order="desc"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = NewsletterListWelcome;
|
@ -1,20 +1,26 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import { Router, Route, IndexRoute, Link, useRouterHistory } from 'react-router'
|
import { Router, Route, IndexRedirect, Link, useRouterHistory } from 'react-router'
|
||||||
import { createHashHistory } from 'history'
|
import { createHashHistory } from 'history'
|
||||||
import NewsletterList from 'newsletters/list.jsx'
|
|
||||||
import NewsletterTypes from 'newsletters/types.jsx'
|
import NewsletterTypes from 'newsletters/types.jsx'
|
||||||
import NewsletterTemplates from 'newsletters/templates.jsx'
|
import NewsletterTemplates from 'newsletters/templates.jsx'
|
||||||
import NewsletterSend from 'newsletters/send.jsx'
|
import NewsletterSend from 'newsletters/send.jsx'
|
||||||
import NewsletterStandard from 'newsletters/types/standard.jsx'
|
|
||||||
import NewsletterWelcome from 'newsletters/types/welcome/welcome.jsx'
|
import NewsletterTypeStandard from 'newsletters/types/standard.jsx'
|
||||||
import NewsletterNotification from 'newsletters/types/notification/notification.jsx'
|
import NewsletterTypeWelcome from 'newsletters/types/welcome/welcome.jsx'
|
||||||
|
import NewsletterTypeNotification from 'newsletters/types/notification/notification.jsx'
|
||||||
|
|
||||||
|
import NewsletterListStandard from 'newsletters/listings/standard.jsx'
|
||||||
|
import NewsletterListWelcome from 'newsletters/listings/welcome.jsx'
|
||||||
|
import NewsletterListNotification from 'newsletters/listings/notification.jsx'
|
||||||
|
import NewsletterListNotificationHistory from 'newsletters/listings/notification_history.jsx'
|
||||||
|
|
||||||
const history = useRouterHistory(createHashHistory)({ queryKey: false });
|
const history = useRouterHistory(createHashHistory)({ queryKey: false });
|
||||||
|
|
||||||
const App = React.createClass({
|
const App = React.createClass({
|
||||||
render() {
|
render() {
|
||||||
return this.props.children
|
return this.props.children;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -24,15 +30,22 @@ if(container) {
|
|||||||
ReactDOM.render((
|
ReactDOM.render((
|
||||||
<Router history={ history }>
|
<Router history={ history }>
|
||||||
<Route path="/" component={ App }>
|
<Route path="/" component={ App }>
|
||||||
<IndexRoute component={ NewsletterList } />
|
<IndexRedirect to="standard" />
|
||||||
|
{/* Listings */}
|
||||||
|
<Route path="standard(/)**" params={{ tab: 'standard' }} component={ NewsletterListStandard } />
|
||||||
|
<Route path="welcome(/)**" component={ NewsletterListWelcome } />
|
||||||
|
<Route path="notification/history/:parent_id(/)**" component={ NewsletterListNotificationHistory } />
|
||||||
|
<Route path="notification(/)**" component={ NewsletterListNotification } />
|
||||||
|
{/* Newsletter: type selection */}
|
||||||
<Route path="new" component={ NewsletterTypes } />
|
<Route path="new" component={ NewsletterTypes } />
|
||||||
<Route name="standard" path="new/standard" component={ NewsletterStandard } />
|
{/* New newsletter: types */}
|
||||||
<Route name="welcome" path="new/welcome" component={ NewsletterWelcome } />
|
<Route path="new/standard" component={ NewsletterTypeStandard } />
|
||||||
<Route name="notification" path="new/notification" component={ NewsletterNotification } />
|
<Route path="new/welcome" component={ NewsletterTypeWelcome } />
|
||||||
|
<Route path="new/notification" component={ NewsletterTypeNotification } />
|
||||||
|
{/* Template selection */}
|
||||||
<Route name="template" path="template/:id" component={ NewsletterTemplates } />
|
<Route name="template" path="template/:id" component={ NewsletterTemplates } />
|
||||||
|
{/* Sending options */}
|
||||||
<Route path="send/:id" component={ NewsletterSend } />
|
<Route path="send/:id" component={ NewsletterSend } />
|
||||||
<Route path="filter[:filter]" component={ NewsletterList } />
|
|
||||||
<Route path="*" component={ NewsletterList } />
|
|
||||||
</Route>
|
</Route>
|
||||||
</Router>
|
</Router>
|
||||||
), container);
|
), container);
|
||||||
|
82
assets/js/src/newsletters/scheduling/common.jsx
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
import _ from 'underscore'
|
||||||
|
import MailPoet from 'mailpoet'
|
||||||
|
|
||||||
|
const timeFormat = window.mailpoet_time_format || 'H:i';
|
||||||
|
|
||||||
|
// welcome emails
|
||||||
|
const _timeDelayValues = {
|
||||||
|
'immediate': MailPoet.I18n.t('delayImmediately'),
|
||||||
|
'hours': MailPoet.I18n.t('delayHoursAfter'),
|
||||||
|
'days': MailPoet.I18n.t('delayDaysAfter'),
|
||||||
|
'weeks': MailPoet.I18n.t('delayWeeksAfter')
|
||||||
|
};
|
||||||
|
|
||||||
|
const _intervalValues = {
|
||||||
|
'daily': MailPoet.I18n.t('daily'),
|
||||||
|
'weekly': MailPoet.I18n.t('weekly'),
|
||||||
|
'monthly': MailPoet.I18n.t('monthly'),
|
||||||
|
'nthWeekDay': MailPoet.I18n.t('monthlyEvery'),
|
||||||
|
'immediately': MailPoet.I18n.t('immediately')
|
||||||
|
};
|
||||||
|
|
||||||
|
// notification emails
|
||||||
|
const SECONDS_IN_DAY = 86400;
|
||||||
|
const TIME_STEP_SECONDS = 3600;
|
||||||
|
const numberOfTimeSteps = SECONDS_IN_DAY / TIME_STEP_SECONDS;
|
||||||
|
|
||||||
|
const _timeOfDayValues = _.object(_.map(
|
||||||
|
_.times(numberOfTimeSteps,function(step) {
|
||||||
|
return step * TIME_STEP_SECONDS;
|
||||||
|
}), function(seconds) {
|
||||||
|
let date = new Date(null);
|
||||||
|
date.setSeconds(seconds);
|
||||||
|
const timeLabel = MailPoet.Date.format(date, { format: timeFormat, offset: 0 });
|
||||||
|
return [seconds, timeLabel];
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
const _weekDayValues = {
|
||||||
|
0: MailPoet.I18n.t('sunday'),
|
||||||
|
1: MailPoet.I18n.t('monday'),
|
||||||
|
2: MailPoet.I18n.t('tuesday'),
|
||||||
|
3: MailPoet.I18n.t('wednesday'),
|
||||||
|
4: MailPoet.I18n.t('thursday'),
|
||||||
|
5: MailPoet.I18n.t('friday'),
|
||||||
|
6: MailPoet.I18n.t('saturday')
|
||||||
|
};
|
||||||
|
|
||||||
|
const NUMBER_OF_DAYS_IN_MONTH = 28;
|
||||||
|
const _monthDayValues = _.object(
|
||||||
|
_.map(
|
||||||
|
_.times(NUMBER_OF_DAYS_IN_MONTH, function(day) {
|
||||||
|
return day;
|
||||||
|
}), function(day) {
|
||||||
|
const labels = {
|
||||||
|
0: MailPoet.I18n.t('first'),
|
||||||
|
1: MailPoet.I18n.t('second'),
|
||||||
|
2: MailPoet.I18n.t('third')
|
||||||
|
};
|
||||||
|
let label;
|
||||||
|
if (labels[day] !== undefined) {
|
||||||
|
label = labels[day];
|
||||||
|
} else {
|
||||||
|
label = MailPoet.I18n.t('nth').replace("%$1d", day + 1);
|
||||||
|
}
|
||||||
|
return [day + 1, label];
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const _nthWeekDayValues = {
|
||||||
|
'1': MailPoet.I18n.t('first'),
|
||||||
|
'2': MailPoet.I18n.t('second'),
|
||||||
|
'3': MailPoet.I18n.t('third'),
|
||||||
|
'L': MailPoet.I18n.t('last')
|
||||||
|
};
|
||||||
|
|
||||||
|
export { _timeDelayValues as timeDelayValues };
|
||||||
|
export { _intervalValues as intervalValues };
|
||||||
|
export { _timeOfDayValues as timeOfDayValues };
|
||||||
|
export { _weekDayValues as weekDayValues };
|
||||||
|
export { _monthDayValues as monthDayValues };
|
||||||
|
export { _nthWeekDayValues as nthWeekDayValues };
|
@ -34,15 +34,20 @@ define(
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
getFieldsByNewsletter: function(newsletter) {
|
getFieldsByNewsletter: function(newsletter) {
|
||||||
|
var type = this.getSubtype(newsletter);
|
||||||
|
return type.getFields(newsletter);
|
||||||
|
},
|
||||||
|
getSendButtonOptions: function() {
|
||||||
|
var type = this.getSubtype(this.state.item);
|
||||||
|
return type.getSendButtonOptions(this.state.item);
|
||||||
|
},
|
||||||
|
getSubtype: function(newsletter) {
|
||||||
switch(newsletter.type) {
|
switch(newsletter.type) {
|
||||||
case 'notification': return NotificationNewsletterFields;
|
case 'notification': return NotificationNewsletterFields;
|
||||||
case 'welcome': return WelcomeNewsletterFields;
|
case 'welcome': return WelcomeNewsletterFields;
|
||||||
default: return StandardNewsletterFields;
|
default: return StandardNewsletterFields;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
isAutomatedNewsletter: function() {
|
|
||||||
return this.state.item.type !== 'standard';
|
|
||||||
},
|
|
||||||
isValid: function() {
|
isValid: function() {
|
||||||
return jQuery('#mailpoet_newsletter').parsley().isValid();
|
return jQuery('#mailpoet_newsletter').parsley().isValid();
|
||||||
},
|
},
|
||||||
@ -61,22 +66,22 @@ define(
|
|||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
endpoint: 'newsletters',
|
endpoint: 'newsletters',
|
||||||
action: 'get',
|
action: 'get',
|
||||||
data: id
|
data: {
|
||||||
}).done((response) => {
|
id: id
|
||||||
if(response === false) {
|
|
||||||
this.setState({
|
|
||||||
loading: false,
|
|
||||||
item: {},
|
|
||||||
}, function() {
|
|
||||||
this.context.router.push('/new');
|
|
||||||
}.bind(this));
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
loading: false,
|
|
||||||
item: response,
|
|
||||||
fields: this.getFieldsByNewsletter(response),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
}).done((response) => {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
item: response.data,
|
||||||
|
fields: this.getFieldsByNewsletter(response.data)
|
||||||
|
});
|
||||||
|
}).fail((response) => {
|
||||||
|
this.setState({
|
||||||
|
loading: false,
|
||||||
|
item: {}
|
||||||
|
}, () => {
|
||||||
|
this.context.router.push('/new');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleSend: function(e) {
|
handleSend: function(e) {
|
||||||
@ -85,65 +90,110 @@ define(
|
|||||||
if(!this.isValid()) {
|
if(!this.isValid()) {
|
||||||
jQuery('#mailpoet_newsletter').parsley().validate();
|
jQuery('#mailpoet_newsletter').parsley().validate();
|
||||||
} else {
|
} else {
|
||||||
this.setState({ loading: true });
|
this._save(e).done(() => {
|
||||||
|
this.setState({ loading: true });
|
||||||
MailPoet.Ajax.post({
|
|
||||||
endpoint: 'newsletters',
|
|
||||||
action: 'save',
|
|
||||||
data: this.state.item,
|
|
||||||
}).then((response) => {
|
|
||||||
if (response.result === true) {
|
|
||||||
return MailPoet.Ajax.post({
|
|
||||||
endpoint: 'sendingQueue',
|
|
||||||
action: 'add',
|
|
||||||
data: _.extend({}, this.state.item, {
|
|
||||||
newsletter_id: this.props.params.id,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return response;
|
|
||||||
}
|
|
||||||
}).done((response) => {
|
}).done((response) => {
|
||||||
this.setState({ loading: false });
|
switch (response.data.type) {
|
||||||
if(response.result === true) {
|
case 'notification':
|
||||||
this.context.router.push('/');
|
case 'welcome':
|
||||||
MailPoet.Notice.success(response.data.message);
|
return MailPoet.Ajax.post({
|
||||||
} else {
|
endpoint: 'newsletters',
|
||||||
if(response.errors) {
|
action: 'setStatus',
|
||||||
MailPoet.Notice.error(response.errors);
|
data: {
|
||||||
} else {
|
id: this.props.params.id,
|
||||||
MailPoet.Notice.error(
|
status: 'active'
|
||||||
MailPoet.I18n.t('newsletterSendingError').replace("%$1s", '?page=mailpoet-settings')
|
}
|
||||||
);
|
}).done((response) => {
|
||||||
}
|
// redirect to listing based on newsletter type
|
||||||
|
this.context.router.push(`/${ this.state.item.type || '' }`);
|
||||||
|
|
||||||
|
// display success message depending on newsletter type
|
||||||
|
if (response.data.type === 'welcome') {
|
||||||
|
MailPoet.Notice.success(
|
||||||
|
MailPoet.I18n.t('welcomeEmailActivated')
|
||||||
|
);
|
||||||
|
} else if (response.data.type === 'notification') {
|
||||||
|
MailPoet.Notice.success(
|
||||||
|
MailPoet.I18n.t('postNotificationActivated')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}).fail(this._showError);
|
||||||
|
default:
|
||||||
|
return MailPoet.Ajax.post({
|
||||||
|
endpoint: 'sendingQueue',
|
||||||
|
action: 'add',
|
||||||
|
data: {
|
||||||
|
newsletter_id: this.props.params.id
|
||||||
|
}
|
||||||
|
}).done((response) => {
|
||||||
|
// redirect to listing based on newsletter type
|
||||||
|
this.context.router.push(`/${ this.state.item.type || '' }`);
|
||||||
|
|
||||||
|
if (response.data.status === 'scheduled') {
|
||||||
|
MailPoet.Notice.success(
|
||||||
|
MailPoet.I18n.t('newsletterHasBeenScheduled')
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
MailPoet.Notice.success(
|
||||||
|
MailPoet.I18n.t('newsletterBeingSent')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}).fail(this._showError);
|
||||||
}
|
}
|
||||||
|
}).fail(this._showError).always(() => {
|
||||||
|
this.setState({ loading: false });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
handleSave: function(e) {
|
handleSave: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
this._save(e).done((response) => {
|
||||||
|
MailPoet.Notice.success(
|
||||||
|
MailPoet.I18n.t('newsletterUpdated')
|
||||||
|
);
|
||||||
|
}).done(() => {
|
||||||
|
this.context.router.push(`/${ this.state.item.type || '' }`);
|
||||||
|
}).fail(this._showError);
|
||||||
|
},
|
||||||
|
handleRedirectToDesign: function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var redirectTo = e.target.href;
|
||||||
|
|
||||||
|
this._save(e).done((response) => {
|
||||||
|
MailPoet.Notice.success(
|
||||||
|
MailPoet.I18n.t('newsletterUpdated')
|
||||||
|
);
|
||||||
|
}).done(() => {
|
||||||
|
window.location = redirectTo;
|
||||||
|
}).fail(this._showError);
|
||||||
|
},
|
||||||
|
_save: function(e) {
|
||||||
|
var data = this.state.item;
|
||||||
this.setState({ loading: true });
|
this.setState({ loading: true });
|
||||||
|
|
||||||
MailPoet.Ajax.post({
|
// Ensure that body is JSON encoded
|
||||||
|
if (!_.isUndefined(data.body)) {
|
||||||
|
data.body = JSON.stringify(data.body);
|
||||||
|
}
|
||||||
|
|
||||||
|
return MailPoet.Ajax.post({
|
||||||
endpoint: 'newsletters',
|
endpoint: 'newsletters',
|
||||||
action: 'save',
|
action: 'save',
|
||||||
data: this.state.item,
|
data: data,
|
||||||
}).done((response) => {
|
}).always(() => {
|
||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
|
|
||||||
if(response.result === true) {
|
|
||||||
this.context.router.push('/');
|
|
||||||
MailPoet.Notice.success(
|
|
||||||
MailPoet.I18n.t('newsletterUpdated')
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
if(response.errors) {
|
|
||||||
MailPoet.Notice.error(response.errors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
_showError: (response) => {
|
||||||
|
if (response.errors.length > 0) {
|
||||||
|
MailPoet.Notice.error(
|
||||||
|
response.errors.map(function(error) { return error.message; }),
|
||||||
|
{ scroll: true }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
handleFormChange: function(e) {
|
handleFormChange: function(e) {
|
||||||
var item = this.state.item,
|
var item = this.state.item,
|
||||||
field = e.target.name;
|
field = e.target.name;
|
||||||
@ -175,10 +225,9 @@ define(
|
|||||||
className="button button-primary"
|
className="button button-primary"
|
||||||
type="button"
|
type="button"
|
||||||
onClick={ this.handleSend }
|
onClick={ this.handleSend }
|
||||||
value={
|
value={MailPoet.I18n.t('send')}
|
||||||
this.isAutomatedNewsletter()
|
{...this.getSendButtonOptions()}
|
||||||
? MailPoet.I18n.t('activate')
|
/>
|
||||||
: MailPoet.I18n.t('send')} />
|
|
||||||
|
|
||||||
<input
|
<input
|
||||||
className="button button-secondary"
|
className="button button-secondary"
|
||||||
@ -188,7 +237,8 @@ define(
|
|||||||
<a
|
<a
|
||||||
href={
|
href={
|
||||||
'?page=mailpoet-newsletter-editor&id='+this.props.params.id
|
'?page=mailpoet-newsletter-editor&id='+this.props.params.id
|
||||||
}>
|
}
|
||||||
|
onClick={this.handleRedirectToDesign}>
|
||||||
{MailPoet.I18n.t('goBackToDesign')}
|
{MailPoet.I18n.t('goBackToDesign')}
|
||||||
</a>.
|
</a>.
|
||||||
</p>
|
</p>
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
define(
|
define(
|
||||||
[
|
[
|
||||||
'mailpoet',
|
'mailpoet',
|
||||||
'newsletters/types/notification/scheduling.jsx'
|
'newsletters/types/notification/scheduling.jsx',
|
||||||
|
'underscore'
|
||||||
],
|
],
|
||||||
function(
|
function(
|
||||||
MailPoet,
|
MailPoet,
|
||||||
Scheduling
|
Scheduling,
|
||||||
|
_
|
||||||
) {
|
) {
|
||||||
|
|
||||||
var settings = window.mailpoet_settings || {};
|
var settings = window.mailpoet_settings || {};
|
||||||
@ -23,7 +25,7 @@ define(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'options',
|
name: 'options',
|
||||||
label: MailPoet.I18n.t('selectPeriodicity'),
|
label: MailPoet.I18n.t('selectFrequency'),
|
||||||
type: 'reactComponent',
|
type: 'reactComponent',
|
||||||
component: Scheduling,
|
component: Scheduling,
|
||||||
},
|
},
|
||||||
@ -40,11 +42,15 @@ define(
|
|||||||
return !!(!segment.deleted_at);
|
return !!(!segment.deleted_at);
|
||||||
},
|
},
|
||||||
getLabel: function(segment) {
|
getLabel: function(segment) {
|
||||||
var name = segment.name;
|
return segment.name + ' (' + parseInt(segment.subscribers).toLocaleString() + ')';
|
||||||
if (segment.subscribers > 0) {
|
},
|
||||||
name += ' (%$1s)'.replace('%$1s', parseInt(segment.subscribers).toLocaleString());
|
transformChangedValue: function(segment_ids) {
|
||||||
}
|
var all_segments = this.state.items;
|
||||||
return name;
|
return _.map(segment_ids, function(id) {
|
||||||
|
return _.find(all_segments, function(segment) {
|
||||||
|
return segment.id === id;
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
validation: {
|
validation: {
|
||||||
'data-parsley-required': true,
|
'data-parsley-required': true,
|
||||||
@ -95,6 +101,15 @@ define(
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
return fields;
|
return {
|
||||||
|
getFields: function(newsletter) {
|
||||||
|
return fields;
|
||||||
|
},
|
||||||
|
getSendButtonOptions: function(newsletter) {
|
||||||
|
return {
|
||||||
|
value: MailPoet.I18n.t('activate')
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -253,7 +253,13 @@ define(
|
|||||||
|
|
||||||
var StandardScheduling = React.createClass({
|
var StandardScheduling = React.createClass({
|
||||||
_getCurrentValue: function() {
|
_getCurrentValue: function() {
|
||||||
return this.props.item[this.props.field.name] || {};
|
return _.defaults(
|
||||||
|
this.props.item[this.props.field.name] || {},
|
||||||
|
{
|
||||||
|
isScheduled: '0',
|
||||||
|
scheduledAt: defaultDateTime
|
||||||
|
}
|
||||||
|
);
|
||||||
},
|
},
|
||||||
handleValueChange: function(event) {
|
handleValueChange: function(event) {
|
||||||
var oldValue = this._getCurrentValue(),
|
var oldValue = this._getCurrentValue(),
|
||||||
@ -290,7 +296,7 @@ define(
|
|||||||
<DateTime
|
<DateTime
|
||||||
name="scheduledAt"
|
name="scheduledAt"
|
||||||
value={this._getCurrentValue().scheduledAt}
|
value={this._getCurrentValue().scheduledAt}
|
||||||
onChange={this.handleValueChange}
|
onChange={this.handleValueChange}
|
||||||
dateValidation={this.getDateValidation()} />
|
dateValidation={this.getDateValidation()} />
|
||||||
|
|
||||||
<span>
|
<span>
|
||||||
@ -340,11 +346,15 @@ define(
|
|||||||
return !!(!segment.deleted_at);
|
return !!(!segment.deleted_at);
|
||||||
},
|
},
|
||||||
getLabel: function(segment) {
|
getLabel: function(segment) {
|
||||||
var name = segment.name;
|
return segment.name + ' (' + parseInt(segment.subscribers).toLocaleString() + ')';
|
||||||
if (segment.subscribers > 0) {
|
},
|
||||||
name += ' (%$1s)'.replace('%$1s', parseInt(segment.subscribers).toLocaleString());
|
transformChangedValue: function(segment_ids) {
|
||||||
}
|
var all_segments = this.state.items;
|
||||||
return name;
|
return _.map(segment_ids, function(id) {
|
||||||
|
return _.find(all_segments, function(segment) {
|
||||||
|
return segment.id === id;
|
||||||
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
validation: {
|
validation: {
|
||||||
'data-parsley-required': true,
|
'data-parsley-required': true,
|
||||||
@ -401,6 +411,30 @@ define(
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
return fields;
|
return {
|
||||||
|
getFields: function(newsletter) {
|
||||||
|
return fields;
|
||||||
|
},
|
||||||
|
getSendButtonOptions: function(newsletter) {
|
||||||
|
newsletter = newsletter || {};
|
||||||
|
|
||||||
|
let isScheduled = (
|
||||||
|
typeof newsletter.options === 'object'
|
||||||
|
&& newsletter.options.isScheduled === '1'
|
||||||
|
);
|
||||||
|
let options = {
|
||||||
|
value: (isScheduled
|
||||||
|
? MailPoet.I18n.t('schedule')
|
||||||
|
: MailPoet.I18n.t('send'))
|
||||||
|
};
|
||||||
|
|
||||||
|
if (newsletter.status === 'sent'
|
||||||
|
|| newsletter.status === 'sending') {
|
||||||
|
options['disabled'] = 'disabled';
|
||||||
|
}
|
||||||
|
|
||||||
|
return options;
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -71,7 +71,16 @@ define(
|
|||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
return fields;
|
return {
|
||||||
|
getFields: function(newsletter) {
|
||||||
|
return fields;
|
||||||
|
},
|
||||||
|
getSendButtonOptions: function(newsletter) {
|
||||||
|
return {
|
||||||
|
value: MailPoet.I18n.t('activate')
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -30,33 +30,35 @@ define(
|
|||||||
endpoint: 'newsletterTemplates',
|
endpoint: 'newsletterTemplates',
|
||||||
action: 'save',
|
action: 'save',
|
||||||
data: template
|
data: template
|
||||||
}).done(function(response) {
|
}).always(function() {
|
||||||
MailPoet.Modal.loading(false);
|
MailPoet.Modal.loading(false);
|
||||||
if(response.result === true) {
|
}).done((response) => {
|
||||||
this.props.onImport(template);
|
this.props.onImport(response.data);
|
||||||
} else {
|
}).fail((response) => {
|
||||||
response.map(function(error) {
|
if (response.errors.length > 0) {
|
||||||
MailPoet.Notice.error(error);
|
MailPoet.Notice.error(
|
||||||
});
|
response.errors.map(function(error) { return error.message; }),
|
||||||
|
{ scroll: true }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}.bind(this));
|
});
|
||||||
},
|
},
|
||||||
handleSubmit: function(e) {
|
handleSubmit: function(e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
if (_.size(this.refs.templateFile.files) <= 0) return false;
|
if (_.size(this.refs.templateFile.files) <= 0) return false;
|
||||||
|
|
||||||
var file = _.first(this.refs.templateFile.files),
|
var file = _.first(this.refs.templateFile.files);
|
||||||
reader = new FileReader(),
|
var reader = new FileReader();
|
||||||
saveTemplate = this.saveTemplate;
|
var saveTemplate = this.saveTemplate;
|
||||||
|
|
||||||
reader.onload = function(e) {
|
reader.onload = (e) => {
|
||||||
try {
|
try {
|
||||||
saveTemplate(JSON.parse(e.target.result));
|
saveTemplate(JSON.parse(e.target.result));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
MailPoet.Notice.error(MailPoet.I18n.t('templateFileMalformedError'));
|
MailPoet.Notice.error(MailPoet.I18n.t('templateFileMalformedError'));
|
||||||
}
|
}
|
||||||
}.bind(this);
|
};
|
||||||
|
|
||||||
reader.readAsText(file);
|
reader.readAsText(file);
|
||||||
},
|
},
|
||||||
@ -97,12 +99,12 @@ define(
|
|||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
endpoint: 'newsletterTemplates',
|
endpoint: 'newsletterTemplates',
|
||||||
action: 'getAll',
|
action: 'getAll',
|
||||||
}).done(function(response) {
|
}).always(() => {
|
||||||
MailPoet.Modal.loading(false);
|
MailPoet.Modal.loading(false);
|
||||||
if(this.isMounted()) {
|
}).done((response) => {
|
||||||
|
if (this.isMounted()) {
|
||||||
if(response.length === 0) {
|
if (response.data.length === 0) {
|
||||||
response = [
|
response.data = [
|
||||||
{
|
{
|
||||||
name:
|
name:
|
||||||
MailPoet.I18n.t('mailpoetGuideTemplateTitle'),
|
MailPoet.I18n.t('mailpoetGuideTemplateTitle'),
|
||||||
@ -110,14 +112,14 @@ define(
|
|||||||
MailPoet.I18n.t('mailpoetGuideTemplateDescription'),
|
MailPoet.I18n.t('mailpoetGuideTemplateDescription'),
|
||||||
readonly: "1"
|
readonly: "1"
|
||||||
}
|
}
|
||||||
]
|
];
|
||||||
}
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
templates: response,
|
templates: response.data,
|
||||||
loading: false
|
loading: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}.bind(this));
|
});
|
||||||
},
|
},
|
||||||
handleSelectTemplate: function(template) {
|
handleSelectTemplate: function(template) {
|
||||||
var body = template.body;
|
var body = template.body;
|
||||||
@ -134,19 +136,17 @@ define(
|
|||||||
id: this.props.params.id,
|
id: this.props.params.id,
|
||||||
body: body
|
body: body
|
||||||
}
|
}
|
||||||
}).done(function(response) {
|
}).done((response) => {
|
||||||
if(response.result === true) {
|
// TODO: Move this URL elsewhere
|
||||||
// TODO: Move this URL elsewhere
|
window.location = 'admin.php?page=mailpoet-newsletter-editor&id=' + response.data.id;
|
||||||
window.location = 'admin.php?page=mailpoet-newsletter-editor&id=' + this.props.params.id;
|
}).fail((response) => {
|
||||||
} else {
|
if (response.errors.length > 0) {
|
||||||
response.errors.map(function(error) {
|
MailPoet.Notice.error(
|
||||||
MailPoet.Notice.error(error);
|
response.errors.map(function(error) { return error.message; }),
|
||||||
});
|
{ scroll: true }
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}.bind(this));
|
});
|
||||||
},
|
|
||||||
handlePreviewTemplate: function(template) {
|
|
||||||
console.log('preview template #'+template.id);
|
|
||||||
},
|
},
|
||||||
handleDeleteTemplate: function(template) {
|
handleDeleteTemplate: function(template) {
|
||||||
this.setState({ loading: true });
|
this.setState({ loading: true });
|
||||||
@ -160,10 +160,12 @@ define(
|
|||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
endpoint: 'newsletterTemplates',
|
endpoint: 'newsletterTemplates',
|
||||||
action: 'delete',
|
action: 'delete',
|
||||||
data: template.id
|
data: {
|
||||||
}).done(function(response) {
|
id: template.id
|
||||||
|
}
|
||||||
|
}).done((response) => {
|
||||||
this.getTemplates();
|
this.getTemplates();
|
||||||
}.bind(this));
|
});
|
||||||
} else {
|
} else {
|
||||||
this.setState({ loading: false });
|
this.setState({ loading: false });
|
||||||
}
|
}
|
||||||
@ -172,7 +174,7 @@ define(
|
|||||||
MailPoet.Modal.popup({
|
MailPoet.Modal.popup({
|
||||||
title: template.name,
|
title: template.name,
|
||||||
template: '<div class="mailpoet_boxes_preview" style="background-color: {{ body.globalStyles.body.backgroundColor }}"><img src="{{ thumbnail }}" /></div>',
|
template: '<div class="mailpoet_boxes_preview" style="background-color: {{ body.globalStyles.body.backgroundColor }}"><img src="{{ thumbnail }}" /></div>',
|
||||||
data: template,
|
data: template
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleTemplateImport: function() {
|
handleTemplateImport: function() {
|
||||||
@ -213,20 +215,19 @@ define(
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mailpoet_actions">
|
<div className="mailpoet_actions">
|
||||||
|
<a
|
||||||
|
className="button button-secondary"
|
||||||
|
onClick={ this.handleShowTemplate.bind(null, template) }
|
||||||
|
>
|
||||||
|
{MailPoet.I18n.t('preview')}
|
||||||
|
</a>
|
||||||
|
|
||||||
<a
|
<a
|
||||||
className="button button-primary"
|
className="button button-primary"
|
||||||
onClick={ this.handleSelectTemplate.bind(null, template) }
|
onClick={ this.handleSelectTemplate.bind(null, template) }
|
||||||
>
|
>
|
||||||
{MailPoet.I18n.t('select')}
|
{MailPoet.I18n.t('select')}
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a
|
|
||||||
style={ { display: 'none' }}
|
|
||||||
className="button button-secondary"
|
|
||||||
onClick={ this.handlePreviewTemplate.bind(null, template) }
|
|
||||||
>
|
|
||||||
{MailPoet.I18n.t('preview')}
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
{ (template.readonly === "1") ? false : deleteLink }
|
{ (template.readonly === "1") ? false : deleteLink }
|
||||||
</li>
|
</li>
|
||||||
|
@ -28,17 +28,16 @@ define(
|
|||||||
type: type,
|
type: type,
|
||||||
subject: MailPoet.I18n.t('draftNewsletterTitle'),
|
subject: MailPoet.I18n.t('draftNewsletterTitle'),
|
||||||
}
|
}
|
||||||
}).done(function(response) {
|
}).done((response) => {
|
||||||
if(response.result && response.newsletter.id) {
|
this.context.router.push(`/template/${response.data.id}`);
|
||||||
this.context.router.push(`/template/${response.newsletter.id}`);
|
}).fail((response) => {
|
||||||
} else {
|
if (response.errors.length > 0) {
|
||||||
if(response.errors.length > 0) {
|
MailPoet.Notice.error(
|
||||||
response.errors.map(function(error) {
|
response.errors.map(function(error) { return error.message; }),
|
||||||
MailPoet.Notice.error(error);
|
{ scroll: true }
|
||||||
});
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}.bind(this));
|
});
|
||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
return (
|
return (
|
||||||
|
@ -18,7 +18,6 @@ define(
|
|||||||
|
|
||||||
var field = {
|
var field = {
|
||||||
name: 'options',
|
name: 'options',
|
||||||
label: 'Periodicity',
|
|
||||||
type: 'reactComponent',
|
type: 'reactComponent',
|
||||||
component: Scheduling,
|
component: Scheduling,
|
||||||
};
|
};
|
||||||
@ -51,17 +50,16 @@ define(
|
|||||||
type: 'notification',
|
type: 'notification',
|
||||||
subject: MailPoet.I18n.t('draftNewsletterTitle'),
|
subject: MailPoet.I18n.t('draftNewsletterTitle'),
|
||||||
}),
|
}),
|
||||||
}).done(function(response) {
|
}).done((response) => {
|
||||||
if(response.result && response.newsletter.id) {
|
this.showTemplateSelection(response.data.id);
|
||||||
this.showTemplateSelection(response.newsletter.id);
|
}).fail((response) => {
|
||||||
} else {
|
if (response.errors.length > 0) {
|
||||||
if(response.errors.length > 0) {
|
MailPoet.Notice.error(
|
||||||
response.errors.map(function(error) {
|
response.errors.map(function(error) { return error.message; }),
|
||||||
MailPoet.Notice.error(error);
|
{ scroll: true }
|
||||||
});
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}.bind(this));
|
});
|
||||||
},
|
},
|
||||||
showTemplateSelection: function(newsletterId) {
|
showTemplateSelection: function(newsletterId) {
|
||||||
this.context.router.push(`/template/${newsletterId}`);
|
this.context.router.push(`/template/${newsletterId}`);
|
||||||
@ -72,7 +70,7 @@ define(
|
|||||||
<h1>{MailPoet.I18n.t('postNotificationNewsletterTypeTitle')}</h1>
|
<h1>{MailPoet.I18n.t('postNotificationNewsletterTypeTitle')}</h1>
|
||||||
<Breadcrumb step="type" />
|
<Breadcrumb step="type" />
|
||||||
|
|
||||||
<h3>{MailPoet.I18n.t('selectPeriodicity')}</h3>
|
<h3>{MailPoet.I18n.t('selectFrequency')}</h3>
|
||||||
|
|
||||||
<Scheduling
|
<Scheduling
|
||||||
item={this.state}
|
item={this.state}
|
||||||
|
@ -1,200 +1,143 @@
|
|||||||
define(
|
import _ from 'underscore'
|
||||||
[
|
import React from 'react'
|
||||||
'underscore',
|
import Select from 'form/fields/select.jsx'
|
||||||
'react',
|
import {
|
||||||
'react-router',
|
intervalValues,
|
||||||
'mailpoet',
|
timeOfDayValues,
|
||||||
'form/fields/select.jsx'
|
weekDayValues,
|
||||||
],
|
monthDayValues,
|
||||||
function(
|
nthWeekDayValues
|
||||||
_,
|
} from 'newsletters/scheduling/common.jsx'
|
||||||
React,
|
|
||||||
Router,
|
|
||||||
MailPoet,
|
|
||||||
Select
|
|
||||||
) {
|
|
||||||
|
|
||||||
var intervalField = {
|
const intervalField = {
|
||||||
name: 'intervalType',
|
name: 'intervalType',
|
||||||
values: {
|
values: intervalValues
|
||||||
'daily': MailPoet.I18n.t('daily'),
|
};
|
||||||
'weekly': MailPoet.I18n.t('weekly'),
|
|
||||||
'monthly': MailPoet.I18n.t('monthly'),
|
|
||||||
'nthWeekDay': MailPoet.I18n.t('monthlyEvery'),
|
|
||||||
'immediately': MailPoet.I18n.t('immediately'),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
var SECONDS_IN_DAY = 86400;
|
const timeOfDayField = {
|
||||||
var TIME_STEP_SECONDS = 3600; // Default: 3600
|
name: 'timeOfDay',
|
||||||
var numberOfTimeSteps = SECONDS_IN_DAY / TIME_STEP_SECONDS;
|
values: timeOfDayValues
|
||||||
var timeOfDayValues = _.object(_.map(
|
};
|
||||||
_.times(numberOfTimeSteps, function(step) { return step * TIME_STEP_SECONDS; }),
|
|
||||||
function(seconds) {
|
const weekDayField = {
|
||||||
var date = new Date(null);
|
name: 'weekDay',
|
||||||
date.setSeconds(seconds);
|
values: weekDayValues
|
||||||
var timeLabel = date.toISOString().substr(11, 5);
|
};
|
||||||
return [seconds, timeLabel];
|
|
||||||
|
const monthDayField = {
|
||||||
|
name: 'monthDay',
|
||||||
|
values: monthDayValues
|
||||||
|
};
|
||||||
|
|
||||||
|
const nthWeekDayField = {
|
||||||
|
name: 'nthWeekDay',
|
||||||
|
values: nthWeekDayValues
|
||||||
|
};
|
||||||
|
|
||||||
|
const NotificationScheduling = React.createClass({
|
||||||
|
_getCurrentValue: function() {
|
||||||
|
return (this.props.item[this.props.field.name] || {});
|
||||||
|
},
|
||||||
|
handleValueChange: function(name, value) {
|
||||||
|
const oldValue = this._getCurrentValue();
|
||||||
|
let newValue = {};
|
||||||
|
|
||||||
|
newValue[name] = value;
|
||||||
|
|
||||||
|
return this.props.onValueChange({
|
||||||
|
target: {
|
||||||
|
name: this.props.field.name,
|
||||||
|
value: _.extend({}, oldValue, newValue)
|
||||||
}
|
}
|
||||||
));
|
|
||||||
var timeOfDayField = {
|
|
||||||
name: 'timeOfDay',
|
|
||||||
values: timeOfDayValues,
|
|
||||||
};
|
|
||||||
|
|
||||||
var weekDayField = {
|
|
||||||
name: 'weekDay',
|
|
||||||
values: {
|
|
||||||
0: MailPoet.I18n.t('sunday'),
|
|
||||||
1: MailPoet.I18n.t('monday'),
|
|
||||||
2: MailPoet.I18n.t('tuesday'),
|
|
||||||
3: MailPoet.I18n.t('wednesday'),
|
|
||||||
4: MailPoet.I18n.t('thursday'),
|
|
||||||
5: MailPoet.I18n.t('friday'),
|
|
||||||
6: MailPoet.I18n.t('saturday')
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
var NUMBER_OF_DAYS_IN_MONTH = 28; // 28 for compatibility with MP2
|
|
||||||
var monthDayField = {
|
|
||||||
name: 'monthDay',
|
|
||||||
values: _.object(_.map(
|
|
||||||
_.times(NUMBER_OF_DAYS_IN_MONTH, function(day) { return day; }),
|
|
||||||
function(day) {
|
|
||||||
var labels = {
|
|
||||||
0: MailPoet.I18n.t('first'),
|
|
||||||
1: MailPoet.I18n.t('second'),
|
|
||||||
2: MailPoet.I18n.t('third')
|
|
||||||
},
|
|
||||||
label;
|
|
||||||
if (labels[day] !== undefined) {
|
|
||||||
label = labels[day];
|
|
||||||
} else {
|
|
||||||
label = MailPoet.I18n.t('nth').replace("%$1d", day + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [day, label];
|
|
||||||
},
|
|
||||||
)),
|
|
||||||
};
|
|
||||||
|
|
||||||
var nthWeekDayField = {
|
|
||||||
name: 'nthWeekDay',
|
|
||||||
values: {
|
|
||||||
'1': MailPoet.I18n.t('first'),
|
|
||||||
'2': MailPoet.I18n.t('second'),
|
|
||||||
'3': MailPoet.I18n.t('third'),
|
|
||||||
'L': MailPoet.I18n.t('last'),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
var NotificationScheduling = React.createClass({
|
|
||||||
_getCurrentValue: function() {
|
|
||||||
return this.props.item[this.props.field.name] || {};
|
|
||||||
},
|
|
||||||
handleValueChange: function(name, value) {
|
|
||||||
var oldValue = this._getCurrentValue(),
|
|
||||||
newValue = {};
|
|
||||||
newValue[name] = value;
|
|
||||||
|
|
||||||
return this.props.onValueChange({
|
|
||||||
target: {
|
|
||||||
name: this.props.field.name,
|
|
||||||
value: _.extend({}, oldValue, newValue)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleIntervalChange: function(event) {
|
|
||||||
return this.handleValueChange(
|
|
||||||
'intervalType',
|
|
||||||
event.target.value
|
|
||||||
);
|
|
||||||
},
|
|
||||||
handleTimeOfDayChange: function(event) {
|
|
||||||
return this.handleValueChange(
|
|
||||||
'timeOfDay',
|
|
||||||
event.target.value
|
|
||||||
);
|
|
||||||
},
|
|
||||||
handleWeekDayChange: function(event) {
|
|
||||||
return this.handleValueChange(
|
|
||||||
'weekDay',
|
|
||||||
event.target.value
|
|
||||||
);
|
|
||||||
},
|
|
||||||
handleMonthDayChange: function(event) {
|
|
||||||
return this.handleValueChange(
|
|
||||||
'monthDay',
|
|
||||||
event.target.value
|
|
||||||
);
|
|
||||||
},
|
|
||||||
handleNthWeekDayChange: function(event) {
|
|
||||||
return this.handleValueChange(
|
|
||||||
'nthWeekDay',
|
|
||||||
event.target.value
|
|
||||||
);
|
|
||||||
},
|
|
||||||
render: function() {
|
|
||||||
var value = this._getCurrentValue(),
|
|
||||||
timeOfDaySelection,
|
|
||||||
weekDaySelection,
|
|
||||||
monthDaySelection,
|
|
||||||
nthWeekDaySelection;
|
|
||||||
|
|
||||||
|
|
||||||
if (value.intervalType !== 'immediately') {
|
|
||||||
timeOfDaySelection = (
|
|
||||||
<Select
|
|
||||||
field={timeOfDayField}
|
|
||||||
item={this._getCurrentValue()}
|
|
||||||
onValueChange={this.handleTimeOfDayChange} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value.intervalType === 'weekly'
|
|
||||||
|| value.intervalType === 'nthWeekDay') {
|
|
||||||
weekDaySelection = (
|
|
||||||
<Select
|
|
||||||
field={weekDayField}
|
|
||||||
item={this._getCurrentValue()}
|
|
||||||
onValueChange={this.handleWeekDayChange} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value.intervalType === 'monthly') {
|
|
||||||
monthDaySelection = (
|
|
||||||
<Select
|
|
||||||
field={monthDayField}
|
|
||||||
item={this._getCurrentValue()}
|
|
||||||
onValueChange={this.handleMonthDayChange} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value.intervalType === 'nthWeekDay') {
|
|
||||||
nthWeekDaySelection = (
|
|
||||||
<Select
|
|
||||||
field={nthWeekDayField}
|
|
||||||
item={this._getCurrentValue()}
|
|
||||||
onValueChange={this.handleNthWeekDayChange} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Select
|
|
||||||
field={intervalField}
|
|
||||||
item={this._getCurrentValue()}
|
|
||||||
onValueChange={this.handleIntervalChange} />
|
|
||||||
|
|
||||||
{nthWeekDaySelection}
|
|
||||||
{monthDaySelection}
|
|
||||||
{weekDaySelection}
|
|
||||||
{timeOfDaySelection}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
handleIntervalChange: function(event) {
|
||||||
|
return this.handleValueChange(
|
||||||
|
'intervalType',
|
||||||
|
event.target.value
|
||||||
|
);
|
||||||
|
},
|
||||||
|
handleTimeOfDayChange: function(event) {
|
||||||
|
return this.handleValueChange(
|
||||||
|
'timeOfDay',
|
||||||
|
event.target.value
|
||||||
|
);
|
||||||
|
},
|
||||||
|
handleWeekDayChange: function(event) {
|
||||||
|
return this.handleValueChange(
|
||||||
|
'weekDay',
|
||||||
|
event.target.value
|
||||||
|
);
|
||||||
|
},
|
||||||
|
handleMonthDayChange: function(event) {
|
||||||
|
return this.handleValueChange(
|
||||||
|
'monthDay',
|
||||||
|
event.target.value
|
||||||
|
);
|
||||||
|
},
|
||||||
|
handleNthWeekDayChange: function(event) {
|
||||||
|
return this.handleValueChange(
|
||||||
|
'nthWeekDay',
|
||||||
|
event.target.value
|
||||||
|
);
|
||||||
|
},
|
||||||
|
render: function() {
|
||||||
|
const value = this._getCurrentValue();
|
||||||
|
let timeOfDaySelection;
|
||||||
|
let weekDaySelection;
|
||||||
|
let monthDaySelection;
|
||||||
|
let nthWeekDaySelection;
|
||||||
|
|
||||||
return NotificationScheduling;
|
if (value.intervalType !== 'immediately') {
|
||||||
|
timeOfDaySelection = (
|
||||||
|
<Select
|
||||||
|
field={timeOfDayField}
|
||||||
|
item={this._getCurrentValue()}
|
||||||
|
onValueChange={this.handleTimeOfDayChange} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.intervalType === 'weekly' || value.intervalType === 'nthWeekDay') {
|
||||||
|
weekDaySelection = (
|
||||||
|
<Select
|
||||||
|
field={weekDayField}
|
||||||
|
item={this._getCurrentValue()}
|
||||||
|
onValueChange={this.handleWeekDayChange} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.intervalType === 'monthly') {
|
||||||
|
monthDaySelection = (
|
||||||
|
<Select
|
||||||
|
field={monthDayField}
|
||||||
|
item={this._getCurrentValue()}
|
||||||
|
onValueChange={this.handleMonthDayChange} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value.intervalType === 'nthWeekDay') {
|
||||||
|
nthWeekDaySelection = (
|
||||||
|
<Select
|
||||||
|
field={nthWeekDayField}
|
||||||
|
item={this._getCurrentValue()}
|
||||||
|
onValueChange={this.handleNthWeekDayChange} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Select
|
||||||
|
field={intervalField}
|
||||||
|
item={this._getCurrentValue()}
|
||||||
|
onValueChange={this.handleIntervalChange} />
|
||||||
|
|
||||||
|
{nthWeekDaySelection}
|
||||||
|
{monthDaySelection}
|
||||||
|
{weekDaySelection}
|
||||||
|
{timeOfDaySelection}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
);
|
});
|
||||||
|
|
||||||
|
module.exports = NotificationScheduling;
|
||||||
|
@ -25,19 +25,18 @@ define(
|
|||||||
endpoint: 'newsletters',
|
endpoint: 'newsletters',
|
||||||
action: 'create',
|
action: 'create',
|
||||||
data: {
|
data: {
|
||||||
type: 'standard',
|
type: 'standard'
|
||||||
}
|
}
|
||||||
}).done(function(response) {
|
}).done((response) => {
|
||||||
if(response.result && response.newsletter.id) {
|
this.showTemplateSelection(response.data.id);
|
||||||
this.showTemplateSelection(response.newsletter.id);
|
}).fail((response) => {
|
||||||
} else {
|
if (response.errors.length > 0) {
|
||||||
if(response.errors.length > 0) {
|
MailPoet.Notice.error(
|
||||||
response.errors.map(function(error) {
|
response.errors.map(function(error) { return error.message; }),
|
||||||
MailPoet.Notice.error(error);
|
{ scroll: true }
|
||||||
});
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}.bind(this));
|
});
|
||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
return (
|
return (
|
||||||
|