Compare commits

...

555 Commits

Author SHA1 Message Date
dc52ba0d93 Bump up release version to 3.2.3 2017-11-29 18:35:43 +03:00
dee2ff810c Fixes undefined index error 2017-11-29 10:19:30 +00:00
fbf58f23fc Bump up release version to 3.2.2 2017-11-28 20:18:18 +03:00
b6f62bd9bc Catches exceptions during sending 2017-11-28 16:42:22 +00:00
88ef454844 Merge pull request #1203 from mailpoet/nov28_survey
Updates weekly survey [MAILPOET-1224]
2017-11-28 16:07:22 +03:00
3572df6c0c Fixes "other" method test email sending when MSS is enabled
[MAILPOET-1218]
2017-11-28 09:28:56 +00:00
714e6e013f Updates weekly survey 2017-11-27 19:51:40 -05:00
91568cbeb6 Merge pull request #1202 from mailpoet/post_notification_creation_acceptance_test
Tests post notification creation [MAILPOET-1219]
2017-11-27 12:59:48 +02:00
393c89b21f Tests that post notifications can be created 2017-11-23 21:02:42 -05:00
0b491b7943 Adds method to get current URL 2017-11-23 21:02:41 -05:00
e5d7f66561 Adds new id to create standard/notification newsletters 2017-11-23 21:02:36 -05:00
b7a7f40cde Merge pull request #1199 from mailpoet/image_url_space_fix
Encodes URLs in inlined images [MAILPOET-1220]
2017-11-23 16:03:57 +03:00
a267c7524c Close the a tag to make valid HTML [MAILPOET-1220] 2017-11-23 16:02:40 +03:00
20b59d11a7 Merge pull request #1201 from mailpoet/user_profile_language_fix
Changes plugin language based on user's locale [MAILPOET-1211]
2017-11-23 13:40:59 +02:00
94c7e2a5c0 Changes plugin language based on user's locale 2017-11-22 20:13:56 -05:00
d603d99a04 Merge pull request #1190 from mailpoet/multisite_unit_tests
Adds new CI multisite test environment
2017-11-22 15:16:20 +02:00
e7ffe4d694 Replaces spaces in image URLs 2017-11-21 21:02:33 -05:00
018d7bce77 Corrects test to work on multisite environment 2017-11-21 12:26:02 -05:00
64c40d5a1c Adds test for multisite environment 2017-11-21 12:25:54 -05:00
7e49328d5e Corrects test to work on multisite environment 2017-11-21 12:24:19 -05:00
b50b636371 Adds multisite test environment to CI
Adds Robo command to run multisite tests locally and on CI
2017-11-21 12:24:18 -05:00
ec3bb5b95c Release 3.2.1 2017-11-21 15:18:40 +00:00
6b2503fb36 Merge pull request #1196 from mailpoet/minimum_wp_version_notice
Shows notice on WP version < 4.6 and deactivates plugin [MAILPOET-1215]
2017-11-21 16:26:03 +02:00
e71d47f983 Adds link to minimum requirements page for WP version 2017-11-21 08:57:28 -05:00
085d4f566a Merge pull request #1198 from mailpoet/hide-honeypot
Hide honeypot field to prevent Safari autocomplete [MAILPOET-1180]
2017-11-21 16:08:45 +03:00
29b249de6e Remove an attribute we don't need anymore
[MAILPOET-1180]
2017-11-21 12:54:00 +00:00
883ae5b0e4 Hide honeypot field to prevent Safari autocomplete
[MAILPOET-1180]
2017-11-21 11:47:46 +00:00
d78990cda3 Shows notice on WP version < 4.6 and deactivates plugin 2017-11-20 14:26:31 -05:00
e5b5a8df37 Merge pull request #1197 from mailpoet/poll_nov20
Update the poll [MAILPOET-1212]
2017-11-20 11:30:29 -05:00
2ea2db66ec Update the poll [MAILPOET-1212] 2017-11-20 19:03:47 +03:00
7b76ddefd5 Merge pull request #1194 from mailpoet/double_opt-in_test
Add an acceptance test for subscription confirmation [MAILPOET-1205]
2017-11-20 14:36:55 +02:00
6c56ac8509 Clean up the acceptance dump from unused pages [MAILPOET-1206] 2017-11-20 10:42:17 +00:00
dc074bcb14 Add acceptances tests for admin listings [MAILPOET-1206] [MAILPOET-1207] [MAILPOET-1208] [MAILPOET-1209] 2017-11-20 10:42:17 +00:00
0193644b18 Merge pull request #1195 from mailpoet/test_email_send_fix
Fixes "mailer not defined" JS error [MAILPOET-1217]
2017-11-20 13:21:16 +03:00
66de11ecd4 Fixes "mailer not defined" JS error 2017-11-18 19:51:53 -05:00
1238b1711d Add an acceptance test for subscription confirmation [MAILPOET-1205] 2017-11-16 14:57:56 +03:00
0061a9daf9 Move key checks from constructor to init() in Menu class [MAILPOET-1204] 2017-11-15 11:23:39 +00:00
52a55d3bd1 Updates changelog and bumps up release version to 3.2.0 2017-11-14 14:13:49 -05:00
7d686eb1d1 Merge pull request #1191 from mailpoet/post_excerpt_shortcode_fix
Fixes shortcodes not being properly stripped in excerpts [MAILPOET-1210]
2017-11-14 20:51:21 +02:00
962188bdb8 Adds unit test 2017-11-14 13:39:56 -05:00
72c3f763ec Removes shortcodes from full post content 2017-11-14 13:17:47 -05:00
44c5d8490f Fixes shortcodes not being properly stripped on excerpts 2017-11-14 12:35:08 -05:00
fb85623b86 Merge pull request #1185 from mailpoet/mp_api_unsubscribe_from_lists
Adds API method to unsubscribe from lists [MAILPOET-1202]
2017-11-14 17:38:53 +02:00
d7bf6addf1 Fixes error due to throwing exception inside array_map 2017-11-14 09:58:01 -05:00
adea1e9be1 Fixes condition that allowed unsubscribing from WP segments 2017-11-14 09:56:53 -05:00
4f77ca31a3 Rebased master 2017-11-13 12:41:46 -05:00
087f2ebcdd Uses a built-in method to handle plural exception cases
Implements check for empty segments
Implements check for WP segment when unsubscribing
2017-11-13 10:12:50 -05:00
3d2a63f319 Adds methods to unsubscribe from list(s) 2017-11-13 10:12:50 -05:00
54dd3b621a Improves error messages, cleans up code 2017-11-13 10:11:07 -05:00
7fea134109 Merge pull request #1183 from mailpoet/dynamic-segments-listings
Dynamic segments subscribers listings [PREMIUM-38] [PREMIUM-43]
2017-11-13 16:52:48 +03:00
fcf4bd12d9 Merge pull request #1186 from mailpoet/mp_api_get_subscriber
Adds API method to get subscriber [MAILPOET-1203]
2017-11-13 15:38:47 +02:00
6694555592 Adds method to get subscriber 2017-11-10 18:47:53 -05:00
e6eb3d691e Fix quality problems
[PREMIUM-38]
2017-11-09 12:14:01 +00:00
00f2d418cc Load subscribers from dynamic segments
[PREMIUM-38]
2017-11-09 10:11:47 +00:00
c63f218edd Enable to add segments to subscribers listing filter
[PREMIUM-38]
2017-11-09 10:11:47 +00:00
fae849bbfc Merge pull request #1182 from mailpoet/es6_rules_1
Fix ES6 rules 1 [MAILPOET-1137]
2017-11-08 22:32:43 -05:00
2a253ccb8d Move ES6 no-script-url rule to exceptions [MAILPOET-1137] 2017-11-08 21:42:10 -05:00
ff55e55ad2 Fix indentation [MAILPOET-1137] 2017-11-08 21:42:10 -05:00
d798ec446d Fix ES6 no-alert eslint rule (replace confirm() with a custom UI component) [MAILPOET-1137] 2017-11-08 21:41:17 -05:00
56b4038073 Fix padded-blocks after rebasing [MAILPOET-1137] 2017-11-08 21:41:16 -05:00
076a55f1fb Fix ES6 no-underscore-dangle eslint rule [MAILPOET-1137] 2017-11-08 21:41:16 -05:00
10eca98dc3 Fix ES6 padded-blocks eslint rule [MAILPOET-1137] 2017-11-08 21:41:16 -05:00
37aec3ee4f Fix ES6 wrap-iife eslint rule [MAILPOET-1137] 2017-11-08 21:41:16 -05:00
dc7c629e3b Fix ES6 no-shadow eslint rule [MAILPOET-1137] 2017-11-08 21:41:16 -05:00
e4f16eda49 Fix ES6 dot-notation eslint rule [MAILPOET-1137] 2017-11-08 21:41:16 -05:00
bf15bda84f Merge pull request #1181 from mailpoet/norwegian
Update translations in readme [MAILPOET-1196]
2017-11-08 09:19:20 -05:00
8472a837e8 Fix an 'Undefined index: SERVER_NAME' error in ConflictResolverTest [MAILPOET-1187] 2017-11-08 14:18:58 +00:00
fc326131ae Rebased master 2017-11-08 14:04:45 +00:00
a19753205f Increases timeout value when tests are run on slow hosts 2017-11-08 14:04:45 +00:00
ee404e3b84 Uses CLI to truncate table 2017-11-08 14:04:45 +00:00
f1918ac953 Removes timeouts and uses data-automation-id as element selector 2017-11-08 14:04:45 +00:00
d399ddf6b6 Fixed acceptance tests for me 2017-11-08 14:04:45 +00:00
3f06448f37 Uses data-automation-id/iframe id and bypasses throttling for
consecutive signups
2017-11-08 14:04:45 +00:00
83d84e67d6 Adds test for iframe form subscription 2017-11-08 14:04:45 +00:00
46c42c1bb4 Re-adds vendor folder installation (this is needed for Alex's setup) 2017-11-08 14:04:45 +00:00
944bf67190 Updates docker-compose 2017-11-08 14:04:45 +00:00
7cac061a73 Renames test 2017-11-08 14:04:45 +00:00
17764b708f Adds check for JS errors 2017-11-08 14:04:45 +00:00
2e0f4dfb19 Removes the need to reinstall vendor folder 2017-11-08 14:04:45 +00:00
7f5bc8681c Adds acceptance tests for unsubscribe/manage subscription links 2017-11-08 14:04:45 +00:00
bfcb85f744 Updates existing tests format 2017-11-08 14:04:45 +00:00
cb9aaf120e Cleans up DB dump 2017-11-08 14:04:45 +00:00
97a9465db3 Adds MailHog for SMTP testing 2017-11-08 14:04:45 +00:00
8dfaf9ba32 Release 3.1.0 2017-11-07 15:20:00 +02:00
89d0da93d3 Merge pull request #1180 from mailpoet/wp_sync_db_error_fix
Fixes "column cannot be null" error during WP sync [MAILPOET-1191]
2017-11-07 12:23:39 +02:00
c9cbfb4317 Update translations in readme [MAILPOET-1196] 2017-11-07 12:04:56 +03:00
a8ccfec5c6 Merge pull request #1178 from mailpoet/superadmin_access
Enable permissions for superadmin users [MAILPOET-1200]
2017-11-07 11:15:33 +03:00
d8609c9e84 Merge pull request #1179 from mailpoet/survey_nov7
Updates weekly survey [MAILPOET-1199]
2017-11-07 10:41:07 +03:00
5461c975d4 Fixes "column cannot be null" error during WP sync 2017-11-06 22:29:59 -05:00
11298bc101 Updates weekly survey 2017-11-06 22:25:35 -05:00
c42cf2f622 Switch to using current_user_can function to check capabilities 2017-11-06 18:09:38 +02:00
c9f1d38baa Merge pull request #1177 from mailpoet/mpapi_create_list
Add a method to create a new list to public API [MAILPOET-1197]
2017-11-02 18:54:06 -04:00
3d78d6bbe9 Add a method to create a new list to public API [MAILPOET-1197] 2017-11-02 22:13:50 +03:00
2b4288f301 Merge pull request #1176 from mailpoet/throttling_test_fix
Fix an off-by-one error in some timezones [MAILPOET-1186]
2017-11-02 14:34:03 +02:00
09a2dd231a Fix an off-by-one error in some timezones [MAILPOET-1186] 2017-11-02 14:56:44 +03:00
3fd4ef9985 Cleanup after WP sync test [MAILPOET-1185] 2017-11-01 15:43:31 +00:00
05979965ba Merge pull request #1174 from mailpoet/es6
ESLint: ES6 rules 2 [MAILPOET-1138]
2017-11-01 11:32:34 -04:00
e625a7602a Merge pull request #1171 from mailpoet/mixpanel
Report more system environment data via MixPanel [MAILPOET-1189]
2017-11-01 11:21:29 -04:00
a0c41ad7ab Merge pull request #1168 from mailpoet/jquery
plugin scripts should be loaded with a dependency on jquery [MAILPOET-1149]
2017-11-01 15:01:38 +02:00
7163747eb9 no-extra-boolean-cast 2017-11-01 10:20:13 +00:00
c30e2b6cf3 no-sequences 2017-10-31 17:16:24 +00:00
e9eae92ba9 no-useless-concat 2017-10-31 17:15:09 +00:00
0fd6fa8879 max-len 2017-10-31 17:12:59 +00:00
52ca6eac18 no-else-return 2017-10-31 17:10:10 +00:00
28776b8558 no-case-declarations 2017-10-31 16:52:00 +00:00
588ad3eab7 class-methods-use-this 2017-10-31 16:46:19 +00:00
d791538086 no-lonely-if 2017-10-31 16:40:08 +00:00
62173e7996 Bump up release version to 3.0.9 2017-10-31 19:18:42 +03:00
0acdcd1ca7 Merge pull request #1170 from mailpoet/jquery_serialize_object
Rename jQuery Serialize Object function to prevent conflicts [MAILPOET-1190]
2017-10-31 15:05:00 +01:00
f39a2c8dda added env data to weekly report 2017-10-31 11:17:34 +00:00
b648852ef5 Rename jQuery Serialize Object function to prevent conflicts [MAILPOET-1190] 2017-10-30 22:49:00 +03:00
6e45892118 trim values on listing search 2017-10-30 16:24:00 +00:00
cd145c51f7 public.js now depends on jquery 2017-10-30 14:25:05 +00:00
2c12d9ee2d changes on welcome and update pages 2017-10-30 11:36:40 +00:00
5fe28623f1 Merge pull request #1164 from mailpoet/acceptance_js_errors
Add JS error checking to acceptance tests [MAILPOET-1179]
2017-10-29 21:31:45 -04:00
3086b3cfc2 Merge pull request #1165 from mailpoet/esltests
ESLint: Test rules 2 [MAILPOET-1135]
2017-10-29 21:30:27 -04:00
5fd29872ff Merge pull request #1166 from mailpoet/remove-tags
Remove tags from ALC display
2017-10-26 14:28:02 +03:00
732c8a314f Merge pull request #1160 from mailpoet/ci-tables-prefix
changing the tables prefix to "mp_" on CircleCI [MAILPOET-1178]
2017-10-26 13:43:08 +03:00
23c650bfa6 Merge pull request #1163 from mailpoet/new-poll
new poll [MAILPOET-1172]
2017-10-26 13:34:16 +03:00
f5ced785e0 Tests: padded-blocks 2017-10-25 14:54:28 +00:00
4dc9004303 Tests: no-shaddow 2017-10-25 14:52:53 +00:00
893c6bd72b Remove tags from ALC display
[MAILPOET-1182]
2017-10-25 15:49:23 +01:00
2ac32484e1 Tests: max-len 2017-10-25 12:16:32 +00:00
b31e8ce5f2 Tests: no-bitwise 2017-10-25 12:10:29 +00:00
4270e4c315 Check for missing CSS files in acceptance tests [MAILPOET-1177] 2017-10-25 14:04:11 +03:00
4b13395b0c Add JS error checking to acceptance tests [MAILPOET-1179] 2017-10-25 13:34:16 +03:00
2e67029ef5 Merge pull request #1162 from mailpoet/new
Capitalize new [MAILPOET-1174]
2017-10-24 17:48:05 +03:00
257517b9a9 new poll 2017-10-24 14:13:07 +00:00
88ee64e15d Capitalize new 2017-10-24 14:03:27 +00:00
c2030e9a86 Fix readme.txt rendering 2017-10-24 14:55:21 +01:00
16111a99fb Release 3.0.8 2017-10-24 13:17:49 +01:00
543b3e5a91 changing tables prefix for acceptance tests 2017-10-24 09:13:43 +00:00
e33b60065e Merge pull request #1159 from mailpoet/ci_js_compile
Compile JS and CSS assets on CI before running acceptance tests [MAILPOET-1166]
2017-10-24 11:55:24 +03:00
3bcfadd2ab Merge pull request #1161 from mailpoet/translations_update
Translations update [MAILPOET-1161]
2017-10-24 11:30:59 +03:00
4729583d8d Merge pull request #1158 from mailpoet/scroll
enabling body scroll when settings are open [MAILPOET-1148]
2017-10-23 21:52:39 -04:00
aa3f457595 Updates welcome page translations that were not included in pot file 2017-10-23 21:45:48 -04:00
3ad490f840 Loads translations before the rest of the plugin 2017-10-23 21:45:48 -04:00
eb27ed65ae Adds missing translations to migration page 2017-10-23 21:45:40 -04:00
d543f62c5b Merge pull request #1157 from mailpoet/poll
new poll [MAILPOET-1171]
2017-10-23 20:11:19 +03:00
4e6f7a05de changing the tables prefix to "mp_" on CircleCI 2017-10-23 16:49:36 +00:00
5d467115ad Compile JS and CSS assets on CI before running acceptance tests [MAILPOET-1166] 2017-10-23 19:02:28 +03:00
6858b266fe enabling body scroll when settings are open 2017-10-23 16:01:28 +00:00
852b1a4c08 new poll 2017-10-23 14:59:29 +00:00
b2324db7b4 Merge pull request #1156 from mailpoet/number_formatting_update
Formats number as per locale's convention [MAILPOET-1125]
2017-10-23 15:19:47 +02:00
e8c85e2a54 Merge pull request #1155 from mailpoet/wp_user_sync_db_query_fix
Fixes MySQL's "column is ambiguous" error in WP user sync [MAILPOET-1177]
2017-10-23 14:15:14 +03:00
a4ac74c84a Remove more ambiguity in WP sync queries [MAILPOET-1177] 2017-10-23 13:58:23 +03:00
4e378484ea Formats number as per locale's convention 2017-10-22 21:56:33 -04:00
c55be70b2c Merge pull request #1154 from mailpoet/php_version_mixpanel
Report PHP version in weekly MixPanel analytics [MAILPOET-1175]
2017-10-20 17:10:14 +02:00
70898790f5 Cleans up code & fixes possible MySQL's "column is ambiguous" error 2017-10-19 21:14:45 -04:00
bfdb535f5b Fixes method name typo 2017-10-19 21:00:15 -04:00
996e6b16e7 Merge pull request #1142 from mailpoet/links
Enabling links on header and footer on preview [MAILPOET-1121]
2017-10-19 20:07:32 +03:00
0217e21753 Restore a default argument value [MAILPOET-1121] 2017-10-19 19:43:39 +03:00
f6f79d42e1 Report PHP version in weekly MixPanel analytics [MAILPOET-1175] 2017-10-19 19:03:55 +03:00
4bbd26b098 Merge pull request #1152 from mailpoet/form_translation_fix
Adds translated "required field" message to subscription form [MAILPOET-1173]
2017-10-19 18:55:02 +03:00
028179af37 Merge pull request #1153 from mailpoet/form_acceptance_tests
Add an acceptance test for the public subscription form widget [MAILPOET-1166]
2017-10-19 17:46:54 +03:00
87283bf838 Merge pull request #1143 from mailpoet/image-url
Force absolute path for images [MAILPOET-1160]
2017-10-19 12:38:45 +03:00
c680badaa2 Fix WP uploads folder permissions [MAILPOET-1166] 2017-10-19 12:34:16 +03:00
df4a936e43 Fix exit code returned by acceptance tests [MAILPOET-1166] 2017-10-19 12:34:16 +03:00
e27946ebcc Fix artifacts storage [MAILPOET-1166] 2017-10-19 12:34:16 +03:00
13e64c012f Restore PHP 5 support [MAILPOET-1166] 2017-10-19 12:34:16 +03:00
f69302be48 Add an acceptance test for the public subscription form widget [MAILPOET-1166] 2017-10-19 12:34:16 +03:00
16edfc16ea Merge pull request #1144 from mailpoet/dynamic-segments
Dynamic segments [PREMIUM-38]
2017-10-18 18:57:48 +03:00
229a9c8102 Fix QA issue
[PREMIUM-38]
2017-10-18 15:11:57 +01:00
490091a7e2 Move table definition to premium plugin
[PREMIUM-38]
2017-10-18 15:09:16 +01:00
5f58e5ca82 Add tests
[PREMIUM-38]
2017-10-18 15:04:44 +01:00
16beda530a Fix post notifications to work with dynamic segments
[PREMIUM-38]
2017-10-18 10:08:04 +01:00
f1b373924f Remove subscribers filtering for now
[PREMIUM-38]
2017-10-18 10:08:04 +01:00
6a73c463cb QA fixes
[PREMIUM-38]
2017-10-18 10:08:04 +01:00
0271675cd0 Use dynamic segments for sending queue
[PREMIUM-38]
2017-10-18 10:08:04 +01:00
b7555aa640 Show only default segments in listings
[PREMIUM-38]
2017-10-18 10:08:04 +01:00
fa9ef6e5bd Add 500 status code
[PREMIUM-38]
2017-10-18 10:08:04 +01:00
1c97b004ca Add blank template for premium plugin
[PREMIUM-38]
2017-10-18 10:08:04 +01:00
f0ab42adf1 Expose packages for premium
[PREMIUM-38]
2017-10-18 10:08:04 +01:00
165d8358d4 Add action after lists menu item
[PREMIUM-38]
2017-10-18 10:08:04 +01:00
6bd6e74bcb Add dynamic filters table
[PREMIUM-38]
2017-10-18 10:08:04 +01:00
b23df9e0a4 Adds translated "required field" message 2017-10-17 21:43:55 -04:00
7b12affb77 Bumps up release version to 3.0.7 and updates changelog 2017-10-17 14:08:16 -04:00
8c8c01aa75 shows links when previewing sent newsletters 2017-10-17 14:14:08 +00:00
0150e699a2 Merge pull request #1151 from mailpoet/oct17_poll_update
Updates weekly poll [MAILPOET-1170]
2017-10-17 17:06:39 +03:00
e6943e2638 Updates weekly poll 2017-10-17 09:34:04 -04:00
6f80dcb1de adding unit tests 2017-10-17 13:09:37 +00:00
60ed294302 no need to normalize src on the frontend 2017-10-17 12:57:39 +00:00
e8017b58f5 removing tooltip message 2017-10-17 12:48:20 +00:00
c79bf7d337 forcing absolute image source when rendering 2017-10-17 12:35:11 +00:00
ac268c1ec9 Merge pull request #1150 from mailpoet/beacon_cron_url_update
Uses CronHelper's method to return cron ping URL in beacon [MAILPOET-1164]
2017-10-17 09:54:12 +03:00
1ef131fa2d Merge pull request #1149 from mailpoet/capabilities_fix
Fixes "Call to a member function add_cap() on null" error [MAILPOET-1169]
2017-10-17 09:46:48 +03:00
1873007550 Improve a unit test for non-existent roles' capabilities [MAILPOET-1169] 2017-10-17 09:35:50 +03:00
fa2ccb51c9 Uses CronHelper's method to return cron ping URL in beacon 2017-10-16 23:46:17 -04:00
8f87d654af Merge pull request #1148 from mailpoet/stats_cta
Add CTA links for detailed stats [MAILPOET-1152]
2017-10-16 23:33:10 -04:00
dee6e9fbad Fixes "Call to a member function add_cap() on null" error 2017-10-16 22:55:11 -04:00
ef90264316 Add CTA links for detailed stats [MAILPOET-1152] 2017-10-13 01:11:06 +03:00
70bf4be723 ESLint: Test rules 1
[MAILPOET-1134]
2017-10-12 15:36:40 +01:00
07ef727654 Merge pull request #1139 from mailpoet/throttling
Add progressive throttling of subscriptions from the same IP address [MAILPOET-1128]
2017-10-12 15:56:40 +02:00
a346e5be29 normalizing image URL on render 2017-10-12 13:55:04 +00:00
5ce1eadde7 Merge pull request #1147 from mailpoet/honeypot-autofill
Subscription form honeypot gets filled by Autofill [MAILPOET-1163]
2017-10-12 16:52:22 +03:00
8a4d5395b1 Add attribute for Chrome
[MAILPOET-1163]
2017-10-12 14:38:45 +01:00
b5feed0f46 Remove WP subscribers with empty emails when syncing [MAILPOET-1158] 2017-10-12 10:31:11 +01:00
11f9579101 Don't synchronize WP users without emails [MAILPOET-1158] 2017-10-12 10:31:11 +01:00
c6000c959a Force absolute path for images 2017-10-11 14:21:16 +00:00
19e67ea2b0 Enabling links on header and footer on preview 2017-10-11 12:45:07 +00:00
0f6619e25d Merge pull request #1140 from mailpoet/svn_publish
Remove a dependency on WP in svn:publish command [MAILPOET-1156]
2017-10-11 13:21:10 +03:00
daf747d3be Throw an exception if plugin version could not be determined [MAILPOET-1156] 2017-10-11 13:07:53 +03:00
7393b1f2cf Remove a dependency on WP in svn:publish command [MAILPOET-1156] 2017-10-11 10:54:28 +03:00
efe861a9ba Merge pull request #1137 from mailpoet/eslint4
Eslint for tests [MAILPOET-1083]
2017-10-11 10:00:53 +03:00
2c358ab179 Add progressive throttling of subscriptions from the same IP address [MAILPOET-1128] 2017-10-10 19:36:20 +03:00
ca157fc91d Release 3.0.6 2017-10-10 16:46:37 +03:00
1fbe5d7bc6 Merge pull request #1138 from mailpoet/parsley
fixing missing parsley method [MAILPOET-1157]
2017-10-10 16:34:18 +03:00
71c031ccf9 fixing missing parsley method 2017-10-10 13:10:49 +00:00
6449b7ccca fixed minor issue 2017-10-10 09:29:22 +00:00
6a956472fe Release 3.0.5 2017-10-10 12:27:16 +03:00
d6af88d667 Tests object-curly-spacing 2017-10-10 09:09:03 +00:00
b9184a202f Tests func-call-spacing 2017-10-10 09:09:03 +00:00
f898746967 Tests keyword-spacing 2017-10-10 09:09:03 +00:00
68165b7b78 Tests space-before-function-paren 2017-10-10 09:09:03 +00:00
bb8591a67b Tests space-before-blocks 2017-10-10 09:07:29 +00:00
bda71ae78e Tests space-unary-ops 2017-10-10 09:07:29 +00:00
abd4f6cac2 Tests no-spaced-func 2017-10-10 09:07:29 +00:00
87e6cc2a4f Tests no-whitespace-before-property 2017-10-10 09:07:29 +00:00
dde598eb64 rebasing on master 2017-10-10 09:07:29 +00:00
0c4407f43a Merge pull request #1126 from mailpoet/eslint3
Eslint rules [MAILPOET-1084]
2017-10-10 11:46:45 +03:00
b6c864e7a1 Change the JSON API error message
[MAILPOET-1103]
2017-10-10 09:45:50 +01:00
3d9dc6465d Merge pull request #1132 from mailpoet/image_alignment
Add image alignment option to newsletter editor [MAILPOET-1124]
2017-10-10 11:37:11 +03:00
9a6fec094a fixing divider and spacer resize 2017-10-10 08:35:26 +00:00
61af224d7d Fixing image resize 2017-10-09 12:12:47 +00:00
9b41641e97 Tests vars-on-top 2017-10-09 11:17:23 +00:00
4e2e9f6f8f rebasing on master 2017-10-09 11:17:23 +00:00
c29dc8b4c7 fixing tests 2017-10-09 11:15:58 +00:00
98a3c6b156 Tests no-unused-vars 2017-10-09 11:15:58 +00:00
69c540288b Tests one-var 2017-10-09 11:15:58 +00:00
651c9f5692 Tests one-var-declaration-per-line 2017-10-09 11:15:58 +00:00
9ad3778cf7 ES6 rules 2017-10-09 11:15:58 +00:00
c90e0e9f64 ES5 no-unused-vars 2017-10-09 11:15:58 +00:00
cb1730c4e2 ES5 no-var 2017-10-09 11:15:58 +00:00
3dd8a973fd ES5 vars-on-top 2017-10-09 11:15:58 +00:00
c3ea088fca ES5 one-var 2017-10-09 11:15:58 +00:00
a11d6d7868 ES5 one-var-declaration-per-line 2017-10-09 11:15:58 +00:00
a596add838 ES5 block-scoped-var 2017-10-09 11:15:58 +00:00
7e7103ddab ES5 block-scoped-var 2017-10-09 11:15:58 +00:00
0064970ed7 Add a test for an alignment setting of an image block in the editor [MAILPOET-1124] 2017-10-09 13:00:39 +03:00
9d93f3ea95 Add a test for image alignment rendering [MAILPOET-1124] 2017-10-09 09:37:31 +03:00
ff2a3cd19e Release 3.0.4 2017-10-05 12:09:28 +00:00
8419d95ea1 Fix spacer and divider resizing [MAILPOET-1131] 2017-10-05 10:48:52 +01:00
4ad317ac7b Release MP3 3.0.3 2017-10-03 21:37:51 +03:00
7cccebbf2c Merge pull request #1135 from mailpoet/wp_sync_collations_fix
Get rid of WP user IDs updating query in favor of an insert-update due to collation problems [MAILPOET-1132]
2017-10-03 21:01:44 +03:00
e4f76ee9eb Get rid of WP user IDs updating query in favor of an insert-update due to collation problems [MAILPOET-1132] 2017-10-03 20:52:35 +03:00
7f52f72c25 Releasing 3.0.2 2017-10-03 14:27:56 +00:00
44afcbbeaf Merge pull request #1134 from mailpoet/new-poll
Add a new poll to update page [MAILPOET-1129]
2017-10-02 19:55:36 +03:00
e816c59539 Add a new poll to update page 2017-10-02 18:47:39 +03:00
c74421a42a Merge pull request #1133 from mailpoet/permission_update_fix
Remove the check for a plugin update permission [MAILPOET-1130]
2017-10-02 14:58:08 +02:00
23eb4633c4 Remove the check for a plugin update permission [MAILPOET-1130] 2017-10-02 15:44:06 +03:00
26241afb86 Add image alignment option to newsletter editor [MAILPOET-1124] 2017-10-02 15:30:43 +03:00
92dbf966a1 Add a UI hint for managing capabilities using the Members plugin [MAILPOET-1123] 2017-10-02 10:33:20 +01:00
db226b54a8 Include admin-global.css only on admin pages [MAILPOET-493] 2017-10-02 10:22:40 +01:00
3af059f5c4 Fix MailPoet icon displaying in Members tab on production [MAILPOET-493] 2017-10-02 10:22:40 +01:00
8706abcdf0 Change access_plugin_admin permission label [MAILPOET-493] 2017-10-02 10:22:40 +01:00
2129d041ac Fix indentation [MAILPOET-493] 2017-10-02 10:22:40 +01:00
2a4a44ebb5 Make a condition more easy to read [MAILPOET-493] 2017-10-02 10:22:40 +01:00
a4f2d5402c Manage MP3 permissions with WP role capabilities, add Members plugin support [MAILPOET-493] 2017-10-02 10:22:40 +01:00
9f5fc151b4 Move throttling out of the Subscriber model to the API 'subscribe' method [MAILPOET-1115] 2017-09-28 15:45:35 +01:00
8a91eb46e6 Fix the possibility of repeatedly submitting a form with an existing e-mail address [MAILPOET-1115] 2017-09-28 12:59:57 +01:00
e4ab928e82 Merge pull request #1127 from mailpoet/presubscribed_wp_sync_fix
Fix synchronization of presubscribed WP users [MAILPOET-1127]
2017-09-28 11:24:32 +02:00
a1b02cb862 Fix synchronization of presubscribed WP users [MAILPOET-1127] 2017-09-28 10:44:29 +03:00
84b942b9d2 Merge pull request #1121 from mailpoet/template_sort
Applies sorting by date created and name [MAILPOET-1119]
2017-09-27 11:14:00 +02:00
1ca99a6209 Updates Premium tab language 2017-09-27 10:07:36 +01:00
6b61abe8c0 Removes text domain from plugin header 2017-09-27 10:05:10 +01:00
27028ca1ef Merge pull request #1124 from mailpoet/alc_and_post_exclude_search_results
Prevents excluded post types from being displayed in newsletter editor [MAILPOET-701]
2017-09-27 11:40:51 +03:00
eed88926a2 Merge pull request #1120 from mailpoet/editor_horizontal_scroll_fix
Fixes horizontal scrolling inside post/ALC options panel [MAILPOET-1118]
2017-09-27 11:31:34 +03:00
b25877c514 Bump up release version to 3.0.1 2017-09-26 18:18:17 +03:00
119e574495 Prevents excluded post types from being displayed in newsletter editor 2017-09-25 19:45:33 -04:00
7308d253b2 Applies sorting by date created and name 2017-09-25 18:47:43 -04:00
1c19b71697 Fixes horizontal scrolling inside post/ALC options panel 2017-09-25 18:09:58 -04:00
7551fff93f Merge pull request #1116 from mailpoet/fix-tests
Fixing Shortcodes issue [MAILPOET-1104]
2017-09-25 17:14:35 -04:00
b2aa919574 Merge pull request #1118 from mailpoet/fix-query
Add index to improve query performance [MAILPOET-1117]
2017-09-25 17:04:25 -04:00
1102bbe483 Merge pull request #1056 from mailpoet/resize-image
Add image resize feature [MAILPOET-1047]
2017-09-25 13:07:10 +03:00
b78dd22ba9 Merge pull request #1109 from mailpoet/templates-images-src
Adding https prefix the image sources [MAILPOET-1109]
2017-09-25 12:08:02 +03:00
73110ada46 fixing ESLint tests 2017-09-25 09:06:55 +00:00
74dedd06bc changing missing tempaltes 2017-09-25 08:57:18 +00:00
20c936d13b limitting width with CSS 2017-09-21 18:58:17 +00:00
f135b89de9 Fixed image resize bugs 2017-09-21 18:58:16 +00:00
6a83930ae0 Resizing the image fixed 2017-09-21 18:57:35 +00:00
a1d0acfac2 Add image resize feature 2017-09-21 18:56:47 +00:00
04be06c0cb remove additional new line 2017-09-21 18:47:43 +00:00
78d52d6298 Merge pull request #1117 from mailpoet/eslint
Eslint rules [MAILPOET-1081]
2017-09-21 19:42:19 +03:00
5ff7c28c43 Merge pull request #1110 from mailpoet/es6_spacing
Fix ESLint spacing rules for ES6 [MAILPOET-1082]
2017-09-21 17:15:57 +03:00
5526f315d2 Merge pull request #1115 from mailpoet/scheduled_newsletter_status_fix
Sets newsletter status to draft when it's unscheduled [MAILPOET-1060]
2017-09-21 16:32:12 +03:00
d5e25fdeb1 Merge pull request #1114 from mailpoet/long_email_sql_error_fix
Fixes SQL error resulting from subscription with long email [MAILPOET-1113]
2017-09-21 16:17:21 +03:00
90a7bf5179 Adds back rendered subject clearing test
Removes duplicate line
2017-09-21 09:13:13 -04:00
bf1f696870 Add index to improve query performance
[MAILPOET-1117]
2017-09-21 13:17:02 +01:00
95551ad049 ES5 keyword-spacing 2017-09-21 09:13:36 +00:00
1ad90680f4 ES5 object-curly-spacing 2017-09-21 09:12:52 +00:00
d69d3cb421 ES5 array-bracket-spacing 2017-09-21 09:12:37 +00:00
9adca07393 ES5 computed-property-spacing 2017-09-21 09:12:23 +00:00
a9d129fddc ES5 block-spacing 2017-09-21 09:12:09 +00:00
b4ac09bea3 ES5 key-spacing 2017-09-21 09:11:55 +00:00
b1a403d9b5 ES5 space-infix-ops 2017-09-21 09:09:29 +00:00
28504fb5e3 ES5 spaced-comment 2017-09-21 09:08:52 +00:00
8ebb8e3c02 ES5 no-trailing-spaces 2017-09-21 09:04:47 +00:00
c95c2cd1ae ES5 space-in-parens 2017-09-21 09:04:32 +00:00
946bee2194 ES5 space-before-blocks 2017-09-21 09:02:50 +00:00
1f9bd04308 ES5 space-unary-ops 2017-09-21 08:52:30 +00:00
33572b2dc7 ES5 no-multi-spaces 2017-09-21 08:47:23 +00:00
680446b77e ES5 space-before-function-parens 2017-09-21 08:35:12 +00:00
bf1d76a3a7 Fix readme.txt 2017-09-20 16:57:17 +01:00
c915fcfdff Release 3.0.0 2017-09-20 15:21:55 +01:00
02966c3b93 Sets cron daemon timeout to 5s across the plugin
Adds hook to override cron request arguments
2017-09-20 14:59:48 +01:00
84dc48daec Allow passing cron timeouts
[MAILPOET-1114]
2017-09-20 14:59:48 +01:00
12225004f4 Apply hook on cron timeout
[MAILPOET-1114]
2017-09-20 14:59:48 +01:00
320dfa2ec5 Extracts duplicate code into reusable methods
Updates unit test
2017-09-20 14:59:48 +01:00
b5f3016085 Removes URL from user agent
(https://mailpoet.slack.com/archives/C02MTKAJL/p1505488541000029?thread_ts=1505488163.000795&cid=C02MTKAJL)
2017-09-20 14:59:48 +01:00
cd53e369d0 Allows accessing full URL from within custom cron hook 2017-09-20 14:59:48 +01:00
6fc11af774 Returns error message instead of empty body 2017-09-20 14:59:48 +01:00
42e3a97616 Fixing Shortcodes issue 2017-09-20 12:34:27 +00:00
6b16aa1692 Sets newsletter status to draft when it's unscheduled 2017-09-19 21:59:03 -04:00
03d0de74e4 Merge pull request #1108 from mailpoet/send_twice_tooltip
Show a tooltip about sending an email twice only when the Send button is disabled [MAILPOET-1098]
2017-09-19 20:38:10 -04:00
c3b643df84 Prevents leaking SQL errors in API response 2017-09-19 20:32:26 -04:00
697f9ba5bc Adds min/max email length in UI and backend 2017-09-19 20:04:49 -04:00
28c75c5b96 Adds a thousand separator 2017-09-19 09:55:38 -04:00
6f255854f2 Merge pull request #1112 from mailpoet/copy_update
Update free MSS plan size to 2000 subscribers [MAILPOET-1112]
2017-09-19 12:46:36 +03:00
91c5f9c43e Clarify Premium plugin benefits 2017-09-19 12:41:25 +03:00
62acd6404a Update free MSS plan size to 2k subscribers, update plugin description 2017-09-19 12:15:46 +03:00
adc1461771 Don't show send tooltip for paused newsletters [MAILPOET-1098] 2017-09-19 08:51:16 +03:00
66cc0964ce Merge pull request #1106 from mailpoet/fix-tests
Fixing MP API test
2017-09-18 18:23:20 -04:00
10d77720ad Merge pull request #1107 from mailpoet/hooks_unit_test_update
Updates hooks unit test [MAILPOET-1110]
2017-09-18 17:39:50 +02:00
475114c6f9 Fix ES6 no-irregular-whitespace eslint rule [MAILPOET-1082] 2017-09-18 18:31:13 +03:00
a0fec7d103 Fix ES6 space-infix-ops eslint rule [MAILPOET-1082] 2017-09-18 18:27:43 +03:00
4d9d92a026 Fix ES6 array-bracket-spacing eslint rule [MAILPOET-1082] 2017-09-18 18:26:43 +03:00
e51aa8c271 Fix ES6 space-in-parens eslint rule [MAILPOET-1082] 2017-09-18 18:25:37 +03:00
d44adedade Fix ES6 key-spacing eslint rule [MAILPOET-1082] 2017-09-18 18:24:26 +03:00
9fb3c50aa7 Fix ES6 no-multi-spaces eslint rule [MAILPOET-1082] 2017-09-18 18:23:36 +03:00
907053a349 Fix ES6 space-unary-ops eslint rule [MAILPOET-1082] 2017-09-18 18:22:48 +03:00
f0f85cfb59 Fix ES6 template-curly-spacing eslint rule [MAILPOET-1082] 2017-09-18 18:21:44 +03:00
44d0341fb2 Fix ES6 keyword-spacing eslint rule [MAILPOET-1082] 2017-09-18 18:20:55 +03:00
0cdae52c66 Fix ES6 react/jsx-curly-spacing eslint rule [MAILPOET-1082] 2017-09-18 18:18:45 +03:00
0cd9c8e416 Adding https prefix the image sources 2017-09-18 15:11:55 +00:00
9e3010ab52 Fix ES6 react/jsx-tag-spacing eslint rule [MAILPOET-1082] 2017-09-18 18:05:57 +03:00
d831b2df55 Explicitly sets up hooks instead of assuming they are already set up 2017-09-18 10:43:17 -04:00
16ff630e88 Show a tooltip about sending an email twice only when the Send button is dsiabled [MAILPOET-1098] 2017-09-18 17:42:24 +03:00
d35763662e Fixing MP API test 2017-09-18 12:00:43 +00:00
10be411b12 Prepare release v3.0.0 2017-09-18 11:35:59 +01:00
6ecce192f7 Merge pull request #1105 from mailpoet/wp_sync_multisite
Fix WP sync throwing 'Table "users" doesn't exist' errors on multisite subsites [MAILPOET-1107]
2017-09-18 11:48:30 +03:00
ee07e60fe9 Adds new survey 2017-09-18 09:13:06 +01:00
a35d7a1154 Fix WP sync throwing 'Table users doesn't exist' errors on multisite subsites [MAILPOET-1107] 2017-09-18 10:55:49 +03:00
ebba8dbfd6 Merge pull request #1103 from mailpoet/twig_version_conflict_detection_improvement
Updates Twig version conflict detection logic [MAILPOET-1068]
2017-09-18 10:42:51 +03:00
44c637c06b Merge pull request #1101 from mailpoet/premium_key_in_beacon
Add Premium key to Help Scout beacon [MAILPOET-1090]
2017-09-17 12:08:52 -04:00
d54ba734bf Adds a min-max range of supported Twig versions 2017-09-17 11:25:35 -04:00
b45fc22306 Updates coding style and cleans up JS script inclusion part 2017-09-16 11:34:21 -04:00
994935d4ae Adds check for minimum Twig version loaded by external plugins 2017-09-16 11:33:40 -04:00
ceb5ce850c Removes deprecated Twig_ExtensionInterface::getName()
(https://github.com/twigphp/Twig/blob/2.x/CHANGELOG#L207)
Removes deprecated Twig_Extension_GlobalsInterface
(https://github.com/twigphp/Twig/blob/2.x/CHANGELOG#L259)
2017-09-16 11:30:40 -04:00
97b5ed945d Merge pull request #1100 from mailpoet/update-send-copy
Update send copy [MAILPOET-1101]
2017-09-14 20:02:28 +02:00
873b322245 Translate
[MAILPOET-1101]
2017-09-14 18:52:33 +01:00
12ad9e41e7 Translate a string
[MAILPOET-1101]
2017-09-14 18:40:04 +01:00
96b418e455 Our free plan will be for 1,000 subscribers and not 250
[MAILPOET-1101]
2017-09-14 17:35:15 +01:00
8ea7861f77 Merge pull request #1102 from mailpoet/welcome-tab-update
Update welcome tab [MAILPOET-1099]
2017-09-14 19:34:01 +03:00
821976c881 Make text random
[MAILPOET-1099]
2017-09-14 17:19:55 +01:00
6f1443e43d Update welcome tab
[MAILPOET-1099]
2017-09-14 15:35:07 +01:00
09fcaecdfc Add Premium key to Help Scout beacon [MAILPOET-1090] 2017-09-14 16:24:15 +03:00
efd72ca9f6 Merge pull request #1099 from mailpoet/update-readme
Update readme.txt for launch v3
2017-09-14 15:38:36 +03:00
550b5e9aed More readme.txt updates
[MAILPOET-1105]
2017-09-14 13:37:10 +01:00
4b7ae5fcff Fix typo
[MAILPOET-1105]
2017-09-14 13:28:44 +01:00
fa85e12127 Update premium section in readme.txt
[MAILPOET-1105]
2017-09-14 13:27:07 +01:00
1cce50902b Update Send with... other copy
[MAILPOET-1101]
2017-09-14 11:39:20 +01:00
2048fa5cf9 Update Send with... mailpoet copy
[MAILPOET-1101]
2017-09-14 11:31:43 +01:00
f438c8fd31 Update readme.txt for launch v3
[MAILPOET-1105]
2017-09-14 10:15:00 +01:00
0bfa832dad Merge pull request #1098 from mailpoet/subscribers-fix
Subscribers fix [MAILPOET-1102]
2017-09-13 18:17:56 +03:00
483dfbe1ec Fix removal of WP segment subscribers without wp_user_id [MAILPOET-1102] 2017-09-13 16:46:50 +03:00
561fee491d Merge pull request #1097 from mailpoet/makepot_views_fix
Fix makepot adding extra slashes to escaped characters in views [MAILPOET-1093]
2017-09-13 14:54:25 +02:00
97d157192a Remove orphaned links
[MAILPOET-1102]
2017-09-13 13:30:23 +01:00
6b14a8a057 Remove data from usermeta
[MAILPOET-1102]
2017-09-13 13:18:39 +01:00
d27b187f5e Fix QA problems
[MAILPOET-1102]
2017-09-13 13:15:50 +01:00
02d49ba2ca DELETE subscribers in WP list which are not WP users
[MAILPOET-1102]
2017-09-13 13:07:01 +01:00
f3571a5855 Add another testing scenario
[MAILPOET-1102]
2017-09-13 08:54:54 +01:00
3d5f0df213 Don't delete subscribers with wp_user_id = 0 [MAILPOET-1102] 2017-09-13 10:15:09 +03:00
595a201fe7 Stop deleting subscribers
[MAILPOET-1102]
2017-09-12 17:53:12 +01:00
c3db7d8148 Release 3.0.0-rc.2.0.3 2017-09-12 15:41:06 +03:00
4a2187ff32 Merge pull request #1096 from mailpoet/translation_strings_update
Removes escape character in translations [MAILPOET-1093]
2017-09-12 14:24:38 +03:00
279c36a30d Merge pull request #1094 from mailpoet/initializer_update
Updates plugin initialization logic [MAILPOET-1097]
2017-09-12 12:34:27 +03:00
fd65117a5d Fix makepot adding extra slashes to escaped characters in views [MAILPOET-1093] 2017-09-12 11:17:04 +03:00
9305beace3 Removes escape character in translations 2017-09-11 19:27:03 -04:00
ba86cbfb18 Updates unit test 2017-09-11 11:40:14 -04:00
2ac7d1d4ab Breaks plugin initialization into 3 stages: preInit, init and postInit 2017-09-11 11:33:03 -04:00
e9c55260c8 Merge pull request #1092 from mailpoet/db_version_settings_logic_update
Uses plugin's settings to store DB version [MAILPOET-1095]
2017-09-11 18:15:17 +03:00
99b6a287f8 Highlight a container block when hovering over its tools [MAILPOET-1088] 2017-09-11 15:32:45 +01:00
d645f0cad4 Merge pull request #1087 from mailpoet/eslint-un
Eslint un [MAILPOET-1073]
2017-09-11 16:16:51 +02:00
b0343254c0 Renames db version setting value 2017-09-11 10:05:09 -04:00
cc368f015b Remove redundant argument
[MAILPOET-1085]
2017-09-11 15:03:30 +01:00
4e508855fc Fix eslint no-unused-expressions in tests
[MAILPOET-1085]
2017-09-11 15:03:30 +01:00
72c0a6f165 Fix eslint no-undef in tests
[MAILPOET-1085]
2017-09-11 15:03:30 +01:00
f266508654 Fix eslint no-undef in ES6
[MAILPOET-1085]
2017-09-11 15:03:30 +01:00
1893d82b2d Fix eslint no-unused-expressions in ES6
[MAILPOET-1085]
2017-09-11 15:03:30 +01:00
bb1dd6a2ec Fix eslint import/no-unresolved in ES6
[MAILPOET-1085]
2017-09-11 15:03:30 +01:00
7097ea5d9b Fix eslint no-unreachable in ES6
[MAILPOET-1085]
2017-09-11 15:03:30 +01:00
b4092e0641 Fix eslint no-unneeded-ternary in ES5
[MAILPOET-1085]
2017-09-11 15:03:30 +01:00
2c068c7bb6 Fix eslint no-unreachable in ES5
[MAILPOET-1085]
2017-09-11 15:03:30 +01:00
a1a4fcb978 Fix eslint no-unused-expressions in ES5
[MAILPOET-1085]
2017-09-11 15:03:30 +01:00
f77620d649 Fix eslint no-undef in ES5
[MAILPOET-1085]
2017-09-11 15:03:30 +01:00
9e932c9078 Merge pull request #1085 from mailpoet/improve-user-sync
Improve user sync [MAILPOET-1073]
2017-09-11 14:56:41 +03:00
de47dbe41b Removes arrow functions that are not supported in IE 2017-09-11 10:25:43 +01:00
6d36d67a60 Delete orphaned subscribers instead of updating their id
[MAILPOET-1073]
2017-09-11 10:09:32 +01:00
607bf51b37 Merge two test cases for one class
[MAILPOET-1073]
2017-09-11 09:28:39 +01:00
f38ed0272c Merge pull request #1093 from mailpoet/cron_helper_improvement
Cron helper improvement [MAILPOET-1096]
2017-09-11 11:23:01 +03:00
eef969439b Code comment
[MAILPOET-1073]
2017-09-11 09:22:40 +01:00
272f552f3c Clean data befre and after test run
[MAILPOET-1073]
2017-09-11 09:22:18 +01:00
dff9c1012b Moves widget initialization back to widgets_init hook
Removes priority from plugin initialization
2017-09-10 19:49:05 -04:00
52470360a1 Returns ping response body instead of boolean 2017-09-10 18:49:15 -04:00
6c62459ed4 Adds filter to override default cron request URL 2017-09-10 18:36:22 -04:00
98482cebf9 Uses plugin's settings to store DB version 2017-09-10 16:31:36 -04:00
509880119e Merge pull request #1090 from mailpoet/eslint-indent
Eslint indent [MAILPOET-1029]
2017-09-07 20:13:20 -04:00
195ccb5eed Fix indent rule in tests
[MAILPOET-1029]
2017-09-07 16:05:45 +01:00
122af1c943 Fix react/jsx-indent rule in ES6
[MAILPOET-1029]
2017-09-07 15:59:38 +01:00
169940058b Fix react/jsx-indent-props rule in ES6
[MAILPOET-1029]
2017-09-07 15:52:46 +01:00
478e60d60e Fix indent rule in ES5
[MAILPOET-1029]
2017-09-07 15:51:25 +01:00
9fc0ac8c4f Merge pull request #1089 from mailpoet/color_picker
Change color on click, add history to color picker [MAILPOET-1087]
2017-09-07 17:08:09 +03:00
e86b780479 Fix build`
[MAILPOET-1073]
2017-09-07 14:44:55 +01:00
42f08bdc65 Fix handling of empty color and transparent color selected from palette [MAILPOET-1087] 2017-09-07 15:48:14 +03:00
c2789cdac3 Don't load all ids to memory, PHP could crash
[MAILPOET-1073]
2017-09-07 13:42:18 +01:00
8a362f49f8 Add test for users synchronisation
[MAILPOET-1073]
2017-09-07 13:42:18 +01:00
784a80d1a5 Use ->prefix instead of wp_
[MAILPOET-1073]
2017-09-07 13:42:18 +01:00
922d2b4b5f Fix migration
[MAILPOET-1073]
2017-09-07 13:42:18 +01:00
91e8461cac Clean the code
[MAILPOET-1073]
2017-09-07 13:42:18 +01:00
8757598a2d Add index
[MAILPOET-1073]
2017-09-07 13:42:18 +01:00
524aabea1d Split users sync into multiple queries
[MAILPOET-1073]
2017-09-07 13:42:18 +01:00
513181ff47 Change color on click, add history to color picker [MAILPOET-1087] 2017-09-07 13:17:57 +03:00
6bc288ed54 Merge pull request #1088 from mailpoet/depreciated_twig_notice_fix
Fixed Twig's deprecated notice [MAILPOET-1092]
2017-09-07 12:48:11 +03:00
77f3a875dd Does not set global is_rtl variable 2017-09-06 20:56:52 -04:00
6584250d1a Adds is_rtl() function to Twig 2017-09-06 20:55:44 -04:00
e42db162aa Merge pull request #1086 from mailpoet/translation_fixes
Fix translations based on translator feedback on TX [MAILPOET-1091]
2017-09-06 16:30:13 +03:00
2762096167 Switch strtoupper to mb_strtoupper based on feedback 2017-09-06 16:14:52 +03:00
b2ec3e5f7b Fix translations based on translator feedback on TX [MAILPOET-1091] 2017-09-06 13:45:42 +03:00
e012bd6cbe Updates changelog & bumps up release version to 3.0.0-rc.2.0.2 2017-09-05 11:17:32 -04:00
a02e64e805 Merge pull request #1084 from mailpoet/editor_get_post_type_optimization
Removes unused properties from the object used to display post types in editor [MAILPOET-1086]
2017-09-05 17:43:27 +03:00
e4bb3e1133 Adds unit test 2017-09-05 10:33:10 -04:00
998795e0e0 Fix tests semi eslint rule [MAILPOET-1030] 2017-09-05 12:31:51 +01:00
ec44b84cc9 Fix ES6 no-extra-semi eslint rule [MAILPOET-1030] 2017-09-05 12:31:51 +01:00
efece061d0 Fix ES5 semi eslint rule [MAILPOET-1030] 2017-09-05 12:31:51 +01:00
e347fc74a2 Fix ES5 no-extra-semi eslint rule [MAILPOET-1030] 2017-09-05 12:31:51 +01:00
027418a86c Fix ES5 semi-spacing eslint rule [MAILPOET-1030] 2017-09-05 12:31:51 +01:00
864187aa02 Merge pull request #1080 from mailpoet/json_api_method_check_fix
Throws error when JSON API endpoint method is not found [MAILPOET-1074]
2017-09-05 13:08:37 +03:00
59ae6619c0 Browser preview mixed content error fix
Strips protocol from preview URL

[MAILPOET-1080]
2017-09-05 08:54:23 +01:00
6aa0be8d01 Removes unused properties from the object 2017-09-04 21:07:15 -04:00
657658ea2b Adds new poll 2017-09-04 10:49:11 +02:00
8647128e12 Merge pull request #1081 from mailpoet/default_status_update
Default status is set depending on the signup confirmation option [MAILPOET-1079]
2017-09-04 10:02:45 +03:00
c8d92b3cd2 Default status is set depending on the signup confirmation option 2017-08-31 18:48:43 -04:00
cc8b7b45ed Throws error when endpoint method is not found 2017-08-31 15:18:22 -04:00
5b8b8c8441 Merge pull request #1077 from mailpoet/helpscout
Split support inquiries into Free and Premium inboxes [MAILPOET-869]
2017-08-31 12:38:18 -04:00
7106c640ef Refactor HelpScout Beacon embed script 2017-08-31 19:24:32 +03:00
300b84983d Merge pull request #1078 from mailpoet/spellchecker
Enable browser spellchecker [MAILPOET-1078]
2017-08-31 18:14:47 +03:00
49c1b92838 Enable browser spellchecker 2017-08-31 18:03:19 +03:00
d900827850 Merge pull request #1076 from mailpoet/lint-lines
Lint lines [MAILPOET-1031]
2017-08-31 12:49:10 +03:00
1688d4dbe1 Split support inquiries into Free and Premium inboxes [MAILPOET-869] 2017-08-31 12:02:20 +03:00
856c636089 Releasing 3.0.0-rc.2.0.1 2017-08-30 16:06:39 +00:00
8f9e8ea185 Merge pull request #1075 from mailpoet/forms-bug
Fix form issue when using list selection field [MAILPOET-1077]
2017-08-30 18:10:33 +03:00
b0b88693f1 Merge pull request #1071 from mailpoet/initializer_cleanup
Fixes activation on MS environments and cleans up Initializer [MAILPOET-1076]
2017-08-30 17:56:16 +03:00
9916eb9da8 updated tests 2017-08-30 14:52:17 +00:00
79b5426e01 Fix a constant name [MAILPOET-1076] 2017-08-30 17:47:53 +03:00
5807fd2e02 Merge pull request #1067 from mailpoet/emoji
Add emoji support to newsletter body [MAILPOET-1009]
2017-08-30 10:04:26 -04:00
0ee39143f4 Runs hooks setup only when plugin is initilized 2017-08-30 09:50:49 -04:00
10c39bd650 Removes unused constructor 2017-08-30 09:47:34 -04:00
20593cc5a5 Fix form issue when using list selection field 2017-08-30 13:29:41 +00:00
f438eee842 Fix ESLint newline-per-chained-call in tests
[MAILPOET-1031]
2017-08-30 15:26:02 +02:00
cb4b599d97 Merge pull request #1073 from mailpoet/fix-notice
Fix php notice
2017-08-30 16:25:50 +03:00
33733219f6 Fix ESLint object-property-newline in tests
[MAILPOET-1031]
2017-08-30 15:20:39 +02:00
737a83cdf3 Fix ESLint linebreak-style in tests
[MAILPOET-1031]
2017-08-30 15:19:15 +02:00
9061e1b495 Fix ESLint no-multipe-empty-lines ES6
[MAILPOET-1031]
2017-08-30 15:11:56 +02:00
09199e41a1 Fix ESLint linebreak-style ES5
[MAILPOET-1031]
2017-08-30 14:59:34 +02:00
4e91932613 Fix ESLint lines-around-directive ES5
[MAILPOET-1031]
2017-08-30 14:45:25 +02:00
227de4ecfa Fix ESLint newline-per-chained-call ES5
[MAILPOET-1031]
2017-08-30 14:40:42 +02:00
c1ccacf851 Fix ESLint newline-per-chained-call
[MAILPOET-1031]
2017-08-30 14:30:48 +02:00
53f7953566 Fix browser preview bypassing emoji encoding [MAILPOET-1009] 2017-08-30 14:39:38 +03:00
61ae2da1e3 Fix a constant not defined in PHP 5.3 [MAILPOET-1009] 2017-08-30 14:02:29 +03:00
36abd8e5e6 Don't show network activation notice for other plugins
[MAILPOET-1072]
2017-08-30 11:39:42 +02:00
7e9de1fd07 Fix php notice 2017-08-30 11:25:42 +02:00
7ac5e65963 Fix php notice 2017-08-30 10:30:16 +02:00
cf992852b5 Validate for unsubscribe link only for MSS sending method [MAILPOET-1050] 2017-08-30 10:16:24 +02:00
59482b2bfa Uses init hook to initilize AccessControl 2017-08-29 23:30:35 -04:00
053f9e0cdf Adds higher priority to init hook so that it fires before the widgets hook 2017-08-29 23:20:46 -04:00
e1cc25239b Maintains code consistency when setting up JSON API
Updates exception handler return statement
2017-08-29 20:33:50 -04:00
2f4452ad36 Removes redundant exception handler 2017-08-29 20:28:20 -04:00
f453d685d6 Fixes translation not being picked up by makepot 2017-08-29 20:24:04 -04:00
2d2b4ca7f0 Moves setup actions from plugins_loaded hook to init hook
Rearranges class methods to follow the order by which they are called
2017-08-29 20:22:19 -04:00
546e012fbf releasing 3.0.0-rc.2.0.0 2017-08-29 13:43:15 +00:00
83adf089c5 Merge pull request #1070 from mailpoet/permissions
Fix Endpoint to use single global permission and not array of them [MAILPOET-1057]
2017-08-29 14:47:18 +02:00
2f45bb05d7 Fix Endpoint to use single global permission and not array of them
[MAILPOET-1057]
2017-08-29 15:34:35 +03:00
9ef8ab3e28 Merge pull request #1065 from mailpoet/events
Track extra events on MixPanel [MAILPOET-970]
2017-08-29 15:26:24 +03:00
f4db4f05c4 minor fixes 2017-08-29 12:18:12 +00:00
e7e08dbb3a minor fixes 2017-08-29 12:07:57 +00:00
02e2f0c07a Merge pull request #1066 from mailpoet/premium-update-warning
Premium update warning [PREMIUM-28]
2017-08-29 12:52:18 +03:00
c75b6bd7eb Show warning only on plugins page
[PREMIUM-28]
2017-08-29 11:22:51 +02:00
b74be8777a Display warning on Email pages
[PREMIUM-28]
2017-08-29 11:22:51 +02:00
7463e0d1f1 Update invalid key message
[PREMIUM-28]
2017-08-29 11:22:51 +02:00
a378880cf8 Merge pull request #1069 from mailpoet/bridge_forbidden_response
Adds 403 response code that mirrors 401 behavior [MAILPOET-1070]
2017-08-29 11:20:56 +03:00
33fa496913 Add a message for an already used MSS key [MAILPOET-1070] 2017-08-29 11:10:09 +03:00
eff996e1f8 Unify key state constant names, leave back compat with unlocker [MAILPOET-1070] 2017-08-29 10:58:16 +03:00
28b894b26b Add test cases [MAILPOET-1070] 2017-08-29 09:20:03 +03:00
c914aedc0d Simplify API response codes handling [MAILPOET-1070] 2017-08-29 09:18:08 +03:00
1745b67d64 Adds 403 response code that mirrors 401 behavior 2017-08-28 21:25:54 -04:00
2d25974fdc Merge pull request #1068 from mailpoet/helpscout
Update HS Beacon icon to question mark [MAILPOET-869]
2017-08-28 19:49:12 -04:00
51a02784e2 Update HS Beacon icon to question mark [MAILPOET-869] 2017-08-28 19:12:27 +03:00
b9bdc86fd9 Add emoji support to newsletter body [MAILPOET-1009] 2017-08-28 19:07:17 +03:00
e580e6b92b Merge pull request #1041 from mailpoet/access_control
Allows granular control of access to various parts of the plugin [MAILPOET-1057] [MAILPOET-1048]
2017-08-28 16:48:47 +03:00
96f77498f7 Merge pull request #1061 from mailpoet/safari-error-fix
Safari error fix [MAILPOET-1011]
2017-08-28 13:33:43 +02:00
62ce7c0437 Merge pull request #1062 from mailpoet/wp_user_subscription_update_fix
Prevents WP subscribers' first/last name from being erased [MAILPOET-1062]
2017-08-28 12:57:25 +03:00
c1e542cb5a Reschedules past due scheduled queues when reactivating notification 2017-08-28 09:20:17 +02:00
544bf0ddfd Merge pull request #1064 from mailpoet/welcome_alc_fix
Don't track sent ALC posts for welcome and standard emails, always send the latest posts [MAILPOET-1069]
2017-08-25 10:36:46 -04:00
609f1b5e67 Tracking new events 2017-08-25 13:19:52 +00:00
4616cf67bf Fix a test [MAILPOET-1069] 2017-08-25 16:10:01 +03:00
cc5227ca0d Don't track sent ALC posts for welcome and standard emails (always send the latest posts) [MAILPOET-1069] 2017-08-25 15:51:45 +03:00
26bccd95d4 Uses method vs. accessing class internals to get user capability 2017-08-24 13:58:54 -04:00
af58814fe7 Moves AccessControl intialization outside of Router to Initializer 2017-08-24 13:56:17 -04:00
7d9b4b31aa Removes unused constructor parameter 2017-08-24 13:37:49 -04:00
8a8108b41d Prevents WP subscribers' first/last name from being erased when updating
subscription
2017-08-24 13:19:42 -04:00
d92b1f57bd Merge pull request #1060 from mailpoet/mp2_forms_fix
Don't process the wysija_form shortcode to allow MP2 forms to work [MAILPOET-1067]
2017-08-24 10:40:10 -04:00
52ef7bece4 Merge pull request #1053 from mailpoet/editor_save
Save newsletter when clicked on "Next" button [MAILPOET-1051]
2017-08-24 09:03:34 -04:00
dc11046ad1 Fixes undefined JS error when vendor.js is loaded deferred
[MAILPOET-1026]
2017-08-24 13:37:15 +02:00
01f41b9798 Fix App and Application argument naming 2017-08-24 14:17:32 +03:00
9c0d9c31f8 Refactor cancelAutosave to return early 2017-08-24 13:48:13 +03:00
df499095c4 Fix test indentation 2017-08-24 13:40:46 +03:00
05dca3d2ce Excludes honeypot from subscription management form 2017-08-24 11:17:40 +02:00
ec35b90f3e Fix react warning
[MAILPOET-1011]
2017-08-24 11:01:33 +02:00
1b7e3a997f Fix not fully formated selector
[MAILPOET-1011]
2017-08-24 10:23:42 +02:00
c598537025 Remove empty lines 2017-08-24 09:16:51 +02:00
6f149e3ec4 tests: quote-props 2017-08-24 09:16:51 +02:00
d181bde0e9 tests: quotes 2017-08-24 09:16:51 +02:00
2985705b14 ES6: quote-props 2017-08-24 09:16:51 +02:00
6ce925fbe8 ES6: quotes 2017-08-24 09:16:51 +02:00
b8aceff61f ES5: quote-props 2017-08-24 09:16:51 +02:00
cd091c2af6 ES5: quotes 2017-08-24 09:16:51 +02:00
510cacf2fd Don't process the wysija_form shortcode to allow MP2 forms to work [MAILPOET-1067] 2017-08-24 08:22:10 +03:00
eac6b1b414 Corrects coding style 2017-08-23 11:45:33 -04:00
316fa91a10 Moves AccessControl initialization outside of API to Initializer 2017-08-23 11:28:09 -04:00
7c23415d26 Updates unit test as a result of AccessControl implementation 2017-08-23 11:28:09 -04:00
28320cdbb6 Updates permission validation method on AccessControl
Adds/updates unit tests
2017-08-23 11:28:08 -04:00
48f3ae4ea1 Adds access control unit tests 2017-08-23 11:28:08 -04:00
e47c8bc701 Adds access control tests for Router 2017-08-23 11:28:08 -04:00
78429d8f91 Validates global permission at the AccessControl level
Changes error response code on invalid permission
2017-08-23 11:27:54 -04:00
80c4eeed5e Merge pull request #1055 from mailpoet/new-poll
New poll [MAILPOET-1040]
2017-08-23 14:45:05 +02:00
5985d659f9 New poll
[MAILPOET-1040]
2017-08-23 14:11:35 +02:00
638de3cf55 Merge pull request #1054 from mailpoet/coverage-fix
Coverage fix [MAILPOET-1064]
2017-08-23 13:41:43 +03:00
967fa09f4f Remove redundant build
[MAILPOET-1064]
2017-08-23 12:32:34 +02:00
a15e1200b5 Upgrade codeception version
[MAILPOET-1064]
2017-08-23 12:32:34 +02:00
a15b46cbab Fix Code coverage reporting
[MAILPOET-1064]
2017-08-23 12:15:56 +02:00
dcb0b45c21 Save newsletter before navigating away when clicked on "Next" button 2017-08-22 17:34:23 +03:00
1b756ef0b2 Adds access management to router and updates endpoints accordingly 2017-08-22 09:06:20 -04:00
5553817f9a Creates method to get user's first capability 2017-08-22 09:06:20 -04:00
4b7fb3ae3d Updates access permission names to improve clarity 2017-08-22 09:06:20 -04:00
efa231b08f Removes AccessControl from Migrator and Changelog 2017-08-22 09:06:20 -04:00
8d8dfaa11f Uses Intializer to check permissions before running Activator 2017-08-22 09:06:20 -04:00
5ba2c4bc3a Removes AccessControl from individual API endpoints 2017-08-22 09:06:20 -04:00
788494ec47 Updates API initialization 2017-08-22 09:06:20 -04:00
5e7f9e3edf Passes AccessControl to JSON API via constructor parameter
Removes passing AccessControl to individual API endpoints
2017-08-22 09:06:20 -04:00
2e5554a3af Refactors AccessControl and passes it as dependency to JSON API and Menu 2017-08-22 09:06:20 -04:00
51fbf29031 Modifies Activator to use AccessControl 2017-08-22 09:06:19 -04:00
c3c6ce989c Modifies Menu to use AccessControl 2017-08-22 09:06:19 -04:00
a241d0c7bc Modifies JSON API to use AccessControl 2017-08-22 09:06:19 -04:00
632bce7894 Adds AccessControl class that defines permissions for major plugin
operations
2017-08-22 09:04:39 -04:00
1151354278 Conditionally uses set_time_limit() when function is not disabled 2017-08-22 09:04:39 -04:00
365 changed files with 20971 additions and 7885 deletions

View File

@ -1,6 +1,4 @@
Listen 8080 <VirtualHost *:80>
<VirtualHost *:8080>
UseCanonicalName Off UseCanonicalName Off
ServerName mailpoet.loc ServerName mailpoet.loc
DocumentRoot /home/circleci/mailpoet/wordpress DocumentRoot /home/circleci/mailpoet/wordpress
@ -8,6 +6,9 @@ Listen 8080
LogLevel notice LogLevel notice
<Directory /home/circleci/mailpoet/wordpress> <Directory /home/circleci/mailpoet/wordpress>
Options Indexes FollowSymLinks
AllowOverride All
RewriteEngine On
Require all granted Require all granted
</Directory> </Directory>
</VirtualHost> </VirtualHost>

View File

@ -81,6 +81,7 @@ jobs:
curl -sS https://getcomposer.org/installer | php curl -sS https://getcomposer.org/installer | php
php composer.phar install php composer.phar install
./do install ./do install
./do compile:all --env production
- save_cache: - save_cache:
key: composer-{{ checksum "composer.json" }}-{{ checksum "composer.lock" }} key: composer-{{ checksum "composer.json" }}-{{ checksum "composer.lock" }}
paths: paths:
@ -94,9 +95,9 @@ jobs:
command: | command: |
docker-compose run codeception --steps --debug -vvv --html --xml docker-compose run codeception --steps --debug -vvv --html --xml
- store_artifacts: - store_artifacts:
path: ~/mailpoet/tests/acceptance-tests/_output path: tests/_output
- store_test_results: - store_test_results:
path: ~/mailpoet/tests/acceptance-tests/_output path: tests/_output
php7: php7:
working_directory: /home/circleci/mailpoet working_directory: /home/circleci/mailpoet
docker: docker:
@ -119,7 +120,38 @@ jobs:
- run: - run:
name: "PHP Unit tests" name: "PHP Unit tests"
command: | command: |
WP_TEST_PATH="/home/circleci/mailpoet/wordpress" ./do t:u --xml ./do t:u --xml
- store_test_results:
path: tests/_output
- store_artifacts:
path: tests/_output
destination: codeception
- store_artifacts:
path: /tmp/fake-mailer/
destination: fake-mailer
php7_multisite:
working_directory: /home/circleci/mailpoet
docker:
- image: circleci/php:7.1-apache-browsers
- image: circleci/mysql:5.7
environment:
TZ: /usr/share/zoneinfo/Etc/UTC
steps:
- checkout
- run:
name: "Set up virtual host"
command: echo 127.0.0.1 mailpoet.loc | sudo tee -a /etc/hosts
- restore_cache:
key: composer-{{ checksum "composer.json" }}-{{ checksum "composer.lock" }}
- restore_cache:
key: npm-{{ checksum "package.json" }}
- run:
name: "Set up test environment"
command: source ./.circleci/setup.bash && setup php7_multisite
- run:
name: "PHP Unit tests"
command: |
./do t:multisite-unit --xml
- store_test_results: - store_test_results:
path: tests/_output path: tests/_output
- store_artifacts: - store_artifacts:
@ -134,4 +166,5 @@ workflows:
jobs: jobs:
- qa_js_php5 - qa_js_php5
- php7 - php7
- php7_multisite
- acceptance_tests - acceptance_tests

View File

@ -2,8 +2,11 @@
function setup { function setup {
local version=$1 local version=$1
local wp_cli_wordpress_path="--path=wordpress"
local wp_cli_allow_root="--allow-root"
# install PHP dependencies for WordPress # install PHP dependencies for WordPress
if [[ $version == "php7" ]]; then if [[ $version == "php7" ]] || [[ $version == "php7_multisite" ]]; then
echo "deb http://packages.dotdeb.org jessie all" | sudo tee -a /etc/apt/sources.list.d/dotdeb.list echo "deb http://packages.dotdeb.org jessie all" | sudo tee -a /etc/apt/sources.list.d/dotdeb.list
echo "deb-src http://packages.dotdeb.org jessie all" | sudo tee -a /etc/apt/sources.list.d/dotdeb.list echo "deb-src http://packages.dotdeb.org jessie all" | sudo tee -a /etc/apt/sources.list.d/dotdeb.list
wget -qO - http://www.dotdeb.org/dotdeb.gpg | sudo apt-key add - wget -qO - http://www.dotdeb.org/dotdeb.gpg | sudo apt-key add -
@ -15,34 +18,66 @@ function setup {
sudo apt-get install mysql-client php5-mysql zlib1g-dev sudo apt-get install mysql-client php5-mysql zlib1g-dev
sudo docker-php-ext-install mysql mysqli pdo pdo_mysql zip sudo docker-php-ext-install mysql mysqli pdo pdo_mysql zip
fi fi
# Add a fake sendmail mailer # Add a fake sendmail mailer
sudo cp ./.circleci/fake-sendmail.php /usr/local/bin/ sudo cp ./.circleci/fake-sendmail.php /usr/local/bin/
# configure Apache # configure Apache
sudo cp ./.circleci/mailpoet_php.ini /usr/local/etc/php/conf.d/ sudo cp ./.circleci/mailpoet_php.ini /usr/local/etc/php/conf.d/
sudo cp ./.circleci/apache/mailpoet.loc.conf /etc/apache2/sites-available sudo cp ./.circleci/apache/mailpoet.loc.conf /etc/apache2/sites-available
sudo a2dissite 000-default.conf
sudo a2ensite mailpoet.loc sudo a2ensite mailpoet.loc
sudo a2enmod rewrite sudo a2enmod rewrite
sudo service apache2 restart sudo service apache2 restart
# Install NodeJS+NPM # Install NodeJS+NPM
curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash - curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
sudo apt-get install nodejs build-essential sudo apt-get install nodejs build-essential
# install plugin dependencies # install plugin dependencies
curl -sS https://getcomposer.org/installer | php curl -sS https://getcomposer.org/installer | php
./composer.phar install ./composer.phar install
./do install ./do install
# Set up Wordpress
# Set up WordPress
mysql -h 127.0.0.1 -u root -e "create database wordpress" mysql -h 127.0.0.1 -u root -e "create database wordpress"
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
chmod +x wp-cli.phar chmod +x wp-cli.phar
./wp-cli.phar core download --allow-root --path=wordpress sudo mv wp-cli.phar /usr/local/bin/wp
wp core download $wp_cli_wordpress_path $wp_cli_allow_root
# Generate `wp-config.php` file with debugging enabled # Generate `wp-config.php` file with debugging enabled
echo "define(\"WP_DEBUG\", true);" | ./wp-cli.phar core config --allow-root --dbname=wordpress --dbuser=root --dbhost=127.0.0.1 --path=wordpress --extra-php echo "define(\"WP_DEBUG\", true);" | wp core config --dbname=wordpress --dbuser=root --dbhost=127.0.0.1 --extra-php $wp_cli_wordpress_path $wp_cli_allow_root
# Change default table prefix
sed -i "s/\$table_prefix = 'wp_';/\$table_prefix = 'mp_';/" ./wordpress/wp-config.php
# Install WordPress # Install WordPress
./wp-cli.phar core install --allow-root --admin_name=admin --admin_password=admin --admin_email=admin@mailpoet.loc --url=http://mailpoet.loc:8080 --title=WordPress --path=wordpress if [[ $version == "php7_multisite" ]]; then
# Configure multisite environment
wp core multisite-install --admin_name=admin --admin_password=admin --admin_email=admin@mailpoet.loc --url=http://mailpoet.loc --title="WordPress MultiSite" $wp_cli_wordpress_path $wp_cli_allow_root
cp ./.circleci/wordpress/.htaccess ./wordpress/
# Add a second blog
wp site create --slug=php7_multisite $wp_cli_wordpress_path $wp_cli_allow_root
echo "WP_TEST_MULTISITE_SLUG=php7_multisite" >> .env
echo "WP_TEST_PATH_MULTISITE=/home/circleci/mailpoet/wordpress" >> .env
echo "HTTP_HOST=mailpoet.loc" >> .env
# Add a third dummy blog
wp site create --slug=dummy_multisite $wp_cli_wordpress_path $wp_cli_allow_root
else
wp core install --admin_name=admin --admin_password=admin --admin_email=admin@mailpoet.loc --url=http://mailpoet.loc --title="WordPress Single" $wp_cli_wordpress_path $wp_cli_allow_root
echo "WP_TEST_PATH=/home/circleci/mailpoet/wordpress" >> .env
fi
# Softlink plugin to plugin path # Softlink plugin to plugin path
ln -s ../../.. wordpress/wp-content/plugins/mailpoet ln -s ../../.. wordpress/wp-content/plugins/mailpoet
./wp-cli.phar plugin activate mailpoet --path=wordpress
# Create .env file with correct path to WP installation # Activate plugin
# TODO: Remove this line after PR gets merged and CircleCI env variables change if [[ $version == "php7_multisite" ]]; then
echo "WP_TEST_PATH=\"/home/circleci/mailpoet/wordpress\"" > .env wp plugin activate mailpoet --url=http://mailpoet.loc/php7_multisite/ $wp_cli_wordpress_path $wp_cli_allow_root
else
wp plugin activate mailpoet $wp_cli_wordpress_path $wp_cli_allow_root
fi
} }

View File

@ -0,0 +1,12 @@
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?wp-admin$ $1wp-admin/ [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(wp-(content|admin|includes).*) $2 [L]
RewriteRule ^([_0-9a-zA-Z-]+/)?(.*\.php)$ $2 [L]
RewriteRule . index.php [L]

View File

@ -1,4 +1,6 @@
WP_TEST_PATH="/var/www/wordpress" WP_TEST_PATH="/var/www/wordpress"
WP_TEST_PATH_MULTISITE="/var/www/wordpress"
WP_TEST_MULTISITE_SLUG=""
WP_TEST_ENABLE_NETWORK_TESTS="true" WP_TEST_ENABLE_NETWORK_TESTS="true"
WP_TEST_IMPORT_MAILCHIMP_API="" WP_TEST_IMPORT_MAILCHIMP_API=""
WP_TEST_IMPORT_MAILCHIMP_LISTS="" // (separated with comma) WP_TEST_IMPORT_MAILCHIMP_LISTS="" // (separated with comma)
@ -17,3 +19,4 @@ WP_TEST_MAILER_SMTP_PASSWORD=""
WP_SVN_USERNAME="" WP_SVN_USERNAME=""
WP_SVN_PASSWORD="" WP_SVN_PASSWORD=""
WP_TRANSIFEX_API_TOKEN="" WP_TRANSIFEX_API_TOKEN=""
HTTP_HOST="" // URL of your site (used for multisite env and equals to DOMAIN_CURRENT_SITE from wp-config.php)

View File

@ -9,85 +9,48 @@
}, },
"rules": { "rules": {
"import/no-amd": 0, "import/no-amd": 0,
"space-before-function-paren": 0,
"prefer-arrow-callback": 0, "prefer-arrow-callback": 0,
"no-undef": 0,
"key-spacing": 0,
"radix": 0, "radix": 0,
"no-alert": 0, "no-alert": 0,
"block-scoped-var": 0,
"guard-for-in": 0, "guard-for-in": 0,
"no-prototype-builtins": 0, "no-prototype-builtins": 0,
"no-restricted-syntax": 0, "no-restricted-syntax": 0,
"newline-per-chained-call": 0,
"no-useless-concat": 0, "no-useless-concat": 0,
"no-multi-spaces": 0,
"no-nested-ternary": 0, "no-nested-ternary": 0,
"semi-spacing": 0,
"no-sequences": 0, "no-sequences": 0,
"no-useless-return": 0, "no-useless-return": 0,
"array-callback-return": 0, "array-callback-return": 0,
"new-cap": 0, "new-cap": 0,
"no-continue": 0, "no-continue": 0,
"no-new": 0, "no-new": 0,
"space-unary-ops": 0,
"no-redeclare": 0, "no-redeclare": 0,
"no-console": 0, "no-console": 0,
"no-empty": 0, "no-empty": 0,
"no-extra-semi": 0,
"no-useless-escape": 0, "no-useless-escape": 0,
"wrap-iife": 0, "wrap-iife": 0,
"no-unused-expressions": 0,
"block-spacing": 0,
"computed-property-spacing": 0,
"no-plusplus": 0, "no-plusplus": 0,
"array-bracket-spacing": 0,
"lines-around-directive": 0,
"no-unreachable": 0,
"default-case": 0, "default-case": 0,
"no-lonely-if": 0, "no-lonely-if": 0,
"space-before-blocks": 0,
"no-unneeded-ternary": 0,
"no-mixed-operators": 0, "no-mixed-operators": 0,
"eqeqeq": 0, "eqeqeq": 0,
"space-in-parens": 0,
"semi": 0,
"max-len": 0, "max-len": 0,
"no-trailing-spaces": 0,
"global-require": 0, "global-require": 0,
"no-throw-literal": 0, "no-throw-literal": 0,
"no-extra-bind": 0, "no-extra-bind": 0,
"one-var-declaration-per-line": 0,
"consistent-return": 0, "consistent-return": 0,
"no-shadow": 0, "no-shadow": 0,
"no-underscore-dangle": 0, "no-underscore-dangle": 0,
"brace-style": 0, "brace-style": 0,
"no-else-return": 0, "no-else-return": 0,
"no-use-before-define": 0, "no-use-before-define": 0,
"one-var": 0,
"camelcase": 0, "camelcase": 0,
"spaced-comment": 0,
"quotes": 0,
"padded-blocks": 0, "padded-blocks": 0,
"object-curly-spacing": 0,
"strict": 0, "strict": 0,
"vars-on-top": 0,
"no-var": 0,
"space-infix-ops": 0, "space-infix-ops": 0,
"no-unused-vars": 0,
"object-shorthand": 0, "object-shorthand": 0,
"new-parens": 0, "new-parens": 0,
"keyword-spacing": 0,
"eol-last": 0, "eol-last": 0,
"dot-notation": 0, "dot-notation": 0,
"linebreak-style": 0,
"indent": 0,
"quote-props": 0,
"prefer-template": 0, "prefer-template": 0,
"func-names": 0 "func-names": 0
} }

View File

@ -10,87 +10,48 @@
"jsx": true "jsx": true
} }
}, },
"settings": {
"import/resolver": "webpack"
},
"rules": { "rules": {
// Exceptions
"comma-dangle": ["error", "always-multiline"], "comma-dangle": ["error", "always-multiline"],
"no-script-url": 0,
// Temporary
"import/no-amd": 0, "import/no-amd": 0,
"react/no-multi-comp": 0, "react/no-multi-comp": 0,
"react/sort-comp": 0, "react/sort-comp": 0,
"react/jsx-max-props-per-line": 0, "react/jsx-max-props-per-line": 0,
"react/prop-types": 0, "react/prop-types": 0,
"react/jsx-first-prop-new-line": 0, "react/jsx-first-prop-new-line": 0,
"react/jsx-indent-props": 0,
"react/no-is-mounted": 0, "react/no-is-mounted": 0,
"react/jsx-no-target-blank": 0, "react/jsx-no-target-blank": 0,
"react/no-render-return-value": 0, "react/no-render-return-value": 0,
"react/jsx-boolean-value": 0, "react/jsx-boolean-value": 0,
"react/jsx-indent": 0,
"react/jsx-no-bind": 0, "react/jsx-no-bind": 0,
"react/no-array-index-key": 0, "react/no-array-index-key": 0,
"react/self-closing-comp": 0, "react/self-closing-comp": 0,
"react/jsx-tag-spacing": 0,
"react/jsx-closing-bracket-location": 0, "react/jsx-closing-bracket-location": 0,
"react/no-string-refs": 0, "react/no-string-refs": 0,
"react/jsx-curly-spacing": 0,
"react/no-did-mount-set-state": 0, "react/no-did-mount-set-state": 0,
"react/prefer-stateless-function": 0, "react/prefer-stateless-function": 0,
"jsx-a11y/label-has-for": 0, "jsx-a11y/label-has-for": 0,
"jsx-a11y/no-static-element-interactions": 0, "jsx-a11y/no-static-element-interactions": 0,
"jsx-a11y/alt-text": 0, "jsx-a11y/alt-text": 0,
"func-names": 0, "func-names": 0,
"object-shorthand": 0, "object-shorthand": 0,
"no-bitwise": 0, "no-bitwise": 0,
"arrow-body-style": 0, "arrow-body-style": 0,
"prefer-template": 0, "prefer-template": 0,
"keyword-spacing": 0,
"default-case": 0, "default-case": 0,
"quote-props": 0,
"array-callback-return": 0, "array-callback-return": 0,
"consistent-return": 0, "consistent-return": 0,
"no-unreachable": 0,
"no-extra-semi": 0,
"import/no-unresolved": 0,
"import/extensions": 0, "import/extensions": 0,
"import/no-extraneous-dependencies": 0, "import/no-extraneous-dependencies": 0,
"camelcase": 0, "camelcase": 0,
"template-curly-spacing": 0,
"quotes": 0,
"eqeqeq": 0, "eqeqeq": 0,
"no-lonely-if": 0,
"space-unary-ops": 0, "space-unary-ops": 0,
"block-scoped-var": 0,
"no-extra-bind": 0,
"no-multi-spaces": 0,
"class-methods-use-this": 0,
"key-spacing": 0,
"no-multiple-empty-lines": 0,
"space-in-parens": 0,
"no-case-declarations": 0,
"array-bracket-spacing": 0,
"newline-per-chained-call": 0,
"no-else-return": 0,
"max-len": 0,
"no-useless-concat": 0,
"no-unused-expressions": 0,
"no-sequences": 0,
"no-extra-boolean-cast": 0,
"dot-notation": 0,
"no-shadow": 0,
"one-var": 0,
"no-alert": 0,
"one-var-declaration-per-line": 0,
"no-script-url": 0,
"wrap-iife": 0,
"vars-on-top": 0,
"space-infix-ops": 0, "space-infix-ops": 0,
"no-irregular-whitespace": 0, "no-irregular-whitespace": 0
"padded-blocks": 0,
"no-underscore-dangle": 0,
"no-undef": 0
} }
} }

View File

@ -8,37 +8,9 @@
"ecmaVersion": 6 "ecmaVersion": 6
}, },
"rules": { "rules": {
"import/no-amd": 0, // Exceptions
"no-undef": 0,
"one-var": 0,
"indent": 0,
"linebreak-style": 0,
"no-whitespace-before-property": 0,
"object-property-newline": 0,
"global-require": 0,
"semi": 0,
"keyword-spacing": 0,
"no-bitwise": 0,
"newline-per-chained-call": 0,
"no-spaced-func": 0,
"func-call-spacing": 0,
"max-len": 0,
"space-unary-ops": 0,
"quotes": 0,
"no-unused-vars": 0,
"no-unused-expressions": 0,
"no-underscore-dangle": 0,
"quote-props": 0,
"no-shadow": 0,
"padded-blocks": 0,
"vars-on-top": 0,
"space-before-blocks": 0,
"object-curly-spacing": 0,
"one-var-declaration-per-line": 0,
"func-names": 0, "func-names": 0,
"space-before-function-paren": 0 // Temporary
"no-underscore-dangle": 0
} }
} }

1
.gitignore vendored
View File

@ -2,6 +2,7 @@
TODO TODO
composer.phar composer.phar
/vendor /vendor
/vendor_backup
tests/_output/* tests/_output/*
tests/_support/_generated/* tests/_support/_generated/*
node_modules node_modules

View File

@ -90,6 +90,7 @@ class RoboFile extends \Robo\Tasks {
$css_files = array( $css_files = array(
'assets/css/src/admin.styl', 'assets/css/src/admin.styl',
'assets/css/src/admin-global.styl',
'assets/css/src/newsletter_editor/newsletter_editor.styl', 'assets/css/src/newsletter_editor/newsletter_editor.styl',
'assets/css/src/public.styl', 'assets/css/src/public.styl',
'assets/css/src/rtl.styl', 'assets/css/src/rtl.styl',
@ -152,23 +153,34 @@ class RoboFile extends \Robo\Tasks {
return $this->_exec('./tasks/transifex_init.sh'); return $this->_exec('./tasks/transifex_init.sh');
} }
function testUnit($opts=['file' => null, 'xml' => false]) { function testUnit($opts=['file' => null, 'xml' => false, 'multisite' => false]) {
$this->loadEnv(); $this->loadEnv();
$this->_exec('vendor/bin/codecept build -c codeception.unit.yml');
$command = 'vendor/bin/codecept run unit -c codeception.unit.yml -f '.(($opts['file']) ? $opts['file'] : ''); $command = 'vendor/bin/codecept run unit -c codeception.unit.yml';
if($opts['multisite']) {
$command = 'MULTISITE=true ' . $command;
}
if($opts['file']) {
$command .= ' -f ' . $opts['file'];
}
if($opts['xml']) { if($opts['xml']) {
$command .= ' --xml'; $command .= ' --xml';
} }
return $this->_exec($command); return $this->_exec($command);
} }
function testMultisiteUnit($opts=['file' => null, 'xml' => false, 'multisite' => true]) {
return $this->testUnit($opts);
}
function testCoverage($opts=['file' => null, 'xml' => false]) { function testCoverage($opts=['file' => null, 'xml' => false]) {
$this->loadEnv(); $this->loadEnv();
$this->_exec('vendor/bin/codecept build -c codeception.unit.yml');
$command = join(' ', array( $command = join(' ', array(
'vendor/bin/codecept run -c codeception.unit.yml ', 'vendor/bin/codecept run unit -c codeception.unit.yml ',
(($opts['file']) ? $opts['file'] : ''), (($opts['file']) ? $opts['file'] : ''),
'--coverage', '--coverage',
($opts['xml']) ? '--coverage-xml' : '--coverage-html' ($opts['xml']) ? '--coverage-xml' : '--coverage-html'
@ -290,15 +302,16 @@ class RoboFile extends \Robo\Tasks {
} }
function svnPublish($opts = ['force' => false]) { function svnPublish($opts = ['force' => false]) {
$this->loadWPFunctions(); $this->loadEnv();
$svn_dir = ".mp_svn"; $svn_dir = ".mp_svn";
$plugin_data = get_plugin_data('mailpoet.php', false, false); $plugin_version = $this->getPluginVersion('mailpoet.php');
$plugin_version = $plugin_data['Version']; $plugin_dist_name = 'mailpoet';
$plugin_dist_name = sanitize_title_with_dashes($plugin_data['Name']);
$plugin_dist_name = explode('-', $plugin_dist_name);
$plugin_dist_name = $plugin_dist_name[0];
$plugin_dist_file = $plugin_dist_name . '.zip'; $plugin_dist_file = $plugin_dist_name . '.zip';
if(!$plugin_version) {
throw new \Exception('Could not parse plugin version, check the plugin header');
}
$this->say('Publishing version: ' . $plugin_version); $this->say('Publishing version: ' . $plugin_version);
// Sanity checks // Sanity checks
@ -417,13 +430,9 @@ class RoboFile extends \Robo\Tasks {
$dotenv->load(); $dotenv->load();
} }
protected function loadWPFunctions() { protected function getPluginVersion($file) {
$this->loadEnv(); $data = file_get_contents($file);
define('ABSPATH', getenv('WP_TEST_PATH') . '/'); preg_match('/^[ \t*]*Version:(.*)$/mi', $data, $m);
define('WPINC', 'wp-includes'); return !empty($m[1]) ? trim($m[1]) : false;
require_once(ABSPATH . WPINC . '/functions.php');
require_once(ABSPATH . WPINC . '/formatting.php');
require_once(ABSPATH . WPINC . '/plugin.php');
require_once(ABSPATH . 'wp-admin/includes/plugin.php');
} }
} }

View File

@ -0,0 +1,15 @@
@import 'nib'
@require 'icons'
/*
Style for Members plugin
*/
.members-tab-title
.mailpoet-icon-logo
vertical-align: middle;
height: 20px;
width: 20px;
font-size: 20px;
margin-right: 3px;

View File

@ -27,3 +27,5 @@
@require 'pages_custom' @require 'pages_custom'
@require 'mp2migrator' @require 'mp2migrator'
@require '../../../node_modules/react-confirm-alert/src/react-confirm-alert.css'

24
assets/css/src/icons.styl Normal file
View File

@ -0,0 +1,24 @@
icon-font-path ?= "../fonts"
@font-face
font-family 'mailpoet'
src url(icon-font-path + '/mailpoet.ttf?mx0b6n') format('truetype'), url(icon-font-path + '/mailpoet.woff?mx0b6n') format('woff'), url(icon-font-path + '/mailpoet.svg?mx0b6n#mailpoet') format('svg')
font-weight normal
font-style normal
[class^="mailpoet-icon-"], [class*=" mailpoet-icon-"]
font-family 'mailpoet' !important
speak none
font-style normal
font-weight normal
font-variant normal
text-transform none
line-height 1
/* Better Font Rendering =========== */
-webkit-font-smoothing antialiased
-moz-osx-font-smoothing grayscale
.mailpoet-icon-logo
&:before
content "\e900"

View File

@ -48,3 +48,41 @@ $resize-handle-z-index = 2
.mailpoet_resize_handle .mailpoet_resize_handle
display: inline-block display: inline-block
.mailpoet_image_resize_handle_container
position: absolute
bottom: 0
right: 0
width: 20px
height: 20px
.mailpoet_image_resize_handle
position: relative
background: $resize-handle-background-color
border-radius(3px)
display: inline-block
width: 20px
height: 20px
cursor: nwse-resize
z-index: $resize-handle-z-index
.mailpoet_image_resize_handle_text,
.mailpoet_image_resize_handle_icon
pointer-events: none
.mailpoet_image_resize_handle_icon
position: absolute
top: 0
right: 0
& > svg
width: 100%
height: 100%
fill: $resize-handle-font-color
.mailpoet_block.mailpoet_image_resize_active > .mailpoet_block_highlight
border: 1px dashed $resize-active-color
.mailpoet_image_resize_handle
display: inline-block

View File

@ -23,9 +23,11 @@ $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
&.mailpoet_highlight > .mailpoet_block_highlight
border: 1px dashed $block-hover-highlight-color !important
.mailpoet_content .mailpoet_content
position: relative position: relative
line-height: $block-text-line-height line-height: $block-text-line-height

View File

@ -3,14 +3,19 @@
img img
vertical-align: bottom vertical-align: bottom
max-width: 100% max-width: 100%
width: auto
height: auto height: auto
&.mailpoet_full_image &.mailpoet_full_image
padding-left: 0 padding-left: 0
padding-right: 0 padding-right: 0
margin: auto
margin-bottom: 0 margin-bottom: 0
.mailpoet_content a:hover .mailpoet_content
margin: auto
max-width: 100%
min-width: 36px
a:hover
cursor: all-scroll cursor: all-scroll

View File

@ -2,7 +2,7 @@ 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: $max-height max-height: $max-height
opacity: 1 opacity: 1
overflow-y: hidden overflow-y: inherit
&.mailpoet_closed &.mailpoet_closed
max-height: 0px max-height: 0px

View File

@ -33,3 +33,6 @@ Custom styles for MailPoet pages.
p.top-space-triple p.top-space-triple
margin-top: 3em margin-top: 3em
p.mailpoet-top-text
margin-right: 0

View File

@ -62,6 +62,15 @@
margin-bottom: 2em margin-bottom: 2em
margin-top: 2em margin-top: 2em
.sending-free-plan-button
background: #FF5301
border-color: #e64c03
text-shadow: 0 -1px 1px #e64c03
box-shadow: 0 1px 0 #e64c03
margin: 10px 0
strong
text-transform: uppercase
.mailpoet_success_item::before .mailpoet_success_item::before
content ' ' content ' '

11
assets/fonts/mailpoet.svg Normal file
View File

@ -0,0 +1,11 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata>Generated by IcoMoon</metadata>
<defs>
<font id="mailpoet" horiz-adv-x="1024">
<font-face units-per-em="1024" ascent="960" descent="-64" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" horiz-adv-x="0" d="" />
<glyph unicode="&#xe900;" glyph-name="optimised" horiz-adv-x="972" d="M230.188 949.695c-21.982-3.361-41.376-14.741-48.618-28.188l-5.948-11.637 0.517-265.588c0.776-263.779 0.776-265.847 6.206-273.088 11.12-15.258 40.601-22.24 68.79-16.551 16.551 3.621 25.861 9.827 32.584 21.723 3.879 7.499 4.397 23.791 5.689 185.161l1.293 176.628 60.514-161.111c33.102-88.702 63.875-168.612 68.013-177.404 13.707-29.481 35.687-41.376 72.151-39.049 21.206 1.293 39.308 9.827 47.584 22.499 3.361 5.172 35.947 91.806 72.41 192.662s67.237 185.42 68.53 187.49c1.551 2.587 2.587-69.307 2.587-185.937v-190.335l5.948-11.379c8.533-16.809 20.172-21.982 49.652-21.982 27.929 0.259 39.825 4.914 49.911 20.172l6.982 10.603v530.401l-5.689 9.31c-12.671 20.43-50.17 31.033-91.806 25.601-34.394-4.138-53.79-16.292-66.72-41.118-2.587-5.172-35.947-101.89-73.961-214.902s-69.824-206.367-70.6-207.403c-1.034-1.034-32.326 86.115-69.824 193.954-37.757 107.581-71.892 205.075-76.030 216.453-10.086 26.118-25.601 42.929-45.514 48.877-17.326 5.172-46.807 6.982-64.652 4.138zM54.854 243.443c-20.172-3.879-43.963-19.136-51.204-33.619-6.206-11.379-4.914-32.843 2.587-47.841 23.533-46.807 71.634-86.892 126.717-104.736 17.068-5.689 23.274-5.948 120.252-7.499 97.235-1.551 102.926-1.81 116.373-7.241 29.739-11.896 51.204-35.687 61.807-68.013 3.621-11.12 13.964-21.206 25.861-25.344 4.914-1.551 18.361-2.844 29.739-2.844 16.809 0 23.533 1.293 32.584 5.689 11.896 6.206 13.964 9.31 26.895 38.791 11.896 27.671 39.567 49.652 70.858 56.117 8.533 1.81 47.067 2.844 100.856 2.844 99.563 0 113.786 2.068 151.801 20.689 49.652 24.567 96.978 77.84 101.373 113.529 3.104 26.118-17.326 49.394-51.204 58.187-25.601 6.465-41.635-0.517-54.825-24.050-11.12-19.655-29.998-38.015-47.841-46.29l-14.741-6.982-99.563-1.551c-90.77-1.293-101.373-2.068-120.252-6.982-27.154-7.499-58.444-23.016-80.427-40.084l-17.844-13.964-16.809 13.964c-20.689 16.809-51.462 32.584-78.875 39.825-19.136 5.172-28.705 5.948-120.252 7.241l-99.563 1.551-15.775 7.241c-18.102 8.533-32.584 21.982-48.36 45.773-16.034 24.567-26.895 29.998-50.17 25.601z" />
</font></defs></svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
assets/fonts/mailpoet.ttf Normal file

Binary file not shown.

BIN
assets/fonts/mailpoet.woff Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 819 B

After

Width:  |  Height:  |  Size: 814 B

View File

@ -2,11 +2,10 @@ function requestFailed(errorMessage, xhr) {
if (xhr.responseJSON) { if (xhr.responseJSON) {
return xhr.responseJSON; return xhr.responseJSON;
} }
var message = errorMessage.replace("%d", xhr.status);
return { return {
errors: [ errors: [
{ {
message: message message: errorMessage.replace('%d', xhr.status)
} }
] ]
}; };
@ -35,7 +34,7 @@ define('ajax', ['mailpoet', 'jquery', 'underscore'], function(mp, jQuery, _) {
// set default url // set default url
if (this.options.url === null) { if (this.options.url === null) {
this.options.url = ajaxurl; this.options.url = window.ajaxurl;
} }
// set default token // set default token
@ -54,11 +53,13 @@ define('ajax', ['mailpoet', 'jquery', 'underscore'], function(mp, jQuery, _) {
}; };
}, },
request: function (method, options) { request: function (method, options) {
var params;
var deferred;
// set options // set options
this.init(options); this.init(options);
// set request params // set request params
var params = this.getParams(); params = this.getParams();
// remove null values from the data object // remove null values from the data object
if (_.isObject(params.data)) { if (_.isObject(params.data)) {
@ -68,7 +69,7 @@ define('ajax', ['mailpoet', 'jquery', 'underscore'], function(mp, jQuery, _) {
} }
// ajax request // ajax request
var deferred = jQuery.post( deferred = jQuery.post(
this.options.url, this.options.url,
params, params,
null, null,

View File

@ -18,7 +18,7 @@
var eventsCache = []; var eventsCache = [];
function track(name, data) { function track(name, data) {
if (typeof window.mixpanel.track !== "function") { if (typeof window.mixpanel.track !== 'function') {
window.mixpanel.init(window.mixpanelTrackingId); window.mixpanel.init(window.mixpanelTrackingId);
} }
window.mixpanel.track(name, data); window.mixpanel.track(name, data);
@ -38,20 +38,11 @@ function exportMixpanel(mp) {
function trackCachedEvents() { function trackCachedEvents() {
eventsCache.map(function (event) { eventsCache.map(function (event) {
if (window.mailpoet_analytics_enabled || event.forced) { if (window.mailpoet_analytics_enabled || event.forced) {
window.mixpanel.track(event.name, event.data) window.mixpanel.track(event.name, event.data);
} }
}); });
} }
function initializeMixpanelWhenLoaded() {
if (typeof window.mixpanel === "object") {
exportMixpanel(MailPoet);
trackCachedEvents();
} else {
setTimeout(initializeMixpanelWhenLoaded, 100);
}
}
function cacheEvent(forced, name, data) { function cacheEvent(forced, name, data) {
eventsCache.push({ eventsCache.push({
name: name, name: name,
@ -65,6 +56,15 @@ define(
function (mp, _) { function (mp, _) {
var MailPoet = mp; var MailPoet = mp;
function initializeMixpanelWhenLoaded() {
if (typeof window.mixpanel === 'object') {
exportMixpanel(MailPoet);
trackCachedEvents();
} else {
setTimeout(initializeMixpanelWhenLoaded, 100);
}
}
MailPoet.trackEvent = _.partial(cacheEvent, false); MailPoet.trackEvent = _.partial(cacheEvent, false);
MailPoet.forceTrackEvent = _.partial(cacheEvent, true); MailPoet.forceTrackEvent = _.partial(cacheEvent, true);

View File

@ -43,9 +43,10 @@ define('date',
}, },
format: function (date, opts) { format: function (date, opts) {
var options = opts || {}; var options = opts || {};
var momentDate;
this.init(options); this.init(options);
var momentDate = Moment(date, this.convertFormat(options.parseFormat)); momentDate = Moment(date, this.convertFormat(options.parseFormat));
if (options.offset === 0) momentDate = momentDate.utc(); if (options.offset === 0) momentDate = momentDate.utc();
return momentDate.format(this.convertFormat(this.options.format)); return momentDate.format(this.convertFormat(this.options.format));
}, },
@ -71,6 +72,11 @@ define('date',
}); });
}, },
convertFormat: function (format) { convertFormat: function (format) {
var replacements;
var convertedFormat;
var escapeToken;
var index;
var token;
var format_mappings = { var format_mappings = {
date: { date: {
d: 'DD', d: 'DD',
@ -140,12 +146,11 @@ define('date',
if (!format || format.length <= 0) return format; if (!format || format.length <= 0) return format;
var replacements = format_mappings['date']; replacements = format_mappings['date'];
convertedFormat = [];
escapeToken = false;
var convertedFormat = []; for (index = 0, token = ''; format.charAt(index); index += 1) {
var escapeToken = false;
for(var index = 0, token = ''; format.charAt(index); index += 1){
token = format.charAt(index); token = format.charAt(index);
if (escapeToken === true) { if (escapeToken === true) {
convertedFormat.push('[' + token + ']'); convertedFormat.push('[' + token + ']');

View File

@ -143,28 +143,28 @@ define([
switch (dateType) { switch (dateType) {
case 'year_month_day': case 'year_month_day':
value = { value = {
'year': this.state.year, year: this.state.year,
'month': this.state.month, month: this.state.month,
'day': this.state.day, day: this.state.day,
}; };
break; break;
case 'year_month': case 'year_month':
value = { value = {
'year': this.state.year, year: this.state.year,
'month': this.state.month, month: this.state.month,
}; };
break; break;
case 'month': case 'month':
value = { value = {
'month': this.state.month, month: this.state.month,
}; };
break; break;
case 'year': case 'year':
value = { value = {
'year': this.state.year, year: this.state.year,
}; };
break; break;
} }
@ -212,7 +212,6 @@ define([
year={this.state.year} year={this.state.year}
placeholder={this.props.field.year_placeholder} placeholder={this.props.field.year_placeholder}
/>); />);
break;
case 'MM': case 'MM':
return (<FormFieldDateMonth return (<FormFieldDateMonth
@ -224,7 +223,6 @@ define([
monthNames={monthNames} monthNames={monthNames}
placeholder={this.props.field.month_placeholder} placeholder={this.props.field.month_placeholder}
/>); />);
break;
case 'DD': case 'DD':
return (<FormFieldDateDay return (<FormFieldDateDay
@ -235,7 +233,6 @@ define([
day={this.state.day} day={this.state.day}
placeholder={this.props.field.day_placeholder} placeholder={this.props.field.day_placeholder}
/>); />);
break;
} }
}); });
@ -245,7 +242,7 @@ define([
</div> </div>
); );
} }
}; }
return FormFieldDate; return FormFieldDate;
}); });

View File

@ -7,6 +7,7 @@ define([
'form/fields/checkbox.jsx', 'form/fields/checkbox.jsx',
'form/fields/selection.jsx', 'form/fields/selection.jsx',
'form/fields/date.jsx', 'form/fields/date.jsx',
'jquery',
], ],
( (
React, React,
@ -16,7 +17,8 @@ define([
FormFieldRadio, FormFieldRadio,
FormFieldCheckbox, FormFieldCheckbox,
FormFieldSelection, FormFieldSelection,
FormFieldDate FormFieldDate,
jQuery
) => { ) => {
const FormField = React.createClass({ const FormField = React.createClass({
renderField: function (data, inline = false) { renderField: function (data, inline = false) {
@ -30,7 +32,7 @@ define([
let field = false; let field = false;
let dataField = data.field; let dataField = data.field;
if(data.field['field'] !== undefined) { if (data.field.field !== undefined) {
dataField = jQuery.merge(dataField, data.field.field); dataField = jQuery.merge(dataField, data.field.field);
} }
@ -75,19 +77,18 @@ define([
{ description } { description }
</span> </span>
); );
} else { }
return ( return (
<div key={'field-' + (data.index || 0)}> <div key={'field-' + (data.index || 0)}>
{ field } { field }
{ description } { description }
</div> </div>
); );
}
}, },
render: function () { render: function () {
let field = false; let field = false;
if(this.props.field['fields'] !== undefined) { if (this.props.field.fields !== undefined) {
field = this.props.field.fields.map((subfield, index) => { field = this.props.field.fields.map((subfield, index) => {
return this.renderField({ return this.renderField({
index: index, index: index,

View File

@ -17,7 +17,7 @@ const FormFieldSelect = React.createClass({
); );
} }
if (this.props.field['filter'] !== undefined) { if (this.props.field.filter !== undefined) {
filter = this.props.field.filter; filter = this.props.field.filter;
} }
@ -43,7 +43,6 @@ const FormFieldSelect = React.createClass({
const options = keys.map( 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) {
return; return;
} }

View File

@ -60,13 +60,10 @@ define([
templateResult: function (item) { templateResult: function (item) {
if (item.element && item.element.selected) { if (item.element && item.element.selected) {
return null; return null;
} else { } else if (item.title) {
if(item.title) {
return item.title; return item.title;
} else { }
return item.text; return item.text;
}
}
}, },
}); });
@ -86,8 +83,8 @@ define([
this.setState({ select2: true }); this.setState({ select2: true });
}, },
getSelectedValues: function () { getSelectedValues: 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) {
if (this.allowMultipleValues()) { if (this.allowMultipleValues()) {
if (Array.isArray(this.props.item[this.props.field.name])) { if (Array.isArray(this.props.item[this.props.field.name])) {
@ -106,7 +103,7 @@ define([
let items = window['mailpoet_' + this.props.field.endpoint]; let items = window['mailpoet_' + this.props.field.endpoint];
if(this.props.field['filter'] !== undefined) { if (this.props.field.filter !== undefined) {
items = items.filter(this.props.field.filter); items = items.filter(this.props.field.filter);
} }
@ -116,6 +113,7 @@ define([
} }
}, },
handleChange: function (e) { handleChange: function (e) {
let value;
if (this.props.onValueChange !== undefined) { if (this.props.onValueChange !== undefined) {
if (this.props.field.multiple) { if (this.props.field.multiple) {
value = jQuery('#' + this.refs.select.id).val(); value = jQuery('#' + this.refs.select.id).val();
@ -132,19 +130,19 @@ define([
} }
}, },
getLabel: function (item) { getLabel: function (item) {
if(this.props.field['getLabel'] !== undefined) { if (this.props.field.getLabel !== undefined) {
return this.props.field.getLabel(item, this.props.item); return this.props.field.getLabel(item, this.props.item);
} }
return item.name; return item.name;
}, },
getSearchLabel: function (item) { getSearchLabel: function (item) {
if(this.props.field['getSearchLabel'] !== undefined) { if (this.props.field.getSearchLabel !== undefined) {
return this.props.field.getSearchLabel(item, this.props.item); return this.props.field.getSearchLabel(item, this.props.item);
} }
return null; return null;
}, },
getValue: function (item) { getValue: function (item) {
if(this.props.field['getValue'] !== undefined) { if (this.props.field.getValue !== undefined) {
return this.props.field.getValue(item, this.props.item); return this.props.field.getValue(item, this.props.item);
} }
return item.id; return item.id;
@ -153,11 +151,10 @@ define([
// this function may be used to transform the placeholder value into // this function may be used to transform the placeholder value into
// desired value. // desired value.
transformChangedValue: function (value) { transformChangedValue: function (value) {
if(typeof this.props.field['transformChangedValue'] === 'function') { if (typeof this.props.field.transformChangedValue === 'function') {
return this.props.field.transformChangedValue.call(this, value); return this.props.field.transformChangedValue.call(this, value);
} else {
return value;
} }
return value;
}, },
render: function () { render: function () {
const options = this.state.items.map((item, index) => { const options = this.state.items.map((item, index) => {

View File

@ -11,7 +11,7 @@ const FormFieldText = React.createClass({
<input <input
type="text" type="text"
disabled={ disabled={
(this.props.field['disabled'] !== undefined) (this.props.field.disabled !== undefined)
? this.props.field.disabled(this.props.item) ? this.props.field.disabled(this.props.item)
: false : false
} }

View File

@ -5,15 +5,16 @@ define(
'classnames', 'classnames',
'react-router', 'react-router',
'form/fields/field.jsx', 'form/fields/field.jsx',
'jquery',
], ],
( (
React, React,
MailPoet, MailPoet,
classNames, classNames,
Router, Router,
FormField FormField,
jQuery
) => { ) => {
const Form = React.createClass({ const Form = React.createClass({
contextTypes: { contextTypes: {
router: React.PropTypes.object.isRequired, router: React.PropTypes.object.isRequired,
@ -42,7 +43,7 @@ define(
this.loadItem(this.props.params.id); this.loadItem(this.props.params.id);
} else { } else {
this.setState({ this.setState({
item: jQuery('.mailpoet_form').serializeObject(), item: jQuery('.mailpoet_form').mailpoetSerializeObject(),
}); });
} }
} }
@ -99,7 +100,7 @@ define(
// only get values from displayed fields // only get values from displayed fields
const item = {}; const item = {};
this.props.fields.map((field) => { this.props.fields.map((field) => {
if(field['fields'] !== undefined) { if (field.fields !== undefined) {
field.fields.map((subfield) => { field.fields.map((subfield) => {
item[subfield.name] = this.state.item[subfield.name]; item[subfield.name] = this.state.item[subfield.name];
}); });
@ -140,7 +141,7 @@ define(
handleValueChange: function (e) { handleValueChange: function (e) {
if (this.props.onChange) { if (this.props.onChange) {
return this.props.onChange(e); return this.props.onChange(e);
} else { }
const item = this.state.item; const item = this.state.item;
const field = e.target.name; const field = e.target.name;
@ -150,7 +151,6 @@ define(
item: item, item: item,
}); });
return true; return true;
}
}, },
render: function () { render: function () {
let errors; let errors;
@ -166,7 +166,7 @@ define(
const formClasses = classNames( const formClasses = classNames(
'mailpoet_form', 'mailpoet_form',
{ 'mailpoet_form_loading': this.state.loading || this.props.loading } { mailpoet_form_loading: this.state.loading || this.props.loading }
); );
let beforeFormContent = false; let beforeFormContent = false;

View File

@ -4,8 +4,13 @@
* company: Wysija * company: Wysija
* framework: prototype 1.7.2 * framework: prototype 1.7.2
*/ */
'use strict'; 'use strict';
var Observable;
var WysijaHistory;
var WysijaForm;
Event.cacheDelegated = {}; Event.cacheDelegated = {};
Object.extend(document, (function () { Object.extend(document, (function () {
var cache = Event.cacheDelegated; var cache = Event.cacheDelegated;
@ -24,23 +29,26 @@ Object.extend(document, (function() {
function findWrapper(selector, eventName, handler) { function findWrapper(selector, eventName, handler) {
var c = getWrappersForSelector(selector, eventName); var c = getWrappersForSelector(selector, eventName);
return c.find(function (wrapper) { return c.find(function (wrapper) {
return wrapper.handler === handler return wrapper.handler === handler;
}); });
} }
function destroyWrapper(selector, eventName, handler) { function destroyWrapper(selector, eventName, handler) {
var wrapper;
var c = getCacheForSelector(selector); var c = getCacheForSelector(selector);
if (!c[eventName]) return false; if (!c[eventName]) return false;
var wrapper = findWrapper(selector, eventName, handler) wrapper = findWrapper(selector, eventName, handler);
c[eventName] = c[eventName].without(wrapper); c[eventName] = c[eventName].without(wrapper);
return wrapper; return wrapper;
} }
function createWrapper(selector, eventName, handler, context) { function createWrapper(selector, eventName, handler, context) {
var wrapper, c = getWrappersForSelector(selector, eventName); var wrapper;
var element;
var c = getWrappersForSelector(selector, eventName);
if (c.pluck('handler').include(handler)) return false; if (c.pluck('handler').include(handler)) return false;
wrapper = function (event) { wrapper = function (event) {
var element = event.findElement(selector); element = event.findElement(selector);
if (element) handler.call(context || element, event, element); if (element) handler.call(context || element, event, element);
}; };
wrapper.handler = handler; wrapper.handler = handler;
@ -48,13 +56,14 @@ Object.extend(document, (function() {
return wrapper; return wrapper;
} }
return { return {
delegate: function(selector, eventName, handler, context) { delegate: function (selector, eventName) {
var wrapper = createWrapper.apply(null, arguments); var wrapper = createWrapper.apply(null, arguments);
if (wrapper) document.observe(eventName, wrapper); if (wrapper) document.observe(eventName, wrapper);
return document; return document;
}, },
stopDelegating: function(selector, eventName, handler) { stopDelegating: function (selector, eventName) {
var length = arguments.length; var length = arguments.length;
var wrapper;
switch (length) { switch (length) {
case 2: case 2:
getWrappersForSelector(selector, eventName).each(function (wrapper) { getWrappersForSelector(selector, eventName).each(function (wrapper) {
@ -72,15 +81,15 @@ Object.extend(document, (function() {
}); });
break; break;
default: default:
var wrapper = destroyWrapper.apply(null, arguments); wrapper = destroyWrapper.apply(null, arguments);
if (wrapper) document.stopObserving(eventName, wrapper); if (wrapper) document.stopObserving(eventName, wrapper);
} }
return document; return document;
} }
} };
})()); })());
var Observable = (function() { Observable = (function () {
function getEventName(nameA, namespace) { function getEventName(nameA, namespace) {
var name = nameA.substring(2); var name = nameA.substring(2);
if (namespace) name = namespace + ':' + name; if (namespace) name = namespace + ':' + name;
@ -88,9 +97,9 @@ var Observable = (function() {
} }
function getHandlers(klass) { function getHandlers(klass) {
var proto = klass.prototype, var proto = klass.prototype;
namespace = proto.namespace; var namespace = proto.namespace;
return Object.keys(proto).grep(/^on/).inject($H(), function(handlers, name) { return Object.keys(proto).grep(/^on/).inject(window.$H(), function (handlers, name) {
if (name === 'onDomLoaded') return handlers; if (name === 'onDomLoaded') return handlers;
handlers.set(getEventName(name, namespace), getWrapper(proto[name], klass)); handlers.set(getEventName(name, namespace), getWrapper(proto[name], klass));
return handlers; return handlers;
@ -100,20 +109,26 @@ var Observable = (function() {
function getWrapper(handler, klass) { function getWrapper(handler, klass) {
return function (event) { return function (event) {
return handler.call(new klass(this), event, event.memo); return handler.call(new klass(this), event, event.memo);
} };
} }
function onDomLoad(selector, klass) { function onDomLoad(selector, klass) {
$$(selector).each(function(element) { window.$$(selector).each(function (element) {
new klass(element).onDomLoaded(); new klass(element).onDomLoaded();
}); });
} }
return { return {
observe: function (selector) { observe: function (selector) {
var klass = this;
if (!this.handlers) this.handlers = {}; if (!this.handlers) this.handlers = {};
if (this.handlers[selector]) return; if (this.handlers[selector]) return;
var klass = this; if (this.prototype.onDomLoaded) {
if(this.prototype.onDomLoaded) document.loaded ? onDomLoad(selector, klass) : document.observe('dom:loaded', onDomLoad.curry(selector, klass)); if (document.loaded) {
onDomLoad(selector, klass);
} else {
document.observe('dom:loaded', onDomLoad.curry(selector, klass));
}
}
this.handlers[selector] = getHandlers(klass).each(function (handler) { this.handlers[selector] = getHandlers(klass).each(function (handler) {
document.delegate(selector, handler.key, handler.value); document.delegate(selector, handler.key, handler.value);
}); });
@ -125,40 +140,41 @@ var Observable = (function() {
}); });
delete this.handlers[selector]; delete this.handlers[selector];
} }
} };
})(); })();
// override droppables // override droppables
Object.extend(Droppables, { Object.extend(window.Droppables, {
deactivate: Droppables.deactivate.wrap(function(proceed, drop, draggable) { deactivate: window.Droppables.deactivate.wrap(function (proceed, drop, draggable) {
if (drop.onLeave) drop.onLeave(draggable, drop.element); if (drop.onLeave) drop.onLeave(draggable, drop.element);
return proceed(drop); return proceed(drop);
}), }),
activate: Droppables.activate.wrap(function(proceed, drop, draggable) { activate: window.Droppables.activate.wrap(function (proceed, drop, draggable) {
if (drop.onEnter) drop.onEnter(draggable, drop.element); if (drop.onEnter) drop.onEnter(draggable, drop.element);
return proceed(drop); return proceed(drop);
}), }),
show: function (point, element) { show: function (point, element) {
var drop;
var affected = [];
if (!this.drops.length) return; if (!this.drops.length) return;
var drop, affected = [];
this.drops.each(function (drop) { this.drops.each(function (drop) {
if(Droppables.isAffected(point, element, drop)) affected.push(drop); if (window.Droppables.isAffected(point, element, drop)) affected.push(drop);
}); });
if(affected.length > 0) drop = Droppables.findDeepestChild(affected); if (affected.length > 0) drop = window.Droppables.findDeepestChild(affected);
if (this.last_active && this.last_active !== drop) this.deactivate(this.last_active, element); if (this.last_active && this.last_active !== drop) this.deactivate(this.last_active, element);
if (drop) { if (drop) {
Position.within(drop.element, point[0], point[1]); window.Position.within(drop.element, point[0], point[1]);
if(drop.onHover) drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); if (drop.onHover) drop.onHover(element, drop.element, window.Position.overlap(drop.overlap, drop.element));
if(drop !== this.last_active) Droppables.activate(drop, element); if (drop !== this.last_active) window.Droppables.activate(drop, element);
} }
}, },
displayArea: function(draggable) { displayArea: function () {
if (!this.drops.length) return; if (!this.drops.length) return;
// hide controls when displaying drop areas. // hide controls when displaying drop areas.
WysijaForm.hideBlockControls(); WysijaForm.hideBlockControls();
this.drops.each(function(drop, iterator) { this.drops.each(function (drop) {
if (drop.element.hasClassName('block_placeholder')) { if (drop.element.hasClassName('block_placeholder')) {
drop.element.addClassName('active'); drop.element.addClassName('active');
} }
@ -166,7 +182,7 @@ Object.extend(Droppables, {
}, },
hideArea: function () { hideArea: function () {
if (!this.drops.length) return; if (!this.drops.length) return;
this.drops.each(function(drop, iterator) { this.drops.each(function (drop) {
if (drop.element.hasClassName('block_placeholder')) { if (drop.element.hasClassName('block_placeholder')) {
drop.element.removeClassName('active'); drop.element.removeClassName('active');
} else if (drop.element.hasClassName('image_placeholder')) { } else if (drop.element.hasClassName('image_placeholder')) {
@ -188,7 +204,7 @@ Object.extend(Droppables, {
- set a maximum number of items to be stored - set a maximum number of items to be stored
*/ */
var WysijaHistory = { WysijaHistory = {
container: 'mailpoet_form_history', container: 'mailpoet_form_history',
size: 30, size: 30,
enqueue: function (element) { enqueue: function (element) {
@ -198,41 +214,41 @@ var WysijaHistory = {
// check if the field is unique // check if the field is unique
if (parseInt(clone.readAttribute('wysija_unique'), 10) === 1) { if (parseInt(clone.readAttribute('wysija_unique'), 10) === 1) {
// check if the field is already in the queue // check if the field is already in the queue
$(WysijaHistory.container).select('[wysija_name="' + clone.readAttribute('wysija_name') + '"]').invoke('remove'); window.$(WysijaHistory.container).select('[wysija_name="' + clone.readAttribute('wysija_name') + '"]').invoke('remove');
} }
// check history size // check history size
if($(WysijaHistory.container).select('> div').length >= WysijaHistory.size) { if (window.$(WysijaHistory.container).select('> div').length >= WysijaHistory.size) {
// remove oldest element (last in the list) // remove oldest element (last in the list)
$(WysijaHistory.container).select('> div').last().remove(); window.$(WysijaHistory.container).select('> div').last().remove();
} }
// store block in history // store block in history
$(WysijaHistory.container).insert({ window.$(WysijaHistory.container).insert({
top: clone top: clone
}); });
}, },
dequeue: function () { dequeue: function () {
// pop last block off the history // pop last block off the history
var block = $(WysijaHistory.container).select('div').first(); var block = window.$(WysijaHistory.container).select('div').first();
if (block !== undefined) { if (block !== undefined) {
// insert block back into the editor // insert block back into the editor
$(WysijaForm.options.body).insert({ window.$(WysijaForm.options.body).insert({
top: block top: block
}); });
} }
}, },
clear: function () { clear: function () {
$(WysijaHistory.container).innerHTML = ''; window.$(WysijaHistory.container).innerHTML = '';
}, },
remove: function (field) { remove: function (field) {
$(WysijaHistory.container).select('[wysija_name="' + field + '"]').invoke('remove'); window.$(WysijaHistory.container).select('[wysija_name="' + field + '"]').invoke('remove');
} }
}; };
/* MailPoet Form */ /* MailPoet Form */
var WysijaForm = { WysijaForm = {
version: '0.7', version: '0.7',
options: { options: {
container: 'mailpoet_form_container', container: 'mailpoet_form_container',
@ -271,31 +287,32 @@ var WysijaForm = {
}, },
loading: function (is_loading) { loading: function (is_loading) {
if (is_loading) { if (is_loading) {
$(WysijaForm.options.editor).addClassName('loading'); window.$(WysijaForm.options.editor).addClassName('loading');
$(WysijaForm.options.toolbar).addClassName('loading'); window.$(WysijaForm.options.toolbar).addClassName('loading');
} else { } else {
$(WysijaForm.options.editor).removeClassName('loading'); window.$(WysijaForm.options.editor).removeClassName('loading');
$(WysijaForm.options.toolbar).removeClassName('loading'); window.$(WysijaForm.options.toolbar).removeClassName('loading');
} }
}, },
loadStatic: function (blocks) { loadStatic: function (blocks) {
$A(blocks).each(function(block) { window.$A(blocks).each(function (block) {
// create block // create block
WysijaForm.Block.create(block, $('block_placeholder')); WysijaForm.Block.create(block, window.$('block_placeholder'));
}); });
}, },
load: function (data) { load: function (data) {
var settings_elements;
if (data === undefined) return; if (data === undefined) return;
// load body // load body
if (data.body !== undefined) { if (data.body !== undefined) {
$A(data.body).each(function(block) { window.$A(data.body).each(function (block) {
// create block // create block
WysijaForm.Block.create(block, $('block_placeholder')); WysijaForm.Block.create(block, window.$('block_placeholder'));
}); });
// load settings // load settings
var settings_elements = $('mailpoet_form_settings').getElements(); settings_elements = window.$('mailpoet_form_settings').getElements();
settings_elements.each(function (setting) { settings_elements.each(function (setting) {
// skip lists // skip lists
if (setting.name === 'segments') { if (setting.name === 'segments') {
@ -304,7 +321,7 @@ var WysijaForm = {
// if the input value is equal to the one stored in the settings // if the input value is equal to the one stored in the settings
if (setting.value === data.settings[setting.name]) { if (setting.value === data.settings[setting.name]) {
// check selected value // check selected value
$(setting).checked = true; window.$(setting).checked = true;
} }
} else if (data.settings[setting.name] !== undefined) { } else if (data.settings[setting.name] !== undefined) {
if (typeof data.settings[setting.name] === 'string') { if (typeof data.settings[setting.name] === 'string') {
@ -317,12 +334,12 @@ var WysijaForm = {
} }
}, },
save: function () { save: function () {
var position = 1, var position = 1;
data = { var data = {
'name': $F('mailpoet_form_name'), name: window.$F('mailpoet_form_name'),
'settings': $('mailpoet_form_settings').serialize(true), settings: window.$('mailpoet_form_settings').serialize(true),
'body': [], body: [],
'styles': (MailPoet.CodeEditor !== undefined) ? MailPoet.CodeEditor.getValue() : null styles: (window.MailPoet.CodeEditor !== undefined) ? window.MailPoet.CodeEditor.getValue() : null
}; };
// body // body
WysijaForm.getBlocks().each(function (b) { WysijaForm.getBlocks().each(function (b) {
@ -394,33 +411,35 @@ var WysijaForm = {
return data; return data;
}, },
toggleWidgets: function () { toggleWidgets: function () {
$$('a[wysija_unique="1"]').invoke('removeClassName', 'disabled'); var hasSegmentSelection;
window.$$('a[wysija_unique="1"]').invoke('removeClassName', 'disabled');
// loop through each unique field already inserted in the editor and disable its toolbar equivalent // loop through each unique field already inserted in the editor and disable its toolbar equivalent
$$('#' + WysijaForm.options.editor + ' [wysija_unique="1"]').map(function(element) { window.$$('#' + WysijaForm.options.editor + ' [wysija_unique="1"]').map(function (element) {
var field = $$('#' + WysijaForm.options.toolbar + ' [wysija_id="' + element.readAttribute('wysija_id') + '"]'); var field = window.$$('#' + WysijaForm.options.toolbar + ' [wysija_id="' + element.readAttribute('wysija_id') + '"]');
if (field.length > 0) { if (field.length > 0) {
field.first().addClassName('disabled'); field.first().addClassName('disabled');
} }
}); });
var hasSegmentSelection = WysijaForm.hasSegmentSelection(); hasSegmentSelection = WysijaForm.hasSegmentSelection();
if (hasSegmentSelection) { if (hasSegmentSelection) {
$('mailpoet_form_segments').writeAttribute('required', false).disable(); window.$('mailpoet_form_segments').writeAttribute('required', false).disable();
$('mailpoet_settings_segment_selection').hide(); window.$('mailpoet_settings_segment_selection').hide();
} else { } else {
$('mailpoet_form_segments').writeAttribute('required', true).enable(); window.$('mailpoet_form_segments').writeAttribute('required', true).enable();
$('mailpoet_settings_segment_selection').show(); window.$('mailpoet_settings_segment_selection').show();
} }
}, },
hasSegmentSelection: function () { hasSegmentSelection: function () {
return ($$('#' + WysijaForm.options.editor + ' [wysija_id="segments"]').length > 0); return (window.$$('#' + WysijaForm.options.editor + ' [wysija_id="segments"]').length > 0);
}, },
isSegmentSelectionValid: function () { isSegmentSelectionValid: function () {
var segment_selection = $$('#' + WysijaForm.options.editor + ' [wysija_id="segments"]')[0]; var segment_selection = window.$$('#' + WysijaForm.options.editor + ' [wysija_id="segments"]')[0];
var block;
if (segment_selection !== undefined) { if (segment_selection !== undefined) {
var block = WysijaForm.get(segment_selection).block.getData(); block = WysijaForm.get(segment_selection).block.getData();
return ( return (
(block.params.values !== undefined) (block.params.values !== undefined)
&& &&
@ -430,10 +449,12 @@ var WysijaForm = {
return false; return false;
}, },
setBlockPositions: function (event, target) { setBlockPositions: function (event, target) {
var index = 1;
var block_placeholder;
var previous_placeholder;
// release dragging lock // release dragging lock
WysijaForm.locks.dragging = false; WysijaForm.locks.dragging = false;
var index = 1;
WysijaForm.getBlocks().each(function (container) { WysijaForm.getBlocks().each(function (container) {
container.setPosition(index++); container.setPosition(index++);
// remove z-index value to avoid issues when resizing images // remove z-index value to avoid issues when resizing images
@ -446,7 +467,7 @@ var WysijaForm = {
if (target !== undefined) { if (target !== undefined) {
// get placeholders (previous placeholder matches the placeholder linked to the next block) // get placeholders (previous placeholder matches the placeholder linked to the next block)
var block_placeholder = $(target.element.readAttribute('wysija_placeholder')), block_placeholder = window.$(target.element.readAttribute('wysija_placeholder'));
previous_placeholder = target.element.previous('.block_placeholder'); previous_placeholder = target.element.previous('.block_placeholder');
if (block_placeholder !== null) { if (block_placeholder !== null) {
@ -468,64 +489,59 @@ var WysijaForm = {
WysijaForm.scroll = document.viewport.getScrollOffsets(); WysijaForm.scroll = document.viewport.getScrollOffsets();
}, },
hideSettings: function () { hideSettings: function () {
$(WysijaForm.options.container).select('.wysija_settings').invoke('hide'); window.$(WysijaForm.options.container).select('.wysija_settings').invoke('hide');
}, },
setSettingsPosition: function () { setSettingsPosition: function () {
// get viewport offsets and dimensions // get viewport offsets and dimensions
var viewportHeight = document.viewport.getHeight(), var viewportHeight = document.viewport.getHeight();
blockPadding = 5;
$(WysijaForm.options.container).select('.wysija_settings').each(function(element) { window.$(WysijaForm.options.container).select('.wysija_settings').each(function (element) {
// get parent dimensions and position // get parent dimensions and position
var parentDim = element.up('.mailpoet_form_block').getDimensions(), var parentDim = element.up('.mailpoet_form_block').getDimensions();
parentPos = element.up('.mailpoet_form_block').cumulativeOffset(), var parentPos = element.up('.mailpoet_form_block').cumulativeOffset();
is_visible = (parentPos.top <= (WysijaForm.scroll.top + viewportHeight)) ? true : false, var is_visible = (parentPos.top <= (WysijaForm.scroll.top + viewportHeight));
buttonMargin = 5, var buttonMargin = 5;
relativeTop = buttonMargin; var relativeTop = buttonMargin;
if (is_visible) { if (is_visible) {
// desired position is set to center of viewport
var absoluteTop = parseInt(WysijaForm.scroll.top + ((viewportHeight / 2) - (element.getHeight() / 2)), 10),
parentTop = parseInt(parentPos.top - blockPadding, 10),
parentBottom = parseInt(parentPos.top + parentDim.height - blockPadding, 10);
// always center // always center
relativeTop = parseInt((parentDim.height / 2) - (element.getHeight() / 2), 10); relativeTop = parseInt((parentDim.height / 2) - (element.getHeight() / 2), 10);
} }
// set position for button // set position for button
$(element).setStyle({ window.$(element).setStyle({
left: parseInt((parentDim.width / 2) - (element.getWidth() / 2)) + 'px', left: parseInt((parentDim.width / 2) - (element.getWidth() / 2)) + 'px',
top: relativeTop + 'px' top: relativeTop + 'px'
}); });
}); });
}, },
initToolbarPosition: function () { initToolbarPosition: function () {
if(WysijaForm.toolbar.top === null) WysijaForm.toolbar.top = parseInt($(WysijaForm.options.container).positionedOffset().top); if (WysijaForm.toolbar.top === null) WysijaForm.toolbar.top = parseInt(window.$(WysijaForm.options.container).positionedOffset().top);
if (WysijaForm.toolbar.y === null) WysijaForm.toolbar.y = parseInt(WysijaForm.toolbar.top); if (WysijaForm.toolbar.y === null) WysijaForm.toolbar.y = parseInt(WysijaForm.toolbar.top);
if(isRtl) { if (window.isRtl) {
if (WysijaForm.toolbar.left === null) WysijaForm.toolbar.left = 0; if (WysijaForm.toolbar.left === null) WysijaForm.toolbar.left = 0;
} else { } else {
if(WysijaForm.toolbar.left === null) WysijaForm.toolbar.left = parseInt($(WysijaForm.options.container).positionedOffset().left); if (WysijaForm.toolbar.left === null) WysijaForm.toolbar.left = parseInt(window.$(WysijaForm.options.container).positionedOffset().left);
} }
if(WysijaForm.toolbar.x === null) WysijaForm.toolbar.x = parseInt(WysijaForm.toolbar.left + $(WysijaForm.options.container).getDimensions().width + 15); if (WysijaForm.toolbar.x === null) WysijaForm.toolbar.x = parseInt(WysijaForm.toolbar.left + window.$(WysijaForm.options.container).getDimensions().width + 15);
}, },
setToolbarPosition: function () { setToolbarPosition: function () {
var position;
WysijaForm.initToolbarPosition(); WysijaForm.initToolbarPosition();
var position = { position = {
top: WysijaForm.toolbar.y + 'px', top: WysijaForm.toolbar.y + 'px',
visibility: 'visible' visibility: 'visible'
}; };
if(isRtl) { if (window.isRtl) {
position.right = WysijaForm.toolbar.x + 'px'; position.right = WysijaForm.toolbar.x + 'px';
} else { } else {
position.left = WysijaForm.toolbar.x + 'px'; position.left = WysijaForm.toolbar.x + 'px';
} }
$(WysijaForm.options.toolbar).setStyle(position); window.$(WysijaForm.options.toolbar).setStyle(position);
}, },
updateToolbarPosition: function () { updateToolbarPosition: function () {
// init toolbar position (updates scroll and toolbar y) // init toolbar position (updates scroll and toolbar y)
@ -537,31 +553,31 @@ var WysijaForm = {
if (WysijaForm.scroll.top >= (WysijaForm.toolbar.top - 20)) { if (WysijaForm.scroll.top >= (WysijaForm.toolbar.top - 20)) {
WysijaForm.toolbar.y = parseInt(20 + WysijaForm.scroll.top); WysijaForm.toolbar.y = parseInt(20 + WysijaForm.scroll.top);
// start effect // start effect
WysijaForm.toolbar.effect = new Effect.Move(WysijaForm.options.toolbar, { WysijaForm.toolbar.effect = new window.Effect.Move(WysijaForm.options.toolbar, {
x: WysijaForm.toolbar.x, x: WysijaForm.toolbar.x,
y: WysijaForm.toolbar.y, y: WysijaForm.toolbar.y,
mode: 'absolute', mode: 'absolute',
duration: 0.2 duration: 0.2
}); });
} else { } else {
$(WysijaForm.options.toolbar).setStyle({ window.$(WysijaForm.options.toolbar).setStyle({
left: WysijaForm.toolbar.x + 'px', left: WysijaForm.toolbar.x + 'px',
top: WysijaForm.toolbar.top + 'px' top: WysijaForm.toolbar.top + 'px'
}); });
} }
}, },
blockDropOptions: { blockDropOptions: {
accept: $w('mailpoet_form_field'), // acceptable items (classes array) accept: window.$w('mailpoet_form_field'), // acceptable items (classes array)
onEnter: function (draggable, droppable) { onEnter: function (draggable, droppable) {
$(droppable).addClassName('hover'); window.$(droppable).addClassName('hover');
}, },
onLeave: function (draggable, droppable) { onLeave: function (draggable, droppable) {
$(droppable).removeClassName('hover'); window.$(droppable).removeClassName('hover');
}, },
onDrop: function (draggable, droppable) { onDrop: function (draggable, droppable) {
// custom data for images // custom data for images
droppable.fire('wjfe:item:drop', WysijaForm.getFieldData(draggable)); droppable.fire('wjfe:item:drop', WysijaForm.getFieldData(draggable));
$(droppable).removeClassName('hover'); window.$(droppable).removeClassName('hover');
} }
}, },
hideControls: function () { hideControls: function () {
@ -572,26 +588,28 @@ var WysijaForm = {
} }
}, },
hideTools: function () { hideTools: function () {
$$('.wysija_tools').invoke('hide'); window.$$('.wysija_tools').invoke('hide');
WysijaForm.locks.showingTools = false; WysijaForm.locks.showingTools = false;
}, },
instances: {}, instances: {},
get: function (element, typ) { get: function (element, typ) {
var type = typ; var type = typ;
var id;
var instance;
if (type === undefined) type = 'block'; if (type === undefined) type = 'block';
// identify element // identify element
var id = element.identify(); id = element.identify();
var instance = WysijaForm.instances[id] || new WysijaForm[type.capitalize().camelize()](id); instance = WysijaForm.instances[id] || new WysijaForm[type.capitalize().camelize()](id);
WysijaForm.instances[id] = instance; WysijaForm.instances[id] = instance;
return instance; return instance;
}, },
makeDroppable: function () { makeDroppable: function () {
Droppables.add('block_placeholder', WysijaForm.blockDropOptions); window.Droppables.add('block_placeholder', WysijaForm.blockDropOptions);
}, },
makeSortable: function () { makeSortable: function () {
var body = $(WysijaForm.options.body); var body = window.$(WysijaForm.options.body);
Sortable.create(body, { window.Sortable.create(body, {
tag: 'div', tag: 'div',
only: 'mailpoet_form_block', only: 'mailpoet_form_block',
scroll: window, scroll: window,
@ -599,15 +617,15 @@ var WysijaForm = {
constraint: 'vertical' constraint: 'vertical'
}); });
Draggables.removeObserver(body); window.Draggables.removeObserver(body);
Draggables.addObserver({ window.Draggables.addObserver({
element: body, element: body,
onStart: WysijaForm.startBlockPositions, onStart: WysijaForm.startBlockPositions,
onEnd: WysijaForm.setBlockPositions onEnd: WysijaForm.setBlockPositions
}); });
}, },
hideBlockControls: function () { hideBlockControls: function () {
$$('.wysija_controls').invoke('hide'); window.$$('.wysija_controls').invoke('hide');
this.getBlockElements().invoke('removeClassName', 'hover'); this.getBlockElements().invoke('removeClassName', 'hover');
}, },
getBlocks: function () { getBlocks: function () {
@ -616,7 +634,7 @@ var WysijaForm = {
}); });
}, },
getBlockElements: function () { getBlockElements: function () {
return $(WysijaForm.options.container).select('.mailpoet_form_block'); return window.$(WysijaForm.options.container).select('.mailpoet_form_block');
}, },
startBlockPositions: function (event, target) { startBlockPositions: function (event, target) {
if (target.element.hasClassName('mailpoet_form_block')) { if (target.element.hasClassName('mailpoet_form_block')) {
@ -629,8 +647,8 @@ var WysijaForm = {
}, },
encodeURIComponent: function (str) { encodeURIComponent: function (str) {
// check if it's a url and if so, prevent encoding of protocol // check if it's a url and if so, prevent encoding of protocol
var regexp = new RegExp(/^http[s]?:\/\//), var regexp = new RegExp(/^http[s]?:\/\//);
protocol = regexp.exec(str); var protocol = regexp.exec(str);
if (protocol === null) { if (protocol === null) {
// this is not a url so encode the whole thing // this is not a url so encode the whole thing
@ -664,19 +682,19 @@ var WysijaForm = {
} }
}; };
WysijaForm.DraggableItem = Class.create({ WysijaForm.DraggableItem = window.Class.create({
initialize: function (element) { initialize: function (element) {
this.elementType = $(element).readAttribute('wysija_type'); this.elementType = window.$(element).readAttribute('wysija_type');
this.element = $(element).down() || $(element); this.element = window.$(element).down() || window.$(element);
this.clone = this.cloneElement(); this.clone = this.cloneElement();
this.insert(); this.insert();
}, },
STYLES: new Template('position: absolute; top: #{top}px; left: #{left}px;'), STYLES: new window.Template('position: absolute; top: #{top}px; left: #{left}px;'),
cloneElement: function () { cloneElement: function () {
var clone = this.element.clone(), var clone = this.element.clone();
offset = this.element.cumulativeOffset(), var offset = this.element.cumulativeOffset();
list = this.getList(), var list = this.getList();
styles = this.STYLES.evaluate({ var styles = this.STYLES.evaluate({
top: offset.top - list.scrollTop, top: offset.top - list.scrollTop,
left: offset.left - list.scrollLeft left: offset.left - list.scrollLeft
}); });
@ -694,27 +712,27 @@ WysijaForm.DraggableItem = Class.create({
return this.element.up('ul'); return this.element.up('ul');
}, },
insert: function () { insert: function () {
$$("body")[0].insert(this.clone); window.$$('body')[0].insert(this.clone);
}, },
onMousedown: function (event) { onMousedown: function (event) {
var draggable = new Draggable(this.clone, { var draggable = new window.Draggable(this.clone, {
scroll: window, scroll: window,
onStart: function () { onStart: function () {
Droppables.displayArea(draggable); window.Droppables.displayArea(draggable);
}, },
onEnd: function (drag) { onEnd: function (drag) {
drag.destroy(); drag.destroy();
drag.element.remove(); drag.element.remove();
Droppables.hideArea(); window.Droppables.hideArea();
}, },
starteffect: function (element) { starteffect: function (element) {
new Effect.Opacity(element, { new window.Effect.Opacity(element, {
duration: 0.2, duration: 0.2,
from: element.getOpacity(), from: element.getOpacity(),
to: 0.7 to: 0.7
}); });
}, },
endeffect: Prototype.emptyFunction endeffect: window.Prototype.emptyFunction
}); });
draggable.initDrag(event); draggable.initDrag(event);
draggable.startDrag(event); draggable.startDrag(event);
@ -724,12 +742,12 @@ WysijaForm.DraggableItem = Class.create({
Object.extend(WysijaForm.DraggableItem, Observable).observe('a[class="mailpoet_form_field"]'); Object.extend(WysijaForm.DraggableItem, Observable).observe('a[class="mailpoet_form_field"]');
WysijaForm.Block = Class.create({ WysijaForm.Block = window.Class.create({
/* Invoked on load */ /* Invoked on load */
initialize: function (element) { initialize: function (element) {
info('block -> init'); info('block -> init');
this.element = $(element); this.element = window.$(element);
this.block = new WysijaForm.Widget(this.element); this.block = new WysijaForm.Widget(this.element);
// enable block placeholder // enable block placeholder
@ -755,21 +773,23 @@ WysijaForm.Block = Class.create({
this.element.addClassName('hover'); this.element.addClassName('hover');
try { try {
this.getControls().show(); this.getControls().show();
} catch(e) {; } catch (e) {
} }
} }
}, },
makeBlockDroppable: function () { makeBlockDroppable: function () {
var block_placeholder;
if (this.isBlockDroppableEnabled() === false) { if (this.isBlockDroppableEnabled() === false) {
var block_placeholder = this.getBlockDroppable(); block_placeholder = this.getBlockDroppable();
Droppables.add(block_placeholder.identify(), WysijaForm.blockDropOptions); window.Droppables.add(block_placeholder.identify(), WysijaForm.blockDropOptions);
block_placeholder.addClassName('enabled'); block_placeholder.addClassName('enabled');
} }
}, },
removeBlockDroppable: function () { removeBlockDroppable: function () {
var block_placeholder;
if (this.isBlockDroppableEnabled()) { if (this.isBlockDroppableEnabled()) {
var block_placeholder = this.getBlockDroppable(); block_placeholder = this.getBlockDroppable();
Droppables.remove(block_placeholder.identify()); window.Droppables.remove(block_placeholder.identify());
block_placeholder.removeClassName('enabled'); block_placeholder.removeClassName('enabled');
} }
}, },
@ -785,7 +805,7 @@ WysijaForm.Block = Class.create({
createBlockDroppable: function () { createBlockDroppable: function () {
info('block -> createBlockDroppable'); info('block -> createBlockDroppable');
this.element.insert({ this.element.insert({
before: '<div class=\"block_placeholder\">' + $('block_placeholder').innerHTML + '</div>' before: '<div class=\"block_placeholder\">' + window.$('block_placeholder').innerHTML + '</div>'
}); });
return this.element.previous('.block_placeholder'); return this.element.previous('.block_placeholder');
}, },
@ -800,6 +820,7 @@ WysijaForm.Block = Class.create({
return this.element.down('.wysija_controls'); return this.element.down('.wysija_controls');
}, },
setupControls: function () { setupControls: function () {
var block;
// enable controls // enable controls
this.controls = this.getControls(); this.controls = this.getControls();
@ -850,9 +871,8 @@ WysijaForm.Block = Class.create({
if (this.settingsButton !== null) { if (this.settingsButton !== null) {
this.settingsButton.observe('click', function (event) { this.settingsButton.observe('click', function (event) {
// TODO: refactor // TODO: refactor
var block = $(event.target).up('.mailpoet_form_block') || null; block = window.$(event.target).up('.mailpoet_form_block') || null;
if (block !== null) { if (block !== null) {
var field = WysijaForm.getFieldData(block);
this.editSettings(); this.editSettings();
} }
}.bind(this)); }.bind(this));
@ -866,7 +886,7 @@ WysijaForm.Block = Class.create({
// save block in history // save block in history
WysijaHistory.enqueue(this.element); WysijaHistory.enqueue(this.element);
Effect.Fade(this.element.identify(), { window.Effect.Fade(this.element.identify(), {
duration: 0.2, duration: 0.2,
afterFinish: function (effect) { afterFinish: function (effect) {
// remove placeholder // remove placeholder
@ -898,20 +918,25 @@ WysijaForm.Block = Class.create({
/* Invoked on item dropped */ /* Invoked on item dropped */
WysijaForm.Block.create = function (createBlock, target) { WysijaForm.Block.create = function (createBlock, target) {
var block = createBlock; var block = createBlock;
if($('form_template_' + block.type) === null) { var body;
var block_template;
var template;
var output;
var settings_segments;
if (window.$('form_template_' + block.type) === null) {
return false; return false;
} }
var body = $(WysijaForm.options.body), body = window.$(WysijaForm.options.body);
block_template = Handlebars.compile($('form_template_block').innerHTML), block_template = window.Handlebars.compile(window.$('form_template_block').innerHTML);
template = Handlebars.compile($('form_template_' + block.type).innerHTML), template = window.Handlebars.compile(window.$('form_template_' + block.type).innerHTML);
output = ''; output = '';
if (block.type === 'segment') { if (block.type === 'segment') {
if (block.params.values === undefined) { if (block.params.values === undefined) {
var settings_segments = jQuery('#mailpoet_form_segments').val(); settings_segments = window.jQuery('#mailpoet_form_segments').val();
if (settings_segments !== null && settings_segments.length > 0) { if (settings_segments !== null && settings_segments.length > 0) {
block.params.values = mailpoet_segments.filter(function(segment) { block.params.values = window.mailpoet_segments.filter(function (segment) {
return (settings_segments.indexOf(segment.id) !== -1); return (settings_segments.indexOf(segment.id) !== -1);
}); });
} }
@ -929,14 +954,13 @@ WysijaForm.Block.create = function(createBlock, target) {
} }
// if the drop target was the bottom placeholder // if the drop target was the bottom placeholder
var element = null;
if (target.identify() === 'block_placeholder') { if (target.identify() === 'block_placeholder') {
// insert block at the bottom // insert block at the bottom
element = body.insert(output); body.insert(output);
// block = body.childElements().last(); // block = body.childElements().last();
} else { } else {
// insert block before the drop target // insert block before the drop target
element = target.insert({ target.insert({
before: output before: output
}); });
// block = target.previous('.mailpoet_form_block'); // block = target.previous('.mailpoet_form_block');
@ -966,10 +990,10 @@ document.observe('wjfe:item:drop', function(event) {
}); });
/* Form Widget */ /* Form Widget */
WysijaForm.Widget = Class.create(WysijaForm.Block, { WysijaForm.Widget = window.Class.create(WysijaForm.Block, {
initialize: function (element) { initialize: function (element) {
info('widget -> init'); info('widget -> init');
this.element = $(element); this.element = window.$(element);
return this; return this;
}, },
setup: function () { setup: function () {
@ -977,8 +1001,8 @@ WysijaForm.Widget = Class.create(WysijaForm.Block, {
this.setupControls(); this.setupControls();
}, },
save: function () { save: function () {
info('widget -> save');
var data = this.getData(); var data = this.getData();
info('widget -> save');
if (data.element !== undefined) { if (data.element !== undefined) {
delete data.element; delete data.element;
@ -987,8 +1011,8 @@ WysijaForm.Widget = Class.create(WysijaForm.Block, {
return data; return data;
}, },
setData: function (data) { setData: function (data) {
var current_data = this.getData(), var current_data = this.getData();
params = $H(current_data.params).merge(data.params).toObject(); var params = window.$H(current_data.params).merge(data.params).toObject();
// update type if it changed // update type if it changed
if (data.type !== undefined && data.type !== current_data.type) { if (data.type !== undefined && data.type !== current_data.type) {
@ -1013,26 +1037,30 @@ WysijaForm.Widget = Class.create(WysijaForm.Block, {
this.removeBlock(); this.removeBlock();
}, },
redraw: function (data) { redraw: function (data) {
var options;
var block_template;
var template;
var params;
// set parameters // set parameters
this.setData(data); this.setData(data);
var options = this.getData(); options = this.getData();
// redraw block // redraw block
var block_template = Handlebars.compile($('form_template_block').innerHTML), block_template = window.Handlebars.compile(window.$('form_template_block').innerHTML);
template = Handlebars.compile($('form_template_' + options.type).innerHTML), template = window.Handlebars.compile(window.$('form_template_' + options.type).innerHTML);
data = $H(options).merge({ params = window.$H(options).merge({
template: template(options) template: template(options)
}).toObject(); }).toObject();
this.element.replace(block_template(data)); this.element.replace(block_template(params));
WysijaForm.init(); WysijaForm.init();
}, },
editSettings: function () { editSettings: function () {
MailPoet.Modal.popup({ window.MailPoet.Modal.popup({
title: MailPoet.I18n.t('editFieldSettings'), title: window.MailPoet.I18n.t('editFieldSettings'),
template: jQuery('#form_template_field_settings').html(), template: window.jQuery('#form_template_field_settings').html(),
data: this.getData(), data: this.getData(),
onSuccess: function () { onSuccess: function () {
var data = jQuery('#form_field_settings').serializeObject(); var data = window.jQuery('#form_field_settings').mailpoetSerializeObject();
this.redraw(data); this.redraw(data);
}.bind(this) }.bind(this)
}); });
@ -1054,8 +1082,8 @@ function info(value) {
var noop = function () {}; var noop = function () {};
var methods = ['assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error', 'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log', 'markTimeline', 'profile', 'profileEnd', 'markTimeline', 'table', 'time', 'timeEnd', 'timeStamp', 'trace', 'warn']; var methods = ['assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error', 'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log', 'markTimeline', 'profile', 'profileEnd', 'markTimeline', 'table', 'time', 'timeEnd', 'timeStamp', 'trace', 'warn'];
var length = methods.length; var length = methods.length;
window.console = {};
var console = {}; var console = {};
window.console = {};
while (length--) { while (length--) {
console[methods[length]] = noop; console[methods[length]] = noop;
} }

View File

@ -2,7 +2,7 @@ import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { Router, Route, IndexRoute, useRouterHistory } from 'react-router'; import { Router, Route, IndexRoute, useRouterHistory } from 'react-router';
import { createHashHistory } from 'history'; import { createHashHistory } from 'history';
import FormList from 'forms/list.jsx'; import FormList from './list.jsx';
const history = useRouterHistory(createHashHistory)({ queryKey: false }); const history = useRouterHistory(createHashHistory)({ queryKey: false });

View File

@ -1,7 +1,8 @@
import React from 'react'; import React from 'react';
import Listing from 'listing/listing.jsx';
import classNames from 'classnames'; import classNames from 'classnames';
import MailPoet from 'mailpoet'; import MailPoet from 'mailpoet';
import jQuery from 'jquery';
import Listing from '../listing/listing.jsx';
const columns = [ const columns = [
{ {
@ -128,7 +129,7 @@ const FormList = React.createClass({
endpoint: 'forms', endpoint: 'forms',
action: 'create', action: 'create',
}).done((response) => { }).done((response) => {
window.location = mailpoet_form_edit_url + response.data.id; window.location = window.mailpoet_form_edit_url + response.data.id;
}).fail((response) => { }).fail((response) => {
if (response.errors.length > 0) { if (response.errors.length > 0) {
MailPoet.Notice.error( MailPoet.Notice.error(
@ -145,7 +146,7 @@ const FormList = React.createClass({
'has-row-actions' 'has-row-actions'
); );
let segments = mailpoet_segments.filter((segment) => { let segments = window.mailpoet_segments.filter((segment) => {
return (jQuery.inArray(segment.id, form.segments) !== -1); return (jQuery.inArray(segment.id, form.segments) !== -1);
}).map((segment) => { }).map((segment) => {
return segment.name; return segment.name;
@ -190,7 +191,7 @@ const FormList = React.createClass({
</h1> </h1>
<Listing <Listing
limit={ mailpoet_listing_per_page } limit={window.mailpoet_listing_per_page}
location={this.props.location} location={this.props.location}
params={this.props.params} params={this.props.params}
messages={messages} messages={messages}

View File

@ -1,34 +1,36 @@
define('handlebars_helpers', ['handlebars'], function (Handlebars) { define('handlebars_helpers', ['handlebars'], function (Handlebars) {
// Handlebars helpers // Handlebars helpers
Handlebars.registerHelper('concat', function () { Handlebars.registerHelper('concat', function () {
var size = (arguments.length - 1), var size = (arguments.length - 1);
output = ''; var output = '';
for(var i = 0; i < size; i++) { var i;
for (i = 0; i < size; i++) {
output += arguments[i]; output += arguments[i];
}; }
return output; return output;
}); });
Handlebars.registerHelper('number_format', function(value, block) { Handlebars.registerHelper('number_format', function (value) {
return Number(value).toLocaleString(); return Number(value).toLocaleString();
}); });
Handlebars.registerHelper('date_format', function (timestamp, block) { Handlebars.registerHelper('date_format', function (timestamp, block) {
var f;
if (window.moment) { if (window.moment) {
if (timestamp === undefined || isNaN(timestamp) || timestamp <= 0) { if (timestamp === undefined || isNaN(timestamp) || timestamp <= 0) {
return; return;
} }
// set date format // set date format
var f = block.hash.format || "MMM Do, YYYY"; f = block.hash.format || 'MMM Do, YYYY';
// check if we passed a timestamp // check if we passed a timestamp
if (parseInt(timestamp, 10) == timestamp) { if (parseInt(timestamp, 10) == timestamp) {
return moment.unix(timestamp).format(f); return window.moment.unix(timestamp).format(f);
} else { } else {
return moment.utc(timestamp).format(f); return window.moment.utc(timestamp).format(f);
} }
} else { } else {
return timestamp; return timestamp;
}; }
}); });
Handlebars.registerHelper('cycle', function (value, block) { Handlebars.registerHelper('cycle', function (value, block) {
@ -59,26 +61,25 @@ define('handlebars_helpers', ['handlebars'], function(Handlebars) {
case '||': case '||':
return (v1 || v2) ? options.fn(this) : options.inverse(this); return (v1 || v2) ? options.fn(this) : options.inverse(this);
case 'in': case 'in':
var values = v2.split(',');
return (v2.indexOf(v1) !== -1) ? options.fn(this) : options.inverse(this); return (v2.indexOf(v1) !== -1) ? options.fn(this) : options.inverse(this);
default: default:
return options.inverse(this); return options.inverse(this);
} }
}); });
Handlebars.registerHelper('nl2br', function(value, block) { Handlebars.registerHelper('nl2br', function (value) {
return value.gsub("\n", "<br />"); return value.gsub('\n', '<br />');
}); });
Handlebars.registerHelper('json_encode', function(value, block) { Handlebars.registerHelper('json_encode', function (value) {
return JSON.stringify(value); return JSON.stringify(value);
}); });
Handlebars.registerHelper('json_decode', function(value, block) { Handlebars.registerHelper('json_decode', function (value) {
return JSON.parse(value); return JSON.parse(value);
}); });
Handlebars.registerHelper('url', function(value, block) { Handlebars.registerHelper('url', function (value) {
var url = window.location.protocol + "//" + window.location.host + window.location.pathname; var url = window.location.protocol + '//' + window.location.host + window.location.pathname;
return url + value; return url + value;
}); });
@ -90,16 +91,17 @@ define('handlebars_helpers', ['handlebars'], function(Handlebars) {
return value; return value;
} }
}); });
Handlebars.registerHelper('lookup', function(obj, field, options) { Handlebars.registerHelper('lookup', function (obj, field) {
return obj && obj[field]; return obj && obj[field];
}); });
Handlebars.registerHelper('rsa_key', function(value, block) { Handlebars.registerHelper('rsa_key', function (value) {
var lines;
// extract all lines into an array // extract all lines into an array
if (value === undefined) return ''; if (value === undefined) return '';
var lines = value.trim().split("\n"); lines = value.trim().split('\n');
// remove header & footer // remove header & footer
lines.shift(); lines.shift();
@ -109,7 +111,7 @@ define('handlebars_helpers', ['handlebars'], function(Handlebars) {
return lines.join(''); return lines.join('');
}); });
Handlebars.registerHelper('trim', function(value, block) { Handlebars.registerHelper('trim', function (value) {
if (value === null || value === undefined) return ''; if (value === null || value === undefined) return '';
return value.trim(); return value.trim();
}); });
@ -126,10 +128,10 @@ define('handlebars_helpers', ['handlebars'], function(Handlebars) {
*/ */
Handlebars.registerHelper('ellipsis', function (str, limit, append) { Handlebars.registerHelper('ellipsis', function (str, limit, append) {
var strAppend = append; var strAppend = append;
var sanitized = str.replace(/(<([^>]+)>)/g, '');
if (strAppend === undefined) { if (strAppend === undefined) {
strAppend = ''; strAppend = '';
} }
var sanitized = str.replace(/(<([^>]+)>)/g, '');
if (sanitized.length > limit) { if (sanitized.length > limit) {
return sanitized.substr(0, limit - strAppend.length) + strAppend; return sanitized.substr(0, limit - strAppend.length) + strAppend;
} else { } else {
@ -148,10 +150,10 @@ define('handlebars_helpers', ['handlebars'], function(Handlebars) {
case 'Courier New': return new Handlebars.SafeString("'Courier New', Courier, 'Lucida Sans Typewriter', 'Lucida Typewriter', monospace"); case 'Courier New': return new Handlebars.SafeString("'Courier New', Courier, 'Lucida Sans Typewriter', 'Lucida Typewriter', monospace");
case 'Georgia': return new Handlebars.SafeString("Georgia, Times, 'Times New Roman', serif"); case 'Georgia': return new Handlebars.SafeString("Georgia, Times, 'Times New Roman', serif");
case 'Lucida': return new Handlebars.SafeString("'Lucida Sans Unicode', 'Lucida Grande', sans-serif"); case 'Lucida': return new Handlebars.SafeString("'Lucida Sans Unicode', 'Lucida Grande', sans-serif");
case 'Tahoma': return new Handlebars.SafeString("Tahoma, Verdana, Segoe, sans-serif"); case 'Tahoma': return new Handlebars.SafeString('Tahoma, Verdana, Segoe, sans-serif');
case 'Times New Roman': return new Handlebars.SafeString("'Times New Roman', Times, Baskerville, Georgia, serif"); case 'Times New Roman': return new Handlebars.SafeString("'Times New Roman', Times, Baskerville, Georgia, serif");
case 'Trebuchet MS': return new Handlebars.SafeString("'Trebuchet MS', 'Lucida Grande', 'Lucida Sans Unicode', 'Lucida Sans', Tahoma, sans-serif"); case 'Trebuchet MS': return new Handlebars.SafeString("'Trebuchet MS', 'Lucida Grande', 'Lucida Sans Unicode', 'Lucida Sans', Tahoma, sans-serif");
case 'Verdana': return new Handlebars.SafeString("Verdana, Geneva, sans-serif"); case 'Verdana': return new Handlebars.SafeString('Verdana, Geneva, sans-serif');
default: return font; default: return font;
} }
}); });

View File

@ -1,6 +1,7 @@
define('helpTooltip', ['mailpoet', 'react', 'react-dom', 'help-tooltip.jsx'], define('helpTooltip', ['mailpoet', 'react', 'react-dom', 'help-tooltip.jsx'],
function (mp, React, ReactDOM, TooltipComponent) { function (mp, React, ReactDOM, TooltipComponent) {
'use strict'; 'use strict';
var MailPoet = mp; var MailPoet = mp;
MailPoet.helpTooltip = { MailPoet.helpTooltip = {

View File

@ -6,16 +6,16 @@ function Tooltip(props) {
let tooltipId = props.tooltipId; let tooltipId = props.tooltipId;
let tooltip = props.tooltip; let tooltip = props.tooltip;
// tooltip ID must be unique, defaults to tooltip text // tooltip ID must be unique, defaults to tooltip text
if(!props.tooltipId && typeof props.tooltip === "string") { if (!props.tooltipId && typeof props.tooltip === 'string') {
tooltipId = props.tooltip; tooltipId = props.tooltip;
} }
if(typeof props.tooltip === "string") { if (typeof props.tooltip === 'string') {
tooltip = (<span tooltip = (<span
style={{ style={{
pointerEvents: "all", pointerEvents: 'all',
maxWidth: "400", maxWidth: '400',
display: "inline-block", display: 'inline-block',
}} }}
> >
{ReactHtmlParser(props.tooltip)} {ReactHtmlParser(props.tooltip)}
@ -26,7 +26,7 @@ function Tooltip(props) {
<span className={props.className}> <span className={props.className}>
<span <span
style={{ style={{
cursor: "pointer", cursor: 'pointer',
}} }}
className="tooltip dashicons dashicons-editor-help" className="tooltip dashicons dashicons-editor-help"
data-event="click" data-event="click"

View File

@ -17,7 +17,6 @@ const App = React.createClass({
const container = document.getElementById('help_container'); const container = document.getElementById('help_container');
if (container) { if (container) {
ReactDOM.render(( ReactDOM.render((
<Router history={history}> <Router history={history}>
<Route path="/" component={App}> <Route path="/" component={App}>
@ -28,5 +27,4 @@ if(container) {
</Route> </Route>
</Router> </Router>
), container); ), container);
} }

View File

@ -4,7 +4,6 @@ import MailPoet from 'mailpoet';
import Tabs from './tabs.jsx'; import Tabs from './tabs.jsx';
function KnowledgeBase() { function KnowledgeBase() {
return ( return (
<div> <div>
@ -24,6 +23,6 @@ function KnowledgeBase() {
<a target="_blank" href="http://beta.docs.mailpoet.com/" className="button button-primary">{MailPoet.I18n.t('knowledgeBaseButton')}</a> <a target="_blank" href="http://beta.docs.mailpoet.com/" className="button button-primary">{MailPoet.I18n.t('knowledgeBaseButton')}</a>
</div> </div>
); );
}; }
module.exports = KnowledgeBase; module.exports = KnowledgeBase;

View File

@ -17,15 +17,14 @@ function printData(data) {
return (<textarea return (<textarea
readOnly={true} readOnly={true}
onFocus={handleFocus} onFocus={handleFocus}
value={printableData.join("\n")} value={printableData.join('\n')}
style={{ style={{
width: "100%", width: '100%',
height: "400px", height: '400px',
}} }}
/>); />);
} else {
return (<p>{MailPoet.I18n.t('systemInfoDataError')}</p>);
} }
return (<p>{MailPoet.I18n.t('systemInfoDataError')}</p>);
} }
function KnowledgeBase() { function KnowledgeBase() {
@ -35,13 +34,13 @@ function KnowledgeBase() {
<Tabs tab="systemInfo" /> <Tabs tab="systemInfo" />
<div className="mailpoet_notice notice inline notice-success" style={{ marginTop: "1em" }}> <div className="mailpoet_notice notice inline notice-success" style={{ marginTop: '1em' }}>
<p>{MailPoet.I18n.t('systemInfoIntro')}</p> <p>{MailPoet.I18n.t('systemInfoIntro')}</p>
</div> </div>
{printData(data)} {printData(data)}
</div> </div>
); );
}; }
module.exports = KnowledgeBase; module.exports = KnowledgeBase;

View File

@ -17,7 +17,6 @@ const tabs = [
]; ];
function Tabs(props) { function Tabs(props) {
const tabLinks = tabs.map((tab, index) => { const tabLinks = tabs.map((tab, index) => {
const tabClasses = classNames( const tabClasses = classNames(
'nav-tab', 'nav-tab',
@ -38,9 +37,9 @@ function Tabs(props) {
{ tabLinks } { tabLinks }
</h2> </h2>
); );
}; }
Tabs.propTypes = { tab: React.PropTypes.string }; Tabs.propTypes = { tab: React.PropTypes.string };
Tabs.defaultProps = { tab: "knowledgeBase" }; Tabs.defaultProps = { tab: 'knowledgeBase' };
module.exports = Tabs; module.exports = Tabs;

View File

@ -1,3 +0,0 @@
define([], function() {
!function(e, o, n){window.HSCW=o, window.HS=n, n.beacon=n.beacon||{};var t=n.beacon;t.userConfig={}, t.readyQueue=[], t.config=function(e){this.userConfig=e}, t.ready=function(e){this.readyQueue.push(e)}, o.config={docs:{enabled:!0, baseUrl:"//mailpoet3.helpscoutdocs.com/"}, contact:{enabled:!0, formId:"aa21ca80-a4f5-11e6-91aa-0a5fecc78a4d"}};var r=e.getElementsByTagName("script")[0], c=e.createElement("script");c.type="text/javascript", c.async=!0, c.src="https://djtflbt20bdde.cloudfront.net/", r.parentNode.insertBefore(c, r)}(document, window.HSCW||{}, window.HS||{});
});

View File

@ -5,6 +5,7 @@ define('i18n',
mp mp
) { ) {
'use strict'; 'use strict';
var MailPoet = mp; var MailPoet = mp;
var translations = {}; var translations = {};
@ -14,7 +15,7 @@ define('i18n',
translations[key] = value; translations[key] = value;
}, },
t: function (key) { t: function (key) {
return translations[key] || 'TRANSLATION "%$1s" NOT FOUND'.replace("%$1s", key); return translations[key] || 'TRANSLATION "%$1s" NOT FOUND'.replace('%$1s', key);
}, },
all: function () { all: function () {
return translations; return translations;

View File

@ -1,5 +1,6 @@
define('iframe', ['mailpoet'], function (mp) { define('iframe', ['mailpoet'], function (mp) {
'use strict'; 'use strict';
var MailPoet = mp; var MailPoet = mp;
MailPoet.Iframe = { MailPoet.Iframe = {
marginY: 20, marginY: 20,
@ -17,7 +18,7 @@ define('iframe', ['mailpoet'], function(mp) {
iframe.style.height = ( iframe.style.height = (
parseInt(i, 10) + this.marginY parseInt(i, 10) + this.marginY
) + "px"; ) + 'px';
} }
}; };

View File

@ -23,21 +23,21 @@ define(
* Dual licensed under the MIT and GPL licenses. * Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/ * http://benalman.com/about/license/
*/ */
$.fn.serializeObject = function(coerce) { $.fn.mailpoetSerializeObject = function (coerce) {
var obj = {}, var obj = {};
coerce_types = { 'true': !0, 'false': !1, 'null': null }; var coerce_types = { true: !0, false: !1, null: null };
// Iterate over all name=value pairs. // Iterate over all name=value pairs.
$.each(this.serializeArray(), function (j, v) { $.each(this.serializeArray(), function (j, v) {
var key = v.name, var key = v.name;
val = v.value, var val = v.value;
cur = obj, var cur = obj;
i = 0, var i = 0;
// If key is more complex than 'foo', like 'a[]' or 'a[b][c]', split it // If key is more complex than 'foo', like 'a[]' or 'a[b][c]', split it
// into its component parts. // into its component parts.
keys = key.split( '][' ), var keys = key.split('][');
keys_last = keys.length - 1; var keys_last = keys.length - 1;
// If the first keys part contains [ and the last ends with ], then [] // If the first keys part contains [ and the last ends with ], then []
// are correctly balanced. // are correctly balanced.

View File

@ -21,7 +21,7 @@ define([
const action = this.getSelectedAction(); const action = this.getSelectedAction();
// action on select callback // action on select callback
if(action !== null && action['onSelect'] !== undefined) { if (action !== null && action.onSelect !== undefined) {
this.setState({ this.setState({
extra: action.onSelect(e), extra: action.onSelect(e),
}); });
@ -41,14 +41,14 @@ define([
? this.props.selected_ids ? this.props.selected_ids
: []; : [];
const data = (action['getData'] !== undefined) const data = (action.getData !== undefined)
? action.getData() ? action.getData()
: {}; : {};
data.action = this.state.action; data.action = this.state.action;
let onSuccess = function () {}; let onSuccess = function () {};
if(action['onSuccess'] !== undefined) { if (action.onSuccess !== undefined) {
onSuccess = action.onSuccess; onSuccess = action.onSuccess;
} }
@ -56,7 +56,7 @@ define([
const promise = this.props.onBulkAction(selected_ids, data); const promise = this.props.onBulkAction(selected_ids, data);
if (promise !== false) { if (promise !== false) {
promise.then(onSuccess); promise.then(onSuccess);
}; }
} }
this.setState({ this.setState({
@ -67,8 +67,8 @@ define([
getSelectedAction: function () { getSelectedAction: function () {
const selected_action = this.refs.action.value; const selected_action = this.refs.action.value;
if (selected_action.length > 0) { if (selected_action.length > 0) {
const action = this.props.bulk_actions.filter((action) => { const action = this.props.bulk_actions.filter((act) => {
return (action.name === selected_action); return (act.name === selected_action);
}); });
if (action.length > 0) { if (action.length > 0) {

View File

@ -1,5 +1,4 @@
define(['react', 'classnames'], (React, classNames) => { define(['react', 'classnames'], (React, classNames) => {
const ListingGroups = React.createClass({ const ListingGroups = React.createClass({
handleSelect: function (group) { handleSelect: function (group) {
return this.props.onSelectGroup(group); return this.props.onSelectGroup(group);
@ -11,7 +10,7 @@ define(['react', 'classnames'], (React, classNames) => {
} }
const classes = classNames( const classes = classNames(
{ 'current' : (group.name === this.props.group) } { current: (group.name === this.props.group) }
); );
return ( return (

View File

@ -62,9 +62,9 @@ const ListingColumn = React.createClass({
const classes = classNames( const classes = classNames(
'manage-column', 'manage-column',
{ 'column-primary': this.props.column.is_primary }, { 'column-primary': this.props.column.is_primary },
{ 'sortable': this.props.column.sortable }, { sortable: this.props.column.sortable },
this.props.column.sorted, this.props.column.sorted,
{ 'sorted': (this.props.sort_by === this.props.column.name) } { sorted: (this.props.sort_by === this.props.column.name) }
); );
let label; let label;

View File

@ -186,7 +186,7 @@ const ListingItem = React.createClass({
const row_classes = classNames({ 'is-expanded': this.state.expanded }); const row_classes = classNames({ 'is-expanded': this.state.expanded });
return ( return (
<tr className={ row_classes }> <tr className={row_classes} data-automation-id={'listing_item_' + this.props.item.id}>
{ checkbox } { checkbox }
{ this.props.onRenderItem(this.props.item, actions) } { this.props.onRenderItem(this.props.item, actions) }
</tr> </tr>
@ -223,10 +223,10 @@ const ListingItems = React.createClass({
</tr> </tr>
</tbody> </tbody>
); );
} else { }
const select_all_classes = classNames( const select_all_classes = classNames(
'mailpoet_select_all', 'mailpoet_select_all',
{ 'mailpoet_hidden': ( { mailpoet_hidden: (
this.props.selection === false this.props.selection === false
|| (this.props.count <= this.props.limit) || (this.props.count <= this.props.limit)
), ),
@ -276,14 +276,13 @@ const ListingItems = React.createClass({
selection={this.props.selection} selection={this.props.selection}
is_selectable={this.props.is_selectable} is_selectable={this.props.is_selectable}
item_actions={this.props.item_actions} item_actions={this.props.item_actions}
group={ this.props.group } group={this.props.group}
key={`item-${renderItem.id}-${index}`} key={`item-${renderItem.id}-${index}`}
item={renderItem} /> item={renderItem} />
); );
})} })}
</tbody> </tbody>
); );
}
}, },
}); });
@ -321,14 +320,13 @@ const Listing = React.createClass({
if (params.splat) { if (params.splat) {
params.splat.split('/').map((param) => { params.splat.split('/').map((param) => {
const [key, value] = this.getParam(param); const [key, value] = this.getParam(param);
const filters = {};
switch (key) { switch (key) {
case 'filter': case 'filter':
const filters = {};
value.split('&').map((pair) => { value.split('&').map((pair) => {
const [k, v] = pair.split('='); const [k, v] = pair.split('=');
filters[k] = v; filters[k] = v;
} });
);
state.filter = filters; state.filter = filters;
break; break;
@ -414,9 +412,8 @@ const Listing = React.createClass({
if (base_url !== null) { if (base_url !== null) {
base_url = this.setBaseUrlParams(base_url); base_url = this.setBaseUrlParams(base_url);
return `/${base_url}/${params}`; return `/${base_url}/${params}`;
} else {
return `/${ params }`;
} }
return `/${params}`;
}, },
setBaseUrlParams: function (base_url) { setBaseUrlParams: function (base_url) {
let ret = base_url; let ret = base_url;
@ -514,7 +511,7 @@ const Listing = React.createClass({
}).done((response) => { }).done((response) => {
if ( if (
this.props.messages !== undefined this.props.messages !== undefined
&& this.props.messages['onRestore'] !== undefined && this.props.messages.onRestore !== undefined
) { ) {
this.props.messages.onRestore(response); this.props.messages.onRestore(response);
} }
@ -542,7 +539,7 @@ const Listing = React.createClass({
}).done((response) => { }).done((response) => {
if ( if (
this.props.messages !== undefined this.props.messages !== undefined
&& this.props.messages['onTrash'] !== undefined && this.props.messages.onTrash !== undefined
) { ) {
this.props.messages.onTrash(response); this.props.messages.onTrash(response);
} }
@ -570,7 +567,7 @@ const Listing = React.createClass({
}).done((response) => { }).done((response) => {
if ( if (
this.props.messages !== undefined this.props.messages !== undefined
&& this.props.messages['onDelete'] !== undefined && this.props.messages.onDelete !== undefined
) { ) {
this.props.messages.onDelete(response); this.props.messages.onDelete(response);
} }
@ -658,8 +655,8 @@ const Listing = React.createClass({
}); });
}, },
handleSelectItem: function (id, is_checked) { handleSelectItem: function (id, is_checked) {
let selected_ids = this.state.selected_ids, let selected_ids = this.state.selected_ids;
selection = false; let selection = false;
if (is_checked) { if (is_checked) {
selected_ids = jQuery.merge(selected_ids, [id]); selected_ids = jQuery.merge(selected_ids, [id]);
@ -783,7 +780,7 @@ const Listing = React.createClass({
'widefat', 'widefat',
'fixed', 'fixed',
'striped', 'striped',
{ 'mailpoet_listing_loading': this.state.loading } { mailpoet_listing_loading: this.state.loading }
); );
// search // search

View File

@ -7,7 +7,6 @@ define([
classNames, classNames,
MailPoet MailPoet
) => { ) => {
const ListingPages = React.createClass({ const ListingPages = React.createClass({
getInitialState: function () { getInitialState: function () {
return { return {
@ -59,7 +58,7 @@ define([
render: function () { render: function () {
if (this.props.count === 0) { if (this.props.count === 0) {
return false; return false;
} else { }
let pagination = false; let pagination = false;
let firstPage = ( let firstPage = (
<span aria-hidden="true" className="tablenav-pages-navspan">«</span> <span aria-hidden="true" className="tablenav-pages-navspan">«</span>
@ -146,7 +145,7 @@ define([
name="paged" name="paged"
id="current-page-selector" id="current-page-selector"
className="current-page" /> className="current-page" />
&nbsp;{MailPoet.I18n.t('pageOutOf')}&nbsp; {MailPoet.I18n.t('pageOutOf')}&nbsp;
<span className="total-pages"> <span className="total-pages">
{Math.ceil(this.props.count / this.props.limit).toLocaleString()} {Math.ceil(this.props.count / this.props.limit).toLocaleString()}
</span> </span>
@ -177,7 +176,6 @@ define([
{ pagination } { pagination }
</div> </div>
); );
}
}, },
}); });

View File

@ -5,12 +5,11 @@ define([
MailPoet, MailPoet,
React React
) => { ) => {
const ListingSearch = React.createClass({ const ListingSearch = React.createClass({
handleSearch: function (e) { handleSearch: function (e) {
e.preventDefault(); e.preventDefault();
this.props.onSearch( this.props.onSearch(
this.refs.search.value this.refs.search.value.trim()
); );
}, },
componentWillReceiveProps: function (nextProps) { componentWillReceiveProps: function (nextProps) {
@ -19,7 +18,7 @@ define([
render: function () { render: function () {
if (this.props.search === false) { if (this.props.search === false) {
return false; return false;
} else { }
return ( return (
<form name="search" onSubmit={this.handleSearch}> <form name="search" onSubmit={this.handleSearch}>
<p className="search-box"> <p className="search-box">
@ -39,7 +38,6 @@ define([
</p> </p>
</form> </form>
); );
}
}, },
}); });

View File

@ -1,6 +1,7 @@
define('modal', ['mailpoet', 'jquery'], define('modal', ['mailpoet', 'jquery'],
function (mp, jQuery) { function (mp, jQuery) {
'use strict'; 'use strict';
var MailPoet = mp; var MailPoet = mp;
/** ************************************************************************* /** *************************************************************************
MailPoet Modal: MailPoet Modal:
@ -111,11 +112,11 @@ define('modal', ['mailpoet', 'jquery'],
if (this.renderer === 'html') { if (this.renderer === 'html') {
return function () { return template; }; return function () { return template; };
} else { } else {
return Handlebars.compile(template); return window.Handlebars.compile(template);
} }
return false;
}, },
init: function (options) { init: function (options) {
var modal;
if (this.initialized === true) { if (this.initialized === true) {
this.close(); this.close();
} }
@ -134,7 +135,7 @@ define('modal', ['mailpoet', 'jquery'],
if (this.options.type !== null) { if (this.options.type !== null) {
// insert modal depending on its type // insert modal depending on its type
if (this.options.type === 'popup') { if (this.options.type === 'popup') {
var modal = this.compileTemplate( modal = this.compileTemplate(
this.templates[this.options.type] this.templates[this.options.type]
); );
// create modal // create modal
@ -178,7 +179,7 @@ define('modal', ['mailpoet', 'jquery'],
return this; return this;
}, },
initOverlay: function(toggle) { initOverlay: function () {
if (jQuery('#mailpoet_modal_overlay').length === 0) { if (jQuery('#mailpoet_modal_overlay').length === 0) {
// insert overlay into the DOM // insert overlay into the DOM
jQuery('body').append(this.templates.overlay); jQuery('body').append(this.templates.overlay);
@ -309,7 +310,6 @@ define('modal', ['mailpoet', 'jquery'],
setDimensions: function () { setDimensions: function () {
switch (this.options.type) { switch (this.options.type) {
case 'popup': case 'popup':
console.log(this.options)
// set popup dimensions // set popup dimensions
jQuery('#mailpoet_popup').css({ jQuery('#mailpoet_popup').css({
width: this.options.width, width: this.options.width,
@ -344,20 +344,21 @@ define('modal', ['mailpoet', 'jquery'],
return this; return this;
}, },
setPosition: function () { setPosition: function () {
var screenWidth;
var screenHeight;
var modalWidth;
var modalHeight;
switch (this.options.type) { switch (this.options.type) {
case 'popup': case 'popup':
var screenWidth = jQuery(window).width(), screenWidth = jQuery(window).width();
screenHeight = jQuery(window).height(), screenHeight = jQuery(window).height();
modalWidth = jQuery('.mailpoet_'+ this.options.type +'_wrapper').width(), modalWidth = jQuery('.mailpoet_'+ this.options.type +'_wrapper').width();
modalHeight = jQuery('.mailpoet_'+ this.options.type +'_wrapper').height(); modalHeight = jQuery('.mailpoet_'+ this.options.type +'_wrapper').height();
var top = Math.max(48, parseInt((screenHeight / 2) - (modalHeight / 2))),
left = Math.max(0, parseInt((screenWidth / 2) - (modalWidth / 2)));
// set position of popup depending on screen dimensions. // set position of popup depending on screen dimensions.
jQuery('#mailpoet_popup').css({ jQuery('#mailpoet_popup').css({
top: top, top: Math.max(48, parseInt((screenHeight / 2) - (modalHeight / 2))),
left: left left: Math.max(0, parseInt((screenWidth / 2) - (modalWidth / 2)))
}); });
break; break;
case 'panel': case 'panel':
@ -385,9 +386,6 @@ define('modal', ['mailpoet', 'jquery'],
// remember the previously focused element // remember the previously focused element
this.prevFocus = jQuery(':focus'); this.prevFocus = jQuery(':focus');
// add a flag on the body so that we can prevent scrolling
jQuery('body').addClass('mailpoet_modal_opened');
// show popup // show popup
jQuery('#mailpoet_' + this.options.type).show(); jQuery('#mailpoet_' + this.options.type).show();
@ -437,7 +435,7 @@ define('modal', ['mailpoet', 'jquery'],
.removeClass('mailpoet_modal_highlight'); .removeClass('mailpoet_modal_highlight');
return this; return this;
}, },
hideModal: function(callback) { hideModal: function () {
// set modal as closed // set modal as closed
this.opened = false; this.opened = false;
@ -447,12 +445,9 @@ define('modal', ['mailpoet', 'jquery'],
// remove class on highlighted elements // remove class on highlighted elements
this.highlightOff(); this.highlightOff();
// remove class from body to let it be scrollable
jQuery('body').removeClass('mailpoet_modal_opened');
return this; return this;
}, },
showOverlay: function(force) { showOverlay: function () {
jQuery('#mailpoet_modal_overlay').show(); jQuery('#mailpoet_modal_overlay').show();
return this; return this;
}, },

View File

@ -1,5 +1,6 @@
define('mp2migrator', ['mailpoet', 'jquery'], function (mp, jQuery) { define('mp2migrator', ['mailpoet', 'jquery'], function (mp, jQuery) {
'use strict'; 'use strict';
var MailPoet = mp; var MailPoet = mp;
MailPoet.MP2Migrator = { MailPoet.MP2Migrator = {
@ -11,7 +12,7 @@ define('mp2migrator', ['mailpoet', 'jquery'], function(mp, jQuery) {
clearTimeout(MailPoet.MP2Migrator.displayLogs_timeout); clearTimeout(MailPoet.MP2Migrator.displayLogs_timeout);
clearTimeout(MailPoet.MP2Migrator.updateProgressbar_timeout); clearTimeout(MailPoet.MP2Migrator.updateProgressbar_timeout);
clearTimeout(MailPoet.MP2Migrator.update_wordpress_info_timeout); clearTimeout(MailPoet.MP2Migrator.update_wordpress_info_timeout);
setTimeout(MailPoet.MP2Migrator.updateDisplay, 1000) setTimeout(MailPoet.MP2Migrator.updateDisplay, 1000);
}, },
stopLogger: function () { stopLogger: function () {
@ -25,11 +26,11 @@ define('mp2migrator', ['mailpoet', 'jquery'], function(mp, jQuery) {
displayLogs: function () { displayLogs: function () {
jQuery.ajax({ jQuery.ajax({
url: mailpoet_mp2_migrator.log_file_url, url: window.mailpoet_mp2_migrator.log_file_url,
cache: false cache: false
}).done(function (result) { }).done(function (result) {
jQuery("#logger").html(''); jQuery('#logger').html('');
result.split("\n").forEach(function (resultRow) { result.split('\n').forEach(function (resultRow) {
var row = resultRow; var row = resultRow;
if (row.substr(0, 7) === '[ERROR]' || row.substr(0, 9) === '[WARNING]' || row === MailPoet.I18n.t('import_stopped_by_user')) { if (row.substr(0, 7) === '[ERROR]' || row.substr(0, 9) === '[WARNING]' || row === MailPoet.I18n.t('import_stopped_by_user')) {
row = '<span class="error_msg">' + row + '</span>'; // Mark the errors in red row = '<span class="error_msg">' + row + '</span>'; // Mark the errors in red
@ -39,10 +40,10 @@ define('mp2migrator', ['mailpoet', 'jquery'], function(mp, jQuery) {
jQuery('#import-actions').hide(); jQuery('#import-actions').hide();
jQuery('#upgrade-completed').show(); jQuery('#upgrade-completed').show();
} }
jQuery("#logger").append(row + "<br />\n"); jQuery('#logger').append(row + '<br />\n');
}); });
jQuery("#logger").append('<span class="error_msg">' + MailPoet.MP2Migrator.fatal_error + '</span>' + "<br />\n"); jQuery('#logger').append('<span class="error_msg">' + MailPoet.MP2Migrator.fatal_error + '</span>' + '<br />\n');
}).always(function () { }).always(function () {
if (MailPoet.MP2Migrator.is_logging) { if (MailPoet.MP2Migrator.is_logging) {
MailPoet.MP2Migrator.displayLogs_timeout = setTimeout(MailPoet.MP2Migrator.displayLogs, 1000); MailPoet.MP2Migrator.displayLogs_timeout = setTimeout(MailPoet.MP2Migrator.displayLogs, 1000);
@ -52,7 +53,7 @@ define('mp2migrator', ['mailpoet', 'jquery'], function(mp, jQuery) {
updateProgressbar: function () { updateProgressbar: function () {
jQuery.ajax({ jQuery.ajax({
url: mailpoet_mp2_migrator.progress_url, url: window.mailpoet_mp2_migrator.progress_url,
cache: false, cache: false,
dataType: 'json' dataType: 'json'
}).always(function (result) { }).always(function (result) {

View File

@ -1,12 +1,8 @@
define([ define([
'backbone', 'backbone',
'backbone.marionette', 'backbone.marionette',
'backbone.radio', 'backbone.radio'
'jquery', ], function (Backbone, Marionette, BackboneRadio) {
'underscore',
'handlebars',
'handlebars_helpers'
], function(Backbone, Marionette, BackboneRadio, jQuery, _, Handlebars) {
var Radio = BackboneRadio; var Radio = BackboneRadio;
var AppView = Marionette.View.extend({ var AppView = Marionette.View.extend({

View File

@ -8,19 +8,39 @@ define([
'newsletter_editor/behaviors/BehaviorsLookup', 'newsletter_editor/behaviors/BehaviorsLookup',
'mailpoet', 'mailpoet',
'spectrum' 'spectrum'
], function(Marionette, BehaviorsLookup, MailPoet, Spectrum) { ], function (Marionette, BehaviorsLookup, MailPoet) {
var BL = BehaviorsLookup; var BL = BehaviorsLookup;
BL.ColorPickerBehavior = Marionette.Behavior.extend({ BL.ColorPickerBehavior = Marionette.Behavior.extend({
onRender: function () { onRender: function () {
this.view.$('.mailpoet_color').spectrum({ var that = this;
var preferredFormat = 'hex6';
this.view.$('.mailpoet_color').each(function () {
var $input = that.view.$(this);
var updateColorInput = function (color) {
if (color && color.getAlpha() > 0) {
$input.val(color.toString(preferredFormat));
} else {
$input.val('');
}
$input.trigger('change');
};
$input.spectrum({
clickoutFiresChange: true, clickoutFiresChange: true,
showInput: true, showInput: true,
showInitial: true, showInitial: true,
preferredFormat: "hex6", showPalette: true,
showSelectionPalette: true,
palette: [],
localStorageKey: 'newsletter_editor.spectrum.palette',
preferredFormat: preferredFormat,
allowEmpty: true, allowEmpty: true,
chooseText: MailPoet.I18n.t('selectColor'), chooseText: MailPoet.I18n.t('selectColor'),
cancelText: MailPoet.I18n.t('cancelColorSelection') cancelText: MailPoet.I18n.t('cancelColorSelection'),
change: updateColorInput,
move: updateColorInput,
hide: updateColorInput
});
}); });
} }
}); });

View File

@ -1,3 +1,4 @@
/** /**
* ContainerDropZoneBehavior * ContainerDropZoneBehavior
* *
@ -24,11 +25,11 @@ define([
this.addDropZone(); this.addDropZone();
} }
}, },
addDropZone: function(_event) { addDropZone: function () {
var that = this, var that = this;
view = this.view, var view = this.view;
domElement = that.$el.get(0), var domElement = that.$el.get(0);
acceptableElementSelector; var acceptableElementSelector;
// TODO: Extract this limitation code to be controlled from containers // TODO: Extract this limitation code to be controlled from containers
if (this.view.renderOptions.depth === 0) { if (this.view.renderOptions.depth === 0) {
@ -46,11 +47,11 @@ define([
interact(domElement).dropzone({ interact(domElement).dropzone({
accept: acceptableElementSelector, accept: acceptableElementSelector,
overlap: 'pointer', // Mouse pointer denotes location of a droppable overlap: 'pointer', // Mouse pointer denotes location of a droppable
ondragenter: function(event) { ondragenter: function () {
// 1. Visually mark block as active for dropping // 1. Visually mark block as active for dropping
view.$el.addClass('mailpoet_drop_active'); view.$el.addClass('mailpoet_drop_active');
}, },
ondragleave: function(event) { ondragleave: function () {
// 1. Remove visual markings of active dropping container // 1. Remove visual markings of active dropping container
// 2. Remove visual markings of drop position visualization // 2. Remove visual markings of drop position visualization
that.cleanup(); that.cleanup();
@ -67,15 +68,21 @@ define([
view.$el, view.$el,
view.model.get('orientation'), view.model.get('orientation'),
view.model.get('blocks').length view.model.get('blocks').length
), );
element = view.$el, var element = view.$el;
markerWidth = '', var markerWidth = '';
markerHeight = '', var markerHeight = '';
containerOffset = element.offset(), var containerOffset = element.offset();
viewCollection = that.getCollection(), var viewCollection = that.getCollection();
marker, targetModel, targetView, targetElement, var marker;
topOffset, leftOffset, isLastBlockInsertion, var targetModel;
$targetBlock, margin; var targetView;
var targetElement;
var topOffset;
var leftOffset;
var isLastBlockInsertion;
var $targetBlock;
var margin;
if (dropPosition === undefined) return; if (dropPosition === undefined) return;
@ -182,10 +189,14 @@ define([
view.$el, view.$el,
view.model.get('orientation'), view.model.get('orientation'),
view.model.get('blocks').length view.model.get('blocks').length
), );
droppableModel = event.draggable.getDropModel(), var droppableModel = event.draggable.getDropModel();
viewCollection = that.getCollection(), var viewCollection = that.getCollection();
droppedView, droppedModel, index, tempCollection, tempCollection2; var droppedView;
var index;
var tempCollection;
var tempCollection2;
var tempModel;
if (dropPosition === undefined) return; if (dropPosition === undefined) return;
@ -195,7 +206,8 @@ define([
if (view.model.get('orientation') === 'horizontal' && droppableModel.get('type') !== 'container') { if (view.model.get('orientation') === 'horizontal' && droppableModel.get('type') !== 'container') {
// Regular blocks always need to be inserted into columns - vertical containers // Regular blocks always need to be inserted into columns - vertical containers
tempCollection = new (EditorApplication.getBlockTypeModel('container'))({
tempCollection = new (window.EditorApplication.getBlockTypeModel('container'))({
orientation: 'vertical' orientation: 'vertical'
}); });
tempCollection.get('blocks').add(droppableModel); tempCollection.get('blocks').add(droppableModel);
@ -208,9 +220,9 @@ define([
} else { } else {
// Special insertion by replacing target block with collection // Special insertion by replacing target block with collection
// and inserting dropModel into that // and inserting dropModel into that
var tempModel = viewCollection.at(dropPosition.index); tempModel = viewCollection.at(dropPosition.index);
tempCollection = new (EditorApplication.getBlockTypeModel('container'))({ tempCollection = new (window.EditorApplication.getBlockTypeModel('container'))({
orientation: (view.model.get('orientation') === 'vertical') ? 'horizontal' : 'vertical' orientation: (view.model.get('orientation') === 'vertical') ? 'horizontal' : 'vertical'
}); });
@ -218,19 +230,19 @@ define([
if (tempCollection.get('orientation') === 'horizontal') { if (tempCollection.get('orientation') === 'horizontal') {
if (dropPosition.position === 'before') { if (dropPosition.position === 'before') {
tempCollection2 = new (EditorApplication.getBlockTypeModel('container'))({ tempCollection2 = new (window.EditorApplication.getBlockTypeModel('container'))({
orientation: 'vertical' orientation: 'vertical'
}); });
tempCollection2.get('blocks').add(droppableModel); tempCollection2.get('blocks').add(droppableModel);
tempCollection.get('blocks').add(tempCollection2); tempCollection.get('blocks').add(tempCollection2);
} }
tempCollection2 = new (EditorApplication.getBlockTypeModel('container'))({ tempCollection2 = new (window.EditorApplication.getBlockTypeModel('container'))({
orientation: 'vertical' orientation: 'vertical'
}); });
tempCollection2.get('blocks').add(tempModel); tempCollection2.get('blocks').add(tempModel);
tempCollection.get('blocks').add(tempCollection2); tempCollection.get('blocks').add(tempCollection2);
if (dropPosition.position === 'after') { if (dropPosition.position === 'after') {
tempCollection2 = new (EditorApplication.getBlockTypeModel('container'))({ tempCollection2 = new (window.EditorApplication.getBlockTypeModel('container'))({
orientation: 'vertical' orientation: 'vertical'
}); });
tempCollection2.get('blocks').add(droppableModel); tempCollection2.get('blocks').add(droppableModel);
@ -270,28 +282,32 @@ define([
this.view.$('.mailpoet_drop_marker').remove(); this.view.$('.mailpoet_drop_marker').remove();
}, },
getDropPosition: function (eventX, eventY, is_unsafe) { getDropPosition: function (eventX, eventY, is_unsafe) {
var SPECIAL_AREA_INSERTION_WIDTH = 0.00, // Disable special insertion. Default: 0.3 var SPECIAL_AREA_INSERTION_WIDTH = 0.00; // Disable special insertion. Default: 0.3
element = this.view.$el, var element = this.view.$el;
orientation = this.view.model.get('orientation'), var orientation = this.view.model.get('orientation');
elementOffset = element.offset(), var elementOffset = element.offset();
elementPageX = elementOffset.left, var elementPageX = elementOffset.left;
elementPageY = elementOffset.top, var elementPageY = elementOffset.top;
elementWidth = element.outerWidth(true), var elementWidth = element.outerWidth(true);
elementHeight = element.outerHeight(true), var elementHeight = element.outerHeight(true);
relativeX = eventX - elementPageX, var relativeX = eventX - elementPageX;
relativeY = eventY - elementPageY, var relativeY = eventY - elementPageY;
relativeOffset, elementLength, var relativeOffset;
var elementLength;
canAcceptNormalInsertion = this._canAcceptNormalInsertion(), var canAcceptNormalInsertion = this._canAcceptNormalInsertion();
canAcceptSpecialInsertion = this._canAcceptSpecialInsertion(), var canAcceptSpecialInsertion = this._canAcceptSpecialInsertion();
insertionType, index, position, indexAndPosition; var insertionType;
var index;
var position;
var indexAndPosition;
unsafe = !!is_unsafe; var unsafe = !!is_unsafe;
if (this.getCollection().length === 0) { if (this.getCollection().length === 0) {
return { return {
@ -357,12 +373,14 @@ define([
// target element if event happens on the second half of the element. // target element if event happens on the second half of the element.
// Halves depend on orientation. // Halves depend on orientation.
var index = this._computeCellIndex(eventX, eventY), var index = this._computeCellIndex(eventX, eventY);
// TODO: Handle case when there are no children, container is empty // TODO: Handle case when there are no children, container is empty
targetView = this.getChildren().findByModel(this.getCollection().at(index)), var targetView = this.getChildren().findByModel(this.getCollection().at(index));
orientation = this.view.model.get('orientation'), var orientation = this.view.model.get('orientation');
element = targetView.$el, var element = targetView.$el;
eventOffset, closeOffset, elementDimension; var eventOffset;
var closeOffset;
var elementDimension;
if (orientation === 'vertical') { if (orientation === 'vertical') {
eventOffset = eventY; eventOffset = eventY;
@ -392,11 +410,12 @@ define([
return this._computeCellIndex(eventX, eventY); return this._computeCellIndex(eventX, eventY);
}, },
_computeCellIndex: function (eventX, eventY) { _computeCellIndex: function (eventX, eventY) {
var orientation = this.view.model.get('orientation'), var orientation = this.view.model.get('orientation');
eventOffset = (orientation === 'vertical') ? eventY : eventX, var eventOffset = (orientation === 'vertical') ? eventY : eventX;
resultView = this.getChildren().find(function(view) { var resultView = this.getChildren().find(function (view) {
var element = view.$el, var element = view.$el;
closeOffset, farOffset; var closeOffset;
var farOffset;
if (orientation === 'vertical') { if (orientation === 'vertical') {
closeOffset = element.offset().top; closeOffset = element.offset().top;
@ -415,16 +434,16 @@ define([
return index; return index;
}, },
_canAcceptNormalInsertion: function () { _canAcceptNormalInsertion: function () {
var orientation = this.view.model.get('orientation'), var orientation = this.view.model.get('orientation');
depth = this.view.renderOptions.depth, var depth = this.view.renderOptions.depth;
childCount = this.getChildren().length; var childCount = this.getChildren().length;
// Note that depth is zero indexed. Root container has depth=0 // Note that depth is zero indexed. Root container has depth=0
return orientation === 'vertical' || (orientation === 'horizontal' && depth === 1 && childCount < this.options.columnLimit); return orientation === 'vertical' || (orientation === 'horizontal' && depth === 1 && childCount < this.options.columnLimit);
}, },
_canAcceptSpecialInsertion: function () { _canAcceptSpecialInsertion: function () {
var orientation = this.view.model.get('orientation'), var orientation = this.view.model.get('orientation');
depth = this.view.renderOptions.depth, var depth = this.view.renderOptions.depth;
childCount = this.getChildren().length; var childCount = this.getChildren().length;
return depth === 0 || (depth === 1 && orientation === 'horizontal' && childCount <= this.options.columnLimit); return depth === 0 || (depth === 1 && orientation === 'horizontal' && childCount <= this.options.columnLimit);
}, },
getCollectionView: function () { getCollectionView: function () {

View File

@ -28,12 +28,12 @@ define([
throw "Missing 'drop' function for DraggableBehavior"; throw "Missing 'drop' function for DraggableBehavior";
}, },
onDrop: function(model, view) {}, onDrop: function () {},
testAttachToInstance: function(model, view) { return true; } testAttachToInstance: function () { return true; }
}, },
onRender: function () { onRender: function () {
var that = this, var that = this;
interactable; var interactable;
// Give instances more control over whether Draggable should be applied // Give instances more control over whether Draggable should be applied
if (!this.options.testAttachToInstance(this.view.model, this.view)) return; if (!this.options.testAttachToInstance(this.view.model, this.view)) return;
@ -49,16 +49,19 @@ define([
onstart: function (startEvent) { onstart: function (startEvent) {
var event = startEvent; var event = startEvent;
var centerXOffset;
var centerYOffset;
var tempClone;
var clone;
var $clone;
if (that.options.cloneOriginal === true) { if (that.options.cloneOriginal === true) {
// Use substitution instead of a clone // Use substitution instead of a clone
var tempClone = (_.isFunction(that.options.onDragSubstituteBy)) ? that.options.onDragSubstituteBy(that) : undefined, tempClone = (_.isFunction(that.options.onDragSubstituteBy)) ? that.options.onDragSubstituteBy(that) : undefined;
// Or use a clone // Or use a clone
clone = tempClone ? tempClone : event.target.cloneNode(true), clone = tempClone || event.target.cloneNode(true);
jQuery(event.target);
$original = jQuery(event.target), $clone = jQuery(clone);
$clone = jQuery(clone),
centerXOffset, centerYOffset, parentOffset;
$clone.addClass('mailpoet_droppable_active'); $clone.addClass('mailpoet_droppable_active');
$clone.css('position', 'absolute'); $clone.css('position', 'absolute');
@ -85,10 +88,10 @@ define([
}, },
// call this function on every dragmove event // call this function on every dragmove event
onmove: function (event) { onmove: function (event) {
var target = event.target, var target = event.target;
// keep the dragged position in the data-x/data-y attributes // keep the dragged position in the data-x/data-y attributes
x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx, var x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx;
y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy; var y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
// translate the element // translate the element
target.style.transform = 'translate(' + x + 'px, ' + y + 'px)'; target.style.transform = 'translate(' + x + 'px, ' + y + 'px)';

View File

@ -0,0 +1,26 @@
/**
* Highlight Container Behavior
*
* Highlights a container block when hovering over its tools
*/
define([
'backbone.marionette',
'newsletter_editor/behaviors/BehaviorsLookup'
], function (Marionette, BehaviorsLookup) {
var BL = BehaviorsLookup;
BL.HighlightContainerBehavior = Marionette.Behavior.extend({
events: {
'mouseenter @ui.tools': 'enableHighlight',
'mouseleave @ui.tools': 'disableHighlight'
},
enableHighlight: function () {
this.$el.addClass('mailpoet_highlight');
},
disableHighlight: function () {
if (!this.view._isBeingEdited) {
this.$el.removeClass('mailpoet_highlight');
}
}
});
});

View File

@ -11,13 +11,15 @@ define([
BL.HighlightEditingBehavior = Marionette.Behavior.extend({ BL.HighlightEditingBehavior = Marionette.Behavior.extend({
modelEvents: { modelEvents: {
'startEditing': 'enableHighlight', startEditing: 'enableHighlight',
'stopEditing': 'disableHighlight' stopEditing: 'disableHighlight'
}, },
enableHighlight: function () { enableHighlight: function () {
this.view._isBeingEdited = true;
this.$el.addClass('mailpoet_highlight'); this.$el.addClass('mailpoet_highlight');
}, },
disableHighlight: function () { disableHighlight: function () {
this.view._isBeingEdited = false;
this.$el.removeClass('mailpoet_highlight'); this.$el.removeClass('mailpoet_highlight');
} }
}); });

View File

@ -14,13 +14,20 @@ define([
defaults: { defaults: {
elementSelector: null, elementSelector: null,
resizeHandleSelector: true, // true will use edges of the element itself resizeHandleSelector: true, // true will use edges of the element itself
transformationFunction: function(y) { return y; }, transformationFunction: function (y) { return y; }, // for blocks that use the default onResize function
minLength: 0, minLength: 0,
modelField: 'styles.block.height' maxLength: Infinity,
modelField: 'styles.block.height',
onResize: function (event) {
var currentLength = parseFloat(this.view.model.get(this.options.modelField));
var newLength = currentLength + this.options.transformationFunction(event.dy);
newLength = Math.min(this.options.maxLength, Math.max(this.options.minLength, newLength));
this.view.model.set(this.options.modelField, newLength + 'px');
}
}, },
events: { events: {
"mouseenter": 'showResizeHandle', mouseenter: 'showResizeHandle',
"mouseleave": 'hideResizeHandle' mouseleave: 'hideResizeHandle'
}, },
onRender: function () { onRender: function () {
this.attachResize(); this.attachResize();
@ -30,8 +37,8 @@ define([
} }
}, },
attachResize: function () { attachResize: function () {
var domElement = (this.options.elementSelector === null) ? this.view.$el.get(0) : this.view.$(this.options.elementSelector).get(0), var domElement = (this.options.elementSelector === null) ? this.view.$el.get(0) : this.view.$(this.options.elementSelector).get(0);
that = this; var that = this;
interact(domElement).resizable({ interact(domElement).resizable({
// axis: 'y', // axis: 'y',
edges: { edges: {
@ -40,17 +47,15 @@ define([
right: false, right: false,
bottom: (typeof this.options.resizeHandleSelector === 'string') ? this.view.$(this.options.resizeHandleSelector).get(0) : this.options.resizeHandleSelector bottom: (typeof this.options.resizeHandleSelector === 'string') ? this.view.$(this.options.resizeHandleSelector).get(0) : this.options.resizeHandleSelector
} }
}).on('resizestart', function(event) { })
.on('resizestart', function () {
that.isBeingResized = true; that.isBeingResized = true;
that.$el.addClass('mailpoet_resize_active'); that.$el.addClass('mailpoet_resize_active');
}).on('resizemove', function (event) { }).on('resizemove', function (event) {
var currentLength = parseFloat(that.view.model.get(that.options.modelField)), var onResize = that.options.onResize.bind(that);
newLength = currentLength + that.options.transformationFunction(event.dy); return onResize(event);
})
if (newLength < that.options.minLength) newLength = that.options.minLength; .on('resizeend', function () {
that.view.model.set(that.options.modelField, newLength + 'px');
}).on('resizeend', function(event) {
that.isBeingResized = null; that.isBeingResized = null;
that.$el.removeClass('mailpoet_resize_active'); that.$el.removeClass('mailpoet_resize_active');
}); });

View File

@ -16,7 +16,7 @@ define([
if (_.isFunction(this.$el.sortable)) { if (_.isFunction(this.$el.sortable)) {
this.$el.sortable({ this.$el.sortable({
cursor: "move", cursor: 'move',
start: function (event, ui) { start: function (event, ui) {
ui.item.data('previousIndex', ui.item.index()); ui.item.data('previousIndex', ui.item.index());
}, },
@ -24,9 +24,9 @@ define([
ui.item.removeData('previousIndex'); ui.item.removeData('previousIndex');
}, },
update: function (event, ui) { update: function (event, ui) {
var previousIndex = ui.item.data('previousIndex'), var previousIndex = ui.item.data('previousIndex');
newIndex = ui.item.index(), var newIndex = ui.item.index();
model = collection.at(previousIndex); var model = collection.at(previousIndex);
// Replicate DOM changes. Move target model to a new position // Replicate DOM changes. Move target model to a new position
// within the collection // within the collection

View File

@ -13,12 +13,12 @@ define([
BL.TextEditorBehavior = Marionette.Behavior.extend({ BL.TextEditorBehavior = Marionette.Behavior.extend({
defaults: { defaults: {
selector: '.mailpoet_content', selector: '.mailpoet_content',
toolbar1: "bold italic link unlink forecolor mailpoet_shortcodes", toolbar1: 'bold italic link unlink forecolor mailpoet_shortcodes',
toolbar2: "", toolbar2: '',
validElements: "p[class|style],span[class|style],a[href|class|title|target|style],strong[class|style],em[class|style],strike,br", validElements: 'p[class|style],span[class|style],a[href|class|title|target|style],strong[class|style],em[class|style],strike,br',
invalidElements: "script", invalidElements: 'script',
blockFormats: 'Paragraph=p', blockFormats: 'Paragraph=p',
plugins: "link textcolor colorpicker mailpoet_shortcodes", plugins: 'link textcolor colorpicker mailpoet_shortcodes',
configurationFilter: function (originalConfig) { return originalConfig; } configurationFilter: function (originalConfig) { return originalConfig; }
}, },
onDomRefresh: function () { onDomRefresh: function () {
@ -34,13 +34,15 @@ define([
toolbar1: this.options.toolbar1, toolbar1: this.options.toolbar1,
toolbar2: this.options.toolbar2, toolbar2: this.options.toolbar2,
browser_spellcheck: true,
valid_elements: this.options.validElements, valid_elements: this.options.validElements,
invalid_elements: this.options.invalidElements, invalid_elements: this.options.invalidElements,
block_formats: this.options.blockFormats, block_formats: this.options.blockFormats,
relative_urls: false, relative_urls: false,
remove_script_host: false, remove_script_host: false,
convert_urls: true, convert_urls: true,
urlconverter_callback: function(url, node, on_save, name) { urlconverter_callback: function (url) {
if (url.match(/\[.+\]/g)) { if (url.match(/\[.+\]/g)) {
// Do not convert URLs with shortcodes // Do not convert URLs with shortcodes
return url; return url;
@ -55,7 +57,7 @@ define([
plugins: this.options.plugins, plugins: this.options.plugins,
setup: function (editor) { setup: function (editor) {
editor.on('change', function(e) { editor.on('change', function () {
that.view.triggerMethod('text:editor:change', editor.getContent()); that.view.triggerMethod('text:editor:change', editor.getContent());
}); });
@ -63,18 +65,18 @@ define([
editor.focus(); editor.focus();
if (that._isActivationClick) { if (that._isActivationClick) {
editor.selection.setRng( editor.selection.setRng(
tinymce.dom.RangeUtils.getCaretRangeFromPoint(e.clientX, e.clientY, editor.getDoc()) window.tinymce.dom.RangeUtils.getCaretRangeFromPoint(e.clientX, e.clientY, editor.getDoc())
); );
that._isActivationClick = false; that._isActivationClick = false;
} }
}); });
editor.on('focus', function(e) { editor.on('focus', function () {
that.view.triggerMethod('text:editor:focus'); that.view.triggerMethod('text:editor:focus');
that._isActivationClick = true; that._isActivationClick = true;
}); });
editor.on('blur', function(e) { editor.on('blur', function () {
that.view.triggerMethod('text:editor:blur'); that.view.triggerMethod('text:editor:blur');
}); });
} }

View File

@ -28,10 +28,10 @@ define([
jQuery jQuery
) { ) {
"use strict"; 'use strict';
var Module = {}, var Module = {};
base = BaseBlock; var base = BaseBlock;
Module.ALCSupervisor = SuperModel.extend({ Module.ALCSupervisor = SuperModel.extend({
initialize: function () { initialize: function () {
@ -43,12 +43,13 @@ define([
); );
}, },
refresh: function () { refresh: function () {
var blocks;
var models = App.findModels(function (model) { var models = App.findModels(function (model) {
return model.get('type') === 'automatedLatestContent'; return model.get('type') === 'automatedLatestContent';
}) || []; }) || [];
if (models.length === 0) return; if (models.length === 0) return;
var blocks = _.map(models, function(model) { blocks = _.map(models, function (model) {
return model.toJSON(); return model.toJSON();
}); });
@ -60,8 +61,8 @@ define([
_.each( _.each(
_.zip(models, renderedBlocks), _.zip(models, renderedBlocks),
function (args) { function (args) {
var model = args[0], var model = args[0];
contents = args[1]; var contents = args[1];
model.trigger('refreshPosts', contents); model.trigger('refreshPosts', contents);
} }
); );
@ -128,14 +129,14 @@ define([
}); });
Module.AutomatedLatestContentBlockView = base.BlockView.extend({ Module.AutomatedLatestContentBlockView = base.BlockView.extend({
className: "mailpoet_block mailpoet_automated_latest_content_block mailpoet_droppable_block", className: 'mailpoet_block mailpoet_automated_latest_content_block mailpoet_droppable_block',
initialize: function () { initialize: function () {
function replaceButtonStylesHandler(data) { function replaceButtonStylesHandler(data) {
this.model.set({"readMoreButton": data}); this.model.set({ readMoreButton: data });
} }
App.getChannel().on("replaceAllButtonStyles", replaceButtonStylesHandler.bind(this)); App.getChannel().on('replaceAllButtonStyles', replaceButtonStylesHandler.bind(this));
}, },
getTemplate: function() { return templates.automatedLatestContentBlock; }, getTemplate: function () { return window.templates.automatedLatestContentBlock; },
regions: { regions: {
toolsRegion: '.mailpoet_tools', toolsRegion: '.mailpoet_tools',
postsRegion: '.mailpoet_automated_latest_content_block_posts' postsRegion: '.mailpoet_automated_latest_content_block_posts'
@ -143,15 +144,15 @@ define([
modelEvents: _.extend( modelEvents: _.extend(
_.omit(base.BlockView.prototype.modelEvents, 'change'), _.omit(base.BlockView.prototype.modelEvents, 'change'),
{ {
'postsChanged': 'render' postsChanged: 'render'
}), }),
events: _.extend(base.BlockView.prototype.events, { events: _.extend(base.BlockView.prototype.events, {
'click .mailpoet_automated_latest_content_block_overlay': 'showSettings' 'click .mailpoet_automated_latest_content_block_overlay': 'showSettings'
}), }),
onDragSubstituteBy: function () { return Module.AutomatedLatestContentWidgetView; }, onDragSubstituteBy: function () { return Module.AutomatedLatestContentWidgetView; },
onRender: function () { onRender: function () {
var ContainerView = App.getBlockTypeView('container'), var ContainerView = App.getBlockTypeView('container');
renderOptions = { var renderOptions = {
disableTextEditor: true, disableTextEditor: true,
disableDragAndDrop: true, disableDragAndDrop: true,
emptyContainerMessage: MailPoet.I18n.t('noPostsToDisplay') emptyContainerMessage: MailPoet.I18n.t('noPostsToDisplay')
@ -168,31 +169,31 @@ define([
// Sidebar view container // Sidebar view container
Module.AutomatedLatestContentBlockSettingsView = base.BlockSettingsView.extend({ Module.AutomatedLatestContentBlockSettingsView = base.BlockSettingsView.extend({
getTemplate: function() { return templates.automatedLatestContentBlockSettings; }, getTemplate: function () { return window.templates.automatedLatestContentBlockSettings; },
events: function () { events: function () {
return { return {
"click .mailpoet_automated_latest_content_hide_display_options": 'toggleDisplayOptions', 'click .mailpoet_automated_latest_content_hide_display_options': 'toggleDisplayOptions',
"click .mailpoet_automated_latest_content_show_display_options": 'toggleDisplayOptions', 'click .mailpoet_automated_latest_content_show_display_options': 'toggleDisplayOptions',
"click .mailpoet_automated_latest_content_select_button": 'showButtonSettings', 'click .mailpoet_automated_latest_content_select_button': 'showButtonSettings',
"click .mailpoet_automated_latest_content_select_divider": 'showDividerSettings', 'click .mailpoet_automated_latest_content_select_divider': 'showDividerSettings',
"change .mailpoet_automated_latest_content_read_more_type": 'changeReadMoreType', 'change .mailpoet_automated_latest_content_read_more_type': 'changeReadMoreType',
"change .mailpoet_automated_latest_content_display_type": 'changeDisplayType', 'change .mailpoet_automated_latest_content_display_type': 'changeDisplayType',
"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'),
"input .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'),
"input .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'),
"input .mailpoet_automated_latest_content_categories": _.partial(this.changeField, "categoriesPrecededBy"), 'input .mailpoet_automated_latest_content_categories': _.partial(this.changeField, 'categoriesPrecededBy'),
"input .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'
}; };
}, },
onRender: function () { onRender: function () {
@ -213,12 +214,13 @@ define([
}, },
transport: function (options, success, failure) { transport: function (options, success, failure) {
var taxonomies; var taxonomies;
var termsPromise;
var promise = CommunicationComponent.getTaxonomies( var promise = CommunicationComponent.getTaxonomies(
that.model.get('contentType') that.model.get('contentType')
).then(function (tax) { ).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({ termsPromise = CommunicationComponent.getTerms({
search: options.data.term, search: options.data.term,
taxonomies: _.keys(taxonomies) taxonomies: _.keys(taxonomies)
}).then(function (terms) { }).then(function (terms) {
@ -227,7 +229,7 @@ define([
terms: terms terms: terms
}; };
}); });
return promise; return termsPromise;
}); });
promise.then(success); promise.then(success);
@ -264,9 +266,9 @@ define([
} }
}).trigger('change'); }).trigger('change');
}, },
toggleDisplayOptions: function(event) { toggleDisplayOptions: function () {
var el = this.$('.mailpoet_automated_latest_content_display_options'), var el = this.$('.mailpoet_automated_latest_content_display_options');
showControl = this.$('.mailpoet_automated_latest_content_show_display_options'); var showControl = this.$('.mailpoet_automated_latest_content_show_display_options');
if (el.hasClass('mailpoet_closed')) { if (el.hasClass('mailpoet_closed')) {
el.removeClass('mailpoet_closed'); el.removeClass('mailpoet_closed');
showControl.addClass('mailpoet_hidden'); showControl.addClass('mailpoet_hidden');
@ -275,7 +277,7 @@ define([
showControl.removeClass('mailpoet_hidden'); showControl.removeClass('mailpoet_hidden');
} }
}, },
showButtonSettings: function(event) { showButtonSettings: function () {
var buttonModule = ButtonBlock; var buttonModule = ButtonBlock;
(new buttonModule.ButtonBlockSettingsView({ (new buttonModule.ButtonBlockSettingsView({
model: this.model.get('readMoreButton'), model: this.model.get('readMoreButton'),
@ -286,7 +288,7 @@ define([
} }
})).render(); })).render();
}, },
showDividerSettings: function(event) { showDividerSettings: function () {
var dividerModule = DividerBlock; var dividerModule = DividerBlock;
(new dividerModule.DividerBlockSettingsView({ (new dividerModule.DividerBlockSettingsView({
model: this.model.get('divider'), model: this.model.get('divider'),
@ -349,8 +351,8 @@ define([
this.changeField('titleFormat', event); this.changeField('titleFormat', event);
}, },
_updateContentTypes: function (postTypes) { _updateContentTypes: function (postTypes) {
var select = this.$('.mailpoet_automated_latest_content_content_type'), var select = this.$('.mailpoet_automated_latest_content_content_type');
selectedValue = this.model.get('contentType'); var selectedValue = this.model.get('contentType');
select.find('option').remove(); select.find('option').remove();
_.each(postTypes, function (type) { _.each(postTypes, function (type) {
@ -364,7 +366,7 @@ define([
}); });
Module.AutomatedLatestContentWidgetView = base.WidgetView.extend({ Module.AutomatedLatestContentWidgetView = base.WidgetView.extend({
getTemplate: function() { return templates.automatedLatestContentInsertion; }, getTemplate: function () { return window.templates.automatedLatestContentInsertion; },
behaviors: { behaviors: {
DraggableBehavior: { DraggableBehavior: {
cloneOriginal: true, cloneOriginal: true,
@ -378,7 +380,7 @@ define([
} }
}); });
App.on('before:start', function(App, options) { App.on('before:start', function (App) {
App.registerBlockType('automatedLatestContent', { App.registerBlockType('automatedLatestContent', {
blockModel: Module.AutomatedLatestContentBlockModel, blockModel: Module.AutomatedLatestContentBlockModel,
blockView: Module.AutomatedLatestContentBlockView blockView: Module.AutomatedLatestContentBlockView
@ -391,7 +393,7 @@ define([
}); });
}); });
App.on('start', function(App, options) { App.on('start', function (App) {
var Application = App; var Application = App;
Application._ALCSupervisor = new Module.ALCSupervisor(); Application._ALCSupervisor = new Module.ALCSupervisor();
Application._ALCSupervisor.refresh(); Application._ALCSupervisor.refresh();

View File

@ -12,17 +12,16 @@ define([
'jquery', 'jquery',
'mailpoet', 'mailpoet',
'modal' 'modal'
], function(App, Marionette, SuperModel, _, jQuery, MailPoet, Modal) { ], function (App, Marionette, SuperModel, _, jQuery, MailPoet) {
"use strict"; 'use strict';
var Module = {}, var Module = {};
AugmentedView = Marionette.View.extend({}); var AugmentedView = Marionette.View.extend({});
Module.BlockModel = SuperModel.extend({ Module.BlockModel = SuperModel.extend({
stale: [], // Attributes to be removed upon saving stale: [], // Attributes to be removed upon saving
initialize: function () { initialize: function () {
var that = this;
this.on('change', function () { this.on('change', function () {
App.getChannel().trigger('autoSave'); App.getChannel().trigger('autoSave');
}); });
@ -50,13 +49,13 @@ define([
toolsRegion: '> .mailpoet_tools' toolsRegion: '> .mailpoet_tools'
}, },
modelEvents: { modelEvents: {
'change': 'render', change: 'render',
'delete': 'deleteBlock', delete: 'deleteBlock',
'duplicate': 'duplicateBlock' duplicate: 'duplicateBlock'
}, },
events: { events: {
"mouseenter": "showTools", mouseenter: 'showTools',
"mouseleave": "hideTools" mouseleave: 'hideTools'
}, },
behaviors: { behaviors: {
DraggableBehavior: { DraggableBehavior: {
@ -68,7 +67,8 @@ define([
options.dragBehavior.view.model.destroy(); options.dragBehavior.view.model.destroy();
}, },
onDragSubstituteBy: function (behavior) { onDragSubstituteBy: function (behavior) {
var WidgetView, node; var WidgetView;
var node;
// When block is being dragged, display the widget icon instead. // When block is being dragged, display the widget icon instead.
// This will create an instance of block's widget view and // This will create an instance of block's widget view and
// use it's rendered DOM element instead of the content block // use it's rendered DOM element instead of the content block
@ -98,13 +98,13 @@ define([
this.on('dom:refresh', this.showBlock, this); this.on('dom:refresh', this.showBlock, this);
this._isFirstRender = true; this._isFirstRender = true;
}, },
showTools: function(_event) { showTools: function () {
if (!this.showingToolsDisabled) { if (!this.showingToolsDisabled) {
this.$('> .mailpoet_tools').addClass('mailpoet_display_tools'); this.$('> .mailpoet_tools').addClass('mailpoet_display_tools');
this.toolsView.triggerMethod('showTools'); this.toolsView.triggerMethod('showTools');
} }
}, },
hideTools: function(e) { hideTools: function () {
this.$('> .mailpoet_tools').removeClass('mailpoet_display_tools'); this.$('> .mailpoet_tools').removeClass('mailpoet_display_tools');
this.toolsView.triggerMethod('hideTools'); this.toolsView.triggerMethod('hideTools');
}, },
@ -178,13 +178,13 @@ define([
}); });
Module.BlockToolsView = AugmentedView.extend({ Module.BlockToolsView = AugmentedView.extend({
getTemplate: function() { return templates.genericBlockTools; }, getTemplate: function () { return window.templates.genericBlockTools; },
events: { events: {
"click .mailpoet_edit_block": "changeSettings", 'click .mailpoet_edit_block': 'changeSettings',
"click .mailpoet_delete_block_activate": "showDeletionConfirmation", 'click .mailpoet_delete_block_activate': 'showDeletionConfirmation',
"click .mailpoet_delete_block_cancel": "hideDeletionConfirmation", 'click .mailpoet_delete_block_cancel': 'hideDeletionConfirmation',
"click .mailpoet_delete_block_confirm": "deleteBlock", 'click .mailpoet_delete_block_confirm': 'deleteBlock',
"click .mailpoet_duplicate_block": "duplicateBlock" 'click .mailpoet_duplicate_block': 'duplicateBlock'
}, },
// Markers of whether these particular tools will be used for this instance // Markers of whether these particular tools will be used for this instance
tools: { tools: {
@ -240,8 +240,9 @@ define([
ColorPickerBehavior: {} ColorPickerBehavior: {}
}, },
initialize: function (params) { initialize: function (params) {
var panelParams;
this.model.trigger('startEditing'); this.model.trigger('startEditing');
var panelParams = { panelParams = {
element: this.$el, element: this.$el,
template: '', template: '',
position: 'right', position: 'right',
@ -262,7 +263,7 @@ define([
model: this.model.toJSON() model: this.model.toJSON()
}; };
}, },
close: function(event) { close: function () {
this.destroy(); this.destroy();
}, },
changeField: function (field, event) { changeField: function (field, event) {
@ -275,7 +276,7 @@ define([
this.model.set(field, jQuery(event.target).val() + suffix); this.model.set(field, jQuery(event.target).val() + suffix);
}, },
changeBoolField: function (field, event) { changeBoolField: function (field, event) {
this.model.set(field, (jQuery(event.target).val() === 'true') ? true : false); this.model.set(field, (jQuery(event.target).val() === 'true'));
}, },
changeBoolCheckboxField: function (field, event) { changeBoolCheckboxField: function (field, event) {
this.model.set(field, (!!jQuery(event.target).prop('checked'))); this.model.set(field, (!!jQuery(event.target).prop('checked')));
@ -298,7 +299,7 @@ define([
behaviors: { behaviors: {
DraggableBehavior: { DraggableBehavior: {
drop: function () { drop: function () {
throw "Unsupported operation"; throw 'Unsupported operation';
} }
} }
} }

View File

@ -9,10 +9,10 @@ define([
'jquery' 'jquery'
], function (App, BaseBlock, MailPoet, _, jQuery) { ], function (App, BaseBlock, MailPoet, _, jQuery) {
"use strict"; 'use strict';
var Module = {}, var Module = {};
base = BaseBlock; var base = BaseBlock;
Module.ButtonBlockModel = base.BlockModel.extend({ Module.ButtonBlockModel = base.BlockModel.extend({
defaults: function () { defaults: function () {
@ -41,8 +41,8 @@ define([
}); });
Module.ButtonBlockView = base.BlockView.extend({ Module.ButtonBlockView = base.BlockView.extend({
className: "mailpoet_block mailpoet_button_block mailpoet_droppable_block", className: 'mailpoet_block mailpoet_button_block mailpoet_droppable_block',
getTemplate: function() { return templates.buttonBlock; }, getTemplate: function () { return window.templates.buttonBlock; },
onDragSubstituteBy: function () { return Module.ButtonWidgetView; }, onDragSubstituteBy: function () { return Module.ButtonWidgetView; },
behaviors: _.extend({}, base.BlockView.prototype.behaviors, { behaviors: _.extend({}, base.BlockView.prototype.behaviors, {
ShowSettingsBehavior: {} ShowSettingsBehavior: {}
@ -65,37 +65,37 @@ define([
}); });
Module.ButtonBlockSettingsView = base.BlockSettingsView.extend({ Module.ButtonBlockSettingsView = base.BlockSettingsView.extend({
getTemplate: function() { return templates.buttonBlockSettings; }, getTemplate: function () { return window.templates.buttonBlockSettings; },
events: function () { events: function () {
return { return {
"input .mailpoet_field_button_text": _.partial(this.changeField, "text"), 'input .mailpoet_field_button_text': _.partial(this.changeField, 'text'),
"input .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'),
"change .mailpoet_field_button_font_size": _.partial(this.changeField, "styles.block.fontSize"), 'change .mailpoet_field_button_font_size': _.partial(this.changeField, 'styles.block.fontSize'),
"change .mailpoet_field_button_background_color": _.partial(this.changeColorField, "styles.block.backgroundColor"), 'change .mailpoet_field_button_background_color': _.partial(this.changeColorField, 'styles.block.backgroundColor'),
"change .mailpoet_field_button_border_color": _.partial(this.changeColorField, "styles.block.borderColor"), 'change .mailpoet_field_button_border_color': _.partial(this.changeColorField, 'styles.block.borderColor'),
"change .mailpoet_field_button_font_weight": "changeFontWeight", 'change .mailpoet_field_button_font_weight': 'changeFontWeight',
"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)),
"input .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)),
"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)),
"input .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)),
"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)),
"input .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)),
"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)),
"input .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)),
"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'
}; };
}, },
templateContext: function () { templateContext: function () {
@ -121,7 +121,7 @@ define([
}); });
Module.ButtonWidgetView = base.WidgetView.extend({ Module.ButtonWidgetView = base.WidgetView.extend({
getTemplate: function() { return templates.buttonInsertion; }, getTemplate: function () { return window.templates.buttonInsertion; },
behaviors: { behaviors: {
DraggableBehavior: { DraggableBehavior: {
cloneOriginal: true, cloneOriginal: true,
@ -132,7 +132,7 @@ define([
} }
}); });
App.on('before:start', function(App, options) { App.on('before:start', function (App) {
App.registerBlockType('button', { App.registerBlockType('button', {
blockModel: Module.ButtonBlockModel, blockModel: Module.ButtonBlockModel,
blockView: Module.ButtonBlockView blockView: Module.ButtonBlockView

View File

@ -12,11 +12,11 @@ define([
'newsletter_editor/blocks/base' 'newsletter_editor/blocks/base'
], function (Backbone, Marionette, _, jQuery, App, BaseBlock) { ], function (Backbone, Marionette, _, jQuery, App, BaseBlock) {
"use strict"; 'use strict';
var Module = {}, var Module = {};
base = BaseBlock, var base = BaseBlock;
BlockCollection; var BlockCollection;
BlockCollection = Backbone.Collection.extend({ BlockCollection = Backbone.Collection.extend({
model: base.BlockModel, model: base.BlockModel,
@ -24,7 +24,6 @@ define([
this.on('add change remove', function () { App.getChannel().trigger('autoSave'); }); this.on('add change remove', function () { App.getChannel().trigger('autoSave'); });
}, },
parse: function (response) { parse: function (response) {
var self = this;
return _.map(response, function (block) { return _.map(response, function (block) {
var Type = App.getBlockTypeModel(block.type); var Type = App.getBlockTypeModel(block.type);
// TODO: If type has no registered model, use a backup one // TODO: If type has no registered model, use a backup one
@ -66,7 +65,7 @@ define([
return response; return response;
}, },
getChildren: function () { getChildren: function () {
var models = this.get('blocks').map(function(model, index, list) { var models = this.get('blocks').map(function (model) {
return [model, model.getChildren()]; return [model, model.getChildren()];
}); });
@ -103,9 +102,9 @@ define([
} }
}), }),
className: 'mailpoet_block mailpoet_container_block mailpoet_droppable_block mailpoet_droppable_layout_block', className: 'mailpoet_block mailpoet_container_block mailpoet_droppable_block mailpoet_droppable_layout_block',
getTemplate: function() { return templates.containerBlock; }, getTemplate: function () { return window.templates.containerBlock; },
events: _.extend({}, base.BlockView.prototype.events, { events: _.extend({}, base.BlockView.prototype.events, {
"click .mailpoet_newsletter_layer_selector": "toggleEditingLayer" 'click .mailpoet_newsletter_layer_selector': 'toggleEditingLayer'
}), }),
ui: { ui: {
tools: '> .mailpoet_tools' tools: '> .mailpoet_tools'
@ -121,7 +120,8 @@ define([
options.dragBehavior.view.model.destroy(); options.dragBehavior.view.model.destroy();
}, },
onDragSubstituteBy: function (behavior) { onDragSubstituteBy: function (behavior) {
var WidgetView, node; var WidgetView;
var node;
// When block is being dragged, display the widget icon instead. // When block is being dragged, display the widget icon instead.
// This will create an instance of block's widget view and // This will create an instance of block's widget view and
// use it's rendered DOM element instead of the content block // use it's rendered DOM element instead of the content block
@ -138,7 +138,8 @@ define([
// for root and column containers. // for root and column containers.
return view.renderOptions.depth === 1; return view.renderOptions.depth === 1;
} }
} },
HighlightContainerBehavior: {}
}), }),
onDragSubstituteBy: function () { onDragSubstituteBy: function () {
// For two and three column layouts display their respective widgets, // For two and three column layouts display their respective widgets,
@ -189,18 +190,18 @@ define([
} }
}, },
toggleEditingLayer: function (event) { toggleEditingLayer: function (event) {
var that = this, var that = this;
$toggleButton = this.$('> .mailpoet_tools .mailpoet_newsletter_layer_selector'), var $toggleButton = this.$('> .mailpoet_tools .mailpoet_newsletter_layer_selector');
$overlay = jQuery('.mailpoet_layer_overlay'), var $overlay = jQuery('.mailpoet_layer_overlay');
$container = this.$('> .mailpoet_container'), var $container = this.$('> .mailpoet_container');
enableContainerLayer = function() { var enableContainerLayer = function () {
that.$el.addClass('mailpoet_container_layer_active'); that.$el.addClass('mailpoet_container_layer_active');
$toggleButton.addClass('mailpoet_container_layer_active'); $toggleButton.addClass('mailpoet_container_layer_active');
$container.addClass('mailpoet_layer_highlight'); $container.addClass('mailpoet_layer_highlight');
$overlay.click(disableContainerLayer); $overlay.click(disableContainerLayer);
$overlay.show(); $overlay.show();
}, };
disableContainerLayer = function() { var disableContainerLayer = function () {
that.$el.removeClass('mailpoet_container_layer_active'); that.$el.removeClass('mailpoet_container_layer_active');
$toggleButton.removeClass('mailpoet_container_layer_active'); $toggleButton.removeClass('mailpoet_container_layer_active');
$container.removeClass('mailpoet_layer_highlight'); $container.removeClass('mailpoet_layer_highlight');
@ -217,7 +218,7 @@ define([
}); });
Module.ContainerBlockEmptyView = Marionette.View.extend({ Module.ContainerBlockEmptyView = Marionette.View.extend({
getTemplate: function() { return templates.containerEmpty; }, getTemplate: function () { return window.templates.containerEmpty; },
initialize: function (options) { initialize: function (options) {
this.renderOptions = _.defaults(options.renderOptions || {}, {}); this.renderOptions = _.defaults(options.renderOptions || {}, {});
}, },
@ -234,11 +235,11 @@ define([
}); });
Module.ContainerBlockSettingsView = base.BlockSettingsView.extend({ Module.ContainerBlockSettingsView = base.BlockSettingsView.extend({
getTemplate: function() { return templates.containerBlockSettings; }, getTemplate: function () { return window.templates.containerBlockSettings; },
events: function () { events: function () {
return { return {
"change .mailpoet_field_container_background_color": _.partial(this.changeColorField, "styles.block.backgroundColor"), 'change .mailpoet_field_container_background_color': _.partial(this.changeColorField, 'styles.block.backgroundColor'),
"click .mailpoet_done_editing": "close" 'click .mailpoet_done_editing': 'close'
}; };
}, },
regions: { regions: {
@ -266,7 +267,7 @@ define([
}); });
Module.ContainerBlockColumnSettingsView = Marionette.View.extend({ Module.ContainerBlockColumnSettingsView = Marionette.View.extend({
getTemplate: function() { return templates.containerBlockColumnSettings; }, getTemplate: function () { return window.templates.containerBlockColumnSettings; },
initialize: function (options) { initialize: function (options) {
this.columnNumber = (options.columnIndex || 0) + 1; this.columnNumber = (options.columnIndex || 0) + 1;
}, },
@ -280,7 +281,7 @@ define([
Module.OneColumnContainerWidgetView = base.WidgetView.extend({ Module.OneColumnContainerWidgetView = base.WidgetView.extend({
className: base.WidgetView.prototype.className + ' mailpoet_droppable_layout_block', className: base.WidgetView.prototype.className + ' mailpoet_droppable_layout_block',
getTemplate: function() { return templates.oneColumnLayoutInsertion; }, getTemplate: function () { return window.templates.oneColumnLayoutInsertion; },
behaviors: { behaviors: {
DraggableBehavior: { DraggableBehavior: {
cloneOriginal: true, cloneOriginal: true,
@ -298,7 +299,7 @@ define([
Module.TwoColumnContainerWidgetView = base.WidgetView.extend({ Module.TwoColumnContainerWidgetView = base.WidgetView.extend({
className: base.WidgetView.prototype.className + ' mailpoet_droppable_layout_block', className: base.WidgetView.prototype.className + ' mailpoet_droppable_layout_block',
getTemplate: function() { return templates.twoColumnLayoutInsertion; }, getTemplate: function () { return window.templates.twoColumnLayoutInsertion; },
behaviors: { behaviors: {
DraggableBehavior: { DraggableBehavior: {
cloneOriginal: true, cloneOriginal: true,
@ -317,7 +318,7 @@ define([
Module.ThreeColumnContainerWidgetView = base.WidgetView.extend({ Module.ThreeColumnContainerWidgetView = base.WidgetView.extend({
className: base.WidgetView.prototype.className + ' mailpoet_droppable_layout_block', className: base.WidgetView.prototype.className + ' mailpoet_droppable_layout_block',
getTemplate: function() { return templates.threeColumnLayoutInsertion; }, getTemplate: function () { return window.templates.threeColumnLayoutInsertion; },
behaviors: { behaviors: {
DraggableBehavior: { DraggableBehavior: {
cloneOriginal: true, cloneOriginal: true,
@ -335,7 +336,7 @@ define([
} }
}); });
App.on('before:start', function(App, options) { App.on('before:start', function (App) {
App.registerBlockType('container', { App.registerBlockType('container', {
blockModel: Module.ContainerBlockModel, blockModel: Module.ContainerBlockModel,
blockView: Module.ContainerBlockView blockView: Module.ContainerBlockView

View File

@ -5,14 +5,13 @@ define([
'newsletter_editor/App', 'newsletter_editor/App',
'newsletter_editor/blocks/base', 'newsletter_editor/blocks/base',
'underscore', 'underscore',
'jquery', 'jquery'
'mailpoet' ], function (App, BaseBlock, _, jQuery) {
], function(App, BaseBlock, _, jQuery, MailPoet) {
"use strict"; 'use strict';
var Module = {}, var Module = {};
base = BaseBlock; var base = BaseBlock;
Module.DividerBlockModel = base.BlockModel.extend({ Module.DividerBlockModel = base.BlockModel.extend({
defaults: function () { defaults: function () {
@ -32,8 +31,8 @@ define([
}); });
Module.DividerBlockView = base.BlockView.extend({ Module.DividerBlockView = base.BlockView.extend({
className: "mailpoet_block mailpoet_divider_block mailpoet_droppable_block", className: 'mailpoet_block mailpoet_divider_block mailpoet_droppable_block',
getTemplate: function() { return templates.dividerBlock; }, getTemplate: function () { return window.templates.dividerBlock; },
modelEvents: _.omit(base.BlockView.prototype.modelEvents, 'change'), modelEvents: _.omit(base.BlockView.prototype.modelEvents, 'change'),
behaviors: _.defaults({ behaviors: _.defaults({
ResizableBehavior: { ResizableBehavior: {
@ -49,8 +48,8 @@ define([
}, base.BlockView.prototype.behaviors), }, base.BlockView.prototype.behaviors),
onDragSubstituteBy: function () { return Module.DividerWidgetView; }, onDragSubstituteBy: function () { return Module.DividerWidgetView; },
initialize: function () { initialize: function () {
base.BlockView.prototype.initialize.apply(this, arguments);
var that = this; var that = this;
base.BlockView.prototype.initialize.apply(this, arguments);
// Listen for attempts to change all dividers in one go // Listen for attempts to change all dividers in one go
this._replaceDividerHandler = function (data) { that.model.set(data); that.model.trigger('applyToAll'); }; this._replaceDividerHandler = function (data) { that.model.set(data); that.model.trigger('applyToAll'); };
@ -84,19 +83,19 @@ define([
}); });
Module.DividerBlockSettingsView = base.BlockSettingsView.extend({ Module.DividerBlockSettingsView = base.BlockSettingsView.extend({
getTemplate: function() { return templates.dividerBlockSettings; }, getTemplate: function () { return window.templates.dividerBlockSettings; },
events: function () { events: function () {
return { return {
"click .mailpoet_field_divider_style": 'changeStyle', 'click .mailpoet_field_divider_style': 'changeStyle',
"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)),
"input .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)),
"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'),
"click .mailpoet_button_divider_apply_to_all": "applyToAll", 'click .mailpoet_button_divider_apply_to_all': 'applyToAll',
"click .mailpoet_done_editing": "close" 'click .mailpoet_done_editing': 'close'
}; };
}, },
modelEvents: function () { modelEvents: function () {
@ -119,7 +118,7 @@ define([
repaintDividerStyleOptions: function () { repaintDividerStyleOptions: function () {
this.$('.mailpoet_field_divider_style > div').css('border-top-color', this.model.get('styles.block.borderColor')); this.$('.mailpoet_field_divider_style > div').css('border-top-color', this.model.get('styles.block.borderColor'));
}, },
applyToAll: function(event) { applyToAll: function () {
App.getChannel().trigger('replaceAllDividers', this.model.toJSON()); App.getChannel().trigger('replaceAllDividers', this.model.toJSON());
}, },
updateValueAndCall: function (fieldToUpdate, callable, event) { updateValueAndCall: function (fieldToUpdate, callable, event) {
@ -129,7 +128,7 @@ define([
}); });
Module.DividerWidgetView = base.WidgetView.extend({ Module.DividerWidgetView = base.WidgetView.extend({
getTemplate: function() { return templates.dividerInsertion; }, getTemplate: function () { return window.templates.dividerInsertion; },
behaviors: { behaviors: {
DraggableBehavior: { DraggableBehavior: {
cloneOriginal: true, cloneOriginal: true,
@ -139,7 +138,7 @@ define([
} }
} }
}); });
App.on('before:start', function(App, options) { App.on('before:start', function (App) {
App.registerBlockType('divider', { App.registerBlockType('divider', {
blockModel: Module.DividerBlockModel, blockModel: Module.DividerBlockModel,
blockView: Module.DividerBlockView blockView: Module.DividerBlockView

View File

@ -4,13 +4,14 @@
define([ define([
'newsletter_editor/App', 'newsletter_editor/App',
'newsletter_editor/blocks/base', 'newsletter_editor/blocks/base',
'underscore' 'underscore',
], function(App, BaseBlock, _) { 'mailpoet'
], function (App, BaseBlock, _, MailPoet) {
"use strict"; 'use strict';
var Module = {}, var Module = {};
base = BaseBlock; var base = BaseBlock;
Module.FooterBlockModel = base.BlockModel.extend({ Module.FooterBlockModel = base.BlockModel.extend({
defaults: function () { defaults: function () {
@ -37,8 +38,8 @@ define([
}); });
Module.FooterBlockView = base.BlockView.extend({ Module.FooterBlockView = base.BlockView.extend({
className: "mailpoet_block mailpoet_footer_block mailpoet_droppable_block", className: 'mailpoet_block mailpoet_footer_block mailpoet_droppable_block',
getTemplate: function() { return templates.footerBlock; }, getTemplate: function () { return window.templates.footerBlock; },
modelEvents: _.extend({ modelEvents: _.extend({
'change:styles.block.backgroundColor change:styles.text.fontColor change:styles.text.fontFamily change:styles.text.fontSize change:styles.text.textAlign change:styles.link.fontColor change:styles.link.textDecoration': 'render' 'change:styles.block.backgroundColor change:styles.text.fontColor change:styles.text.fontFamily change:styles.text.fontSize change:styles.text.textAlign change:styles.link.fontColor change:styles.link.textDecoration': 'render'
}, _.omit(base.BlockView.prototype.modelEvents, 'change')), }, _.omit(base.BlockView.prototype.modelEvents, 'change')),
@ -75,19 +76,19 @@ define([
}); });
Module.FooterBlockSettingsView = base.BlockSettingsView.extend({ Module.FooterBlockSettingsView = base.BlockSettingsView.extend({
getTemplate: function() { return templates.footerBlockSettings; }, getTemplate: function () { return window.templates.footerBlockSettings; },
events: function () { events: function () {
return { return {
"change .mailpoet_field_footer_text_color": _.partial(this.changeColorField, "styles.text.fontColor"), 'change .mailpoet_field_footer_text_color': _.partial(this.changeColorField, 'styles.text.fontColor'),
"change .mailpoet_field_footer_text_font_family": _.partial(this.changeField, "styles.text.fontFamily"), 'change .mailpoet_field_footer_text_font_family': _.partial(this.changeField, 'styles.text.fontFamily'),
"change .mailpoet_field_footer_text_size": _.partial(this.changeField, "styles.text.fontSize"), 'change .mailpoet_field_footer_text_size': _.partial(this.changeField, 'styles.text.fontSize'),
"change #mailpoet_field_footer_link_color": _.partial(this.changeColorField, "styles.link.fontColor"), 'change #mailpoet_field_footer_link_color': _.partial(this.changeColorField, 'styles.link.fontColor'),
"change #mailpoet_field_footer_link_underline": function(event) { 'change #mailpoet_field_footer_link_underline': function (event) {
this.model.set('styles.link.textDecoration', (event.target.checked) ? event.target.value : 'none'); this.model.set('styles.link.textDecoration', (event.target.checked) ? event.target.value : 'none');
}, },
"change .mailpoet_field_footer_background_color": _.partial(this.changeColorField, "styles.block.backgroundColor"), 'change .mailpoet_field_footer_background_color': _.partial(this.changeColorField, 'styles.block.backgroundColor'),
"change .mailpoet_field_footer_alignment": _.partial(this.changeField, "styles.text.textAlign"), 'change .mailpoet_field_footer_alignment': _.partial(this.changeField, 'styles.text.textAlign'),
"click .mailpoet_done_editing": "close" 'click .mailpoet_done_editing': 'close'
}; };
}, },
templateContext: function () { templateContext: function () {
@ -98,7 +99,7 @@ define([
}); });
Module.FooterWidgetView = base.WidgetView.extend({ Module.FooterWidgetView = base.WidgetView.extend({
getTemplate: function() { return templates.footerInsertion; }, getTemplate: function () { return window.templates.footerInsertion; },
behaviors: { behaviors: {
DraggableBehavior: { DraggableBehavior: {
cloneOriginal: true, cloneOriginal: true,
@ -109,7 +110,7 @@ define([
} }
}); });
App.on('before:start', function(App, options) { App.on('before:start', function (App) {
App.registerBlockType('footer', { App.registerBlockType('footer', {
blockModel: Module.FooterBlockModel, blockModel: Module.FooterBlockModel,
blockView: Module.FooterBlockView blockView: Module.FooterBlockView

View File

@ -4,13 +4,14 @@
define([ define([
'newsletter_editor/App', 'newsletter_editor/App',
'newsletter_editor/blocks/base', 'newsletter_editor/blocks/base',
'underscore' 'underscore',
], function(App, BaseBlock, _) { 'mailpoet'
], function (App, BaseBlock, _, MailPoet) {
"use strict"; 'use strict';
var Module = {}, var Module = {};
base = BaseBlock; var base = BaseBlock;
Module.HeaderBlockModel = base.BlockModel.extend({ Module.HeaderBlockModel = base.BlockModel.extend({
defaults: function () { defaults: function () {
@ -37,8 +38,8 @@ define([
}); });
Module.HeaderBlockView = base.BlockView.extend({ Module.HeaderBlockView = base.BlockView.extend({
className: "mailpoet_block mailpoet_header_block mailpoet_droppable_block", className: 'mailpoet_block mailpoet_header_block mailpoet_droppable_block',
getTemplate: function() { return templates.headerBlock; }, getTemplate: function () { return window.templates.headerBlock; },
modelEvents: _.extend({ modelEvents: _.extend({
'change:styles.block.backgroundColor change:styles.text.fontColor change:styles.text.fontFamily change:styles.text.fontSize change:styles.text.textAlign change:styles.link.fontColor change:styles.link.textDecoration': 'render' 'change:styles.block.backgroundColor change:styles.text.fontColor change:styles.text.fontFamily change:styles.text.fontSize change:styles.text.textAlign change:styles.link.fontColor change:styles.link.textDecoration': 'render'
}, _.omit(base.BlockView.prototype.modelEvents, 'change')), }, _.omit(base.BlockView.prototype.modelEvents, 'change')),
@ -75,19 +76,19 @@ define([
}); });
Module.HeaderBlockSettingsView = base.BlockSettingsView.extend({ Module.HeaderBlockSettingsView = base.BlockSettingsView.extend({
getTemplate: function() { return templates.headerBlockSettings; }, getTemplate: function () { return window.templates.headerBlockSettings; },
events: function () { events: function () {
return { return {
"change .mailpoet_field_header_text_color": _.partial(this.changeColorField, "styles.text.fontColor"), 'change .mailpoet_field_header_text_color': _.partial(this.changeColorField, 'styles.text.fontColor'),
"change .mailpoet_field_header_text_font_family": _.partial(this.changeField, "styles.text.fontFamily"), 'change .mailpoet_field_header_text_font_family': _.partial(this.changeField, 'styles.text.fontFamily'),
"change .mailpoet_field_header_text_size": _.partial(this.changeField, "styles.text.fontSize"), 'change .mailpoet_field_header_text_size': _.partial(this.changeField, 'styles.text.fontSize'),
"change #mailpoet_field_header_link_color": _.partial(this.changeColorField, "styles.link.fontColor"), 'change #mailpoet_field_header_link_color': _.partial(this.changeColorField, 'styles.link.fontColor'),
"change #mailpoet_field_header_link_underline": function(event) { 'change #mailpoet_field_header_link_underline': function (event) {
this.model.set('styles.link.textDecoration', (event.target.checked) ? event.target.value : 'none'); this.model.set('styles.link.textDecoration', (event.target.checked) ? event.target.value : 'none');
}, },
"change .mailpoet_field_header_background_color": _.partial(this.changeColorField, "styles.block.backgroundColor"), 'change .mailpoet_field_header_background_color': _.partial(this.changeColorField, 'styles.block.backgroundColor'),
"change .mailpoet_field_header_alignment": _.partial(this.changeField, "styles.text.textAlign"), 'change .mailpoet_field_header_alignment': _.partial(this.changeField, 'styles.text.textAlign'),
"click .mailpoet_done_editing": "close" 'click .mailpoet_done_editing': 'close'
}; };
}, },
templateContext: function () { templateContext: function () {
@ -98,7 +99,7 @@ define([
}); });
Module.HeaderWidgetView = base.WidgetView.extend({ Module.HeaderWidgetView = base.WidgetView.extend({
getTemplate: function() { return templates.headerInsertion; }, getTemplate: function () { return window.templates.headerInsertion; },
behaviors: { behaviors: {
DraggableBehavior: { DraggableBehavior: {
cloneOriginal: true, cloneOriginal: true,
@ -109,7 +110,7 @@ define([
} }
}); });
App.on('before:start', function(App, options) { App.on('before:start', function (App) {
App.registerBlockType('header', { App.registerBlockType('header', {
blockModel: Module.HeaderBlockModel, blockModel: Module.HeaderBlockModel,
blockView: Module.HeaderBlockView blockView: Module.HeaderBlockView

View File

@ -5,14 +5,15 @@ define([
'newsletter_editor/App', 'newsletter_editor/App',
'newsletter_editor/blocks/base', 'newsletter_editor/blocks/base',
'underscore', 'underscore',
'mailpoet' 'mailpoet',
], function(App, BaseBlock, _, MailPoet) { 'jquery'
], function (App, BaseBlock, _, MailPoet, jQuery) {
"use strict"; 'use strict';
var Module = {}, var Module = {};
base = BaseBlock, var base = BaseBlock;
ImageWidgetView; var ImageWidgetView;
Module.ImageBlockModel = base.BlockModel.extend({ Module.ImageBlockModel = base.BlockModel.extend({
defaults: function () { defaults: function () {
@ -34,8 +35,8 @@ define([
}); });
Module.ImageBlockView = base.BlockView.extend({ Module.ImageBlockView = base.BlockView.extend({
className: "mailpoet_block mailpoet_image_block mailpoet_droppable_block", className: 'mailpoet_block mailpoet_image_block mailpoet_droppable_block',
getTemplate: function() { return templates.imageBlock; }, getTemplate: function () { return window.templates.imageBlock; },
onDragSubstituteBy: function () { return Module.ImageWidgetView; }, onDragSubstituteBy: function () { return Module.ImageWidgetView; },
templateContext: function () { templateContext: function () {
return _.extend({ return _.extend({
@ -43,17 +44,28 @@ define([
}, base.BlockView.prototype.templateContext.apply(this)); }, base.BlockView.prototype.templateContext.apply(this));
}, },
behaviors: _.extend({}, base.BlockView.prototype.behaviors, { behaviors: _.extend({}, base.BlockView.prototype.behaviors, {
ShowSettingsBehavior: {} ResizableBehavior: {
elementSelector: '.mailpoet_image',
resizeHandleSelector: '.mailpoet_image_resize_handle',
onResize: function (event) {
var corner = this.$('.mailpoet_image').offset();
var width = event.pageX - corner.left;
this.view.model.set('width', width + 'px');
}
},
ShowSettingsBehavior: {
ignoreFrom: '.mailpoet_image_resize_handle'
}
}), }),
onRender: function () { onRender: function () {
this.toolsView = new Module.ImageBlockToolsView({ model: this.model }); this.toolsView = new Module.ImageBlockToolsView({ model: this.model });
this.showChildView('toolsRegion', this.toolsView); this.showChildView('toolsRegion', this.toolsView);
if (this.model.get('fullWidth')) { if (this.model.get('fullWidth')) {
this.$el.addClass('mailpoet_full_image'); this.$el.addClass('mailpoet_full_image');
} else { } else {
this.$el.removeClass('mailpoet_full_image'); this.$el.removeClass('mailpoet_full_image');
} }
this.$('.mailpoet_content').css('width', this.model.get('width'));
} }
}); });
@ -72,18 +84,41 @@ define([
tooltip: MailPoet.I18n.t('helpTooltipDesignerIdealWidth') tooltip: MailPoet.I18n.t('helpTooltipDesignerIdealWidth')
}); });
}, },
getTemplate: function() { return templates.imageBlockSettings; }, getTemplate: function () { return window.templates.imageBlockSettings; },
events: function () { events: function () {
return { return {
"input .mailpoet_field_image_link": _.partial(this.changeField, "link"), 'input .mailpoet_field_image_link': _.partial(this.changeField, 'link'),
"input .mailpoet_field_image_address": 'changeAddress', 'input .mailpoet_field_image_address': 'changeAddress',
"input .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',
"click .mailpoet_done_editing": "close" 'click .mailpoet_done_editing': 'close',
'input .mailpoet_field_image_width': _.partial(this.updateValueAndCall, '.mailpoet_field_image_width_input', _.partial(this.changePixelField, 'width').bind(this)),
'change .mailpoet_field_image_width': _.partial(this.updateValueAndCall, '.mailpoet_field_image_width_input', _.partial(this.changePixelField, 'width').bind(this)),
'input .mailpoet_field_image_width_input': _.partial(this.updateValueAndCall, '.mailpoet_field_image_width', _.partial(this.changePixelField, 'width').bind(this))
}; };
}, },
modelEvents: function () {
return {
'change:maxWidth': 'updateMaxWidth',
'change:width': 'updateWidth'
};
},
updateValueAndCall: function (fieldToUpdate, callable, event) {
this.$(fieldToUpdate).val(jQuery(event.target).val());
callable(event);
},
updateMaxWidth: function () {
var maxWidth = parseInt(this.model.get('maxWidth'));
this.$('.mailpoet_field_image_width').attr('max', maxWidth);
this.$('.mailpoet_field_image_width_input').attr('max', maxWidth);
},
updateWidth: function () {
var width = parseInt(this.model.get('width'));
this.$('.mailpoet_field_image_width').val(width);
this.$('.mailpoet_field_image_width_input').val(width);
},
initialize: function (options) { initialize: function (options) {
base.BlockSettingsView.prototype.initialize.apply(this, arguments); base.BlockSettingsView.prototype.initialize.apply(this, arguments);
@ -92,16 +127,19 @@ define([
} }
}, },
showMediaManager: function () { showMediaManager: function () {
var that = this;
var MediaManager;
var theFrame;
if (this._mediaManager) { if (this._mediaManager) {
this._mediaManager.resetSelections(); this._mediaManager.resetSelections();
this._mediaManager.open(); this._mediaManager.open();
return; return;
} }
var MediaManager = wp.media.view.MediaFrame.Select.extend({ MediaManager = window.wp.media.view.MediaFrame.Select.extend({
initialize: function () { initialize: function () {
wp.media.view.MediaFrame.prototype.initialize.apply(this, arguments); window.wp.media.view.MediaFrame.prototype.initialize.apply(this, arguments);
_.defaults(this.options, { _.defaults(this.options, {
multiple: true, multiple: true,
@ -123,7 +161,7 @@ define([
}, },
createQuery: function (options) { createQuery: function (options) {
var query = wp.media.query(options); var query = window.wp.media.query(options);
return query; return query;
}, },
@ -133,7 +171,7 @@ define([
// Add the default states. // Add the default states.
this.states.add([ this.states.add([
// Main states. // Main states.
new wp.media.controller.Library({ new window.wp.media.controller.Library({
id: 'insert', id: 'insert',
title: 'Add images', title: 'Add images',
priority: 20, priority: 20,
@ -155,12 +193,13 @@ define([
}) })
]); ]);
if(wp.media.view.settings.post.featuredImageId) { if (window.wp.media.view.settings.post.featuredImageId) {
this.states.add(new wp.media.controller.FeaturedImage()); this.states.add(new window.wp.media.controller.FeaturedImage());
} }
}, },
bindHandlers: function () { bindHandlers: function () {
var handlers;
// from Select // from Select
this.on('router:create:browse', this.createRouter, this); this.on('router:create:browse', this.createRouter, this);
this.on('router:render:browse', this.browseRouter, this); this.on('router:render:browse', this.browseRouter, this);
@ -175,9 +214,9 @@ define([
this.on('updateExcluded', this.browseContent, this); this.on('updateExcluded', this.browseContent, this);
var handlers = { handlers = {
content: { content: {
'embed': 'embedContent', embed: 'embedContent',
'edit-selection': 'editSelectionContent' 'edit-selection': 'editSelectionContent'
}, },
toolbar: { toolbar: {
@ -193,13 +232,13 @@ define([
}, },
uploadContent: function () { uploadContent: function () {
wp.media.view.MediaFrame.Select.prototype.uploadContent.apply(this, arguments); window.wp.media.view.MediaFrame.Select.prototype.uploadContent.apply(this, arguments);
this.$el.addClass('hide-toolbar'); this.$el.addClass('hide-toolbar');
}, },
// Content // Content
embedContent: function () { embedContent: function () {
var view = new wp.media.view.Embed({ var view = new window.wp.media.view.Embed({
controller: this, controller: this,
model: this.state() model: this.state()
}).render(); }).render();
@ -209,11 +248,11 @@ define([
}, },
editSelectionContent: function () { editSelectionContent: function () {
var state = this.state(), var state = this.state();
selection = state.get('selection'), var selection = state.get('selection');
view; var view;
view = new wp.media.view.AttachmentsBrowser({ view = new window.wp.media.view.AttachmentsBrowser({
controller: this, controller: this,
collection: selection, collection: selection,
selection: selection, selection: selection,
@ -222,7 +261,7 @@ define([
search: false, search: false,
dragInfo: true, dragInfo: true,
AttachmentView: wp.media.view.Attachment.EditSelection AttachmentView: window.wp.media.view.Attachment.EditSelection
}).render(); }).render();
view.toolbar.set('backToLibrary', { view.toolbar.set('backToLibrary', {
@ -242,7 +281,7 @@ define([
selectionStatusToolbar: function (view) { selectionStatusToolbar: function (view) {
var editable = this.state().get('editable'); var editable = this.state().get('editable');
view.set('selection', new wp.media.view.Selection({ view.set('selection', new window.wp.media.view.Selection({
controller: this, controller: this,
collection: this.state().get('selection'), collection: this.state().get('selection'),
priority: -40, priority: -40,
@ -267,8 +306,8 @@ define([
requires: { selection: true }, requires: { selection: true },
click: function () { click: function () {
var state = controller.state(), var state = controller.state();
selection = state.get('selection'); var selection = state.get('selection');
controller.close(); controller.close();
state.trigger('insert', selection).reset(); state.trigger('insert', selection).reset();
@ -278,7 +317,7 @@ define([
mainEmbedToolbar: function (toolbar) { mainEmbedToolbar: function (toolbar) {
var tbar = toolbar; var tbar = toolbar;
tbar.view = new wp.media.view.Toolbar.Embed({ tbar.view = new window.wp.media.view.Toolbar.Embed({
controller: this, controller: this,
text: 'Add images' text: 'Add images'
}); });
@ -286,7 +325,7 @@ define([
}); });
var theFrame = new MediaManager({ theFrame = new MediaManager({
id: 'mailpoet-media-manager', id: 'mailpoet-media-manager',
frame: 'select', frame: 'select',
title: 'Select image', title: 'Select image',
@ -299,39 +338,35 @@ define([
button: { button: {
text: 'Select' text: 'Select'
} }
}), });
that = this;
this._mediaManager = theFrame; this._mediaManager = theFrame;
this._mediaManager.on('insert', function () { this._mediaManager.on('insert', function () {
// Append media manager image selections to Images tab // Append media manager image selections to Images tab
var selection = theFrame.state().get('selection'); var selection = theFrame.state().get('selection');
selection.each(function (attachment) { selection.each(function (attachment) {
var sizes = attachment.get('sizes'), var sizes = attachment.get('sizes');
// Following advice from Becs, the target width should // Following advice from Becs, the target width should
// be a double of one column width to render well on // be a double of one column width to render well on
// retina screen devices // retina screen devices
targetImageWidth = 1320, var targetImageWidth = 1320;
// For main image use the size, that's closest to being 660px in width
sizeKeys = _.keys(sizes),
// Pick the width that is closest to target width // Pick the width that is closest to target width
increasingByWidthDifference = _.sortBy( var increasingByWidthDifference = _.sortBy(
_.keys(sizes), _.keys(sizes),
function (size) { return Math.abs(targetImageWidth - sizes[size].width); } function (size) { return Math.abs(targetImageWidth - sizes[size].width); }
), );
bestWidth = sizes[_.first(increasingByWidthDifference)].width, var bestWidth = sizes[_.first(increasingByWidthDifference)].width;
imagesOfBestWidth = _.filter(_.values(sizes), function(size) { return size.width === bestWidth; }), var imagesOfBestWidth = _.filter(_.values(sizes), function (size) { return size.width === bestWidth; });
// Maximize the height if there are multiple images with same width // Maximize the height if there are multiple images with same width
mainSize = _.max(imagesOfBestWidth, function(size) { return size.height; }); var mainSize = _.max(imagesOfBestWidth, function (size) { return size.height; });
that.model.set({ that.model.set({
height: mainSize.height + 'px', height: mainSize.height + 'px',
width: mainSize.width + 'px', width: mainSize.width + 'px',
src: mainSize.url, src: mainSize.url,
alt: (attachment.get('alt') !== "" && attachment.get('alt') !== undefined) ? attachment.get('alt') : attachment.get('title') alt: (attachment.get('alt') !== '' && attachment.get('alt') !== undefined) ? attachment.get('alt') : attachment.get('title')
}); });
// Rerender settings view due to changes from outside of settings view // Rerender settings view due to changes from outside of settings view
that.render(); that.render();
@ -363,7 +398,7 @@ define([
}); });
ImageWidgetView = base.WidgetView.extend({ ImageWidgetView = base.WidgetView.extend({
getTemplate: function() { return templates.imageInsertion; }, getTemplate: function () { return window.templates.imageInsertion; },
behaviors: { behaviors: {
DraggableBehavior: { DraggableBehavior: {
cloneOriginal: true, cloneOriginal: true,
@ -378,7 +413,7 @@ define([
}); });
Module.ImageWidgetView = ImageWidgetView; Module.ImageWidgetView = ImageWidgetView;
App.on('before:start', function(App, options) { App.on('before:start', function (App) {
App.registerBlockType('image', { App.registerBlockType('image', {
blockModel: Module.ImageBlockModel, blockModel: Module.ImageBlockModel,
blockView: Module.ImageBlockView blockView: Module.ImageBlockView

View File

@ -37,10 +37,15 @@ define([
DividerBlock DividerBlock
) { ) {
"use strict"; 'use strict';
var Module = {}, var Module = {};
base = BaseBlock; var base = BaseBlock;
var PostsDisplayOptionsSettingsView;
var SinglePostSelectionSettingsView;
var EmptyPostSelectionSettingsView;
var PostSelectionSettingsView;
var PostsSelectionCollectionView;
Module.PostsBlockModel = base.BlockModel.extend({ Module.PostsBlockModel = base.BlockModel.extend({
stale: ['_selectedPosts', '_availablePosts', '_transformedPosts'], stale: ['_selectedPosts', '_availablePosts', '_transformedPosts'],
@ -89,10 +94,9 @@ define([
}; };
}, },
initialize: function () { initialize: function () {
var that = this, var POST_REFRESH_DELAY_MS = 500;
POST_REFRESH_DELAY_MS = 500, var refreshAvailablePosts = _.debounce(this.fetchAvailablePosts.bind(this), POST_REFRESH_DELAY_MS);
refreshAvailablePosts = _.debounce(this.fetchAvailablePosts.bind(this), POST_REFRESH_DELAY_MS), var refreshTransformedPosts = _.debounce(this._refreshTransformedPosts.bind(this), POST_REFRESH_DELAY_MS);
refreshTransformedPosts = _.debounce(this._refreshTransformedPosts.bind(this), POST_REFRESH_DELAY_MS);
// Attach Radio.Requests API primarily for highlighting // Attach Radio.Requests API primarily for highlighting
_.extend(this, Radio.Requests); _.extend(this, Radio.Requests);
@ -120,9 +124,9 @@ define([
}); });
}, },
_loadMorePosts: function () { _loadMorePosts: function () {
var that = this, var that = this;
postCount = this.get('_availablePosts').length, var postCount = this.get('_availablePosts').length;
nextOffset = this.get('offset') + Number(this.get('amount')); var nextOffset = this.get('offset') + Number(this.get('amount'));
if (postCount === 0 || postCount < nextOffset) { if (postCount === 0 || postCount < nextOffset) {
// No more posts to load // No more posts to load
@ -141,8 +145,8 @@ define([
}); });
}, },
_refreshTransformedPosts: function () { _refreshTransformedPosts: function () {
var that = this, var that = this;
data = this.toJSON(); var data = this.toJSON();
data.posts = this.get('_selectedPosts').pluck('ID'); data.posts = this.get('_selectedPosts').pluck('ID');
@ -158,10 +162,9 @@ define([
}); });
}, },
_insertSelectedPosts: function () { _insertSelectedPosts: function () {
var that = this, var data = this.toJSON();
data = this.toJSON(), var index = this.collection.indexOf(this);
index = this.collection.indexOf(this), var collection = this.collection;
collection = this.collection;
data.posts = this.get('_selectedPosts').pluck('ID'); data.posts = this.get('_selectedPosts').pluck('ID');
@ -176,8 +179,8 @@ define([
}); });
Module.PostsBlockView = base.BlockView.extend({ Module.PostsBlockView = base.BlockView.extend({
className: "mailpoet_block mailpoet_posts_block mailpoet_droppable_block", className: 'mailpoet_block mailpoet_posts_block mailpoet_droppable_block',
getTemplate: function() { return templates.postsBlock; }, getTemplate: function () { return window.templates.postsBlock; },
modelEvents: {}, // Forcefully disable all events modelEvents: {}, // Forcefully disable all events
regions: _.extend({ regions: _.extend({
postsRegion: '.mailpoet_posts_block_posts' postsRegion: '.mailpoet_posts_block_posts'
@ -190,12 +193,14 @@ define([
this.model.reply('blockView', this.notifyAboutSelf, this); this.model.reply('blockView', this.notifyAboutSelf, this);
}, },
onRender: function () { onRender: function () {
var ContainerView;
var renderOptions;
if (!this.getRegion('toolsRegion').hasView()) { if (!this.getRegion('toolsRegion').hasView()) {
this.showChildView('toolsRegion', this.toolsView); this.showChildView('toolsRegion', this.toolsView);
} }
this.trigger('showSettings'); this.trigger('showSettings');
var ContainerView = App.getBlockTypeView('container'), ContainerView = App.getBlockTypeView('container');
renderOptions = { renderOptions = {
disableTextEditor: true, disableTextEditor: true,
disableDragAndDrop: true, disableDragAndDrop: true,
@ -216,7 +221,7 @@ define([
}); });
Module.PostsBlockSettingsView = base.BlockSettingsView.extend({ Module.PostsBlockSettingsView = base.BlockSettingsView.extend({
getTemplate: function() { return templates.postsBlockSettings; }, getTemplate: function () { return window.templates.postsBlockSettings; },
regions: { regions: {
selectionRegion: '.mailpoet_settings_posts_selection', selectionRegion: '.mailpoet_settings_posts_selection',
displayOptionsRegion: '.mailpoet_settings_posts_display_options' displayOptionsRegion: '.mailpoet_settings_posts_display_options'
@ -237,8 +242,8 @@ define([
this.displayOptionsView = new PostsDisplayOptionsSettingsView({ model: this.model }); this.displayOptionsView = new PostsDisplayOptionsSettingsView({ model: this.model });
}, },
onRender: function () { onRender: function () {
var that = this, var that = this;
blockView = this.model.request('blockView'); this.model.request('blockView');
this.showChildView('selectionRegion', this.selectionView); this.showChildView('selectionRegion', this.selectionView);
this.showChildView('displayOptionsRegion', this.displayOptionsView); this.showChildView('displayOptionsRegion', this.displayOptionsView);
@ -283,7 +288,7 @@ define([
} }
}); });
var PostsSelectionCollectionView = Marionette.CollectionView.extend({ PostsSelectionCollectionView = Marionette.CollectionView.extend({
className: 'mailpoet_post_scroll_container', className: 'mailpoet_post_scroll_container',
childView: function () { return SinglePostSelectionSettingsView; }, childView: function () { return SinglePostSelectionSettingsView; },
emptyView: function () { return EmptyPostSelectionSettingsView; }, emptyView: function () { return EmptyPostSelectionSettingsView; },
@ -296,7 +301,7 @@ define([
this.blockModel = options.blockModel; this.blockModel = options.blockModel;
}, },
events: { events: {
'scroll': 'onPostsScroll' scroll: 'onPostsScroll'
}, },
onPostsScroll: function (event) { onPostsScroll: function (event) {
var $postsBox = jQuery(event.target); var $postsBox = jQuery(event.target);
@ -307,8 +312,8 @@ define([
} }
}); });
var PostSelectionSettingsView = Marionette.View.extend({ PostSelectionSettingsView = Marionette.View.extend({
getTemplate: function() { return templates.postSelectionPostsBlockSettings; }, getTemplate: function () { return window.templates.postSelectionPostsBlockSettings; },
regions: { regions: {
posts: '.mailpoet_post_selection_container' posts: '.mailpoet_post_selection_container'
}, },
@ -326,17 +331,18 @@ define([
this.$('.mailpoet_post_scroll_container').scrollTop(0); this.$('.mailpoet_post_scroll_container').scrollTop(0);
} }
}, },
'loadingMorePosts': function() { loadingMorePosts: function () {
this.$('.mailpoet_post_selection_loading').css('visibility', 'visible'); this.$('.mailpoet_post_selection_loading').css('visibility', 'visible');
}, },
'morePostsLoaded': function() { morePostsLoaded: function () {
this.$('.mailpoet_post_selection_loading').css('visibility', 'hidden'); this.$('.mailpoet_post_selection_loading').css('visibility', 'hidden');
} }
}, },
onRender: function () { onRender: function () {
var postsView;
// Dynamically update available post types // Dynamically update available post types
CommunicationComponent.getPostTypes().done(_.bind(this._updateContentTypes, this)); CommunicationComponent.getPostTypes().done(_.bind(this._updateContentTypes, this));
var postsView = new PostsSelectionCollectionView({ postsView = new PostsSelectionCollectionView({
collection: this.model.get('_availablePosts'), collection: this.model.get('_availablePosts'),
blockModel: this.model blockModel: this.model
}); });
@ -358,12 +364,13 @@ define([
}, },
transport: function (options, success, failure) { transport: function (options, success, failure) {
var taxonomies; var taxonomies;
var termsPromise;
var promise = CommunicationComponent.getTaxonomies( var promise = CommunicationComponent.getTaxonomies(
that.model.get('contentType') that.model.get('contentType')
).then(function (tax) { ).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({ termsPromise = CommunicationComponent.getTerms({
search: options.data.term, search: options.data.term,
taxonomies: _.keys(taxonomies) taxonomies: _.keys(taxonomies)
}).then(function (terms) { }).then(function (terms) {
@ -372,7 +379,7 @@ define([
terms: terms terms: terms
}; };
}); });
return promise; return termsPromise;
}); });
promise.then(success); promise.then(success);
@ -413,8 +420,8 @@ define([
this.model.set(field, jQuery(event.target).val()); this.model.set(field, jQuery(event.target).val());
}, },
_updateContentTypes: function (postTypes) { _updateContentTypes: function (postTypes) {
var select = this.$('.mailpoet_settings_posts_content_type'), var select = this.$('.mailpoet_settings_posts_content_type');
selectedValue = this.model.get('contentType'); var selectedValue = this.model.get('contentType');
select.find('option').remove(); select.find('option').remove();
_.each(postTypes, function (type) { _.each(postTypes, function (type) {
@ -427,12 +434,12 @@ define([
} }
}); });
var EmptyPostSelectionSettingsView = Marionette.View.extend({ EmptyPostSelectionSettingsView = Marionette.View.extend({
getTemplate: function() { return templates.emptyPostPostsBlockSettings; } getTemplate: function () { return window.templates.emptyPostPostsBlockSettings; }
}); });
var SinglePostSelectionSettingsView = Marionette.View.extend({ SinglePostSelectionSettingsView = Marionette.View.extend({
getTemplate: function() { return templates.singlePostPostsBlockSettings; }, getTemplate: function () { return window.templates.singlePostPostsBlockSettings; },
events: function () { events: function () {
return { return {
'change .mailpoet_select_post_checkbox': 'postSelectionChange' 'change .mailpoet_select_post_checkbox': 'postSelectionChange'
@ -448,8 +455,8 @@ define([
this.blockModel = options.blockModel; this.blockModel = options.blockModel;
}, },
postSelectionChange: function (event) { postSelectionChange: function (event) {
var checkBox = jQuery(event.target), var checkBox = jQuery(event.target);
selectedPostsCollection = this.blockModel.get('_selectedPosts'); var selectedPostsCollection = this.blockModel.get('_selectedPosts');
if (checkBox.prop('checked')) { if (checkBox.prop('checked')) {
selectedPostsCollection.add(this.model); selectedPostsCollection.add(this.model);
} else { } else {
@ -458,29 +465,29 @@ define([
} }
}); });
var PostsDisplayOptionsSettingsView = base.BlockSettingsView.extend({ PostsDisplayOptionsSettingsView = base.BlockSettingsView.extend({
getTemplate: function() { return templates.displayOptionsPostsBlockSettings; }, getTemplate: function () { return window.templates.displayOptionsPostsBlockSettings; },
events: function () { events: function () {
return { return {
"click .mailpoet_posts_select_button": 'showButtonSettings', 'click .mailpoet_posts_select_button': 'showButtonSettings',
"click .mailpoet_posts_select_divider": 'showDividerSettings', 'click .mailpoet_posts_select_divider': 'showDividerSettings',
"change .mailpoet_posts_read_more_type": 'changeReadMoreType', 'change .mailpoet_posts_read_more_type': 'changeReadMoreType',
"change .mailpoet_posts_display_type": 'changeDisplayType', 'change .mailpoet_posts_display_type': 'changeDisplayType',
"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'),
"input .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'),
"input .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'),
"input .mailpoet_posts_categories": _.partial(this.changeField, "categoriesPrecededBy"), 'input .mailpoet_posts_categories': _.partial(this.changeField, 'categoriesPrecededBy'),
"input .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')
}; };
}, },
templateContext: function () { templateContext: function () {
@ -488,7 +495,7 @@ define([
model: this.model.toJSON() model: this.model.toJSON()
}; };
}, },
showButtonSettings: function(event) { showButtonSettings: function () {
var buttonModule = ButtonBlock; var buttonModule = ButtonBlock;
(new buttonModule.ButtonBlockSettingsView({ (new buttonModule.ButtonBlockSettingsView({
model: this.model.get('readMoreButton'), model: this.model.get('readMoreButton'),
@ -499,7 +506,7 @@ define([
} }
})).render(); })).render();
}, },
showDividerSettings: function(event) { showDividerSettings: function () {
var dividerModule = DividerBlock; var dividerModule = DividerBlock;
(new dividerModule.DividerBlockSettingsView({ (new dividerModule.DividerBlockSettingsView({
model: this.model.get('divider'), model: this.model.get('divider'),
@ -564,7 +571,7 @@ define([
}); });
Module.PostsWidgetView = base.WidgetView.extend({ Module.PostsWidgetView = base.WidgetView.extend({
getTemplate: function() { return templates.postsInsertion; }, getTemplate: function () { return window.templates.postsInsertion; },
behaviors: { behaviors: {
DraggableBehavior: { DraggableBehavior: {
cloneOriginal: true, cloneOriginal: true,
@ -575,7 +582,7 @@ define([
} }
}); });
App.on('before:start', function(App, options) { App.on('before:start', function (App) {
App.registerBlockType('posts', { App.registerBlockType('posts', {
blockModel: Module.PostsBlockModel, blockModel: Module.PostsBlockModel,
blockView: Module.PostsBlockView blockView: Module.PostsBlockView

View File

@ -11,14 +11,15 @@ define([
'jquery' 'jquery'
], function (App, BaseBlock, Backbone, Marionette, SuperModel, _, jQuery) { ], function (App, BaseBlock, Backbone, Marionette, SuperModel, _, jQuery) {
"use strict"; 'use strict';
var Module = {}, var Module = {};
base = BaseBlock, var base = BaseBlock;
SocialBlockSettingsIconSelectorView, var SocialBlockSettingsIconSelectorView;
SocialBlockSettingsIconView, var SocialBlockSettingsIconView;
SocialBlockSettingsIconCollectionView, var SocialBlockSettingsIconCollectionView;
SocialBlockSettingsStylesView; var SocialBlockSettingsStylesView;
var SocialIconView;
Module.SocialIconModel = SuperModel.extend({ Module.SocialIconModel = SuperModel.extend({
defaults: function () { defaults: function () {
@ -33,12 +34,12 @@ define([
text: defaultValues.get('title') text: defaultValues.get('title')
}; };
}, },
initialize: function(options) { initialize: function () {
var that = this; var that = this;
// Make model swap to default values for that type when iconType changes // Make model swap to default values for that type when iconType changes
this.on('change:iconType', function () { this.on('change:iconType', function () {
var defaultValues = App.getConfig().get('socialIcons').get(that.get('iconType')), var defaultValues = App.getConfig().get('socialIcons').get(that.get('iconType'));
iconSet = that.collection.iconBlockModel.getIconSet(); var iconSet = that.collection.iconBlockModel.getIconSet();
this.set({ this.set({
link: defaultValues.get('defaultLink'), link: defaultValues.get('defaultLink'),
image: iconSet.get(that.get('iconType')), image: iconSet.get(that.get('iconType')),
@ -83,11 +84,11 @@ define([
} }
}); });
var SocialIconView = Marionette.View.extend({ SocialIconView = Marionette.View.extend({
tagName: 'span', tagName: 'span',
getTemplate: function() { return templates.socialIconBlock; }, getTemplate: function () { return window.templates.socialIconBlock; },
modelEvents: { modelEvents: {
'change': 'render' change: 'render'
}, },
templateContext: function () { templateContext: function () {
var allIconSets = App.getAvailableStyles().get('socialIconSets'); var allIconSets = App.getAvailableStyles().get('socialIconSets');
@ -105,7 +106,7 @@ define([
Module.SocialBlockView = base.BlockView.extend({ Module.SocialBlockView = base.BlockView.extend({
className: 'mailpoet_block mailpoet_social_block mailpoet_droppable_block', className: 'mailpoet_block mailpoet_social_block mailpoet_droppable_block',
getTemplate: function() { return templates.socialBlock; }, getTemplate: function () { return window.templates.socialBlock; },
regions: _.extend({}, base.BlockView.prototype.regions, { regions: _.extend({}, base.BlockView.prototype.regions, {
icons: '.mailpoet_social' icons: '.mailpoet_social'
}), }),
@ -121,7 +122,7 @@ define([
this.showChildView('toolsRegion', this.toolsView); this.showChildView('toolsRegion', this.toolsView);
this.showChildView('icons', new Module.SocialIconCollectionView({ this.showChildView('icons', new Module.SocialIconCollectionView({
collection: this.model.get('icons') collection: this.model.get('icons')
})) }));
} }
}); });
@ -131,14 +132,14 @@ define([
// Sidebar view container // Sidebar view container
Module.SocialBlockSettingsView = base.BlockSettingsView.extend({ Module.SocialBlockSettingsView = base.BlockSettingsView.extend({
getTemplate: function() { return templates.socialBlockSettings; }, getTemplate: function () { return window.templates.socialBlockSettings; },
regions: { regions: {
iconRegion: '#mailpoet_social_icons_selection', iconRegion: '#mailpoet_social_icons_selection',
stylesRegion: '#mailpoet_social_icons_styles' stylesRegion: '#mailpoet_social_icons_styles'
}, },
events: function () { events: function () {
return { return {
"click .mailpoet_done_editing": "close" 'click .mailpoet_done_editing': 'close'
}; };
}, },
initialize: function () { initialize: function () {
@ -155,14 +156,14 @@ define([
// Single icon settings view, used by the selector view // Single icon settings view, used by the selector view
SocialBlockSettingsIconView = Marionette.View.extend({ SocialBlockSettingsIconView = Marionette.View.extend({
getTemplate: function() { return templates.socialSettingsIcon; }, getTemplate: function () { return window.templates.socialSettingsIcon; },
events: function () { events: function () {
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'),
"input .mailpoet_social_icon_field_image": _.partial(this.changeField, "image"), 'input .mailpoet_social_icon_field_image': _.partial(this.changeField, 'image'),
"input .mailpoet_social_icon_field_link": this.changeLink, 'input .mailpoet_social_icon_field_link': this.changeLink,
"input .mailpoet_social_icon_field_text": _.partial(this.changeField, "text") 'input .mailpoet_social_icon_field_text': _.partial(this.changeField, 'text')
}; };
}, },
modelEvents: { modelEvents: {
@ -175,10 +176,10 @@ define([
} }
}, },
templateContext: function () { templateContext: function () {
var icons = App.getConfig().get('socialIcons'), var icons = App.getConfig().get('socialIcons');
// Construct icon type list of format [{iconType: 'type', title: 'Title'}, ...] // Construct icon type list of format [{iconType: 'type', title: 'Title'}, ...]
availableIconTypes = _.map(_.keys(icons.attributes), function(key) { return { iconType: key, title: icons.get(key).get('title') }; }), var availableIconTypes = _.map(_.keys(icons.attributes), function (key) { return { iconType: key, title: icons.get(key).get('title') }; });
allIconSets = App.getAvailableStyles().get('socialIconSets'); var allIconSets = App.getAvailableStyles().get('socialIconSets');
return _.extend({}, base.BlockView.prototype.templateContext.apply(this, arguments), { return _.extend({}, base.BlockView.prototype.templateContext.apply(this, arguments), {
iconTypes: availableIconTypes, iconTypes: availableIconTypes,
currentType: icons.get(this.model.get('iconType')).toJSON(), currentType: icons.get(this.model.get('iconType')).toJSON(),
@ -212,9 +213,9 @@ define([
// Select icons section container view // Select icons section container view
SocialBlockSettingsIconSelectorView = Marionette.View.extend({ SocialBlockSettingsIconSelectorView = Marionette.View.extend({
getTemplate: function() { return templates.socialSettingsIconSelector; }, getTemplate: function () { return window.templates.socialSettingsIconSelector; },
regions: { regions: {
'icons': '#mailpoet_social_icon_selector_contents' icons: '#mailpoet_social_icon_selector_contents'
}, },
events: { events: {
'click .mailpoet_add_social_icon': 'addSocialIcon' 'click .mailpoet_add_social_icon': 'addSocialIcon'
@ -235,9 +236,9 @@ define([
}); });
SocialBlockSettingsStylesView = Marionette.View.extend({ SocialBlockSettingsStylesView = Marionette.View.extend({
getTemplate: function() { return templates.socialSettingsStyles; }, getTemplate: function () { return window.templates.socialSettingsStyles; },
modelEvents: { modelEvents: {
'change': 'render' change: 'render'
}, },
events: { events: {
'click .mailpoet_social_icon_set': 'changeSocialIconSet' 'click .mailpoet_social_icon_set': 'changeSocialIconSet'
@ -263,7 +264,7 @@ define([
}); });
Module.SocialWidgetView = base.WidgetView.extend({ Module.SocialWidgetView = base.WidgetView.extend({
getTemplate: function() { return templates.socialInsertion; }, getTemplate: function () { return window.templates.socialInsertion; },
behaviors: { behaviors: {
DraggableBehavior: { DraggableBehavior: {
cloneOriginal: true, cloneOriginal: true,
@ -297,7 +298,7 @@ define([
} }
}); });
App.on('before:start', function(App, options) { App.on('before:start', function (App) {
App.registerBlockType('social', { App.registerBlockType('social', {
blockModel: Module.SocialBlockModel, blockModel: Module.SocialBlockModel,
blockView: Module.SocialBlockView blockView: Module.SocialBlockView

View File

@ -7,10 +7,10 @@ define([
'underscore' 'underscore'
], function (App, BaseBlock, _) { ], function (App, BaseBlock, _) {
"use strict"; 'use strict';
var Module = {}, var Module = {};
base = BaseBlock; var base = BaseBlock;
Module.SpacerBlockModel = base.BlockModel.extend({ Module.SpacerBlockModel = base.BlockModel.extend({
defaults: function () { defaults: function () {
@ -27,8 +27,8 @@ define([
}); });
Module.SpacerBlockView = base.BlockView.extend({ Module.SpacerBlockView = base.BlockView.extend({
className: "mailpoet_block mailpoet_spacer_block mailpoet_droppable_block", className: 'mailpoet_block mailpoet_spacer_block mailpoet_droppable_block',
getTemplate: function() { return templates.spacerBlock; }, getTemplate: function () { return window.templates.spacerBlock; },
behaviors: _.defaults({ behaviors: _.defaults({
ResizableBehavior: { ResizableBehavior: {
elementSelector: '.mailpoet_spacer', elementSelector: '.mailpoet_spacer',
@ -66,17 +66,17 @@ define([
}); });
Module.SpacerBlockSettingsView = base.BlockSettingsView.extend({ Module.SpacerBlockSettingsView = base.BlockSettingsView.extend({
getTemplate: function() { return templates.spacerBlockSettings; }, getTemplate: function () { return window.templates.spacerBlockSettings; },
events: function () { events: function () {
return { return {
"change .mailpoet_field_spacer_background_color": _.partial(this.changeColorField, "styles.block.backgroundColor"), 'change .mailpoet_field_spacer_background_color': _.partial(this.changeColorField, 'styles.block.backgroundColor'),
"click .mailpoet_done_editing": "close" 'click .mailpoet_done_editing': 'close'
}; };
} }
}); });
Module.SpacerWidgetView = base.WidgetView.extend({ Module.SpacerWidgetView = base.WidgetView.extend({
getTemplate: function() { return templates.spacerInsertion; }, getTemplate: function () { return window.templates.spacerInsertion; },
behaviors: { behaviors: {
DraggableBehavior: { DraggableBehavior: {
cloneOriginal: true, cloneOriginal: true,
@ -87,7 +87,7 @@ define([
} }
}); });
App.on('before:start', function(App, options) { App.on('before:start', function (App) {
App.registerBlockType('spacer', { App.registerBlockType('spacer', {
blockModel: Module.SpacerBlockModel, blockModel: Module.SpacerBlockModel,
blockView: Module.SpacerBlockView blockView: Module.SpacerBlockView

View File

@ -4,13 +4,14 @@
define([ define([
'newsletter_editor/App', 'newsletter_editor/App',
'newsletter_editor/blocks/base', 'newsletter_editor/blocks/base',
'underscore' 'underscore',
], function(App, BaseBlock, _) { 'mailpoet'
], function (App, BaseBlock, _, MailPoet) {
"use strict"; 'use strict';
var Module = {}, var Module = {};
base = BaseBlock; var base = BaseBlock;
Module.TextBlockModel = base.BlockModel.extend({ Module.TextBlockModel = base.BlockModel.extend({
defaults: function () { defaults: function () {
@ -22,17 +23,17 @@ define([
}); });
Module.TextBlockView = base.BlockView.extend({ Module.TextBlockView = base.BlockView.extend({
className: "mailpoet_block mailpoet_text_block mailpoet_droppable_block", className: 'mailpoet_block mailpoet_text_block mailpoet_droppable_block',
getTemplate: function() { return templates.textBlock; }, getTemplate: function () { return window.templates.textBlock; },
modelEvents: _.omit(base.BlockView.prototype.modelEvents, 'change'), // Prevent rerendering on model change due to text editor redrawing modelEvents: _.omit(base.BlockView.prototype.modelEvents, 'change'), // Prevent rerendering on model change due to text editor redrawing
behaviors: _.extend({}, base.BlockView.prototype.behaviors, { behaviors: _.extend({}, base.BlockView.prototype.behaviors, {
TextEditorBehavior: { TextEditorBehavior: {
toolbar1: "formatselect bold italic forecolor | link unlink", toolbar1: 'formatselect bold italic forecolor | link unlink',
toolbar2: "alignleft aligncenter alignright alignjustify | bullist numlist blockquote | code mailpoet_shortcodes", toolbar2: 'alignleft aligncenter alignright alignjustify | bullist numlist blockquote | code mailpoet_shortcodes',
validElements: "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]", validElements: '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]',
invalidElements: "script", invalidElements: 'script',
blockFormats: 'Heading 1=h1;Heading 2=h2;Heading 3=h3;Paragraph=p', blockFormats: 'Heading 1=h1;Heading 2=h2;Heading 3=h3;Paragraph=p',
plugins: "link lists code textcolor colorpicker mailpoet_shortcodes paste", plugins: 'link lists code textcolor colorpicker mailpoet_shortcodes paste',
configurationFilter: function (originalSettings) { configurationFilter: function (originalSettings) {
return _.extend({}, originalSettings, { return _.extend({}, originalSettings, {
mailpoet_shortcodes: App.getConfig().get('shortcodes').toJSON(), mailpoet_shortcodes: App.getConfig().get('shortcodes').toJSON(),
@ -78,11 +79,11 @@ define([
}); });
Module.TextBlockSettingsView = base.BlockSettingsView.extend({ Module.TextBlockSettingsView = base.BlockSettingsView.extend({
getTemplate: function() { return templates.textBlockSettings; } getTemplate: function () { return window.templates.textBlockSettings; }
}); });
Module.TextWidgetView = base.WidgetView.extend({ Module.TextWidgetView = base.WidgetView.extend({
getTemplate: function() { return templates.textInsertion; }, getTemplate: function () { return window.templates.textInsertion; },
behaviors: { behaviors: {
DraggableBehavior: { DraggableBehavior: {
cloneOriginal: true, cloneOriginal: true,
@ -93,7 +94,7 @@ define([
} }
}); });
App.on('before:start', function(App, options) { App.on('before:start', function (App) {
App.registerBlockType('text', { App.registerBlockType('text', {
blockModel: Module.TextBlockModel, blockModel: Module.TextBlockModel,
blockView: Module.TextBlockView blockView: Module.TextBlockView

View File

@ -7,15 +7,15 @@
*/ */
(function (root, factory) { (function (root, factory) {
var Marionette = require('backbone.marionette');
var Radio = require('backbone.radio');
var _ = require('underscore');
if (typeof define === 'function' && define.amd) { if (typeof define === 'function' && define.amd) {
define(['backbone.marionette', 'backbone.radio', 'underscore'], function (Marionette, Radio, _) { define(['backbone.marionette', 'backbone.radio', 'underscore'], function (Marionette, Radio, _) {
return factory(Marionette, Radio, _); return factory(Marionette, Radio, _);
}); });
} }
else if (typeof exports !== 'undefined') { else if (typeof exports !== 'undefined') {
var Marionette = require('backbone.marionette');
var Radio = require('backbone.radio');
var _ = require('underscore');
module.exports = factory(Marionette, Radio, _); module.exports = factory(Marionette, Radio, _);
} }
else { else {
@ -23,6 +23,7 @@
} }
}(this, function (Marionette, Radio, _) { }(this, function (Marionette, Radio, _) {
'use strict'; 'use strict';
var MarionetteApplication = Marionette.Application; var MarionetteApplication = Marionette.Application;
MarionetteApplication.prototype._initChannel = function () { MarionetteApplication.prototype._initChannel = function () {
this.channelName = _.result(this, 'channelName') || 'global'; this.channelName = _.result(this, 'channelName') || 'global';

View File

@ -98,7 +98,7 @@ define([
}); });
}; };
App.on('start', function(App, options) { App.on('start', function () {
// Prefetch post types // Prefetch post types
Module.getPostTypes(); Module.getPostTypes();
}); });

View File

@ -4,7 +4,7 @@ define([
'underscore', 'underscore',
'mailpoet' 'mailpoet'
], function (App, SuperModel, _, MailPoet) { ], function (App, SuperModel, _, MailPoet) {
"use strict"; 'use strict';
var Module = {}; var Module = {};
@ -13,7 +13,7 @@ define([
// handled by other components. // handled by other components.
Module.NewsletterModel = SuperModel.extend({ Module.NewsletterModel = SuperModel.extend({
whitelisted: ['id', 'subject', 'preheader'], whitelisted: ['id', 'subject', 'preheader'],
initialize: function(options) { initialize: function () {
this.on('change', function () { this.on('change', function () {
App.getChannel().trigger('autoSave'); App.getChannel().trigger('autoSave');
}); });
@ -34,14 +34,14 @@ define([
if (type in Module._blockTypes) { if (type in Module._blockTypes) {
return Module._blockTypes[type].blockModel; return Module._blockTypes[type].blockModel;
} else { } else {
throw "Block type not supported: " + type; throw 'Block type not supported: ' + type;
} }
}; };
Module.getBlockTypeView = function (type) { Module.getBlockTypeView = function (type) {
if (type in Module._blockTypes) { if (type in Module._blockTypes) {
return Module._blockTypes[type].blockView; return Module._blockTypes[type].blockView;
} else { } else {
throw "Block type not supported: " + type; throw 'Block type not supported: ' + type;
} }
}; };

View File

@ -3,15 +3,16 @@ define([
'backbone', 'backbone',
'backbone.marionette', 'backbone.marionette',
'underscore', 'underscore',
'jquery' 'jquery',
], function(App, Backbone, Marionette, _, jQuery) { 'mailpoet'
], function (App, Backbone, Marionette, _, jQuery, MailPoet) {
"use strict"; 'use strict';
var Module = {}; var Module = {};
Module.HeadingView = Marionette.View.extend({ Module.HeadingView = Marionette.View.extend({
getTemplate: function() { return templates.heading; }, getTemplate: function () { return window.templates.heading; },
templateContext: function () { templateContext: function () {
return { return {
model: this.model.toJSON() model: this.model.toJSON()
@ -19,8 +20,8 @@ define([
}, },
events: function () { events: function () {
return { return {
'keyup .mailpoet_input_title': _.partial(this.changeField, "subject"), 'keyup .mailpoet_input_title': _.partial(this.changeField, 'subject'),
'keyup .mailpoet_input_preheader': _.partial(this.changeField, "preheader") 'keyup .mailpoet_input_preheader': _.partial(this.changeField, 'preheader')
}; };
}, },
changeField: function (field, event) { changeField: function (field, event) {
@ -28,12 +29,12 @@ define([
} }
}); });
App.on('start', function(App, options) { App.on('start', function (App) {
App._appView.showChildView('headingRegion', new Module.HeadingView({ model: App.getNewsletter() })); App._appView.showChildView('headingRegion', new Module.HeadingView({ model: App.getNewsletter() }));
MailPoet.helpTooltip.show(document.getElementById('tooltip-designer-subject-line'), { MailPoet.helpTooltip.show(document.getElementById('tooltip-designer-subject-line'), {
tooltipId: 'tooltip-designer-subject-line-ti', tooltipId: 'tooltip-designer-subject-line-ti',
tooltip: MailPoet.I18n.t('helpTooltipDesignerSubjectLine'), tooltip: MailPoet.I18n.t('helpTooltipDesignerSubjectLine'),
place: "right" place: 'right'
}); });
MailPoet.helpTooltip.show(document.getElementById('tooltip-designer-preheader'), { MailPoet.helpTooltip.show(document.getElementById('tooltip-designer-preheader'), {
tooltipId: 'tooltip-designer-preheader-ti', tooltipId: 'tooltip-designer-preheader-ti',

View File

@ -8,7 +8,9 @@ define([
'jquery', 'jquery',
'blob', 'blob',
'file-saver', 'file-saver',
'html2canvas' 'html2canvas',
'underscore',
'jquery'
], function ( ], function (
App, App,
CommunicationComponent, CommunicationComponent,
@ -19,13 +21,15 @@ define([
jQuery, jQuery,
Blob, Blob,
FileSaver, FileSaver,
html2canvas html2canvas,
_,
$
) { ) {
"use strict"; 'use strict';
var Module = {}, var Module = {};
saveTimeout; var saveTimeout;
// Save editor contents to server // Save editor contents to server
Module.save = function () { Module.save = function () {
@ -65,15 +69,6 @@ define([
}); });
}; };
// For getting a promise after triggering save event
Module.saveAndProvidePromise = function(saveResult) {
var result = saveResult;
var promise = Module.save();
if (saveResult !== undefined) {
result.promise = promise;
}
};
Module.getThumbnail = function (element, options) { Module.getThumbnail = function (element, options) {
var promise = html2canvas(element, options || {}); var promise = html2canvas(element, options || {});
@ -81,10 +76,9 @@ define([
// Temporary workaround for html2canvas-alpha2. // Temporary workaround for html2canvas-alpha2.
// Removes 1px left transparent border from resulting canvas. // Removes 1px left transparent border from resulting canvas.
var oldContext = oldCanvas.getContext('2d'), var newCanvas = document.createElement('canvas');
newCanvas = document.createElement("canvas"), var newContext = newCanvas.getContext('2d');
newContext = newCanvas.getContext("2d"), var leftBorderWidth = 1;
leftBorderWidth = 1;
newCanvas.width = oldCanvas.width; newCanvas.width = oldCanvas.width;
newCanvas.height = oldCanvas.height; newCanvas.height = oldCanvas.height;
@ -100,8 +94,7 @@ define([
}; };
Module.saveTemplate = function (options) { Module.saveTemplate = function (options) {
var that = this, var promise = jQuery.Deferred();
promise = jQuery.Deferred();
promise.then(function (thumbnail) { promise.then(function (thumbnail) {
var data = _.extend(options || {}, { var data = _.extend(options || {}, {
@ -127,7 +120,6 @@ define([
}; };
Module.exportTemplate = function (options) { Module.exportTemplate = function (options) {
var that = this;
return Module.getThumbnail( return Module.getThumbnail(
jQuery('#mailpoet_editor_content > .mailpoet_block').get(0) jQuery('#mailpoet_editor_content > .mailpoet_block').get(0)
).then(function (thumbnail) { ).then(function (thumbnail) {
@ -148,7 +140,7 @@ define([
}; };
Module.SaveView = Marionette.View.extend({ Module.SaveView = Marionette.View.extend({
getTemplate: function() { return templates.save; }, getTemplate: function () { return window.templates.save; },
events: { events: {
'click .mailpoet_save_button': 'save', 'click .mailpoet_save_button': 'save',
'click .mailpoet_save_show_options': 'toggleSaveOptions', 'click .mailpoet_save_show_options': 'toggleSaveOptions',
@ -160,7 +152,7 @@ define([
'click .mailpoet_save_export': 'toggleExportTemplate', 'click .mailpoet_save_export': 'toggleExportTemplate',
'click .mailpoet_export_template': 'exportTemplate' 'click .mailpoet_export_template': 'exportTemplate'
}, },
initialize: function(options) { initialize: function () {
App.getChannel().on('beforeEditorSave', this.beforeSave, this); App.getChannel().on('beforeEditorSave', this.beforeSave, this);
App.getChannel().on('afterEditorSave', this.afterSave, this); App.getChannel().on('afterEditorSave', this.afterSave, this);
}, },
@ -169,13 +161,13 @@ define([
}, },
save: function () { save: function () {
this.hideOptionContents(); this.hideOptionContents();
App.getChannel().trigger('save'); App.getChannel().request('save');
}, },
beforeSave: function () { beforeSave: function () {
// TODO: Add a loading animation instead // TODO: Add a loading animation instead
this.$('.mailpoet_autosaved_at').text(MailPoet.I18n.t('saving')); this.$('.mailpoet_autosaved_at').text(MailPoet.I18n.t('saving'));
}, },
afterSave: function(json, response) { afterSave: function (json) {
this.validateNewsletter(json); this.validateNewsletter(json);
// Update 'Last saved timer' // Update 'Last saved timer'
this.$('.mailpoet_editor_last_saved').removeClass('mailpoet_hidden'); this.$('.mailpoet_editor_last_saved').removeClass('mailpoet_hidden');
@ -197,9 +189,9 @@ define([
this.$('.mailpoet_save_as_template_container').addClass('mailpoet_hidden'); this.$('.mailpoet_save_as_template_container').addClass('mailpoet_hidden');
}, },
saveAsTemplate: function () { saveAsTemplate: function () {
var templateName = this.$('.mailpoet_save_as_template_name').val(), var templateName = this.$('.mailpoet_save_as_template_name').val();
templateDescription = this.$('.mailpoet_save_as_template_description').val(), var templateDescription = this.$('.mailpoet_save_as_template_description').val();
that = this; var that = this;
if (templateName === '') { if (templateName === '') {
MailPoet.Notice.error( MailPoet.Notice.error(
@ -253,9 +245,9 @@ define([
this.$('.mailpoet_export_template_container').addClass('mailpoet_hidden'); this.$('.mailpoet_export_template_container').addClass('mailpoet_hidden');
}, },
exportTemplate: function () { exportTemplate: function () {
var templateName = this.$('.mailpoet_export_template_name').val(), var templateName = this.$('.mailpoet_export_template_name').val();
templateDescription = this.$('.mailpoet_export_template_description').val(), var templateDescription = this.$('.mailpoet_export_template_description').val();
that = this; var that = this;
if (templateName === '') { if (templateName === '') {
MailPoet.Notice.error( MailPoet.Notice.error(
@ -289,19 +281,23 @@ define([
next: function () { next: function () {
this.hideOptionContents(); this.hideOptionContents();
if (!this.$('.mailpoet_save_next').hasClass('button-disabled')) { if (!this.$('.mailpoet_save_next').hasClass('button-disabled')) {
Module._cancelAutosave();
Module.save().done(function () {
window.location.href = App.getConfig().get('urls.send'); window.location.href = App.getConfig().get('urls.send');
});
} }
}, },
validateNewsletter: function (jsonObject) { validateNewsletter: function (jsonObject) {
var contents;
if (!App._contentContainer.isValid()) { if (!App._contentContainer.isValid()) {
this.showValidationError(App._contentContainer.validationError); this.showValidationError(App._contentContainer.validationError);
return; return;
} }
var contents = JSON.stringify(jsonObject); contents = JSON.stringify(jsonObject);
if (App.getConfig().get('validation.validateUnsubscribeLinkPresent') && if (App.getConfig().get('validation.validateUnsubscribeLinkPresent') &&
contents.indexOf("[link:subscription_unsubscribe_url]") < 0 && contents.indexOf('[link:subscription_unsubscribe_url]') < 0 &&
contents.indexOf("[link:subscription_unsubscribe]") < 0) { contents.indexOf('[link:subscription_unsubscribe]') < 0) {
this.showValidationError(MailPoet.I18n.t('unsubscribeLinkMissing')); this.showValidationError(MailPoet.I18n.t('unsubscribeLinkMissing'));
return; return;
} }
@ -326,19 +322,27 @@ define([
// may be requested // may be requested
var AUTOSAVE_DELAY_DURATION = 1000; var AUTOSAVE_DELAY_DURATION = 1000;
// Cancel save timer if another change happens before it completes Module._cancelAutosave();
if (saveTimeout) clearTimeout(saveTimeout);
saveTimeout = setTimeout(function () { saveTimeout = setTimeout(function () {
App.getChannel().trigger('save'); App.getChannel().request('save').always(function () {
clearTimeout(saveTimeout); Module._cancelAutosave();
saveTimeout = undefined; });
}, AUTOSAVE_DELAY_DURATION); }, AUTOSAVE_DELAY_DURATION);
}; };
Module._cancelAutosave = function () {
if (!saveTimeout) return;
clearTimeout(saveTimeout);
saveTimeout = undefined;
};
Module.beforeExitWithUnsavedChanges = function (e) { Module.beforeExitWithUnsavedChanges = function (e) {
var message;
var event;
if (saveTimeout) { if (saveTimeout) {
var message = MailPoet.I18n.t('unsavedChangesWillBeLost'); message = MailPoet.I18n.t('unsavedChangesWillBeLost');
var event = e || window.event; event = e || window.event;
if (event) { if (event) {
event.returnValue = message; event.returnValue = message;
@ -348,17 +352,17 @@ define([
} }
}; };
App.on('before:start', function(App, options) { App.on('before:start', function (App) {
var Application = App; var Application = App;
Application.save = Module.saveAndProvidePromise; Application.save = Module.save;
Application.getChannel().on('autoSave', Module.autoSave); Application.getChannel().on('autoSave', Module.autoSave);
window.onbeforeunload = Module.beforeExitWithUnsavedChanges; window.onbeforeunload = Module.beforeExitWithUnsavedChanges;
Application.getChannel().on('save', function(saveResult) { Application.save(saveResult); }); Application.getChannel().reply('save', Application.save);
}); });
App.on('start', function(App, options) { App.on('start', function (App) {
var saveView = new Module.SaveView(); var saveView = new Module.SaveView();
App._appView.showChildView('bottomRegion', saveView); App._appView.showChildView('bottomRegion', saveView);
}); });

View File

@ -6,8 +6,7 @@ define([
'backbone.marionette', 'backbone.marionette',
'backbone.supermodel', 'backbone.supermodel',
'underscore', 'underscore',
'jquery', 'jquery'
'sticky-kit'
], function ( ], function (
App, App,
CommunicationComponent, CommunicationComponent,
@ -16,14 +15,13 @@ define([
Marionette, Marionette,
SuperModel, SuperModel,
_, _,
jQuery, jQuery
StickyKit
) { ) {
"use strict"; 'use strict';
var Module = {}; var Module = {};
var SidebarView;
// Widget handlers for use to create new content blocks via drag&drop // Widget handlers for use to create new content blocks via drag&drop
Module._contentWidgets = new (Backbone.Collection.extend({ Module._contentWidgets = new (Backbone.Collection.extend({
model: SuperModel.extend({ model: SuperModel.extend({
@ -52,8 +50,8 @@ define([
Module.registerLayoutWidget = function (widget) { return Module._layoutWidgets.add(widget); }; Module.registerLayoutWidget = function (widget) { return Module._layoutWidgets.add(widget); };
Module.getLayoutWidgets = function () { return Module._layoutWidgets; }; Module.getLayoutWidgets = function () { return Module._layoutWidgets; };
var SidebarView = Marionette.View.extend({ SidebarView = Marionette.View.extend({
getTemplate: function() { return templates.sidebar; }, getTemplate: function () { return window.templates.sidebar; },
regions: { regions: {
contentRegion: '.mailpoet_content_region', contentRegion: '.mailpoet_content_region',
layoutRegion: '.mailpoet_layout_region', layoutRegion: '.mailpoet_layout_region',
@ -62,14 +60,14 @@ define([
}, },
events: { events: {
'click .mailpoet_sidebar_region h3, .mailpoet_sidebar_region .handlediv': function (event) { 'click .mailpoet_sidebar_region h3, .mailpoet_sidebar_region .handlediv': function (event) {
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'); var $targetRegion = this.$el.find(event.target).closest('.mailpoet_sidebar_region');
$openRegion.find('.mailpoet_region_content').velocity( $openRegion.find('.mailpoet_region_content').velocity(
'slideUp', 'slideUp',
{ {
duration: 250, duration: 250,
easing: "easeOut", easing: 'easeOut',
complete: function () { complete: function () {
$openRegion.addClass('closed'); $openRegion.addClass('closed');
}.bind(this) }.bind(this)
@ -81,7 +79,7 @@ define([
'slideDown', 'slideDown',
{ {
duration: 250, duration: 250,
easing: "easeIn", easing: 'easeIn',
complete: function () { complete: function () {
$targetRegion.removeClass('closed'); $targetRegion.removeClass('closed');
} }
@ -90,7 +88,7 @@ define([
} }
} }
}, },
initialize: function(options) { initialize: function () {
jQuery(window) jQuery(window)
.on('resize', this.updateHorizontalScroll.bind(this)) .on('resize', this.updateHorizontalScroll.bind(this))
.on('scroll', this.updateHorizontalScroll.bind(this)); .on('scroll', this.updateHorizontalScroll.bind(this));
@ -113,9 +111,8 @@ define([
// position of the sidebar would be scrollable and not fixed // position of the sidebar would be scrollable and not fixed
// partially out of visible screen // partially out of visible screen
this.$el.parent().each(function () { this.$el.parent().each(function () {
var calculated_left, self; var calculated_left;
var self = jQuery(this);
self = jQuery(this);
if (self.css('position') === 'fixed') { if (self.css('position') === 'fixed') {
calculated_left = self.parent().offset().left - jQuery(window).scrollLeft(); calculated_left = self.parent().offset().left - jQuery(window).scrollLeft();
@ -147,7 +144,7 @@ define([
* Responsible for rendering draggable content widgets * Responsible for rendering draggable content widgets
*/ */
Module.SidebarWidgetsView = Marionette.View.extend({ Module.SidebarWidgetsView = Marionette.View.extend({
getTemplate: function() { return templates.sidebarContent; }, getTemplate: function () { return window.templates.sidebarContent; },
regions: { regions: {
widgets: '.mailpoet_region_content' widgets: '.mailpoet_region_content'
}, },
@ -167,53 +164,53 @@ define([
* Responsible for rendering draggable layout widgets * Responsible for rendering draggable layout widgets
*/ */
Module.SidebarLayoutWidgetsView = Module.SidebarWidgetsView.extend({ Module.SidebarLayoutWidgetsView = Module.SidebarWidgetsView.extend({
getTemplate: function() { return templates.sidebarLayout; } getTemplate: function () { return window.templates.sidebarLayout; }
}); });
/** /**
* Responsible for managing global styles * Responsible for managing global styles
*/ */
Module.SidebarStylesView = Marionette.View.extend({ Module.SidebarStylesView = Marionette.View.extend({
getTemplate: function() { return templates.sidebarStyles; }, getTemplate: function () { return window.templates.sidebarStyles; },
behaviors: { behaviors: {
ColorPickerBehavior: {} ColorPickerBehavior: {}
}, },
events: function () { events: function () {
return { return {
"change #mailpoet_text_font_color": _.partial(this.changeColorField, 'text.fontColor'), 'change #mailpoet_text_font_color': _.partial(this.changeColorField, 'text.fontColor'),
"change #mailpoet_text_font_family": function(event) { 'change #mailpoet_text_font_family': function (event) {
this.model.set('text.fontFamily', event.target.value); this.model.set('text.fontFamily', event.target.value);
}, },
"change #mailpoet_text_font_size": function(event) { 'change #mailpoet_text_font_size': function (event) {
this.model.set('text.fontSize', event.target.value); this.model.set('text.fontSize', event.target.value);
}, },
"change #mailpoet_h1_font_color": _.partial(this.changeColorField, 'h1.fontColor'), 'change #mailpoet_h1_font_color': _.partial(this.changeColorField, 'h1.fontColor'),
"change #mailpoet_h1_font_family": function(event) { 'change #mailpoet_h1_font_family': function (event) {
this.model.set('h1.fontFamily', event.target.value); this.model.set('h1.fontFamily', event.target.value);
}, },
"change #mailpoet_h1_font_size": function(event) { 'change #mailpoet_h1_font_size': function (event) {
this.model.set('h1.fontSize', event.target.value); this.model.set('h1.fontSize', event.target.value);
}, },
"change #mailpoet_h2_font_color": _.partial(this.changeColorField, 'h2.fontColor'), 'change #mailpoet_h2_font_color': _.partial(this.changeColorField, 'h2.fontColor'),
"change #mailpoet_h2_font_family": function(event) { 'change #mailpoet_h2_font_family': function (event) {
this.model.set('h2.fontFamily', event.target.value); this.model.set('h2.fontFamily', event.target.value);
}, },
"change #mailpoet_h2_font_size": function(event) { 'change #mailpoet_h2_font_size': function (event) {
this.model.set('h2.fontSize', event.target.value); this.model.set('h2.fontSize', event.target.value);
}, },
"change #mailpoet_h3_font_color": _.partial(this.changeColorField, 'h3.fontColor'), 'change #mailpoet_h3_font_color': _.partial(this.changeColorField, 'h3.fontColor'),
"change #mailpoet_h3_font_family": function(event) { 'change #mailpoet_h3_font_family': function (event) {
this.model.set('h3.fontFamily', event.target.value); this.model.set('h3.fontFamily', event.target.value);
}, },
"change #mailpoet_h3_font_size": function(event) { 'change #mailpoet_h3_font_size': function (event) {
this.model.set('h3.fontSize', event.target.value); this.model.set('h3.fontSize', event.target.value);
}, },
"change #mailpoet_a_font_color": _.partial(this.changeColorField, 'link.fontColor'), 'change #mailpoet_a_font_color': _.partial(this.changeColorField, 'link.fontColor'),
"change #mailpoet_a_font_underline": function(event) { 'change #mailpoet_a_font_underline': function (event) {
this.model.set('link.textDecoration', (event.target.checked) ? event.target.value : 'none'); this.model.set('link.textDecoration', (event.target.checked) ? event.target.value : 'none');
}, },
"change #mailpoet_newsletter_background_color": _.partial(this.changeColorField, 'wrapper.backgroundColor'), 'change #mailpoet_newsletter_background_color': _.partial(this.changeColorField, 'wrapper.backgroundColor'),
"change #mailpoet_background_color": _.partial(this.changeColorField, 'body.backgroundColor') 'change #mailpoet_background_color': _.partial(this.changeColorField, 'body.backgroundColor')
}; };
}, },
templateContext: function () { templateContext: function () {
@ -238,7 +235,7 @@ define([
}); });
Module.SidebarPreviewView = Marionette.View.extend({ Module.SidebarPreviewView = Marionette.View.extend({
getTemplate: function() { return templates.sidebarPreview; }, getTemplate: function () { return window.templates.sidebarPreview; },
events: { events: {
'click .mailpoet_show_preview': 'showPreview', 'click .mailpoet_show_preview': 'showPreview',
'click #mailpoet_send_preview': 'sendPreview' 'click #mailpoet_send_preview': 'sendPreview'
@ -271,7 +268,7 @@ define([
previewUrl: response.meta.preview_url previewUrl: response.meta.preview_url
}); });
var view = this.previewView.render(); this.previewView.render();
this.previewView.$el.css('height', '100%'); this.previewView.$el.css('height', '100%');
MailPoet.Modal.popup({ MailPoet.Modal.popup({
@ -321,13 +318,10 @@ define([
MailPoet.Modal.loading(true); MailPoet.Modal.loading(true);
// save before sending // save before sending
var saveResult = {promise: null}; App.getChannel().request('save').always(function () {
App.getChannel().trigger('save', saveResult);
saveResult.promise.always(function() {
CommunicationComponent.previewNewsletter(data).always(function () { CommunicationComponent.previewNewsletter(data).always(function () {
MailPoet.Modal.loading(false); MailPoet.Modal.loading(false);
}).done(function(response) { }).done(function () {
MailPoet.Notice.success( MailPoet.Notice.success(
MailPoet.I18n.t('newsletterPreviewSent'), MailPoet.I18n.t('newsletterPreviewSent'),
{ scroll: true } { scroll: true }
@ -349,7 +343,7 @@ define([
}); });
Module.NewsletterPreviewView = Marionette.View.extend({ Module.NewsletterPreviewView = Marionette.View.extend({
getTemplate: function() { return templates.newsletterPreview; }, getTemplate: function () { return window.templates.newsletterPreview; },
initialize: function (options) { initialize: function (options) {
this.previewUrl = options.previewUrl; this.previewUrl = options.previewUrl;
this.width = '100%'; this.width = '100%';
@ -366,7 +360,7 @@ define([
} }
}); });
App.on('before:start', function(App, options) { App.on('before:start', function (App) {
var Application = App; var Application = App;
Application.registerWidget = Module.registerWidget; Application.registerWidget = Module.registerWidget;
Application.getWidgets = Module.getWidgets; Application.getWidgets = Module.getWidgets;
@ -374,9 +368,8 @@ define([
Application.getLayoutWidgets = Module.getLayoutWidgets; Application.getLayoutWidgets = Module.getLayoutWidgets;
}); });
App.on('start', function(App, options) { App.on('start', function (App) {
var stylesModel = App.getGlobalStyles(), var sidebarView = new SidebarView();
sidebarView = new SidebarView();
App._appView.showChildView('sidebarRegion', sidebarView); App._appView.showChildView('sidebarRegion', sidebarView);

View File

@ -1,10 +1,11 @@
define([ define([
'newsletter_editor/App', 'newsletter_editor/App',
'backbone.marionette', 'backbone.marionette',
'backbone.supermodel' 'backbone.supermodel',
], function(App, Marionette, SuperModel) { 'underscore'
], function (App, Marionette, SuperModel, _) {
"use strict"; 'use strict';
var Module = {}; var Module = {};
@ -47,9 +48,9 @@ define([
}); });
Module.StylesView = Marionette.View.extend({ Module.StylesView = Marionette.View.extend({
getTemplate: function() { return templates.styles; }, getTemplate: function () { return window.templates.styles; },
modelEvents: { modelEvents: {
'change': 'render' change: 'render'
}, },
serializeData: function () { serializeData: function () {
return this.model.toJSON(); return this.model.toJSON();
@ -70,17 +71,19 @@ define([
App.on('before:start', function (App, options) { App.on('before:start', function (App, options) {
var Application = App; var Application = App;
var body;
var globalStyles;
// Expose style methods to global application // Expose style methods to global application
Application.getGlobalStyles = Module.getGlobalStyles; Application.getGlobalStyles = Module.getGlobalStyles;
Application.setGlobalStyles = Module.setGlobalStyles; Application.setGlobalStyles = Module.setGlobalStyles;
Application.getAvailableStyles = Module.getAvailableStyles; Application.getAvailableStyles = Module.getAvailableStyles;
var body = options.newsletter.body; body = options.newsletter.body;
var globalStyles = (_.has(body, 'globalStyles')) ? body.globalStyles : {}; globalStyles = (_.has(body, 'globalStyles')) ? body.globalStyles : {};
this.setGlobalStyles(globalStyles); this.setGlobalStyles(globalStyles);
}); });
App.on('start', function(App, options) { App.on('start', function (App) {
var stylesView = new Module.StylesView({ model: App.getGlobalStyles() }); var stylesView = new Module.StylesView({ model: App.getGlobalStyles() });
App._appView.showChildView('stylesRegion', stylesView); App._appView.showChildView('stylesRegion', stylesView);
}); });

View File

@ -10,12 +10,12 @@
/* jshint unused:false */ /* jshint unused:false */
/* global tinymce:true */ /* global tinymce:true */
tinymce.PluginManager.add('mailpoet_shortcodes', function(editor, url) { tinymce.PluginManager.add('mailpoet_shortcodes', function (editor) {
var appendLabelAndClose = function (shortcode) { var appendLabelAndClose = function (shortcode) {
editor.insertContent(shortcode); editor.insertContent(shortcode);
editor.windowManager.close(); editor.windowManager.close();
}, };
generateOnClickFunc = function(shortcode) { var generateOnClickFunc = function (shortcode) {
return function () { return function () {
appendLabelAndClose(shortcode); appendLabelAndClose(shortcode);
}; };
@ -24,17 +24,19 @@ tinymce.PluginManager.add('mailpoet_shortcodes', function(editor, url) {
editor.addButton('mailpoet_shortcodes', { editor.addButton('mailpoet_shortcodes', {
icon: 'mailpoet_shortcodes', icon: 'mailpoet_shortcodes',
onclick: function () { onclick: function () {
var shortcodes = [], var shortcodes = [];
configShortcodes = editor.settings.mailpoet_shortcodes; var configShortcodes = editor.settings.mailpoet_shortcodes;
var segment;
var i;
for (var segment in configShortcodes) { for (segment in configShortcodes) {
if (configShortcodes.hasOwnProperty(segment)) { if (configShortcodes.hasOwnProperty(segment)) {
shortcodes.push({ shortcodes.push({
type: 'label', type: 'label',
text: segment text: segment
}); });
for (var i = 0; i < configShortcodes[segment].length; i += 1) { for (i = 0; i < configShortcodes[segment].length; i += 1) {
shortcodes.push({ shortcodes.push({
type: 'button', type: 'button',
text: configShortcodes[segment][i].text, text: configShortcodes[segment][i].text,
@ -46,8 +48,8 @@ tinymce.PluginManager.add('mailpoet_shortcodes', function(editor, url) {
// Open window // Open window
editor.windowManager.open({ editor.windowManager.open({
height: parseInt(editor.getParam("plugin_mailpoet_shortcodes_height", 400)), height: parseInt(editor.getParam('plugin_mailpoet_shortcodes_height', 400)),
width: parseInt(editor.getParam("plugin_mailpoet_shortcodes_width", 450)), width: parseInt(editor.getParam('plugin_mailpoet_shortcodes_width', 450)),
autoScroll: true, autoScroll: true,
title: editor.settings.mailpoet_shortcodes_window_title, title: editor.settings.mailpoet_shortcodes_window_title,
body: shortcodes, body: shortcodes,

View File

@ -1,27 +0,0 @@
/**
* A sample implementation of template widgets.
* A draggable widget, on drop creates a container with (image|text) block.
*/
ImageAndTextTemplateWidgetView = EditorApplication.module('blocks.base').WidgetView.extend({
getTemplate: function() { return templates.imageAndTextInsertion; },
className: 'mailpoet_droppable_block mailpoet_droppable_widget',
behaviors: {
DraggableBehavior: {
drop: function() {
return new (EditorApplication.getBlockTypeModel('container'))({
type: 'container',
orientation: 'horizontal',
blocks: [
{
type: 'image'
},
{
type: 'text',
text: 'Some random text'
}
]
}, {parse: true});
}
}
}
});

View File

@ -49,7 +49,7 @@ const stats = {
}; };
class StatsBadge extends React.Component { class StatsBadge extends React.Component {
getBadgeType(stat, rate) { static getBadgeType(stat, rate) {
const len = stat.badgeRanges.length; const len = stat.badgeRanges.length;
for (let i = 0; i < len; i += 1) { for (let i = 0; i < len; i += 1) {
if (rate > stat.badgeRanges[i]) { if (rate > stat.badgeRanges[i]) {
@ -70,7 +70,7 @@ class StatsBadge extends React.Component {
return null; return null;
} }
const badgeType = this.getBadgeType(stat, rate); const badgeType = StatsBadge.getBadgeType(stat, rate);
const badge = badges[badgeType] || null; const badge = badges[badgeType] || null;
if (!badge) { if (!badge) {
return null; return null;

View File

@ -41,12 +41,12 @@ define(
render: function () { render: function () {
const steps = this.state.steps.map((step, index) => { const steps = this.state.steps.map((step, index) => {
const stepClasses = classNames( const stepClasses = classNames(
{ 'mailpoet_current': (this.props.step === step.name) } { mailpoet_current: (this.props.step === step.name) }
); );
let label = step.label; let label = step.label;
if(step['link'] !== undefined && this.props.step !== step.name) { if (step.link !== undefined && this.props.step !== step.name) {
label = ( label = (
<Link to={step.link}>{ step.label }</Link> <Link to={step.link}>{ step.label }</Link>
); );

View File

@ -9,7 +9,7 @@ import jQuery from 'jquery';
import Hooks from 'wp-js-hooks'; import Hooks from 'wp-js-hooks';
import StatsBadge from 'newsletters/badges/stats.jsx'; import StatsBadge from 'newsletters/badges/stats.jsx';
const _QueueMixin = { const QueueMixin = {
pauseSending: function (newsletter) { pauseSending: function (newsletter) {
MailPoet.Ajax.post({ MailPoet.Ajax.post({
api_version: window.mailpoet_api_version, api_version: window.mailpoet_api_version,
@ -59,7 +59,7 @@ const _QueueMixin = {
return ( return (
<span>{MailPoet.I18n.t('paused')}</span> <span>{MailPoet.I18n.t('paused')}</span>
); );
} else { }
if (newsletter.queue.status === 'scheduled') { if (newsletter.queue.status === 'scheduled') {
return ( return (
<span> <span>
@ -69,7 +69,7 @@ const _QueueMixin = {
} }
const progressClasses = classNames( const progressClasses = classNames(
'mailpoet_progress', 'mailpoet_progress',
{ 'mailpoet_progress_complete': newsletter.queue.status === 'completed' } { mailpoet_progress_complete: newsletter.queue.status === 'completed' }
); );
// calculate percentage done // calculate percentage done
@ -84,8 +84,8 @@ const _QueueMixin = {
<span> <span>
{ {
MailPoet.I18n.t('newsletterQueueCompleted') MailPoet.I18n.t('newsletterQueueCompleted')
.replace("%$1d", newsletter.queue.count_processed) .replace('%$1d', parseInt(newsletter.queue.count_processed, 10).toLocaleString())
.replace("%$2d", newsletter.queue.count_total) .replace('%$2d', parseInt(newsletter.queue.count_total, 10).toLocaleString())
} }
</span> </span>
); );
@ -120,7 +120,7 @@ const _QueueMixin = {
percentage = MailPoet.I18n.t('noSubscribers'); percentage = MailPoet.I18n.t('noSubscribers');
} else { } else {
progress_bar_width = percentage; progress_bar_width = percentage;
percentage += "%"; percentage += '%';
} }
return ( return (
@ -128,7 +128,7 @@ const _QueueMixin = {
<div className={progressClasses}> <div className={progressClasses}>
<span <span
className="mailpoet_progress_bar" className="mailpoet_progress_bar"
style={ { width: progress_bar_width + "%" } } style={{ width: progress_bar_width + '%' }}
></span> ></span>
<span className="mailpoet_progress_label"> <span className="mailpoet_progress_label">
{ percentage } { percentage }
@ -139,11 +139,17 @@ const _QueueMixin = {
</p> </p>
</div> </div>
); );
}
}, },
}; };
const _StatisticsMixin = { const trackStatsCTAClicked = function () {
MailPoet.trackEvent(
'User has clicked a CTA to view detailed stats',
{ 'MailPoet Free version': window.mailpoet_version }
);
};
const StatisticsMixin = {
renderStatistics: function (newsletter, is_sent, current_time) { renderStatistics: function (newsletter, is_sent, current_time) {
let sent = is_sent; let sent = is_sent;
if (sent === undefined) { if (sent === undefined) {
@ -159,6 +165,7 @@ const _StatisticsMixin = {
} }
let params = {}; let params = {};
Hooks.addFilter('mailpoet_newsletters_listing_stats_before', this.addStatsCTALink);
params = Hooks.applyFilters('mailpoet_newsletters_listing_stats_before', params, newsletter); params = Hooks.applyFilters('mailpoet_newsletters_listing_stats_before', params, newsletter);
// welcome emails provide explicit total_sent value // welcome emails provide explicit total_sent value
@ -179,11 +186,11 @@ const _StatisticsMixin = {
const percentage_opened_display = MailPoet.Num.toLocaleFixed(percentage_opened, 1); const percentage_opened_display = MailPoet.Num.toLocaleFixed(percentage_opened, 1);
const percentage_unsubscribed_display = MailPoet.Num.toLocaleFixed(percentage_unsubscribed, 1); const percentage_unsubscribed_display = MailPoet.Num.toLocaleFixed(percentage_unsubscribed, 1);
let show_stats_timeout, let show_stats_timeout;
newsletter_date, let newsletter_date;
sent_hours_ago, let sent_hours_ago;
too_early_for_stats, let too_early_for_stats;
show_kb_link; let show_kb_link;
if (current_time !== undefined) { if (current_time !== undefined) {
// standard emails and post notifications: // standard emails and post notifications:
// display green box for newsletters that were just sent // display green box for newsletters that were just sent
@ -239,7 +246,7 @@ const _StatisticsMixin = {
<div> <div>
<span className="mailpoet_stats_text"> <span className="mailpoet_stats_text">
{ percentage_opened_display }%, { percentage_opened_display }%,
{ " " } { ' ' }
{ percentage_clicked_display }% { percentage_clicked_display }%
<span className="mailpoet_stat_hidden"> <span className="mailpoet_stat_hidden">
, { percentage_unsubscribed_display }% , { percentage_unsubscribed_display }%
@ -282,6 +289,20 @@ const _StatisticsMixin = {
if (total_sent > 0 && params.link) { if (total_sent > 0 && params.link) {
// wrap content in a link // wrap content in a link
if (params.externalLink) {
return (
<div>
<a
key={`stats-${newsletter.id}`}
href={params.link}
onClick={params.onClick || null}
>
{content}
</a>
{after_content}
</div>
);
}
return ( return (
<div> <div>
<Link <Link
@ -303,9 +324,40 @@ const _StatisticsMixin = {
</div> </div>
); );
}, },
addStatsCTAAction: function (actions) {
if (window.mailpoet_premium_active) {
return actions;
}
actions.unshift({
name: 'stats',
link: function () {
return (
<a href={'admin.php?page=mailpoet-premium'} onClick={trackStatsCTAClicked}>
{MailPoet.I18n.t('statsListingActionTitle')}
</a>
);
},
display: function (newsletter) {
// welcome emails provide explicit total_sent value
const count_processed = newsletter.queue && newsletter.queue.count_processed;
return ~~(newsletter.total_sent || count_processed) > 0;
},
});
return actions;
},
addStatsCTALink: function (params) {
if (window.mailpoet_premium_active) {
return params;
}
const newParams = params;
newParams.link = 'admin.php?page=mailpoet-premium';
newParams.externalLink = true;
newParams.onClick = trackStatsCTAClicked;
return newParams;
},
}; };
const _MailerMixin = { const MailerMixin = {
checkMailerStatus: function (state) { checkMailerStatus: function (state) {
if (state.meta.mta_log.error && state.meta.mta_log.status === 'paused') { if (state.meta.mta_log.error && state.meta.mta_log.status === 'paused') {
MailPoet.Notice.error( MailPoet.Notice.error(
@ -327,7 +379,7 @@ const _MailerMixin = {
MailPoet.I18n.t('mailerCheckSettingsNotice'), MailPoet.I18n.t('mailerCheckSettingsNotice'),
/\[link\](.*?)\[\/link\]/g, /\[link\](.*?)\[\/link\]/g,
match => ( match => (
<a href={`?page=mailpoet-settings#mta`}>{ match }</a> <a href={'?page=mailpoet-settings#mta'} key="check-sending">{ match }</a>
) )
); );
if (state.meta.mta_log.error.operation === 'send') { if (state.meta.mta_log.error.operation === 'send') {
@ -374,8 +426,6 @@ const _MailerMixin = {
}; };
export { QueueMixin };
export { StatisticsMixin };
export { _QueueMixin as QueueMixin }; export { MailerMixin };
export { _StatisticsMixin as StatisticsMixin };
export { _MailerMixin as MailerMixin };

View File

@ -185,7 +185,7 @@ const NewsletterListNotification = React.createClass({
return ( return (
<select <select
data-id={newsletter.id} data-id={newsletter.id}
defaultValue={ newsletter.status } defaultValue={newsletter.status}
onChange={this.updateStatus} onChange={this.updateStatus}
> >
<option value="active">{ MailPoet.I18n.t('active') }</option> <option value="active">{ MailPoet.I18n.t('active') }</option>
@ -195,12 +195,14 @@ const NewsletterListNotification = React.createClass({
}, },
renderSettings: function (newsletter) { renderSettings: function (newsletter) {
let sendingFrequency; let sendingFrequency;
let sendingToSegments;
// get list of segments' name // get list of segments' name
const segments = newsletter.segments.map((segment) => { const segments = newsletter.segments.map((segment) => {
return segment.name; return segment.name;
}); });
const sendingToSegments = MailPoet.I18n.t('ifNewContentToSegments').replace(
'%$1s', segments.join(', ')
);
// check if the user has specified segments to send to // check if the user has specified segments to send to
if (segments.length === 0) { if (segments.length === 0) {
@ -209,10 +211,7 @@ const NewsletterListNotification = React.createClass({
{ MailPoet.I18n.t('sendingToSegmentsNotSpecified') } { MailPoet.I18n.t('sendingToSegmentsNotSpecified') }
</span> </span>
); );
} else { }
sendingToSegments = MailPoet.I18n.t('ifNewContentToSegments').replace(
'%$1s', segments.join(', ')
);
// set sending frequency // set sending frequency
switch (newsletter.options.intervalType) { switch (newsletter.options.intervalType) {
@ -252,7 +251,7 @@ const NewsletterListNotification = React.createClass({
sendingFrequency = MailPoet.I18n.t('sendImmediately'); sendingFrequency = MailPoet.I18n.t('sendImmediately');
break; break;
} }
}
return ( return (
<span> <span>
@ -266,13 +265,12 @@ const NewsletterListNotification = React.createClass({
return ( return (
MailPoet.I18n.t('notSentYet') MailPoet.I18n.t('notSentYet')
); );
} else { }
return ( return (
<Link <Link
to={`/notification/history/${newsletter.id}`} to={`/notification/history/${newsletter.id}`}
>{ MailPoet.I18n.t('viewHistory') }</Link> >{ MailPoet.I18n.t('viewHistory') }</Link>
); );
}
}, },
renderItem: function (newsletter, actions) { renderItem: function (newsletter, actions) {
const rowClasses = classNames( const rowClasses = classNames(
@ -311,13 +309,13 @@ const NewsletterListNotification = React.createClass({
return ( return (
<div> <div>
<h1 className="title"> <h1 className="title">
{MailPoet.I18n.t('pageTitle')} <Link className="page-title-action" to="/new">{MailPoet.I18n.t('new')}</Link> {MailPoet.I18n.t('pageTitle')} <Link className="page-title-action" to="/new" data-automation-id="new_email">{MailPoet.I18n.t('new')}</Link>
</h1> </h1>
<ListingTabs tab="notification" /> <ListingTabs tab="notification" />
<Listing <Listing
limit={ mailpoet_listing_per_page } limit={window.mailpoet_listing_per_page}
location={this.props.location} location={this.props.location}
params={this.props.params} params={this.props.params}
endpoint="newsletters" endpoint="newsletters"

View File

@ -13,7 +13,7 @@ import {
MailerMixin, MailerMixin,
} from 'newsletters/listings/mixins.jsx'; } from 'newsletters/listings/mixins.jsx';
const mailpoet_tracking_enabled = (!!(window['mailpoet_tracking_enabled'])); const mailpoet_tracking_enabled = (!!(window.mailpoet_tracking_enabled));
const columns = [ const columns = [
{ {
@ -52,6 +52,7 @@ let newsletter_actions = [
}, },
]; ];
Hooks.addFilter('mailpoet_newsletters_listings_notification_history_actions', StatisticsMixin.addStatsCTAAction);
newsletter_actions = Hooks.applyFilters('mailpoet_newsletters_listings_notification_history_actions', newsletter_actions); newsletter_actions = Hooks.applyFilters('mailpoet_newsletters_listings_notification_history_actions', newsletter_actions);
const NewsletterListNotificationHistory = React.createClass({ const NewsletterListNotificationHistory = React.createClass({
@ -99,7 +100,7 @@ const NewsletterListNotificationHistory = React.createClass({
return ( return (
<div> <div>
<h1 className="title"> <h1 className="title">
{MailPoet.I18n.t('pageTitle')} <Link className="page-title-action" to="/new">{MailPoet.I18n.t('new')}</Link> {MailPoet.I18n.t('pageTitle')} <Link className="page-title-action" to="/new" data-automation-id="new_email">{MailPoet.I18n.t('new')}</Link>
</h1> </h1>
<ListingTabs tab="notification" /> <ListingTabs tab="notification" />
@ -110,7 +111,7 @@ const NewsletterListNotificationHistory = React.createClass({
>{MailPoet.I18n.t('backToPostNotifications')}</Link> >{MailPoet.I18n.t('backToPostNotifications')}</Link>
<Listing <Listing
limit={ mailpoet_listing_per_page } limit={window.mailpoet_listing_per_page}
location={this.props.location} location={this.props.location}
params={this.props.params} params={this.props.params}
endpoint="newsletters" endpoint="newsletters"

View File

@ -1,5 +1,6 @@
import React from 'react'; import React from 'react';
import { Link } from 'react-router'; import { Link } from 'react-router';
import { confirmAlert } from 'react-confirm-alert';
import classNames from 'classnames'; import classNames from 'classnames';
import MailPoet from 'mailpoet'; import MailPoet from 'mailpoet';
import Hooks from 'wp-js-hooks'; import Hooks from 'wp-js-hooks';
@ -13,7 +14,7 @@ import {
MailerMixin, MailerMixin,
} from 'newsletters/listings/mixins.jsx'; } from 'newsletters/listings/mixins.jsx';
const mailpoet_tracking_enabled = (!!(window['mailpoet_tracking_enabled'])); const mailpoet_tracking_enabled = (!!(window.mailpoet_tracking_enabled));
const messages = { const messages = {
onTrash: (response) => { onTrash: (response) => {
@ -98,13 +99,23 @@ const bulk_actions = [
]; ];
const confirmEdit = (newsletter) => { const confirmEdit = (newsletter) => {
const redirectToEditing = () => {
window.location.href = `?page=mailpoet-newsletter-editor&id=${newsletter.id}`;
};
if ( if (
!newsletter.queue !newsletter.queue
|| newsletter.status != 'sending' || newsletter.status != 'sending'
|| newsletter.queue.status !== null || newsletter.queue.status !== null
|| window.confirm(MailPoet.I18n.t('confirmEdit'))
) { ) {
window.location.href = `?page=mailpoet-newsletter-editor&id=${ newsletter.id }`; redirectToEditing();
} else {
confirmAlert({
title: MailPoet.I18n.t('confirmTitle'),
message: MailPoet.I18n.t('confirmEdit'),
confirmLabel: MailPoet.I18n.t('confirmLabel'),
cancelLabel: MailPoet.I18n.t('cancelLabel'),
onConfirm: redirectToEditing,
});
} }
}; };
@ -157,6 +168,7 @@ let newsletter_actions = [
}, },
]; ];
Hooks.addFilter('mailpoet_newsletters_listings_standard_actions', StatisticsMixin.addStatsCTAAction);
newsletter_actions = Hooks.applyFilters('mailpoet_newsletters_listings_standard_actions', newsletter_actions); newsletter_actions = Hooks.applyFilters('mailpoet_newsletters_listings_standard_actions', newsletter_actions);
const NewsletterListStandard = React.createClass({ const NewsletterListStandard = React.createClass({
@ -210,6 +222,7 @@ const NewsletterListStandard = React.createClass({
onClick={() => MailPoet.trackEvent('Emails > Add New', onClick={() => MailPoet.trackEvent('Emails > Add New',
{ 'MailPoet Free version': window.mailpoet_version } { 'MailPoet Free version': window.mailpoet_version }
)} )}
data-automation-id="new_email"
> >
{MailPoet.I18n.t('new')} {MailPoet.I18n.t('new')}
</Link> </Link>
@ -218,7 +231,7 @@ const NewsletterListStandard = React.createClass({
<ListingTabs tab="standard" /> <ListingTabs tab="standard" />
<Listing <Listing
limit={ mailpoet_listing_per_page } limit={window.mailpoet_listing_per_page}
location={this.props.location} location={this.props.location}
params={this.props.params} params={this.props.params}
endpoint="newsletters" endpoint="newsletters"

View File

@ -46,7 +46,7 @@ const ListingTabs = React.createClass({
}); });
return ( return (
<h2 className="nav-tab-wrapper"> <h2 className="nav-tab-wrapper" data-automation-id="newsletters_listing_tabs">
{ tabs } { tabs }
</h2> </h2>
); );

View File

@ -13,7 +13,7 @@ import Hooks from 'wp-js-hooks';
const mailpoet_roles = window.mailpoet_roles || {}; const mailpoet_roles = window.mailpoet_roles || {};
const mailpoet_segments = window.mailpoet_segments || {}; const mailpoet_segments = window.mailpoet_segments || {};
const mailpoet_tracking_enabled = (!!(window['mailpoet_tracking_enabled'])); const mailpoet_tracking_enabled = (!!(window.mailpoet_tracking_enabled));
const messages = { const messages = {
onTrash: (response) => { onTrash: (response) => {
@ -124,6 +124,7 @@ let newsletter_actions = [
}, },
]; ];
Hooks.addFilter('mailpoet_newsletters_listings_welcome_notification_actions', StatisticsMixin.addStatsCTAAction);
newsletter_actions = Hooks.applyFilters('mailpoet_newsletters_listings_welcome_notification_actions', newsletter_actions); newsletter_actions = Hooks.applyFilters('mailpoet_newsletters_listings_welcome_notification_actions', newsletter_actions);
const NewsletterListWelcome = React.createClass({ const NewsletterListWelcome = React.createClass({
@ -165,7 +166,7 @@ const NewsletterListWelcome = React.createClass({
<p> <p>
<select <select
data-id={newsletter.id} data-id={newsletter.id}
defaultValue={ newsletter.status } defaultValue={newsletter.status}
onChange={this.updateStatus} onChange={this.updateStatus}
> >
<option value="active">{ MailPoet.I18n.t('active') }</option> <option value="active">{ MailPoet.I18n.t('active') }</option>
@ -179,6 +180,7 @@ const NewsletterListWelcome = React.createClass({
renderSettings: function (newsletter) { renderSettings: function (newsletter) {
let sendingEvent; let sendingEvent;
let sendingDelay; let sendingDelay;
let segment;
// set sending event // set sending event
switch (newsletter.options.event) { switch (newsletter.options.event) {
@ -195,8 +197,8 @@ const NewsletterListWelcome = React.createClass({
case 'segment': case 'segment':
// get segment // get segment
const segment = _.find(mailpoet_segments, (segment) => { segment = _.find(mailpoet_segments, (seg) => {
return (~~(segment.id) === ~~(newsletter.options.segment)); return (~~(seg.id) === ~~(newsletter.options.segment));
}); });
if (segment === undefined) { if (segment === undefined) {
@ -205,11 +207,11 @@ const NewsletterListWelcome = React.createClass({
{ MailPoet.I18n.t('sendingToSegmentsNotSpecified') } { MailPoet.I18n.t('sendingToSegmentsNotSpecified') }
</span> </span>
); );
} else { }
sendingEvent = MailPoet.I18n.t('welcomeEventSegment').replace( sendingEvent = MailPoet.I18n.t('welcomeEventSegment').replace(
'%$1s', segment.name '%$1s', segment.name
); );
}
break; break;
} }
@ -289,13 +291,13 @@ const NewsletterListWelcome = React.createClass({
return ( return (
<div> <div>
<h1 className="title"> <h1 className="title">
{ MailPoet.I18n.t('pageTitle') } <Link className="page-title-action" to="/new">{ MailPoet.I18n.t('new') }</Link> { MailPoet.I18n.t('pageTitle') } <Link className="page-title-action" to="/new" data-automation-id="new_email">{ MailPoet.I18n.t('new') }</Link>
</h1> </h1>
<ListingTabs tab="welcome" /> <ListingTabs tab="welcome" />
<Listing <Listing
limit={ mailpoet_listing_per_page } limit={window.mailpoet_listing_per_page}
location={this.props.location} location={this.props.location}
params={this.props.params} params={this.props.params}
endpoint="newsletters" endpoint="newsletters"

View File

@ -37,7 +37,8 @@ if(container) {
{/* Listings */} {/* Listings */}
<Route path="standard(/)**" params={{ tab: 'standard' }} component={NewsletterListStandard} /> <Route path="standard(/)**" params={{ tab: 'standard' }} component={NewsletterListStandard} />
<Route path="welcome(/)**" component={NewsletterListWelcome} /> <Route path="welcome(/)**" component={NewsletterListWelcome} />
<Route path="notification/history/:parent_id(/)**" component={ NewsletterListNotificationHistory } /> <Route path="notification/history/:parent_id(/)**"
component={NewsletterListNotificationHistory} />
<Route path="notification(/)**" component={NewsletterListNotification} /> <Route path="notification(/)**" component={NewsletterListNotification} />
{/* Newsletter: type selection */} {/* Newsletter: type selection */}
<Route path="new" component={NewsletterTypes} /> <Route path="new" component={NewsletterTypes} />

View File

@ -4,19 +4,19 @@ import MailPoet from 'mailpoet';
const timeFormat = window.mailpoet_time_format || 'H:i'; const timeFormat = window.mailpoet_time_format || 'H:i';
// welcome emails // welcome emails
const _timeDelayValues = { const timeDelayValues = {
'immediate': MailPoet.I18n.t('delayImmediately'), immediate: MailPoet.I18n.t('delayImmediately'),
'hours': MailPoet.I18n.t('delayHoursAfter'), hours: MailPoet.I18n.t('delayHoursAfter'),
'days': MailPoet.I18n.t('delayDaysAfter'), days: MailPoet.I18n.t('delayDaysAfter'),
'weeks': MailPoet.I18n.t('delayWeeksAfter'), weeks: MailPoet.I18n.t('delayWeeksAfter'),
}; };
const _intervalValues = { const intervalValues = {
'daily': MailPoet.I18n.t('daily'), daily: MailPoet.I18n.t('daily'),
'weekly': MailPoet.I18n.t('weekly'), weekly: MailPoet.I18n.t('weekly'),
'monthly': MailPoet.I18n.t('monthly'), monthly: MailPoet.I18n.t('monthly'),
'nthWeekDay': MailPoet.I18n.t('monthlyEvery'), nthWeekDay: MailPoet.I18n.t('monthlyEvery'),
'immediately': MailPoet.I18n.t('immediately'), immediately: MailPoet.I18n.t('immediately'),
}; };
// notification emails // notification emails
@ -24,7 +24,7 @@ const SECONDS_IN_DAY = 86400;
const TIME_STEP_SECONDS = 3600; const TIME_STEP_SECONDS = 3600;
const numberOfTimeSteps = SECONDS_IN_DAY / TIME_STEP_SECONDS; const numberOfTimeSteps = SECONDS_IN_DAY / TIME_STEP_SECONDS;
const _timeOfDayValues = _.object(_.map( const timeOfDayValues = _.object(_.map(
_.times(numberOfTimeSteps, (step) => { _.times(numberOfTimeSteps, (step) => {
return step * TIME_STEP_SECONDS; return step * TIME_STEP_SECONDS;
}), (seconds) => { }), (seconds) => {
@ -35,7 +35,7 @@ const _timeOfDayValues = _.object(_.map(
}) })
); );
const _weekDayValues = { const weekDayValues = {
0: MailPoet.I18n.t('sunday'), 0: MailPoet.I18n.t('sunday'),
1: MailPoet.I18n.t('monday'), 1: MailPoet.I18n.t('monday'),
2: MailPoet.I18n.t('tuesday'), 2: MailPoet.I18n.t('tuesday'),
@ -46,7 +46,7 @@ const _weekDayValues = {
}; };
const NUMBER_OF_DAYS_IN_MONTH = 28; const NUMBER_OF_DAYS_IN_MONTH = 28;
const _monthDayValues = _.object( const monthDayValues = _.object(
_.map( _.map(
_.times(NUMBER_OF_DAYS_IN_MONTH, (day) => { _.times(NUMBER_OF_DAYS_IN_MONTH, (day) => {
return day; return day;
@ -60,23 +60,23 @@ const _monthDayValues = _.object(
if (labels[day] !== undefined) { if (labels[day] !== undefined) {
label = labels[day]; label = labels[day];
} else { } else {
label = MailPoet.I18n.t('nth').replace("%$1d", day + 1); label = MailPoet.I18n.t('nth').replace('%$1d', day + 1);
} }
return [day + 1, label]; return [day + 1, label];
} }
) )
); );
const _nthWeekDayValues = { const nthWeekDayValues = {
'1': MailPoet.I18n.t('first'), 1: MailPoet.I18n.t('first'),
'2': MailPoet.I18n.t('second'), 2: MailPoet.I18n.t('second'),
'3': MailPoet.I18n.t('third'), 3: MailPoet.I18n.t('third'),
'L': MailPoet.I18n.t('last'), L: MailPoet.I18n.t('last'),
}; };
export { _timeDelayValues as timeDelayValues }; export { timeDelayValues };
export { _intervalValues as intervalValues }; export { intervalValues };
export { _timeOfDayValues as timeOfDayValues }; export { timeOfDayValues };
export { _weekDayValues as weekDayValues }; export { weekDayValues };
export { _monthDayValues as monthDayValues }; export { monthDayValues };
export { _nthWeekDayValues as nthWeekDayValues }; export { nthWeekDayValues };

View File

@ -10,6 +10,7 @@ define(
'newsletters/send/welcome.jsx', 'newsletters/send/welcome.jsx',
'newsletters/breadcrumb.jsx', 'newsletters/breadcrumb.jsx',
'help-tooltip.jsx', 'help-tooltip.jsx',
'jquery',
], ],
( (
React, React,
@ -21,9 +22,9 @@ define(
NotificationNewsletterFields, NotificationNewsletterFields,
WelcomeNewsletterFields, WelcomeNewsletterFields,
Breadcrumb, Breadcrumb,
HelpTooltip HelpTooltip,
jQuery
) => { ) => {
const NewsletterSend = React.createClass({ const NewsletterSend = React.createClass({
contextTypes: { contextTypes: {
router: React.PropTypes.object.isRequired, router: React.PropTypes.object.isRequired,
@ -93,7 +94,7 @@ define(
if (!this.isValid()) { if (!this.isValid()) {
jQuery('#mailpoet_newsletter').parsley().validate(); jQuery('#mailpoet_newsletter').parsley().validate();
} else { } else {
this._save(e).done(() => { this.saveNewsletter(e).done(() => {
this.setState({ loading: true }); this.setState({ loading: true });
}).done((response) => { }).done((response) => {
switch (response.data.type) { switch (response.data.type) {
@ -107,30 +108,30 @@ define(
id: this.props.params.id, id: this.props.params.id,
status: 'active', status: 'active',
}, },
}).done((response) => { }).done((response2) => {
// redirect to listing based on newsletter type // redirect to listing based on newsletter type
this.context.router.push(`/${this.state.item.type || ''}`); this.context.router.push(`/${this.state.item.type || ''}`);
const opts = this.state.item.options; const opts = this.state.item.options;
// display success message depending on newsletter type // display success message depending on newsletter type
if (response.data.type === 'welcome') { if (response2.data.type === 'welcome') {
MailPoet.Notice.success( MailPoet.Notice.success(
MailPoet.I18n.t('welcomeEmailActivated') MailPoet.I18n.t('welcomeEmailActivated')
); );
MailPoet.trackEvent('Emails > Welcome email activated', { MailPoet.trackEvent('Emails > Welcome email activated', {
'MailPoet Free version': window.mailpoet_version, 'MailPoet Free version': window.mailpoet_version,
'List type': opts.event, 'List type': opts.event,
'Delay': opts.afterTimeNumber + ' ' + opts.afterTimeType, Delay: opts.afterTimeNumber + ' ' + opts.afterTimeType,
}); });
} else if (response.data.type === 'notification') { } else if (response2.data.type === 'notification') {
MailPoet.Notice.success( MailPoet.Notice.success(
MailPoet.I18n.t('postNotificationActivated') MailPoet.I18n.t('postNotificationActivated')
); );
MailPoet.trackEvent('Emails > Post notifications activated', { MailPoet.trackEvent('Emails > Post notifications activated', {
'MailPoet Free version': window.mailpoet_version, 'MailPoet Free version': window.mailpoet_version,
'Frequency': opts.intervalType, Frequency: opts.intervalType,
}); });
} }
}).fail(this._showError); }).fail(this.showError);
default: default:
return MailPoet.Ajax.post({ return MailPoet.Ajax.post({
api_version: window.mailpoet_api_version, api_version: window.mailpoet_api_version,
@ -139,11 +140,11 @@ define(
data: { data: {
newsletter_id: this.props.params.id, newsletter_id: this.props.params.id,
}, },
}).done((response) => { }).done((response2) => {
// redirect to listing based on newsletter type // redirect to listing based on newsletter type
this.context.router.push(`/${this.state.item.type || ''}`); this.context.router.push(`/${this.state.item.type || ''}`);
if (response.data.status === 'scheduled') { if (response2.data.status === 'scheduled') {
MailPoet.Notice.success( MailPoet.Notice.success(
MailPoet.I18n.t('newsletterHasBeenScheduled') MailPoet.I18n.t('newsletterHasBeenScheduled')
); );
@ -160,9 +161,11 @@ define(
'MailPoet Free version': window.mailpoet_version, 'MailPoet Free version': window.mailpoet_version,
}); });
} }
}).fail(this._showError); }).fail(this.showError);
} }
}).fail(this._showError).always(() => { })
.fail(this.showError)
.always(() => {
this.setState({ loading: false }); this.setState({ loading: false });
}); });
} }
@ -173,7 +176,7 @@ define(
if (!this.isValid()) { if (!this.isValid()) {
jQuery('#mailpoet_newsletter').parsley().validate(); jQuery('#mailpoet_newsletter').parsley().validate();
} else { } else {
this._save(e).done(() => { this.saveNewsletter(e).done(() => {
this.setState({ loading: true }); this.setState({ loading: true });
}).done(() => { }).done(() => {
MailPoet.Ajax.post({ MailPoet.Ajax.post({
@ -196,7 +199,9 @@ define(
); );
} }
}); });
}).fail(this._showError).always(() => { })
.fail(this.showError)
.always(() => {
this.setState({ loading: false }); this.setState({ loading: false });
}); });
} }
@ -205,27 +210,27 @@ define(
handleSave: function (e) { handleSave: function (e) {
e.preventDefault(); e.preventDefault();
this._save(e).done(() => { this.saveNewsletter(e).done(() => {
MailPoet.Notice.success( MailPoet.Notice.success(
MailPoet.I18n.t('newsletterUpdated') MailPoet.I18n.t('newsletterUpdated')
); );
}).done(() => { }).done(() => {
this.context.router.push(`/${this.state.item.type || ''}`); this.context.router.push(`/${this.state.item.type || ''}`);
}).fail(this._showError); }).fail(this.showError);
}, },
handleRedirectToDesign: function (e) { handleRedirectToDesign: function (e) {
e.preventDefault(); e.preventDefault();
const redirectTo = e.target.href; const redirectTo = e.target.href;
this._save(e).done(() => { this.saveNewsletter(e).done(() => {
MailPoet.Notice.success( MailPoet.Notice.success(
MailPoet.I18n.t('newsletterUpdated') MailPoet.I18n.t('newsletterUpdated')
); );
}).done(() => { }).done(() => {
window.location = redirectTo; window.location = redirectTo;
}).fail(this._showError); }).fail(this.showError);
}, },
_save: function () { saveNewsletter: function () {
const data = this.state.item; const data = this.state.item;
data.queue = undefined; data.queue = undefined;
this.setState({ loading: true }); this.setState({ loading: true });
@ -249,7 +254,7 @@ define(
this.setState({ loading: false }); this.setState({ loading: false });
}); });
}, },
_showError: (response) => { showError: (response) => {
if (response.errors.length > 0) { if (response.errors.length > 0) {
MailPoet.Notice.error( MailPoet.Notice.error(
response.errors.map((error) => { return error.message; }), response.errors.map((error) => { return error.message; }),
@ -279,6 +284,7 @@ define(
} }
return newField; return newField;
}); });
const sendButtonOptions = this.getSendButtonOptions();
return ( return (
<div> <div>
<h1>{MailPoet.I18n.t('finalNewsletterStep')}</h1> <h1>{MailPoet.I18n.t('finalNewsletterStep')}</h1>
@ -307,7 +313,7 @@ define(
type="button" type="button"
onClick={this.handleSend} onClick={this.handleSend}
value={MailPoet.I18n.t('send')} value={MailPoet.I18n.t('send')}
{...this.getSendButtonOptions()} {...sendButtonOptions}
/> />
} }
&nbsp; &nbsp;
@ -324,10 +330,12 @@ define(
{MailPoet.I18n.t('goBackToDesign')} {MailPoet.I18n.t('goBackToDesign')}
</a>. </a>.
</p> </p>
{ !isPaused && sendButtonOptions.disabled && sendButtonOptions.disabled === 'disabled' && (
<HelpTooltip <HelpTooltip
tooltip={MailPoet.I18n.t('helpTooltipSendEmail')} tooltip={MailPoet.I18n.t('helpTooltipSendEmail')}
tooltipId="helpTooltipSendEmail" tooltipId="helpTooltipSendEmail"
/> />
) }
</Form> </Form>
</div> </div>
); );

View File

@ -11,7 +11,6 @@ define(
Scheduling, Scheduling,
_ _
) => { ) => {
let fields = [ let fields = [
{ {
name: 'subject', name: 'subject',
@ -40,7 +39,7 @@ define(
endpoint: 'segments', endpoint: 'segments',
multiple: true, multiple: true,
filter: function (segment) { filter: function (segment) {
return !!(!segment.deleted_at); return !segment.deleted_at;
}, },
getLabel: function (segment) { getLabel: function (segment) {
return segment.name + ' (' + parseInt(segment.subscribers, 10).toLocaleString() + ')'; return segment.name + ' (' + parseInt(segment.subscribers, 10).toLocaleString() + ')';

View File

@ -13,11 +13,10 @@ define(
MailPoet, MailPoet,
Hooks Hooks
) => { ) => {
const jQuery = jq; const jQuery = jq;
const currentTime = window.mailpoet_current_time || '00:00'; const currentTime = window.mailpoet_current_time || '00:00';
const defaultDateTime = window.mailpoet_current_date + ' ' + '00:00:00'; const defaultDateTime = window.mailpoet_current_date + ' 00:00:00';
const timeOfDayItems = window.mailpoet_schedule_time_of_day; const timeOfDayItems = window.mailpoet_schedule_time_of_day;
const dateDisplayFormat = window.mailpoet_date_display_format; const dateDisplayFormat = window.mailpoet_date_display_format;
const dateStorageFormat = window.mailpoet_date_storage_format; const dateStorageFormat = window.mailpoet_date_storage_format;
@ -195,16 +194,16 @@ define(
}); });
const DateTime = React.createClass({ const DateTime = React.createClass({
_DATE_TIME_SEPARATOR: " ", DATE_TIME_SEPARATOR: ' ',
getInitialState: function () { getInitialState: function () {
return this._buildStateFromProps(this.props); return this.buildStateFromProps(this.props);
}, },
componentWillReceiveProps: function (nextProps) { componentWillReceiveProps: function (nextProps) {
this.setState(this._buildStateFromProps(nextProps)); this.setState(this.buildStateFromProps(nextProps));
}, },
_buildStateFromProps: function (props) { buildStateFromProps: function (props) {
const value = props.value || defaultDateTime; const value = props.value || defaultDateTime;
const [date, time] = value.split(this._DATE_TIME_SEPARATOR); const [date, time] = value.split(this.DATE_TIME_SEPARATOR);
return { return {
date: date, date: date,
time: time, time: time,
@ -229,7 +228,7 @@ define(
} }
}, },
getDateTime: function () { getDateTime: function () {
return [this.state.date, this.state.time].join(this._DATE_TIME_SEPARATOR); return [this.state.date, this.state.time].join(this.DATE_TIME_SEPARATOR);
}, },
render: function () { render: function () {
return ( return (
@ -254,7 +253,7 @@ define(
}); });
const StandardScheduling = React.createClass({ const StandardScheduling = React.createClass({
_getCurrentValue: function () { getCurrentValue: function () {
return _.defaults( return _.defaults(
this.props.item[this.props.field.name] || {}, this.props.item[this.props.field.name] || {},
{ {
@ -264,7 +263,7 @@ define(
); );
}, },
handleValueChange: function (event) { handleValueChange: function (event) {
const oldValue = this._getCurrentValue(); const oldValue = this.getCurrentValue();
const newValue = {}; const newValue = {};
newValue[event.target.name] = event.target.value; newValue[event.target.name] = event.target.value;
@ -281,7 +280,7 @@ define(
return this.handleValueChange(changeEvent); return this.handleValueChange(changeEvent);
}, },
isScheduled: function () { isScheduled: function () {
return this._getCurrentValue().isScheduled === '1'; return this.getCurrentValue().isScheduled === '1';
}, },
getDateValidation: function () { getDateValidation: function () {
return { return {
@ -298,7 +297,7 @@ define(
<span id="mailpoet_scheduling"> <span id="mailpoet_scheduling">
<DateTime <DateTime
name="scheduledAt" name="scheduledAt"
value={this._getCurrentValue().scheduledAt} value={this.getCurrentValue().scheduledAt}
onChange={this.handleValueChange} onChange={this.handleValueChange}
disabled={this.props.field.disabled} disabled={this.props.field.disabled}
dateValidation={this.getDateValidation()} /> dateValidation={this.getDateValidation()} />
@ -348,7 +347,7 @@ define(
endpoint: 'segments', endpoint: 'segments',
multiple: true, multiple: true,
filter: function (segment) { filter: function (segment) {
return !!(!segment.deleted_at); return !segment.deleted_at;
}, },
getLabel: function (segment) { getLabel: function (segment) {
return segment.name + ' (' + parseInt(segment.subscribers, 10).toLocaleString() + ')'; return segment.name + ' (' + parseInt(segment.subscribers, 10).toLocaleString() + ')';
@ -437,7 +436,7 @@ define(
if (newsletterOptions.status === 'sent' if (newsletterOptions.status === 'sent'
|| newsletterOptions.status === 'sending') { || newsletterOptions.status === 'sending') {
options['disabled'] = 'disabled'; options.disabled = 'disabled';
} }
return options; return options;

View File

@ -9,8 +9,6 @@ define(
Hooks, Hooks,
Scheduling Scheduling
) => { ) => {
let fields = [ let fields = [
{ {
name: 'subject', name: 'subject',

View File

@ -1,22 +1,10 @@
define( import React from 'react';
[ import _ from 'underscore';
'react', import MailPoet from 'mailpoet';
'underscore', import { confirmAlert } from 'react-confirm-alert';
'mailpoet', import classNames from 'classnames';
'react-router', import Breadcrumb from 'newsletters/breadcrumb.jsx';
'classnames', import HelpTooltip from 'help-tooltip.jsx';
'newsletters/breadcrumb.jsx',
'help-tooltip.jsx',
],
(
React,
_,
MailPoet,
Router,
classNames,
Breadcrumb,
HelpTooltip
) => {
const ImportTemplate = React.createClass({ const ImportTemplate = React.createClass({
saveTemplate: function (saveTemplate) { saveTemplate: function (saveTemplate) {
@ -57,9 +45,9 @@ define(
const reader = new FileReader(); const reader = new FileReader();
const saveTemplate = this.saveTemplate; const saveTemplate = this.saveTemplate;
reader.onload = (e) => { reader.onload = (evt) => {
try { try {
saveTemplate(JSON.parse(e.target.result)); saveTemplate(JSON.parse(evt.target.result));
MailPoet.trackEvent('Emails > Template imported', { MailPoet.trackEvent('Emails > Template imported', {
'MailPoet Free version': window.mailpoet_version, 'MailPoet Free version': window.mailpoet_version,
}); });
@ -122,7 +110,7 @@ define(
MailPoet.I18n.t('mailpoetGuideTemplateTitle'), MailPoet.I18n.t('mailpoetGuideTemplateTitle'),
description: description:
MailPoet.I18n.t('mailpoetGuideTemplateDescription'), MailPoet.I18n.t('mailpoetGuideTemplateDescription'),
readonly: "1", readonly: '1',
}, },
]; ];
} }
@ -175,13 +163,7 @@ define(
}, },
handleDeleteTemplate: function (template) { handleDeleteTemplate: function (template) {
this.setState({ loading: true }); this.setState({ loading: true });
if( const onConfirm = () => {
window.confirm(
(
MailPoet.I18n.t('confirmTemplateDeletion')
).replace("%$1s", template.name)
)
) {
MailPoet.Ajax.post({ MailPoet.Ajax.post({
api_version: window.mailpoet_api_version, api_version: window.mailpoet_api_version,
endpoint: 'newsletterTemplates', endpoint: 'newsletterTemplates',
@ -199,9 +181,18 @@ define(
); );
} }
}); });
} else { };
const onCancel = () => {
this.setState({ loading: false }); this.setState({ loading: false });
} };
confirmAlert({
title: MailPoet.I18n.t('confirmTitle'),
message: MailPoet.I18n.t('confirmTemplateDeletion').replace('%$1s', template.name),
confirmLabel: MailPoet.I18n.t('confirmLabel'),
cancelLabel: MailPoet.I18n.t('cancelLabel'),
onConfirm: onConfirm,
onCancel: onCancel,
});
}, },
handleShowTemplate: function (template) { handleShowTemplate: function (template) {
MailPoet.Modal.popup({ MailPoet.Modal.popup({
@ -258,12 +249,13 @@ define(
&nbsp; &nbsp;
<a <a
className="button button-primary" className="button button-primary"
data-automation-id={'select_template_' + index}
onClick={this.handleSelectTemplate.bind(null, template)} onClick={this.handleSelectTemplate.bind(null, template)}
> >
{MailPoet.I18n.t('select')} {MailPoet.I18n.t('select')}
</a> </a>
</div> </div>
{ (template.readonly === "1") ? false : deleteLink } { (template.readonly === '1') ? false : deleteLink }
</li> </li>
); );
}); });
@ -271,7 +263,7 @@ define(
const boxClasses = classNames( const boxClasses = classNames(
'mailpoet_boxes', 'mailpoet_boxes',
'clearfix', 'clearfix',
{ 'mailpoet_boxes_loading': this.state.loading } { mailpoet_boxes_loading: this.state.loading }
); );
return ( return (
@ -290,6 +282,4 @@ define(
}, },
}); });
return NewsletterTemplates; export default NewsletterTemplates;
}
);

View File

@ -53,22 +53,22 @@ define(
render: function () { render: function () {
let types = [ let types = [
{ {
'id': 'standard', id: 'standard',
'title': MailPoet.I18n.t('regularNewsletterTypeTitle'), title: MailPoet.I18n.t('regularNewsletterTypeTitle'),
'description': MailPoet.I18n.t('regularNewsletterTypeDescription'), description: MailPoet.I18n.t('regularNewsletterTypeDescription'),
'action': function () { action: function () {
return ( return (
<a className="button button-primary" onClick={ this.createNewsletter.bind(null, 'standard') }> <a className="button button-primary" data-automation-id="create_standard" onClick={this.createNewsletter.bind(null, 'standard')}>
{MailPoet.I18n.t('create')} {MailPoet.I18n.t('create')}
</a> </a>
); );
}.bind(this)(), }.bind(this)(),
}, },
{ {
'id': 'welcome', id: 'welcome',
'title': MailPoet.I18n.t('welcomeNewsletterTypeTitle'), title: MailPoet.I18n.t('welcomeNewsletterTypeTitle'),
'description': MailPoet.I18n.t('welcomeNewsletterTypeDescription'), description: MailPoet.I18n.t('welcomeNewsletterTypeDescription'),
'action': function () { action: (function () {
return ( return (
<div> <div>
<a href="?page=mailpoet-premium" target="_blank"> <a href="?page=mailpoet-premium" target="_blank">
@ -76,15 +76,15 @@ define(
</a> </a>
</div> </div>
); );
}(), }()),
}, },
{ {
'id': 'notification', id: 'notification',
'title': MailPoet.I18n.t('postNotificationNewsletterTypeTitle'), title: MailPoet.I18n.t('postNotificationNewsletterTypeTitle'),
'description': MailPoet.I18n.t('postNotificationNewsletterTypeDescription'), description: MailPoet.I18n.t('postNotificationNewsletterTypeDescription'),
'action': function () { action: function () {
return ( return (
<a className="button button-primary" onClick={ this.setupNewsletter.bind(null, 'notification') }> <a className="button button-primary" data-automation-id="create_notification" onClick={this.setupNewsletter.bind(null, 'notification')}>
{MailPoet.I18n.t('setUp')} {MailPoet.I18n.t('setUp')}
</a> </a>
); );

Some files were not shown because too many files have changed in this diff Show More