Compare commits

...

214 Commits

Author SHA1 Message Date
f35b66b3cf Release 3.0.0-rc.1.0.2 2017-08-08 17:45:04 +03:00
7900e7eb8d Merge pull request #1035 from mailpoet/new-poll
New poll [MAILPOET-1018]
2017-08-08 09:17:41 -04:00
849a24ced7 Merge pull request #1019 from mailpoet/translate
translate the DB error message [MAILPOET-1019]
2017-08-08 13:08:54 +03:00
f7e73b06be added missing argument 2017-08-08 10:02:51 +00:00
52cbb9fcb2 Merge pull request #1032 from mailpoet/css-form
Update form css [MAILPOET-593]
2017-08-08 11:48:09 +02:00
966ec0cb7a New poll
[MAILPOET-1018]
2017-08-03 13:17:37 +02:00
2ff0d40d10 Updates reference to the hook that displays IIS error 2017-08-03 08:14:46 +02:00
bb249ebe09 Removes leftover debug code 2017-08-02 10:24:35 -04:00
5a57029b38 Bumps up release version & updates changelog 2017-08-02 10:23:37 -04:00
84d427cc4c Upate poll url 2017-08-02 11:40:30 +02:00
22efd2109b Release 3.0.0-rc.1.0.0 2017-08-01 18:04:30 +00:00
f044db5745 Update form css
[MAILPOET-593]
2017-08-01 11:28:53 +02:00
0865995d21 Does not remove padding from the last element in a column 2017-08-01 09:47:29 +02:00
7c30192a03 Adds option to replace shortcodes in one string using contents from
another string
Adds unit tests
2017-08-01 09:32:42 +02:00
334c3ff420 Returns false when data-post-id tag is not found
Uses all post types, including custom, when querying posts
2017-08-01 09:32:42 +02:00
6d738ddb3b Merge pull request #1031 from mailpoet/mss-response
Mss response [MAILPOET-1035]
2017-07-31 14:37:13 -04:00
440052cf2c Remove duplicate code
[MAILPOET-1035]
2017-07-31 16:51:11 +02:00
ccb751b44a Adhere to updated MSS /me response
[MAILPOET-1035]
2017-07-31 16:47:20 +02:00
7cf3d0960d Unify API response constants
[MAILPOET-1035]
2017-07-31 13:51:23 +02:00
6e45856622 Merge pull request #1022 from mailpoet/mediumint_to_int
Switch ID fields from mediumint to int in DB [MAILPOET-1022]
2017-07-31 11:03:16 +02:00
9859df98b7 translate the DB error message 2017-07-31 08:53:30 +00:00
1071688924 Update a poll [MAILPOET-1017] 2017-07-31 09:41:45 +02:00
4f3b0234a4 Move exception rule to top
[MAILPOET-1028]
2017-07-31 09:27:26 +02:00
3e2bbeac11 Fix ES6 comma-dangle eslint rule (functions should be ignored pre-ES2017) [MAILPOET-1028] 2017-07-31 09:27:26 +02:00
08f81bd816 Fix ES5 comma-dangle eslint rule [MAILPOET-1028] 2017-07-31 09:27:26 +02:00
f0c59ff635 Fix tests comma-dangle eslint rule [MAILPOET-1028] 2017-07-31 09:27:26 +02:00
66c6f52646 Fix ES6 comma-spacing eslint rule [MAILPOET-1028] 2017-07-31 09:27:26 +02:00
4988aaf14f Fix ES5 comma-spacing eslint rule [MAILPOET-1028] 2017-07-31 09:27:26 +02:00
5773d46f1c Merge pull request #1029 from mailpoet/alc-rendering
Enable blockquotes and fix image positioning in ALC blocks [MAILPOET-1037] [MAILPOET-1038]
2017-07-30 12:01:39 -04:00
f3a1e1b447 Update Robo test debug rule to accept individual test file paths 2017-07-28 14:36:40 +03:00
6de746162e Update Posts transformer to extract images by splitting the DOM tree 2017-07-28 14:36:12 +03:00
60b3c066a5 Allow rendering blockquote tags 2017-07-28 11:10:57 +03:00
63158dc2d5 Merge pull request #1024 from mailpoet/mta-frequency-fix
Mta frequency fix [MAILPOET-1021]
2017-07-27 19:17:14 +03:00
dede6e56c4 Merge pull request #1026 from mailpoet/beta_end
Remove concept of "Beta" on readme.txt, update banners [MAILPOET-1023]
2017-07-27 15:49:22 +03:00
dd366dde18 Remove concept of "Beta" on readme.txt, update banners [MAILPOET-1023] 2017-07-27 14:04:00 +03:00
2fedafe483 Merge pull request #1025 from mailpoet/tests_sniffs
Enable remaining CodeSniffer rules for PHP tests [MAILPOET-1025]
2017-07-26 21:34:48 -04:00
feae98ac3f Use a single ruleset for both the plugin and its tests [MAILPOET-1025] 2017-07-26 18:56:14 +03:00
6fb18ad321 Fix PSR1.Classes.ClassDeclaration sniffer rule in tests [MAILPOET-1025] 2017-07-26 18:28:56 +03:00
6c843e35b0 Update warning text
[MAILPOET-1021]
2017-07-26 16:27:53 +02:00
cfdb86eb6e Replace default option text
[MAILPOET-1021]
2017-07-26 16:24:31 +02:00
41fb93e453 Remove the number of emails per day calculation
[MAILPOET-1021]
2017-07-26 16:22:23 +02:00
19813b5dad Fix host frequency override
[MAILPOET-1021]
2017-07-26 16:08:49 +02:00
321393f119 Fix Squiz.Classes.ClassFileName sniffer rule in tests [MAIPOET-1025] 2017-07-26 17:03:43 +03:00
ab3f41302c Merge pull request #1023 from mailpoet/remove-subquery
Use Joins instead subqueries [MAILPOET-1027]
2017-07-26 13:56:32 +03:00
9dff4539e6 Use Joins instead subqueries
[MAILPOET-1027]
2017-07-26 11:46:36 +02:00
6520d5eca3 Merge branch 'master' of github.com:mailpoet/mailpoet 2017-07-25 16:45:42 +03:00
f5b152cdfa Bump up release version to 3.0.0-beta.37.0.0 2017-07-25 16:40:12 +03:00
1d2cab1249 Merge pull request #1021 from mailpoet/prevent-mss-override
Prevent to override sending group [MAILPOET-1024]
2017-07-25 15:24:28 +03:00
90b93bd76e Merge pull request #1018 from mailpoet/prevent_sending_with_broken_newsletter_body
Prevents sending emails when rendered newsletter is broken [MAILPOET-1020]
2017-07-25 13:13:03 +03:00
563ca3e605 Switch ID fields from mediumint to int in DB [MAILPOET-1022] 2017-07-25 13:11:56 +03:00
08bbfcb5e8 Track MixPanel events for Settings [MAILPOET-998] 2017-07-25 10:53:28 +02:00
5572a7f1e5 Prevent to override sending group
[MAILPOET-1024]
2017-07-25 08:32:10 +02:00
9dd326e7db Updates class to use newly added validate() method on the model
Validates existing queue's rendered newsletter body
Cleans code formatting
2017-07-24 12:49:39 -04:00
cf00813c7f Adds new method to validate model on request
Cleans up code formatting
2017-07-24 11:20:43 -04:00
4c898b76b2 Uses ValidModel to validate rendered newsletter body
Removes previous validation method
Does not serialize null values
2017-07-24 11:15:00 -04:00
81a2ba8e03 Adds new validation method for rendered newsletter body 2017-07-24 11:11:22 -04:00
7e6d900b53 Merge pull request #997 from mailpoet/scheduled_task_subscribers
Extract subscribers to a separate table in the Bounce worker [MAILPOET-987]
2017-07-24 17:14:38 +03:00
1a522794d6 Adds method to validate rendered newsletter body on sending queue
Prevents sending queue worker from sending when sending queue's rendered
newsletter body is invalid
2017-07-23 11:50:35 -04:00
197537d6ca Merge pull request #1015 from mailpoet/custom_field_shortcodes
Add missing brackets to custom field shortcodes [MAILPOET-1013]
2017-07-21 21:40:25 -04:00
b212ca801b Merge pull request #1016 from mailpoet/sync_deleted_wp_users
Remove deleted WP users from subscribers [MAILPOET-1012]
2017-07-21 21:39:53 -04:00
db8f3216d7 Add tests for syncing deleted WP users [MAILPOET-1012] 2017-07-21 18:43:29 +03:00
78f9945296 Remove deleted WP users from subscribers [MAILPOET-1012] 2017-07-21 17:48:48 +03:00
0cebcd3965 Add missing brackets to custom field shortcodes [MAILPOET-1013] 2017-07-21 14:40:56 +03:00
4062e0662d Merge pull request #1009 from mailpoet/share_data_kb_link
Update link to "Share your data" in Welcome tabs [MAILPOET-1010]
2017-07-20 19:24:53 +02:00
20b7e82d3c Merge pull request #1014 from mailpoet/new-poll
Update poll [MAILPOET-1016]
2017-07-20 19:16:36 +02:00
9ab8a80567 Merge pull request #992 from mailpoet/circleci
Set up CircleCI tests to run on PHP 5.6 and 7.1 [MAILPOET-986]
2017-07-20 09:55:44 -04:00
f98d02121b Fix BatchIterator skipping rows when subscribers' processed status is modified [MAILPOET-987] 2017-07-20 16:31:27 +03:00
e68e212ad0 Update poll
[MAILPOET-1016]
2017-07-20 12:48:55 +01:00
cb1a1e51ba Use fixtures instead of IDs in the sheduled task subscriber test [MAILPOET-987] 2017-07-20 13:26:31 +03:00
b42d8e68d9 Rename removeSubscribers() method and encapsulate task completion logic [MAILPOET-987] 2017-07-20 11:22:47 +03:00
e88d130ebb Remove side-effects from Update page styles [MAILPOET-1001]
Example: Premium page comparison table rows centered
2017-07-20 08:59:03 +01:00
c924778d50 Rename unprocessed status, refactor counting a bit more clearly [MAILPOET-987] 2017-07-20 10:56:34 +03:00
a9051c6d09 merging qa_js and php5 builds to gain execution time 2017-07-19 19:11:35 -04:00
f6243b5d79 Merge pull request #1005 from mailpoet/mixpanel-more-data
MixPanel: extend summarized data collection [MAILPOET-974]
2017-07-19 20:25:14 +03:00
68c0b93586 Fix Premium page scaling on mobile screens [MAILPOET-1001] 2017-07-19 18:14:50 +01:00
0e8be8040c Move custom page styles from views to a separate *.styl file [MAILPOET-1001] 2017-07-19 18:14:50 +01:00
f3ea548d65 Update the Premium page [MAILPOET-1001] 2017-07-19 18:14:50 +01:00
1ab6be8acd Fix Notice and remove redundant field
[MAILPOET-974]
2017-07-19 16:16:08 +01:00
c413acd93d display a warning when unable to connect to database 2017-07-19 16:05:34 +01:00
7614a4d8dc Update link to "Share your data" in Welcome tabs [MAILPOET-1010] 2017-07-19 10:27:59 +03:00
4a94c29b85 Merge pull request #1008 from mailpoet/model_unit_test_update
Uses MailPoet's Model class vs. Idiorm's in test
2017-07-19 09:32:51 +03:00
b5b9531ff3 Merge pull request #1006 from mailpoet/premium_mixpanel
Add handlers for Premium events tracking, expose Premium version to JS [PREMIUM-24]
2017-07-18 16:14:24 +02:00
e2a048a65f Uses MP Model class vs. Idiorm's in test 2017-07-18 09:49:01 -04:00
c28726f118 Release 3.0.0-beta.36.3.1 2017-07-18 13:58:35 +03:00
7c74885669 Merge pull request #1003 from mailpoet/php53_listing_fix
Adds asArray() method to the base Model class [MAILPOET-1007]
2017-07-17 20:00:10 +03:00
5f74f34cba Adds notes explaining the fix 2017-07-17 12:15:39 -04:00
d6ef526a9d Add handlers for Premium events tracking, expose Premium version [PREMIUM-24] 2017-07-17 18:57:18 +03:00
0da0507e0a Fixes SMTP timing out on slow hosts
Increases default connection timeout value
Adds filter to specify custom connection timeout value

[MAILPOET-1004]
2017-07-17 15:21:33 +01:00
3f03c985bf Collect plugins info for analytics
[MAILPOET-974]
2017-07-17 14:46:26 +01:00
77f6e13aa3 Merge pull request #999 from mailpoet/url_extraction_fix
Replaces URL extraction regex with DOM parser [MAILPOET-1003]
2017-07-17 16:32:59 +03:00
213d0e8627 Distinguishes between link TYPE and link CATEGORY NAME
Uses $replacement_link variable for clarity
2017-07-17 09:14:11 -04:00
1d019bc11e Merge pull request #1004 from mailpoet/filter_to_whitelist_plugins_from_conflict_resolver
Adds filters to whitelist styles/scripts unloaded by our plugin [MAILPOET-1008]
2017-07-17 15:11:37 +02:00
ca12487416 moving shell code into a bash file 2017-07-17 11:38:41 +00:00
c5d42a5033 Merge pull request #995 from mailpoet/welcome-tab-update
Welcome tab update [MAILPOET-979]
2017-07-17 07:17:26 -04:00
3b079440b5 try without sharing workspace 2017-07-17 10:52:48 +00:00
419697991f Adding workflows to CircleCI
Splitting build into 2 builds:

- `build_qa_js`: Builds the project and runs the qa checks and JS tests.

- `php_5`: Runs the PHP tests with PHP 5.6.3

and adding a new build

- `php_7`: Runs the PHP tests with PHP 7.1
2017-07-17 10:26:17 +00:00
d119a1e5fa Send settings values to Mixpanel
[MAILPOET-974]
2017-07-17 11:15:29 +01:00
1bd4264dd5 Fix code style
[MAILPOET-979]
2017-07-17 09:20:28 +01:00
21ee60b7d7 Merge pull request #1002 from mailpoet/newsletter_duplication_update
Resets sent at data when duplicating a sent newsletter [MAILPOET-1005]
2017-07-17 10:07:29 +02:00
849ca27d1f Adds filters to whitelist styles or scripts 2017-07-15 14:57:40 -04:00
a4dad46fb7 Adds asArray() method to the base Model that's used as proxy for
Idiorm's as_array()
2017-07-15 14:25:50 -04:00
fac4c8fb41 Merge pull request #1000 from mailpoet/fix-frequency-smtp
Fix default frequency
2017-07-15 13:04:40 -04:00
cdc87c23ea Resets sent at data when duplicating a sent newsletter 2017-07-15 13:00:25 -04:00
34d09ce0c9 Sets mailer log error when queue cannot be saved during newsletter
pre-processing
2017-07-14 23:15:14 -04:00
fe9ae392f2 Replaces URL extraction regex with DOM parser
Simplifies link replacement logic
Cleans up code
2017-07-14 23:15:08 -04:00
9501640f4f Prevents double UTF-8 encoding 2017-07-14 14:03:48 -04:00
ad028ab55d Fix devault frequency 2017-07-14 08:01:54 +01:00
74cb8d9735 Merge pull request #998 from mailpoet/settings_flex_fix
Fix broken layout in IE 11 on a big screen + make it look like in previous versions [MAILPOET-1002]
2017-07-13 14:11:24 -04:00
381608df22 Fix broken layout in IE 11 on a big screen + make it look like in previous versions [MAILPOET-1002] 2017-07-13 21:03:24 +03:00
6aca598dc3 Fix tests: unneeded migration was triggered by resetting the DB version to 1.0.0 (after EnvTest)
This caused errors when pinging the daemon [MAILPOET-940]
2017-07-13 16:26:53 +03:00
acbe2e383a Add tests [MAILPOET-940] 2017-07-13 13:27:28 +03:00
55d3b67a2a Extract common and task-specific methods for subscribers [MAILPOET-940] 2017-07-13 13:27:28 +03:00
c02394b576 Prepare subscribers in the Bounce worker DB-side for performance reasons [MAILPOET-940] 2017-07-13 13:27:27 +03:00
6a9b8d88c2 Extract subscribers to a separate table in the Bounce worker [MAILPOET-940] 2017-07-13 13:27:27 +03:00
b24c51d800 Merge pull request #996 from mailpoet/add-extra-text
Add extra text on Send with... [MAILPOET-954]
2017-07-13 13:24:22 +03:00
d3a3d3b277 Merge pull request #993 from mailpoet/duplicate-content
Add an option to duplicate content blocks [MAILPOET-968]
2017-07-13 13:14:36 +03:00
3dcff8eb8a Update styles to handle more text
[MAILPOET-954]
2017-07-13 09:41:08 +01:00
401339244c Merge pull request #991 from mailpoet/fix-duplicate-smtp
Remove a duplicate field [MAILPOET-995]
2017-07-12 19:30:37 +03:00
653ecdc4d0 Add extra copy
[MAILPOET-954]
2017-07-12 16:54:49 +01:00
88d5952684 Remove duplicate id
[MAILPOET-979]
2017-07-12 14:55:53 +01:00
c4d6c19c67 Merge pull request #990 from mailpoet/eslint-no-var
Eslint fixes [MAILPOET-994]
2017-07-12 15:51:26 +02:00
0554a84f77 Apply new styles
[MAILPOET-979]
2017-07-12 13:38:56 +01:00
c01b57a383 Add poll
[MAILPOET-979]
2017-07-12 10:28:35 +01:00
65f4f493f1 Add sharing section
[MAILPOET-979]
2017-07-12 10:09:17 +01:00
8a7ea791b0 Move button to see all changelogs
[MAILPOET-979]
2017-07-12 09:35:10 +01:00
1823985172 Display only one set of changelog
[MAILPOET-979]
2017-07-12 09:19:22 +01:00
e735b5f3e0 Replace title
[MAILPOET-979]
2017-07-12 08:44:04 +01:00
cd5c57b7e9 Merge pull request #994 from mailpoet/fixing-readme
Fixing 'Get in touch' URL [MAILPOET-996]
2017-07-11 13:35:36 -04:00
fbf59723d8 Fixing 'Get in touch' URL 2017-07-11 16:57:56 +00:00
2e166a233b Update duplicate icon
[MAILPOET-968]
2017-07-11 17:19:41 +01:00
1608ba5893 Remove a duplicate field
[MAILPOET-995]
2017-07-11 15:39:22 +01:00
9d7eb8038d Fix eslint rule arrow-parens 2017-07-11 14:31:19 +01:00
c9c78a7160 Fix eslint rule indent 2017-07-11 14:31:19 +01:00
53df10dc2b Fix eslint rule eol-last 2017-07-11 14:31:19 +01:00
a746c124a3 Fix eslint rule object-curly-spacing 2017-07-11 14:31:19 +01:00
ca5a5301a8 Fix eslint rule no-var 2017-07-11 14:31:19 +01:00
7a2aaa86cf Tests that populator method is not run for versions below
3.0.0-beta.36.2.1
2017-07-11 14:26:29 +01:00
b626c7ea3c Release 3.0.0-beta.36.3.0 2017-07-11 12:50:33 +01:00
695152e947 Allow duplicate content
[MAILPOET-968]
2017-07-11 10:53:52 +01:00
a36fe400ed Merge pull request #966 from mailpoet/mp2tomp3migration
Settings migration from MP2 to MP3
2017-07-11 12:43:19 +03:00
22bb971db5 Merge pull request #980 from mailpoet/newsletter_listing_update
Sorts standard/history notification records by sent_at date in listings [MAILPOET-932]
2017-07-11 12:43:06 +03:00
b88452c5a2 Fixed: the "Skip Import" link was hidden after unit tests 2017-07-10 18:37:23 +02:00
4a2f9ad1f9 Remove unused code 2017-07-10 18:37:22 +02:00
593a7de9fe New: Add extra text when the migration is completed 2017-07-10 18:37:21 +02:00
e5ecf870c7 Fixed: SendGrid provider was selected even when Sendgrid was not selected in MP2 2017-07-10 18:37:21 +02:00
11cc97b201 Fixed: Unit tests failed if the database prefix was not "wp_" 2017-07-10 18:37:20 +02:00
e352b5bfad New: Migrate installation date 2017-07-10 18:37:19 +02:00
334448c964 New: Add paragraph below "What will be kept in MailPoet 3" 2017-07-10 18:37:18 +02:00
7d8d535cb3 New: Hide the progress bar and the logs if the import has not started yet 2017-07-10 18:37:17 +02:00
68988edd7e Fixed: Change the emails number if the frequency is greater than 15 minutes 2017-07-10 18:37:17 +02:00
f164e9bb95 Fixed: Leave the Newsletter task scheduler (cron) to its default value 2017-07-10 18:37:16 +02:00
fe83435d14 Fixed: "Subscribe in comments" always on 2017-07-10 18:37:15 +02:00
453b7683bc Fixed: SendGrid method and provider were not selected 2017-07-10 18:37:14 +02:00
25625b1ce1 Add unit tests for the settings migration 2017-07-10 18:37:13 +02:00
048d71164a Migrate the settings 2017-07-10 18:31:51 +02:00
24e682e92e Corrects typo 2017-07-10 12:20:37 -04:00
23d90c9f73 Merge pull request #985 from mailpoet/fix-mailpoet-activation
Fix firefox double submit [MAILPOET-992]
2017-07-10 15:53:17 +03:00
a9f190661f Remove unnecessary return statement [MAILPOET-992] 2017-07-10 15:51:19 +03:00
c1e56e5fa1 Update button type to prevent form submit
[MAILPOET-992]
2017-07-10 13:28:06 +01:00
e2bb2679e4 Fix firefox double submit
[MAILPOET-992]
2017-07-10 12:07:07 +01:00
d49530da0f Merge pull request #979 from mailpoet/update-readme
Update readme [MAILPOET-978]
2017-07-10 13:58:36 +03:00
0bc28ef3c7 Remove duplication
[MAILPOET-978]
2017-07-10 11:27:08 +01:00
563b7eccb0 Update video link in readme
[MAILPOET-978]
2017-07-10 11:06:42 +01:00
94a9b63136 Merge pull request #984 from mailpoet/fix-mailpoet-activation
Send the correct group to server [MAILPOET-992]
2017-07-10 12:53:48 +03:00
91ff008485 Make key check error messages more descriptive [MAILPOET-990] 2017-07-10 10:34:55 +01:00
cb8fa23c3f Send the correct group to server
[MAILPOET-992]
2017-07-10 09:18:43 +01:00
3499de05e8 Merge pull request #983 from mailpoet/link_tags_replacement_update
Updates the way link tags are replaced in translations [MAILPOET-991]
2017-07-09 12:14:42 +03:00
77ed4d34e8 Uses Helper's replaceLinkTags method to replace activation link in
subscription confirmation email
2017-07-08 12:00:45 -04:00
cfc5f5a88d Allows defining custom link tag 2017-07-08 11:56:51 -04:00
2514d87a00 Uses Helper's replaceLinkTags method to replace tags in translation
strings
2017-07-08 10:31:33 -04:00
23c6750ccc Removes leftover debug condition 2017-07-07 13:12:45 -04:00
bb2af5176b Tests that newsletters can be sorted by sent_at column 2017-07-07 11:05:39 -04:00
95b5206e8b Updates sending queue worker to set newsletter's sent_at field when
newsletter is sent
2017-07-07 11:05:39 -04:00
394118f113 Adds sent_at column to the newsletters table
Modifies populator to update existing newsletters' sent_at field
2017-07-07 11:05:33 -04:00
b691fb5a48 Adds sorting by sent_at to standard & notification history newsletter listings 2017-07-07 11:04:19 -04:00
1ba2492929 Combines Twig's "replaceLink" and Util/Helper's "replaceLinkTags"
methods into one
2017-07-07 11:02:20 -04:00
d08243b0ce Merge pull request #981 from mailpoet/tests_lint_rules
Fix ScopeClosingBrace, EmptyNonVariable sniffer rules in tests [MAILPOET-989]
2017-07-07 11:01:21 -04:00
189656fdc8 Fixes malformed URL 2017-07-07 09:52:08 -04:00
0be872eea9 Fix PHPCompatibility.PHP.EmptyNonVariable rule [MAILPOET-989] 2017-07-07 11:30:16 +03:00
22c39c0092 Fix PEAR.WhiteSpace.ScopeClosingBrace rule in tests [MAILPOET-989] 2017-07-07 11:11:16 +03:00
1b54e356b2 Merge pull request #978 from mailpoet/add-missing-callbacks
Add missing callbacks to ajax calls [MAILPOET-982]
2017-07-06 19:29:30 -04:00
9079d7d4db Merge pull request #977 from mailpoet/subscription_confirmation_update
Prevents repeat subscription confirmation/duplicate welcome notifications [MAILPOET-988]
2017-07-06 22:52:44 +03:00
160b28a632 Merge pull request #976 from mailpoet/editor-drag-and-drop
Fix reverting to mouse cursor auto icon after clicking Draggable object [MAILPOET-965]
2017-07-06 21:54:28 +03:00
03ebb30ac2 Update readme
[MAILPOET-978]
2017-07-06 15:43:04 +01:00
56eac1ae86 Add missing callbacks to ajax calls
[MAILPOET-982]
2017-07-06 13:06:14 +01:00
89da4c9aae Prevents repeat subscription confirmation
Prevents scheduling of duplicate welcome notifications
2017-07-05 19:50:57 -04:00
b510071857 Merge pull request #972 from mailpoet/merge-sending-method
Merge sending method [MAILPOET-953]
2017-07-05 19:59:30 +03:00
4bbec4700d Stub out interact.styleCursor method 2017-07-05 19:45:13 +03:00
29a2af2555 Fix reverting to mouse cursor auto icon after clicking Draggable object 2017-07-05 19:26:33 +03:00
94d57b5287 Make sure all frequency changes are displayed correctly
[MAILPOET-953]
2017-07-05 16:37:08 +01:00
6b7bc8a731 Make sure frequency is always set
[MAILPOET-953]
2017-07-05 16:37:08 +01:00
3dd0f00b7f Fix sending method
[MAILPOET-953]
2017-07-05 16:37:08 +01:00
b58f6cc4e0 Fix broken reporting
[MAILPOET-953]
2017-07-05 16:37:08 +01:00
7c942147ec Show frequency fields on initial page render
[MAILPOET-953]
2017-07-05 16:37:08 +01:00
6fca2061e6 Show fields on initial page render
[MAILPOET-953]
2017-07-05 16:37:08 +01:00
0acc41c887 Pre select the sending method
[MAILPOET-953]
2017-07-05 16:37:08 +01:00
20d1ac81e2 Save correct values
[MAILPOET-953]
2017-07-05 16:37:08 +01:00
cdb7b99728 Merge sending methods
[MAILPOET-953]
2017-07-05 16:37:08 +01:00
54cb838d71 Merge pull request #959 from mailpoet/scheduled_tasks
Refactor simple workers to use a ScheduledTask model [MAILPOET-940]
2017-07-05 17:28:08 +03:00
0b9ea23f0b Temporarily remove pause/resume methods from scheduled tasks [MAILPOET-940] 2017-07-05 17:12:35 +03:00
3e40f768b4 Add migration of simple scheduled tasks [MAILPOET-940] 2017-07-05 17:12:34 +03:00
6e929dcf79 Refactor simple workers to use a ScheduledTask model [MAILPOET-940] 2017-07-05 17:00:23 +03:00
7be01f0e4e Merge pull request #975 from mailpoet/eslint-fix-rules-rad
Bunch of fixed eslint rules
2017-07-05 14:20:24 +03:00
9cb08734a3 Return back function which is needed
[MAILPOET-985]
2017-07-05 11:36:39 +01:00
55fda047f6 Fix prefer-const eslint rule
[MAILPOET-985]
2017-07-05 09:55:00 +01:00
4706c5fc25 Fix prefer-arrow-callback eslint rule
[MAILPOET-985]
2017-07-05 09:48:35 +01:00
3ba857d03f Fix no-unused-vars eslint rule
[MAILPOET-985]
2017-07-05 09:46:08 +01:00
f39cbe6b55 Fix space-before-function-paren eslint rule
[MAILPOET-985]
2017-07-05 09:46:08 +01:00
6dc1bf4e95 Fix semi eslint rule
[MAILPOET-985]
2017-07-05 09:46:08 +01:00
5b65a8f0ac Fix radix eslint rule
[MAILPOET-985]
2017-07-05 09:46:08 +01:00
583adf86da Fix no-plusplus eslint rule
[MAILPOET-985]
2017-07-05 09:46:08 +01:00
3b4a1b686d Make build find command work cross-platform (Linux/Mac/Win) [MAILPOET-984] 2017-07-05 08:33:43 +01:00
5390dd8421 Merge branch 'master' of github.com:mailpoet/mailpoet 2017-07-04 18:15:16 +03:00
1ac6dd8ccb Switch to using CircleCI 2.0
We end up using Docker images for PHP 5.6 and MySQL, handle our own
Composer and NPM caches.
2017-07-04 15:56:02 +01:00
330 changed files with 6278 additions and 4112 deletions

View File

@ -1,8 +0,0 @@
#!/usr/bin/ruby
path = "/tmp"
Dir.mkdir(path) if !File.exists?(path)
File.open("#{path}/mailpoet-#{Time.now.to_f}.txt", "w") do |f|
sleep 5
f.puts ARGV.inspect
$stdin.each_line { |line| f.puts line }
end

View File

@ -1,3 +0,0 @@
; For Unix only. You may supply arguments as well (default: "sendmail -t -i").
; http://php.net/sendmail-path
sendmail_path = /home/ubuntu/mailpoet/.circle_ci/fake-sendmail.rb

View File

@ -3,11 +3,11 @@ Listen 8080
<VirtualHost *:8080>
UseCanonicalName Off
ServerName mailpoet.loc
DocumentRoot /home/ubuntu/mailpoet/wordpress
DocumentRoot /home/circleci/mailpoet/wordpress
DirectoryIndex index.php
LogLevel notice
<Directory /home/ubuntu/mailpoet/wordpress>
<Directory /home/circleci/mailpoet/wordpress>
Require all granted
</Directory>
</VirtualHost>

94
.circleci/config.yml Normal file
View File

@ -0,0 +1,94 @@
version: 2
jobs:
qa_js_php5:
working_directory: /home/circleci/mailpoet
docker:
- image: circleci/php:5.6.30-apache-browsers
- image: circleci/mysql:5.7
environment:
TZ: /usr/share/zoneinfo/Etc/UTC
steps:
- checkout
- run:
name: "Set up virtual host"
command: echo 127.0.0.1 mailpoet.loc | sudo tee -a /etc/hosts
- restore_cache:
key: composer-{{ checksum "composer.json" }}-{{ checksum "composer.lock" }}
- restore_cache:
key: npm-{{ checksum "package.json" }}
- run:
name: "Set up test environment"
command: source ./.circleci/setup.bash && setup php5
- save_cache:
key: composer-{{ checksum "composer.json" }}-{{ checksum "composer.lock" }}
paths:
- vendor
- save_cache:
key: npm-{{ checksum "package.json" }}
paths:
- node_modules
- run:
name: "QA Scripts"
command: ./do qa
- run:
name: "Preparing test results folder"
command: mkdir test-results
- run:
name: "JS tests"
command: |
mkdir test-results/mocha
./do t:j test-results/mocha/junit.xml
- run:
name: "PHP Unit tests"
command: |
WP_TEST_PATH="/home/circleci/mailpoet/wordpress" ./do t:u --xml
- store_test_results:
path: test-results/mocha
- store_artifacts:
path: test-results/mocha
destination: mocha
- store_test_results:
path: tests/_output
- store_artifacts:
path: tests/_output
destination: codeception
- store_artifacts:
path: /tmp/fake-mailer/
destination: fake-mailer
php7:
working_directory: /home/circleci/mailpoet
docker:
- image: circleci/php:7.1-apache-browsers
- image: circleci/mysql:5.7
environment:
TZ: /usr/share/zoneinfo/Etc/UTC
steps:
- checkout
- run:
name: "Set up virtual host"
command: echo 127.0.0.1 mailpoet.loc | sudo tee -a /etc/hosts
- restore_cache:
key: composer-{{ checksum "composer.json" }}-{{ checksum "composer.lock" }}
- restore_cache:
key: npm-{{ checksum "package.json" }}
- run:
name: "Set up test environment"
command: source ./.circleci/setup.bash && setup php7
- run:
name: "PHP Unit tests"
command: |
WP_TEST_PATH="/home/circleci/mailpoet/wordpress" ./do t:u --xml
- store_test_results:
path: tests/_output
- store_artifacts:
path: tests/_output
destination: codeception
- store_artifacts:
path: /tmp/fake-mailer/
destination: fake-mailer
workflows:
version: 2
build_and_test:
jobs:
- qa_js_php5
- php7

17
.circleci/fake-sendmail.php Executable file
View File

@ -0,0 +1,17 @@
#!/usr/local/bin/php
<?php
$path = "/tmp/fake-mailer";
if(!file_exists($path)) {
mkdir($path);
}
$filename = $path . '/mailpoet-' . microtime(true) . '.txt';
$file_handle = fopen($filename, "w");
$call_arguments = print_r($argv, true) . "\n";
fwrite($file_handle, $call_arguments);
while($line = fgets(STDIN)) {
fwrite($file_handle, $line);
}
fclose($file_handle);

View File

@ -0,0 +1,9 @@
; For Unix only. You may supply arguments as well (default: "sendmail -t -i").
; http://php.net/sendmail-path
sendmail_path = /usr/local/bin/fake-sendmail.php
[Date]
; Defines the default timezone used by the date functions
; http://php.net/date.timezone
date.timezone = UTC

48
.circleci/setup.bash Normal file
View File

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

View File

@ -14,7 +14,6 @@
"comma-dangle": 0,
"space-before-function-paren": 0,
"prefer-arrow-callback": 0,
"no-undef": 0,
@ -44,7 +43,6 @@
"no-empty": 0,
"no-extra-semi": 0,
"no-useless-escape": 0,
"comma-spacing": 0,
"wrap-iife": 0,
"no-unused-expressions": 0,
"block-spacing": 0,

View File

@ -11,9 +11,12 @@
}
},
"rules": {
"import/no-amd": 0,
"comma-dangle": ["error", "always-multiline"],
"import/no-amd": 0,
"react/no-multi-comp": 0,
"react/sort-comp": 0,
"react/jsx-max-props-per-line": 0,
@ -39,24 +42,14 @@
"jsx-a11y/no-static-element-interactions": 0,
"jsx-a11y/alt-text": 0,
"comma-dangle": 0,
"prefer-arrow-callback": 0,
"func-names": 0,
"space-before-function-paren": 0,
"object-shorthand": 0,
"no-bitwise": 0,
"arrow-body-style": 0,
"prefer-template": 0,
"eol-last": 0,
"no-unused-vars": 0,
"no-plusplus": 0,
"semi": 0,
"keyword-spacing": 0,
"default-case": 0,
"quote-props": 0,
"indent": 0,
"prefer-const": 0,
"arrow-parens": 0,
"array-callback-return": 0,
"consistent-return": 0,
"no-unreachable": 0,
@ -67,7 +60,6 @@
"camelcase": 0,
"template-curly-spacing": 0,
"quotes": 0,
"radix": 0,
"eqeqeq": 0,
"no-lonely-if": 0,
"space-unary-ops": 0,
@ -83,7 +75,6 @@
"newline-per-chained-call": 0,
"no-else-return": 0,
"max-len": 0,
"comma-spacing": 0,
"no-useless-concat": 0,
"no-unused-expressions": 0,
"no-sequences": 0,
@ -96,13 +87,11 @@
"one-var-declaration-per-line": 0,
"no-script-url": 0,
"wrap-iife": 0,
"no-var": 0,
"vars-on-top": 0,
"space-infix-ops": 0,
"no-irregular-whitespace": 0,
"padded-blocks": 0,
"no-underscore-dangle": 0,
"object-curly-spacing": 0,
"no-undef": 0
}
}

View File

@ -35,7 +35,6 @@
"quote-props": 0,
"no-shadow": 0,
"padded-blocks": 0,
"comma-dangle": 0,
"vars-on-top": 0,
"space-before-blocks": 0,
"object-curly-spacing": 0,

View File

@ -199,10 +199,16 @@ class RoboFile extends \Robo\Tasks {
return $this->_exec($command);
}
function testDebug() {
$this->_exec('vendor/bin/codecept build');
function testDebug($opts=['file' => null, 'xml' => false]) {
$this->loadEnv();
return $this->_exec('vendor/bin/codecept run unit --debug');
$this->_exec('vendor/bin/codecept build');
$command = 'vendor/bin/codecept run unit --debug -f '.(($opts['file']) ? $opts['file'] : '');
if($opts['xml']) {
$command .= ' --xml';
}
return $this->_exec($command);
}
function testFailed() {
@ -239,6 +245,7 @@ class RoboFile extends \Robo\Tasks {
->taskExec(
'./vendor/bin/phpcs '.
'--standard=./tasks/code_sniffer/MailPoet '.
'--runtime-set testVersion 5.3-7.0 '.
'--ignore=./lib/Util/Sudzy/*,./lib/Util/CSS.php,./lib/Util/XLSXWriter.php,'.
'./lib/Util/pQuery/*,./lib/Config/PopulatorData/Templates/* '.
'lib/ '.
@ -246,7 +253,8 @@ class RoboFile extends \Robo\Tasks {
)
->taskExec(
'./vendor/bin/phpcs '.
'--standard=./tasks/code_sniffer/MailPoetTests '.
'--standard=./tasks/code_sniffer/MailPoet '.
'--runtime-set testVersion 5.4-7.0 '.
'--ignore=./tests/unit/_bootstrap.php '.
'tests/unit/ '.
$severityFlag
@ -284,8 +292,9 @@ class RoboFile extends \Robo\Tasks {
$plugin_data = get_plugin_data('mailpoet.php', false, false);
$plugin_version = $plugin_data['Version'];
$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';
$this->say('Publishing version: ' . $plugin_version);
// Sanity checks
@ -413,4 +422,4 @@ class RoboFile extends \Robo\Tasks {
require_once(ABSPATH . WPINC . '/plugin.php');
require_once(ABSPATH . 'wp-admin/includes/plugin.php');
}
}
}

View File

@ -24,5 +24,6 @@
@require 'subscribers'
@require 'pages'
@require 'pages_custom'
@require 'mp2migrator'

View File

@ -21,6 +21,9 @@ a:focus
.mailpoet_spaced_block
margin: 1em 0
.mailpoet_centered
text-align: center
// select 2
.select2-container
width: 25em !important

View File

@ -62,3 +62,9 @@ $draggable-widget-z-index = 2
background-color: $primary-active-color
box-shadow(inset 1px 2px 1px $primary-inset-shadow-color)
color: $white-color
.mailpoet_droppable_block
cursor: move
&.mailpoet_ignore_drag
cursor: auto

View File

@ -26,10 +26,6 @@ $block-text-line-height = $text-line-height
&.mailpoet_highlight > .mailpoet_block_highlight
border: 1px dashed $block-hover-highlight-color
.mailpoet_block:last-child
margin-bottom: 0
.mailpoet_content
position: relative
line-height: $block-text-line-height

View File

@ -2,6 +2,7 @@
Based on /wp-admin/css/about.css of WP 4.7.
This is to make MailPoet pages independent of the WordPress
About page styles that may differ across WP versions.
Please add custom styles to pages_custom.styl
*/
.mailpoet-about-wrap

View File

@ -0,0 +1,35 @@
/*
Custom styles for MailPoet pages.
*/
.mailpoet-about-wrap
.videoWrapper
position: relative
padding-bottom: 56.25% /* 16:9 */
/*padding-top: 25px*/
height: 0
iframe
position: absolute
top: 0
left: 0
width: 100%
height: 100%
.mailpoet_video
border: 1px solid rgba(0, 0, 0, 0.1)
#mailpoet-changelog ul
list-style: disc
padding-left: 20px
h2.mailpoet-feature-top
margin: 50px auto
a.button.go-to-plugin
margin-top: 2em
p.top-space-triple
margin-top: 3em

View File

@ -9,15 +9,25 @@
// sending methods
.mailpoet_sending_methods
margin 25px 0 0 0
li
float left
position relative
padding 15px 15px 0 15px
display flex
flex-direction row
justify-content flex-start
> li
flex-grow 1
flex-shrink 1
display flex
flex-direction column
flex-basis 0
margin 0 25px 25px 0
width 300px
height 300px
border 1px solid #dedede
background-color #fff
max-width 500px
.mailpoet_sending_method_description
padding: 25px
flex-grow 1
flex-shrink 0
> li:last-child
margin-right 0
h3
text-align center
height 54px
@ -25,12 +35,12 @@
.mailpoet_description
font-size 14px
.mailpoet_status
display flex
flex-direction row
justify-content space-between
align-items center
background-color #2f2f2f
color #fff
position absolute
bottom 0
left 0
right 0
text-overflow ellipsis
padding 15px
span
@ -43,23 +53,17 @@
visibility visible
#mailpoet_mta_activate
visibility hidden
.mailpoet_actions
bottom 15px
color #fff
padding 0
position absolute
right 15px
.button-secondary
margin 0 -6px -4px 0
// premium key
.mailpoet_key
&_valid
&::before
content ' '
&_invalid
&::before
content: ' '
ul.sending-method-benefits
list-style-type: none
margin-bottom: 2em
margin-top: 2em
.mailpoet_success_item::before
content ' '
.mailpoet_error_item::before
content ' '
// responsive
@media screen and (max-width: 782px)
@ -67,8 +71,10 @@
width auto
.mailpoet_sending_methods
li
float none
width auto
flex-flow: row wrap
justify-content: space-around
> li
margin-right 0
flex-basis auto

View File

@ -9,7 +9,7 @@ function requestFailed(errorMessage, xhr) {
message: message
}
]
}
};
}
define('ajax', ['mailpoet', 'jquery', 'underscore'], function(MailPoet, jQuery, _) {
@ -50,7 +50,7 @@ define('ajax', ['mailpoet', 'jquery', 'underscore'], function(MailPoet, jQuery,
endpoint: this.options.endpoint,
method: this.options.action,
data: this.options.data || {}
}
};
},
request: function(method, options) {
// set options
@ -62,8 +62,8 @@ define('ajax', ['mailpoet', 'jquery', 'underscore'], function(MailPoet, jQuery,
// remove null values from the data object
if (_.isObject(params.data)) {
params.data = _.pick(params.data, function(value) {
return (value !== null)
})
return (value !== null);
});
}
// ajax request

View File

@ -55,7 +55,7 @@ function cacheEvent(forced, name, data) {
eventsCache.push({
name: name,
data: data,
forced: forced,
forced: forced
});
}

View File

@ -1,15 +1,15 @@
define([
'react'
'react',
],
function(
(
React
) {
) => {
const FormFieldCheckbox = React.createClass({
onValueChange: function(e) {
onValueChange: function (e) {
e.target.value = this.refs.checkbox.checked ? '1' : '0';
return this.props.onValueChange(e);
},
render: function() {
render: function () {
if (this.props.field.values === undefined) {
return false;
}
@ -42,8 +42,8 @@ function(
{ options }
</div>
);
}
},
});
return FormFieldCheckbox;
});
});

View File

@ -1,10 +1,10 @@
define([
'react',
'moment',
], function(
], (
React,
Moment
) {
) => {
class FormFieldDateYear extends React.Component {
render() {
const yearsRange = 100;
@ -17,7 +17,7 @@ define([
}
const currentYear = Moment().year();
for (let i = currentYear; i >= currentYear - yearsRange; i--) {
for (let i = currentYear; i >= currentYear - yearsRange; i -= 1) {
years.push((
<option
key={ i }
@ -47,7 +47,7 @@ define([
));
}
for (let i = 1; i <= 12; i++) {
for (let i = 1; i <= 12; i += 1) {
months.push((
<option
key={ i }
@ -77,7 +77,7 @@ define([
));
}
for (let i = 1; i <= 31; i++) {
for (let i = 1; i <= 31; i += 1) {
days.push((
<option
key={ i }
@ -104,13 +104,13 @@ define([
this.state = {
year: '',
month: '',
day: ''
}
day: '',
};
}
componentDidMount() {
this.extractDateParts();
}
componentDidUpdate(prevProps, prevState) {
componentDidUpdate(prevProps) {
if (
(this.props.item !== undefined && prevProps.item !== undefined)
&& (this.props.item.id !== prevProps.item.id)
@ -132,7 +132,7 @@ define([
this.setState({
year: dateTime.format('YYYY'),
month: dateTime.format('M'),
day: dateTime.format('D')
day: dateTime.format('D'),
});
}
formatValue() {
@ -145,28 +145,28 @@ define([
value = {
'year': this.state.year,
'month': this.state.month,
'day': this.state.day
'day': this.state.day,
};
break;
break;
case 'year_month':
value = {
'year': this.state.year,
'month': this.state.month
'month': this.state.month,
};
break;
break;
case 'month':
value = {
'month': this.state.month
'month': this.state.month,
};
break;
break;
case 'year':
value = {
'year': this.state.year
'year': this.state.year,
};
break;
break;
}
return value;
@ -181,16 +181,16 @@ define([
field = matches[1];
property = matches[2];
let value = ~~(e.target.value);
const value = ~~(e.target.value);
this.setState({
[`${property}`]: value
[`${property}`]: value,
}, () => {
this.props.onValueChange({
target: {
name: field,
value: this.formatValue()
}
value: this.formatValue(),
},
});
});
}
@ -201,7 +201,7 @@ define([
const dateType = this.props.field.params.date_type;
const dateSelects = dateFormats[dateType][0].split('/');
const fields = dateSelects.map(type => {
const fields = dateSelects.map((type) => {
switch(type) {
case 'YYYY':
return (<FormFieldDateYear
@ -212,7 +212,7 @@ define([
year={ this.state.year }
placeholder={ this.props.field.year_placeholder }
/>);
break;
break;
case 'MM':
return (<FormFieldDateMonth
@ -224,7 +224,7 @@ define([
monthNames={ monthNames }
placeholder={ this.props.field.month_placeholder }
/>);
break;
break;
case 'DD':
return (<FormFieldDateDay
@ -235,9 +235,9 @@ define([
day={ this.state.day }
placeholder={ this.props.field.day_placeholder }
/>);
break;
break;
}
});
});
return (
<div>
@ -248,4 +248,4 @@ define([
};
return FormFieldDate;
});
});

View File

@ -8,7 +8,7 @@ define([
'form/fields/selection.jsx',
'form/fields/date.jsx',
],
function(
(
React,
FormFieldText,
FormFieldTextarea,
@ -17,17 +17,17 @@ function(
FormFieldCheckbox,
FormFieldSelection,
FormFieldDate
) {
var FormField = React.createClass({
renderField: function(data, inline = false) {
var description = false;
) => {
const FormField = React.createClass({
renderField: function (data, inline = false) {
let description = false;
if(data.field.description) {
description = (
<p className="description">{ data.field.description }</p>
);
}
var field = false;
let field = false;
if(data.field['field'] !== undefined) {
data.field = jQuery.merge(data.field, data.field.field);
@ -36,35 +36,35 @@ function(
switch(data.field.type) {
case 'text':
field = (<FormFieldText {...data} />);
break;
break;
case 'textarea':
field = (<FormFieldTextarea {...data} />);
break;
break;
case 'select':
field = (<FormFieldSelect {...data} />);
break;
break;
case 'radio':
field = (<FormFieldRadio {...data} />);
break;
break;
case 'checkbox':
field = (<FormFieldCheckbox {...data} />);
break;
break;
case 'selection':
field = (<FormFieldSelection {...data} />);
break;
break;
case 'date':
field = (<FormFieldDate {...data} />);
break;
break;
case 'reactComponent':
field = (<data.field.component {...data} />);
break;
break;
}
if(inline === true) {
@ -83,23 +83,23 @@ function(
);
}
},
render: function() {
var field = false;
render: function () {
let field = false;
if(this.props.field['fields'] !== undefined) {
field = this.props.field.fields.map(function(subfield, index) {
field = this.props.field.fields.map((subfield, index) => {
return this.renderField({
index: index,
field: subfield,
item: this.props.item,
onValueChange: this.props.onValueChange || false
onValueChange: this.props.onValueChange || false,
});
}.bind(this));
});
} else {
field = this.renderField(this.props);
}
var tip = false;
let tip = false;
if(this.props.field.tip) {
tip = (
<p className="description">{ this.props.field.tip }</p>
@ -121,7 +121,7 @@ function(
</td>
</tr>
);
}
},
});
return FormField;

View File

@ -1,11 +1,11 @@
define([
'react'
'react',
],
function(
(
React
) {
) => {
const FormFieldRadio = React.createClass({
render: function() {
render: function () {
if (this.props.field.values === undefined) {
return false;
}
@ -34,8 +34,8 @@ function(
{ options }
</div>
);
}
},
});
return FormFieldRadio;
});
});

View File

@ -1,5 +1,5 @@
import React from 'react'
import _ from 'underscore'
import React from 'react';
import _ from 'underscore';
const FormFieldSelect = React.createClass({
render() {
@ -33,12 +33,12 @@ const FormFieldSelect = React.createClass({
_.map(
_.sortBy(
_.pairs(this.props.field.values),
(item) => sortBy(item[0], item[1])
item => sortBy(item[0], item[1])
),
(item) => item[0]
item => item[0]
);
} else {
keys = Object.keys(this.props.field.values)
keys = Object.keys(this.props.field.values);
}
const options = keys.map(
@ -70,7 +70,7 @@ const FormFieldSelect = React.createClass({
{options}
</select>
);
}
},
});
module.exports = FormFieldSelect;

View File

@ -2,35 +2,35 @@ define([
'react',
'react-dom',
'jquery',
'select2'
'select2',
],
function(
(
React,
ReactDOM,
jQuery
) {
var Selection = React.createClass({
getInitialState: function() {
) => {
const Selection = React.createClass({
getInitialState: function () {
return {
items: [],
select2: false
select2: false,
};
},
componentWillMount: function() {
componentWillMount: function () {
this.loadCachedItems();
},
allowMultipleValues: function() {
allowMultipleValues: function () {
return (this.props.field.multiple === true);
},
isSelect2Initialized: function() {
isSelect2Initialized: function () {
return (this.state.select2 === true);
},
componentDidMount: function() {
componentDidMount: function () {
if(this.allowMultipleValues()) {
this.setupSelect2();
}
},
componentDidUpdate: function(prevProps, prevState) {
componentDidUpdate: function (prevProps) {
if(
(this.props.item !== undefined && prevProps.item !== undefined)
&& (this.props.item.id !== prevProps.item.id)
@ -40,24 +40,24 @@ function(
.trigger('change');
}
},
componentWillUnmount: function() {
componentWillUnmount: function () {
if(this.allowMultipleValues()) {
this.destroySelect2();
}
},
destroySelect2: function() {
destroySelect2: function () {
if(this.isSelect2Initialized()) {
jQuery('#'+this.refs.select.id).select2('destroy');
}
},
setupSelect2: function() {
setupSelect2: function () {
if(this.isSelect2Initialized()) {
return;
}
var select2 = jQuery('#'+this.refs.select.id).select2({
const select2 = jQuery('#'+this.refs.select.id).select2({
width: (this.props.width || ''),
templateResult: function(item) {
templateResult: function (item) {
if(item.element && item.element.selected) {
return null;
} else {
@ -67,14 +67,14 @@ function(
return item.text;
}
}
}
},
});
var hasRemoved = false;
select2.on('select2:unselecting', function(e) {
let hasRemoved = false;
select2.on('select2:unselecting', () => {
hasRemoved = true;
});
select2.on('select2:opening', function(e) {
select2.on('select2:opening', (e) => {
if(hasRemoved === true) {
hasRemoved = false;
e.preventDefault();
@ -85,13 +85,13 @@ function(
this.setState({ select2: true });
},
getSelectedValues: function() {
getSelectedValues: function () {
if(this.props.field['selected'] !== undefined) {
return this.props.field['selected'](this.props.item);
} else if(this.props.item !== undefined && this.props.field.name !== undefined) {
if (this.allowMultipleValues()) {
if (Array.isArray(this.props.item[this.props.field.name])) {
return this.props.item[this.props.field.name].map(function(item) {
return this.props.item[this.props.field.name].map((item) => {
return item.id;
});
}
@ -101,9 +101,9 @@ function(
}
return null;
},
loadCachedItems: function() {
loadCachedItems: function () {
if(typeof(window['mailpoet_'+this.props.field.endpoint]) !== 'undefined') {
var items = window['mailpoet_'+this.props.field.endpoint];
let items = window['mailpoet_'+this.props.field.endpoint];
if(this.props.field['filter'] !== undefined) {
@ -111,39 +111,39 @@ function(
}
this.setState({
items: items
items: items,
});
}
},
handleChange: function(e) {
handleChange: function (e) {
if(this.props.onValueChange !== undefined) {
if(this.props.field.multiple) {
value = jQuery('#'+this.refs.select.id).val();
} else {
value = e.target.value;
}
var transformedValue = this.transformChangedValue(value);
const transformedValue = this.transformChangedValue(value);
this.props.onValueChange({
target: {
target: {
value: transformedValue,
name: this.props.field.name
}
name: this.props.field.name,
},
});
}
},
getLabel: function(item) {
getLabel: function (item) {
if(this.props.field['getLabel'] !== undefined) {
return this.props.field.getLabel(item, this.props.item);
}
return item.name;
},
getSearchLabel: function(item) {
getSearchLabel: function (item) {
if(this.props.field['getSearchLabel'] !== undefined) {
return this.props.field.getSearchLabel(item, this.props.item);
}
return null;
},
getValue: function(item) {
getValue: function (item) {
if(this.props.field['getValue'] !== undefined) {
return this.props.field.getValue(item, this.props.item);
}
@ -152,18 +152,18 @@ function(
// When it's impossible to represent the desired value in DOM,
// this function may be used to transform the placeholder value into
// desired value.
transformChangedValue: function(value) {
transformChangedValue: function (value) {
if(typeof this.props.field['transformChangedValue'] === 'function') {
return this.props.field.transformChangedValue.call(this, value);
} else {
return value;
}
},
render: function() {
render: function () {
const options = this.state.items.map((item, index) => {
let label = this.getLabel(item);
let searchLabel = this.getSearchLabel(item);
let value = this.getValue(item);
const label = this.getLabel(item);
const searchLabel = this.getSearchLabel(item);
const value = this.getValue(item);
return (
<option
@ -186,7 +186,7 @@ function(
{...this.props.field.validation}
>{ options }</select>
);
}
},
});
return Selection;

View File

@ -1,4 +1,4 @@
import React from 'react'
import React from 'react';
const FormFieldText = React.createClass({
render() {
@ -29,7 +29,7 @@ const FormFieldText = React.createClass({
{...this.props.field.validation}
/>
);
}
},
});
module.exports = FormFieldText;
module.exports = FormFieldText;

View File

@ -1,11 +1,11 @@
define([
'react'
'react',
],
function(
(
React
) {
var FormFieldTextarea = React.createClass({
render: function() {
) => {
const FormFieldTextarea = React.createClass({
render: function () {
return (
<textarea
type="text"
@ -19,8 +19,8 @@ function(
{...this.props.field.validation}
/>
);
}
},
});
return FormFieldTextarea;
});
});

View File

@ -4,54 +4,54 @@ define(
'mailpoet',
'classnames',
'react-router',
'form/fields/field.jsx'
'form/fields/field.jsx',
],
function(
(
React,
MailPoet,
classNames,
Router,
FormField
) {
) => {
var Form = React.createClass({
const Form = React.createClass({
contextTypes: {
router: React.PropTypes.object.isRequired
router: React.PropTypes.object.isRequired,
},
getDefaultProps: function() {
getDefaultProps: function () {
return {
params: {},
};
},
getInitialState: function() {
getInitialState: function () {
return {
loading: false,
errors: [],
item: {}
item: {},
};
},
getValues: function() {
getValues: function () {
return this.props.item ? this.props.item : this.state.item;
},
getErrors: function() {
getErrors: function () {
return this.props.errors ? this.props.errors : this.state.errors;
},
componentDidMount: function() {
componentDidMount: function () {
if(this.isMounted()) {
if(this.props.params.id !== undefined) {
this.loadItem(this.props.params.id);
} else {
this.setState({
item: jQuery('.mailpoet_form').serializeObject()
item: jQuery('.mailpoet_form').serializeObject(),
});
}
}
},
componentWillReceiveProps: function(props) {
componentWillReceiveProps: function (props) {
if(props.params.id === undefined) {
this.setState({
loading: false,
item: {}
item: {},
});
if (props.item === undefined) {
this.refs.form.reset();
@ -60,7 +60,7 @@ define(
this.loadItem(props.params.id);
}
},
loadItem: function(id) {
loadItem: function (id) {
this.setState({ loading: true });
MailPoet.Ajax.post({
@ -68,23 +68,23 @@ define(
endpoint: this.props.endpoint,
action: 'get',
data: {
id: id
}
id: id,
},
}).done((response) => {
this.setState({
loading: false,
item: response.data
item: response.data,
});
}).fail((response) => {
}).fail(() => {
this.setState({
loading: false,
item: {}
}, function() {
item: {},
}, function () {
this.context.router.push('/new');
});
});
},
handleSubmit: function(e) {
handleSubmit: function (e) {
e.preventDefault();
// handle validation
@ -97,16 +97,16 @@ define(
this.setState({ loading: true });
// only get values from displayed fields
var item = {};
this.props.fields.map(function(field) {
const item = {};
this.props.fields.map((field) => {
if(field['fields'] !== undefined) {
field.fields.map(function(subfield) {
field.fields.map((subfield) => {
item[subfield.name] = this.state.item[subfield.name];
}.bind(this));
});
} else {
item[field.name] = this.state.item[field.name];
}
}.bind(this));
});
// set id if specified
if(this.props.params.id !== undefined) {
item.id = this.props.params.id;
@ -116,10 +116,10 @@ define(
api_version: window.mailpoet_api_version,
endpoint: this.props.endpoint,
action: 'save',
data: item
data: item,
}).always(() => {
this.setState({ loading: false });
}).done((response) => {
}).done(() => {
if(this.props.onSuccess !== undefined) {
this.props.onSuccess();
} else {
@ -137,24 +137,25 @@ define(
}
});
},
handleValueChange: function(e) {
handleValueChange: function (e) {
if (this.props.onChange) {
return this.props.onChange(e);
} else {
var item = this.state.item,
field = e.target.name;
const item = this.state.item;
const field = e.target.name;
item[field] = e.target.value;
this.setState({
item: item
item: item,
});
return true;
}
},
render: function() {
render: function () {
let errors;
if(this.getErrors() !== undefined) {
var errors = this.getErrors().map(function(error, index) {
errors = this.getErrors().map((error, index) => {
return (
<p key={ 'error-'+index } className="mailpoet_error">
{ error.message }
@ -163,13 +164,13 @@ define(
});
}
var formClasses = classNames(
const formClasses = classNames(
'mailpoet_form',
{ 'mailpoet_form_loading': this.state.loading || this.props.loading }
);
var beforeFormContent = false;
var afterFormContent = false;
let beforeFormContent = false;
let afterFormContent = false;
if (this.props.beforeFormContent !== undefined) {
beforeFormContent = this.props.beforeFormContent(this.getValues());
@ -179,17 +180,26 @@ define(
afterFormContent = this.props.afterFormContent(this.getValues());
}
var fields = this.props.fields.map(function(field, i) {
const fields = this.props.fields.map((field, i) => {
// Compose an onChange handler from the default and custom one
let onValueChange = this.handleValueChange;
if (field.onBeforeChange) {
onValueChange = (e) => {
field.onBeforeChange(e);
return this.handleValueChange(e);
};
}
return (
<FormField
field={ field }
item={ this.getValues() }
onValueChange={ this.handleValueChange }
onValueChange={ onValueChange }
key={ 'field-'+i } />
);
}.bind(this));
});
var actions = false;
let actions = false;
if(this.props.children) {
actions = this.props.children;
} else {
@ -228,7 +238,7 @@ define(
{ afterFormContent }
</div>
);
}
},
});
return Form;

View File

@ -1,15 +1,15 @@
import React from 'react'
import ReactDOM from 'react-dom'
import { Router, Route, IndexRoute, Link, useRouterHistory } from 'react-router'
import { createHashHistory } from 'history'
import FormList from 'forms/list.jsx'
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, IndexRoute, useRouterHistory } from 'react-router';
import { createHashHistory } from 'history';
import FormList from 'forms/list.jsx';
const history = useRouterHistory(createHashHistory)({ queryKey: false });
const App = React.createClass({
render() {
return this.props.children
}
return this.props.children;
},
});
const container = document.getElementById('forms_container');
@ -23,4 +23,4 @@ if(container) {
</Route>
</Router>
), container);
}
}

View File

@ -1,29 +1,27 @@
import React from 'react'
import ReactDOM from 'react-dom'
import { Router, Link } from 'react-router'
import Listing from 'listing/listing.jsx'
import classNames from 'classnames'
import MailPoet from 'mailpoet'
import React from 'react';
import Listing from 'listing/listing.jsx';
import classNames from 'classnames';
import MailPoet from 'mailpoet';
const columns = [
{
name: 'name',
label: MailPoet.I18n.t('formName'),
sortable: true
sortable: true,
},
{
name: 'segments',
label: MailPoet.I18n.t('segments')
label: MailPoet.I18n.t('segments'),
},
{
name: 'signups',
label: MailPoet.I18n.t('signups')
label: MailPoet.I18n.t('signups'),
},
{
name: 'created_at',
label: MailPoet.I18n.t('createdOn'),
sortable: true
}
sortable: true,
},
];
const messages = {
@ -71,38 +69,38 @@ const messages = {
).replace('%$1d', count.toLocaleString());
}
MailPoet.Notice.success(message);
}
},
};
const bulk_actions = [
{
name: 'trash',
label: MailPoet.I18n.t('moveToTrash'),
onSuccess: messages.onTrash
}
onSuccess: messages.onTrash,
},
];
const item_actions = [
{
name: 'edit',
label: MailPoet.I18n.t('edit'),
link: function(item) {
link: function (item) {
return (
<a href={ `admin.php?page=mailpoet-form-editor&id=${item.id}` }>{MailPoet.I18n.t('edit')}</a>
);
}
},
},
{
name: 'duplicate',
label: MailPoet.I18n.t('duplicate'),
onClick: function(item, refresh) {
onClick: function (item, refresh) {
return MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: 'forms',
action: 'duplicate',
data: {
id: item.id
}
id: item.id,
},
}).done((response) => {
MailPoet.Notice.success(
(MailPoet.I18n.t('formDuplicated')).replace('%$1s', response.data.name)
@ -111,16 +109,16 @@ const item_actions = [
}).fail((response) => {
if (response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
}
});
}
},
},
{
name: 'trash'
}
name: 'trash',
},
];
const FormList = React.createClass({
@ -128,28 +126,28 @@ const FormList = React.createClass({
MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: 'forms',
action: 'create'
action: 'create',
}).done((response) => {
window.location = mailpoet_form_edit_url + response.data.id;
}).fail((response) => {
if (response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
}
});
},
renderItem(form, actions) {
let row_classes = classNames(
const row_classes = classNames(
'manage-column',
'column-primary',
'has-row-actions'
);
let segments = mailpoet_segments.filter(function(segment) {
let segments = mailpoet_segments.filter((segment) => {
return (jQuery.inArray(segment.id, form.segments) !== -1);
}).map(function(segment) {
}).map((segment) => {
return segment.name;
}).join(', ');
@ -205,7 +203,7 @@ const FormList = React.createClass({
/>
</div>
);
}
},
});
module.exports = FormList;

View File

@ -1,17 +1,17 @@
import React from 'react'
import ReactDOM from 'react-dom'
import { Router, Route, IndexRedirect, useRouterHistory } from 'react-router'
import { createHashHistory } from 'history'
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, IndexRedirect, useRouterHistory } from 'react-router';
import { createHashHistory } from 'history';
import KnowledgeBase from 'help/knowledge_base.jsx'
import SystemInfo from 'help/system_info.jsx'
import KnowledgeBase from 'help/knowledge_base.jsx';
import SystemInfo from 'help/system_info.jsx';
const history = useRouterHistory(createHashHistory)({ queryKey: false });
const App = React.createClass({
render() {
return this.props.children;
}
},
});
const container = document.getElementById('help_container');

View File

@ -1,7 +1,7 @@
import React from 'react'
import MailPoet from 'mailpoet'
import React from 'react';
import MailPoet from 'mailpoet';
import Tabs from './tabs.jsx'
import Tabs from './tabs.jsx';
function KnowledgeBase() {
@ -26,4 +26,4 @@ function KnowledgeBase() {
);
};
module.exports = KnowledgeBase;
module.exports = KnowledgeBase;

View File

@ -1,8 +1,8 @@
import React from 'react'
import MailPoet from 'mailpoet'
import _ from 'underscore'
import React from 'react';
import MailPoet from 'mailpoet';
import _ from 'underscore';
import Tabs from './tabs.jsx'
import Tabs from './tabs.jsx';
function handleFocus(event) {
event.target.select();
@ -35,7 +35,7 @@ function KnowledgeBase() {
<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>
</div>
@ -44,4 +44,4 @@ function KnowledgeBase() {
);
};
module.exports = KnowledgeBase;
module.exports = KnowledgeBase;

View File

@ -1,18 +1,18 @@
import React from 'react'
import { Link } from 'react-router'
import classNames from 'classnames'
import MailPoet from 'mailpoet'
import React from 'react';
import { Link } from 'react-router';
import classNames from 'classnames';
import MailPoet from 'mailpoet';
const tabs = [
{
name: 'knowledgeBase',
label: MailPoet.I18n.t('tabKnowledgeBaseTitle'),
link: '/knowledgeBase'
link: '/knowledgeBase',
},
{
name: 'systemInfo',
label: MailPoet.I18n.t('tabSystemInfoTitle'),
link: '/systemInfo'
link: '/systemInfo',
},
];

View File

@ -1,3 +1,3 @@
define([], function() {
!function(e,o,n){window.HSCW=o,window.HS=n,n.beacon=n.beacon||{};var t=n.beacon;t.userConfig={},t.readyQueue=[],t.config=function(e){this.userConfig=e},t.ready=function(e){this.readyQueue.push(e)},o.config={docs:{enabled:!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||{});
!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

@ -27,7 +27,7 @@ define(
coerce_types = { 'true': !0, 'false': !1, 'null': null };
// Iterate over all name=value pairs.
$.each( this.serializeArray(), function(j,v){
$.each( this.serializeArray(), function(j, v){
var key = v.name,
val = v.value,
cur = obj,

View File

@ -1,53 +1,53 @@
define([
'react',
'mailpoet'
'mailpoet',
],
function(
(
React,
MailPoet
) {
var ListingBulkActions = React.createClass({
getInitialState: function() {
) => {
const ListingBulkActions = React.createClass({
getInitialState: function () {
return {
action: false,
extra: false
}
extra: false,
};
},
handleChangeAction: function(e) {
handleChangeAction: function (e) {
this.setState({
action: e.target.value,
extra: false
}, function() {
var action = this.getSelectedAction();
extra: false,
}, () => {
const action = this.getSelectedAction();
// action on select callback
if(action !== null && action['onSelect'] !== undefined) {
this.setState({
extra: action.onSelect(e)
extra: action.onSelect(e),
});
}
}.bind(this));
});
},
handleApplyAction: function(e) {
handleApplyAction: function (e) {
e.preventDefault();
var action = this.getSelectedAction();
const action = this.getSelectedAction();
if(action === null) {
return;
}
var selected_ids = (this.props.selection !== 'all')
const selected_ids = (this.props.selection !== 'all')
? this.props.selected_ids
: [];
var data = (action['getData'] !== undefined)
const data = (action['getData'] !== undefined)
? action.getData()
: {};
data.action = this.state.action;
var onSuccess = function() {};
let onSuccess = function () {};
if(action['onSuccess'] !== undefined) {
onSuccess = action.onSuccess;
}
@ -61,13 +61,13 @@ function(
this.setState({
action: false,
extra: false
extra: false,
});
},
getSelectedAction: function() {
var selected_action = this.refs.action.value;
getSelectedAction: function () {
const selected_action = this.refs.action.value;
if(selected_action.length > 0) {
var action = this.props.bulk_actions.filter(function(action) {
const action = this.props.bulk_actions.filter((action) => {
return (action.name === selected_action);
});
@ -77,7 +77,7 @@ function(
}
return null;
},
render: function() {
render: function () {
if(this.props.bulk_actions.length === 0) {
return null;
}
@ -97,14 +97,14 @@ function(
onChange={this.handleChangeAction}
>
<option value="">{MailPoet.I18n.t('bulkActions')}</option>
{ this.props.bulk_actions.map(function(action, index) {
{ this.props.bulk_actions.map((action, index) => {
return (
<option
value={ action.name }
key={ 'action-' + index }
>{ action.label }</option>
);
}.bind(this)) }
}) }
</select>
<input
onClick={ this.handleApplyAction }
@ -115,7 +115,7 @@ function(
{ this.state.extra }
</div>
);
}
},
});
return ListingBulkActions;

View File

@ -1,27 +1,30 @@
define([
'react',
'jquery',
'mailpoet'
'mailpoet',
],
function(
(
React,
jQuery,
MailPoet
) {
var ListingFilters = React.createClass({
handleFilterAction: function() {
let filters = {};
) => {
const ListingFilters = React.createClass({
handleFilterAction: function () {
const filters = {};
this.getAvailableFilters().map((filter, i) => {
filters[this.refs['filter-'+i].name] = this.refs['filter-'+i].value
filters[this.refs['filter-'+i].name] = this.refs['filter-'+i].value;
});
if (this.props.onBeforeSelectFilter) {
this.props.onBeforeSelectFilter(filters);
}
return this.props.onSelectFilter(filters);
},
handleEmptyTrash: function() {
handleEmptyTrash: function () {
return this.props.onEmptyTrash();
},
getAvailableFilters: function() {
let filters = this.props.filters;
return Object.keys(filters).filter(function(filter) {
getAvailableFilters: function () {
const filters = this.props.filters;
return Object.keys(filters).filter((filter) => {
return !(
filters[filter].length === 0
|| (
@ -31,39 +34,39 @@ function(
);
});
},
componentDidUpdate: function() {
componentDidUpdate: function () {
const selected_filters = this.props.filter;
const available_filters = this.getAvailableFilters().map(
function(filter, i) {
this.getAvailableFilters().map(
(filter, i) => {
if (selected_filters[filter] !== undefined && selected_filters[filter]) {
jQuery(this.refs['filter-'+i])
.val(selected_filters[filter])
.trigger('change');
}
}.bind(this)
);
}
);
},
render: function() {
render: function () {
const filters = this.props.filters;
const available_filters = this.getAvailableFilters()
.map(function(filter, i) {
.map((filter, i) => {
return (
<select
ref={ `filter-${i}` }
key={ `filter-${i}` }
name={ filter }
>
{ filters[filter].map(function(option, j) {
{ filters[filter].map((option, j) => {
return (
<option
value={ option.value }
key={ 'filter-option-' + j }
>{ option.label }</option>
);
}.bind(this)) }
}) }
</select>
);
}.bind(this));
});
let button;
@ -97,7 +100,7 @@ function(
{ empty_trash }
</div>
);
}
},
});
return ListingFilters;

View File

@ -1,20 +1,20 @@
define(['react', 'classnames'], function(React, classNames) {
define(['react', 'classnames'], (React, classNames) => {
var ListingGroups = React.createClass({
handleSelect: function(group) {
return this.props.onSelectGroup(group);
},
render: function() {
var groups = this.props.groups.map(function(group, index) {
if(group.name === 'trash' && group.count === 0) {
return false;
}
const ListingGroups = React.createClass({
handleSelect: function (group) {
return this.props.onSelectGroup(group);
},
render: function () {
const groups = this.props.groups.map((group, index) => {
if(group.name === 'trash' && group.count === 0) {
return false;
}
var classes = classNames(
const classes = classNames(
{ 'current' : (group.name === this.props.group) }
);
return (
return (
<li key={index}>
{(index > 0) ? ' |' : ''}
<a
@ -24,17 +24,17 @@ define(['react', 'classnames'], function(React, classNames) {
{group.label} <span className="count">({ group.count.toLocaleString() })</span>
</a>
</li>
);
}.bind(this));
);
});
return (
return (
<ul className="subsubsub">
{ groups }
</ul>
);
}
});
);
},
});
return ListingGroups;
}
);
return ListingGroups;
}
);

View File

@ -1,15 +1,15 @@
import MailPoet from 'mailpoet'
import React from 'react'
import classNames from 'classnames'
import MailPoet from 'mailpoet';
import React from 'react';
import classNames from 'classnames';
const ListingHeader = React.createClass({
handleSelectItems: function() {
handleSelectItems: function () {
return this.props.onSelectItems(
this.refs.toggle.checked
);
},
render: function() {
const columns = this.props.columns.map(function(column, index) {
render: function () {
const columns = this.props.columns.map((column, index) => {
column.is_primary = (index === 0);
column.sorted = (this.props.sort_by === column.name)
? this.props.sort_order
@ -21,7 +21,7 @@ const ListingHeader = React.createClass({
key={ 'column-' + index }
column={column} />
);
}.bind(this));
});
let checkbox;
@ -48,16 +48,16 @@ const ListingHeader = React.createClass({
{columns}
</tr>
);
}
},
});
const ListingColumn = React.createClass({
handleSort: function() {
handleSort: function () {
const sort_by = this.props.column.name;
const sort_order = (this.props.column.sorted === 'asc') ? 'desc' : 'asc';
this.props.onSort(sort_by, sort_order);
},
render: function() {
render: function () {
const classes = classNames(
'manage-column',
{ 'column-primary': this.props.column.is_primary },
@ -85,7 +85,7 @@ const ListingColumn = React.createClass({
width={ this.props.column.width || null }
>{label}</th>
);
}
},
});
module.exports = ListingHeader;
module.exports = ListingHeader;

View File

@ -1,23 +1,23 @@
import MailPoet from 'mailpoet'
import jQuery from 'jquery'
import React from 'react'
import _ from 'underscore'
import { Router, Link } from 'react-router'
import classNames from 'classnames'
import ListingBulkActions from 'listing/bulk_actions.jsx'
import ListingHeader from 'listing/header.jsx'
import ListingPages from 'listing/pages.jsx'
import ListingSearch from 'listing/search.jsx'
import ListingGroups from 'listing/groups.jsx'
import ListingFilters from 'listing/filters.jsx'
import MailPoet from 'mailpoet';
import jQuery from 'jquery';
import React from 'react';
import _ from 'underscore';
import { Link } from 'react-router';
import classNames from 'classnames';
import ListingBulkActions from 'listing/bulk_actions.jsx';
import ListingHeader from 'listing/header.jsx';
import ListingPages from 'listing/pages.jsx';
import ListingSearch from 'listing/search.jsx';
import ListingGroups from 'listing/groups.jsx';
import ListingFilters from 'listing/filters.jsx';
const ListingItem = React.createClass({
getInitialState: function() {
getInitialState: function () {
return {
expanded: false
expanded: false,
};
},
handleSelectItem: function(e) {
handleSelectItem: function (e) {
this.props.onSelectItem(
parseInt(e.target.value, 10),
e.target.checked
@ -25,20 +25,20 @@ const ListingItem = React.createClass({
return !e.target.checked;
},
handleRestoreItem: function(id) {
handleRestoreItem: function (id) {
this.props.onRestoreItem(id);
},
handleTrashItem: function(id) {
handleTrashItem: function (id) {
this.props.onTrashItem(id);
},
handleDeleteItem: function(id) {
handleDeleteItem: function (id) {
this.props.onDeleteItem(id);
},
handleToggleItem: function(id) {
handleToggleItem: function () {
this.setState({ expanded: !this.state.expanded });
},
render: function() {
var checkbox = false;
render: function () {
let checkbox = false;
if (this.props.is_selectable === true) {
checkbox = (
@ -63,7 +63,7 @@ const ListingItem = React.createClass({
if (custom_actions.length > 0) {
let is_first = true;
item_actions = custom_actions.map(function(action, index) {
item_actions = custom_actions.map((action, index) => {
if (action.display !== undefined) {
if (action.display(this.props.item) === false) {
return;
@ -125,7 +125,7 @@ const ListingItem = React.createClass({
}
return custom_action;
}.bind(this));
});
} else {
item_actions = (
<span className="edit">
@ -137,7 +137,7 @@ const ListingItem = React.createClass({
let actions;
if (this.props.group === 'trash') {
actions = (
actions = (
<div>
<div className="row-actions">
<span>
@ -191,12 +191,12 @@ const ListingItem = React.createClass({
{ this.props.onRenderItem(this.props.item, actions) }
</tr>
);
}
},
});
const ListingItems = React.createClass({
render: function() {
render: function () {
if (this.props.items.length === 0) {
let message;
if (this.props.loading === true) {
@ -229,7 +229,7 @@ const ListingItems = React.createClass({
{ 'mailpoet_hidden': (
this.props.selection === false
|| (this.props.count <= this.props.limit)
)
),
}
);
@ -259,7 +259,7 @@ const ListingItems = React.createClass({
</td>
</tr>
{this.props.items.map(function(item, index) {
{this.props.items.map((item, index) => {
item.id = parseInt(item.id, 10);
item.selected = (this.props.selected_ids.indexOf(item.id) !== -1);
@ -279,18 +279,18 @@ const ListingItems = React.createClass({
key={ `item-${item.id}-${index}` }
item={ item } />
);
}.bind(this))}
})}
</tbody>
);
}
}
},
});
const Listing = React.createClass({
contextTypes: {
router: React.PropTypes.object.isRequired
router: React.PropTypes.object.isRequired,
},
getInitialState: function() {
getInitialState: function () {
return {
loading: false,
search: '',
@ -306,31 +306,31 @@ const Listing = React.createClass({
filter: {},
selected_ids: [],
selection: false,
meta: {}
meta: {},
};
},
getParam: function(param) {
getParam: function (param) {
const regex = /(.*)\[(.*)\]/;
const matches = regex.exec(param);
return [matches[1], matches[2]];
},
initWithParams: function(params) {
let state = this.getInitialState();
initWithParams: function (params) {
const state = this.getInitialState();
// check for url params
if (params.splat) {
params.splat.split('/').map(param => {
let [key, value] = this.getParam(param);
params.splat.split('/').map((param) => {
const [key, value] = this.getParam(param);
switch(key) {
case 'filter':
let filters = {};
value.split('&').map(function(pair) {
let [k, v] = pair.split('=')
filters[k] = v
}
const filters = {};
value.split('&').map((pair) => {
const [k, v] = pair.split('=');
filters[k] = v;
}
);
state.filter = filters;
break;
break;
default:
state[key] = value;
}
@ -352,13 +352,13 @@ const Listing = React.createClass({
state.sort_order = this.props.sort_order;
}
this.setState(state, function() {
this.setState(state, () => {
this.getItems();
}.bind(this));
});
},
getParams: function() {
getParams: function () {
// get all route parameters (without the "splat")
let params = _.omit(this.props.params, 'splat');
const params = _.omit(this.props.params, 'splat');
// TODO:
// find a way to set the "type" in the routes definition
// so that it appears in `this.props.params`
@ -367,10 +367,10 @@ const Listing = React.createClass({
}
return params;
},
setParams: function() {
setParams: function () {
if (this.props.location) {
let params = Object.keys(this.state)
.filter(key => {
const params = Object.keys(this.state)
.filter((key) => {
return (
[
'group',
@ -378,34 +378,34 @@ const Listing = React.createClass({
'search',
'page',
'sort_by',
'sort_order'
'sort_order',
].indexOf(key) !== -1
)
);
})
.map(key => {
.map((key) => {
let value = this.state[key];
if (value === Object(value)) {
value = jQuery.param(value)
value = jQuery.param(value);
} else if (value === Boolean(value)) {
value = value.toString()
value = value.toString();
}
if (value !== '' && value !== null) {
return `${key}[${value}]`
return `${key}[${value}]`;
}
})
.filter(key => { return (key !== undefined) })
.filter((key) => { return (key !== undefined); })
.join('/');
// set url
let url = this.getUrlWithParams(params);
const url = this.getUrlWithParams(params);
if (this.props.location.pathname !== url) {
this.context.router.push(`${url}`);
}
}
},
getUrlWithParams: function(params) {
getUrlWithParams: function (params) {
let base_url = (this.props.base_url !== undefined)
? this.props.base_url
: null;
@ -417,7 +417,7 @@ const Listing = React.createClass({
return `/${ params }`;
}
},
setBaseUrlParams: function(base_url) {
setBaseUrlParams: function (base_url) {
if (base_url.indexOf(':') !== -1) {
const params = this.getParams();
Object.keys(params).map((key) => {
@ -429,23 +429,23 @@ const Listing = React.createClass({
return base_url;
},
componentDidMount: function() {
componentDidMount: function () {
if (this.isMounted()) {
const params = this.props.params || {};
this.initWithParams(params);
if (this.props.auto_refresh) {
jQuery(document).on('heartbeat-tick.mailpoet', function(e, data) {
jQuery(document).on('heartbeat-tick.mailpoet', () => {
this.getItems();
}.bind(this));
});
}
}
},
componentWillReceiveProps: function(nextProps) {
componentWillReceiveProps: function (nextProps) {
const params = nextProps.params || {};
this.initWithParams(params);
},
getItems: function() {
getItems: function () {
if (this.isMounted()) {
this.setState({ loading: true });
@ -463,8 +463,8 @@ const Listing = React.createClass({
filter: this.state.filter,
search: this.state.search,
sort_by: this.state.sort_by,
sort_order: this.state.sort_order
}
sort_order: this.state.sort_order,
},
}).always(() => {
this.setState({ loading: false });
}).done((response) => {
@ -473,7 +473,7 @@ const Listing = React.createClass({
filters: response.meta.filters || {},
groups: response.meta.groups || [],
count: response.meta.count || 0,
meta: _.omit(response.meta, ['filters', 'groups', 'count'])
meta: _.omit(response.meta, ['filters', 'groups', 'count']),
}, () => {
// if viewing an empty trash
if (this.state.group === 'trash' && response.meta.count === 0) {
@ -487,19 +487,19 @@ const Listing = React.createClass({
}
});
}).fail((response) => {
if (response.errors.length > 0) {
if(response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
}
});
}
},
handleRestoreItem: function(id) {
handleRestoreItem: function (id) {
this.setState({
loading: true,
page: 1
page: 1,
});
MailPoet.Ajax.post({
@ -507,8 +507,8 @@ const Listing = React.createClass({
endpoint: this.props.endpoint,
action: 'restore',
data: {
id: id
}
id: id,
},
}).done((response) => {
if (
this.props.messages !== undefined
@ -519,15 +519,15 @@ const Listing = React.createClass({
this.getItems();
}).fail((response) => {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
});
},
handleTrashItem: function(id) {
handleTrashItem: function (id) {
this.setState({
loading: true,
page: 1
page: 1,
});
MailPoet.Ajax.post({
@ -535,8 +535,8 @@ const Listing = React.createClass({
endpoint: this.props.endpoint,
action: 'trash',
data: {
id: id
}
id: id,
},
}).done((response) => {
if (
this.props.messages !== undefined
@ -547,15 +547,15 @@ const Listing = React.createClass({
this.getItems();
}).fail((response) => {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
});
},
handleDeleteItem: function(id) {
handleDeleteItem: function (id) {
this.setState({
loading: true,
page: 1
page: 1,
});
MailPoet.Ajax.post({
@ -563,8 +563,8 @@ const Listing = React.createClass({
endpoint: this.props.endpoint,
action: 'delete',
data: {
id: id
}
id: id,
},
}).done((response) => {
if (
this.props.messages !== undefined
@ -575,15 +575,15 @@ const Listing = React.createClass({
this.getItems();
}).fail((response) => {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
});
},
handleEmptyTrash: function() {
handleEmptyTrash: function () {
return this.handleBulkAction('all', {
action: 'delete',
group: 'trash'
group: 'trash',
}).done((response) => {
MailPoet.Notice.success(
MailPoet.I18n.t('permanentlyDeleted').replace('%d', response.meta.count)
@ -592,12 +592,12 @@ const Listing = React.createClass({
this.handleGroup('all');
}).fail((response) => {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
});
},
handleBulkAction: function(selected_ids, params) {
handleBulkAction: function (selected_ids, params) {
if (
this.state.selection === false
&& this.state.selected_ids.length === 0
@ -608,15 +608,15 @@ const Listing = React.createClass({
this.setState({ loading: true });
var data = params || {};
const data = params || {};
data.listing = {
params: this.getParams(),
offset: 0,
limit: 0,
filter: this.state.filter,
group: this.state.group,
search: this.state.search
}
search: this.state.search,
};
if (selected_ids !== 'all') {
data.listing.selection = selected_ids;
}
@ -625,32 +625,39 @@ const Listing = React.createClass({
api_version: window.mailpoet_api_version,
endpoint: this.props.endpoint,
action: 'bulkAction',
data: data
data: data,
}).done(() => {
this.getItems();
}).fail((response) => {
if(response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
}
});
},
handleSearch: function(search) {
handleSearch: function (search) {
this.setState({
search: search,
page: 1,
selection: false,
selected_ids: []
}, function() {
selected_ids: [],
}, () => {
this.setParams();
}.bind(this));
});
},
handleSort: function(sort_by, sort_order = 'asc') {
handleSort: function (sort_by, sort_order = 'asc') {
this.setState({
sort_by: sort_by,
sort_order: (sort_order === 'asc') ? 'asc' : 'desc',
}, function() {
}, () => {
this.setParams();
}.bind(this));
});
},
handleSelectItem: function(id, is_checked) {
var selected_ids = this.state.selected_ids,
selection = false;
handleSelectItem: function (id, is_checked) {
let selected_ids = this.state.selected_ids,
selection = false;
if (is_checked) {
selected_ids = jQuery.merge(selected_ids, [ id ]);
@ -666,48 +673,48 @@ const Listing = React.createClass({
this.setState({
selection: selection,
selected_ids: selected_ids
selected_ids: selected_ids,
});
},
handleSelectItems: function(is_checked) {
handleSelectItems: function (is_checked) {
if (is_checked === false) {
this.clearSelection();
} else {
var selected_ids = this.state.items.map(function(item) {
const selected_ids = this.state.items.map((item) => {
return ~~item.id;
});
this.setState({
selected_ids: selected_ids,
selection: 'page'
selection: 'page',
});
}
},
handleSelectAll: function() {
handleSelectAll: function () {
if (this.state.selection === 'all') {
this.clearSelection();
} else {
this.setState({
selection: 'all',
selected_ids: []
selected_ids: [],
});
}
},
clearSelection: function() {
clearSelection: function () {
this.setState({
selection: false,
selected_ids: []
selected_ids: [],
});
},
handleFilter: function(filters) {
handleFilter: function (filters) {
this.setState({
filter: filters,
page: 1
}, function() {
page: 1,
}, () => {
this.setParams();
}.bind(this));
});
},
handleGroup: function(group) {
handleGroup: function (group) {
// reset search
jQuery('#search_input').val('');
@ -715,35 +722,35 @@ const Listing = React.createClass({
group: group,
filter: {},
search: '',
page: 1
}, function() {
page: 1,
}, () => {
this.setParams();
}.bind(this));
});
},
handleSetPage: function(page) {
handleSetPage: function (page) {
this.setState({
page: page,
selection: false,
selected_ids: []
}, function() {
selected_ids: [],
}, () => {
this.setParams();
}.bind(this));
});
},
handleRenderItem: function(item, actions) {
handleRenderItem: function (item, actions) {
const render = this.props.onRenderItem(item, actions, this.state.meta);
return render.props.children;
},
handleRefreshItems: function() {
handleRefreshItems: function () {
this.getItems();
},
render: function() {
render: function () {
const items = this.state.items;
const sort_by = this.state.sort_by;
const sort_order = this.state.sort_order;
// columns
let columns = this.props.columns || [];
columns = columns.filter(function(column) {
columns = columns.filter((column) => {
return (column.display === undefined || !!(column.display) === true);
});
@ -755,13 +762,13 @@ const Listing = React.createClass({
{
name: 'restore',
label: MailPoet.I18n.t('restore'),
onSuccess: this.props.messages.onRestore
onSuccess: this.props.messages.onRestore,
},
{
name: 'delete',
label: MailPoet.I18n.t('deletePermanently'),
onSuccess: this.props.messages.onDelete
}
onSuccess: this.props.messages.onDelete,
},
];
}
@ -821,6 +828,7 @@ const Listing = React.createClass({
filters={ this.state.filters }
filter={ this.state.filter }
group={ this.state.group }
onBeforeSelectFilter={ this.props.onBeforeSelectFilter || null }
onSelectFilter={ this.handleFilter }
onEmptyTrash={ this.handleEmptyTrash }
/>
@ -889,7 +897,7 @@ const Listing = React.createClass({
</div>
</div>
);
}
},
});
module.exports = Listing;

View File

@ -1,76 +1,76 @@
define([
'react',
'classnames',
'mailpoet'
], function(
'react',
'classnames',
'mailpoet',
], (
React,
classNames,
MailPoet
) {
) => {
var ListingPages = React.createClass({
getInitialState: function() {
const ListingPages = React.createClass({
getInitialState: function () {
return {
page: null
}
page: null,
};
},
setPage: function(page) {
setPage: function (page) {
this.setState({
page: null
}, function () {
page: null,
}, () => {
this.props.onSetPage(this.constrainPage(page));
}.bind(this));
});
},
setFirstPage: function() {
setFirstPage: function () {
this.setPage(1);
},
setLastPage: function() {
setLastPage: function () {
this.setPage(this.getLastPage());
},
setPreviousPage: function() {
setPreviousPage: function () {
this.setPage(this.constrainPage(
parseInt(this.props.page, 10) - 1)
);
},
setNextPage: function() {
setNextPage: function () {
this.setPage(this.constrainPage(
parseInt(this.props.page, 10) + 1)
);
},
constrainPage: function(page) {
constrainPage: function (page) {
return Math.min(Math.max(1, Math.abs(~~page)), this.getLastPage());
},
handleSetManualPage: function(e) {
handleSetManualPage: function (e) {
if(e.which === 13) {
this.setPage(this.state.page);
}
},
handleChangeManualPage: function(e) {
handleChangeManualPage: function (e) {
this.setState({
page: e.target.value
page: e.target.value,
});
},
handleBlurManualPage: function(e) {
handleBlurManualPage: function (e) {
this.setPage(e.target.value);
},
getLastPage: function() {
getLastPage: function () {
return Math.ceil(this.props.count / this.props.limit);
},
render: function() {
render: function () {
if(this.props.count === 0) {
return false;
} else {
var pagination = false;
var firstPage = (
let pagination = false;
let firstPage = (
<span aria-hidden="true" className="tablenav-pages-navspan">«</span>
);
var previousPage = (
let previousPage = (
<span aria-hidden="true" className="tablenav-pages-navspan"></span>
);
var nextPage = (
let nextPage = (
<span aria-hidden="true" className="tablenav-pages-navspan"></span>
);
var lastPage = (
let lastPage = (
<span aria-hidden="true" className="tablenav-pages-navspan">»</span>
);
@ -159,12 +159,12 @@ define([
);
}
var classes = classNames(
const classes = classNames(
'tablenav-pages',
{ 'one-page': (this.props.count <= this.props.limit) }
);
var numberOfItemsLabel;
let numberOfItemsLabel;
if (this.props.count == 1) {
numberOfItemsLabel = MailPoet.I18n.t('numberOfItemsSingular');
} else {
@ -178,7 +178,7 @@ define([
</div>
);
}
}
},
});
return ListingPages;

View File

@ -1,22 +1,22 @@
define([
'mailpoet',
'react'
], function(
'mailpoet',
'react',
], (
MailPoet,
React
) {
) => {
var ListingSearch = React.createClass({
handleSearch: function(e) {
const ListingSearch = React.createClass({
handleSearch: function (e) {
e.preventDefault();
this.props.onSearch(
this.refs.search.value
);
},
componentWillReceiveProps: function(nextProps) {
this.refs.search.value = nextProps.search
componentWillReceiveProps: function (nextProps) {
this.refs.search.value = nextProps.search;
},
render: function() {
render: function () {
if(this.props.search === false) {
return false;
} else {
@ -40,7 +40,7 @@ define([
</form>
);
}
}
},
});
return ListingSearch;

View File

@ -63,6 +63,8 @@ define('mp2migrator', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
jQuery('#progresslabel').html(progress + '%');
if(Number(result.current) !== 0) {
jQuery('#skip-import').hide();
jQuery('#progressbar').show();
jQuery('#logger-container').show();
}
if(MailPoet.MP2Migrator.is_logging) {
MailPoet.MP2Migrator.updateProgressbar_timeout = setTimeout(MailPoet.MP2Migrator.updateProgressbar, 1000);
@ -129,6 +131,15 @@ define('mp2migrator', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
jQuery('#stop-import').removeAttr('disabled'); // Enable the button
MailPoet.MP2Migrator.reactivateImportButton();
MailPoet.MP2Migrator.updateDisplay(); // Get the latest information after the import was stopped
}).fail(function (response) {
if(response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map(function (error) {
return error.message;
}),
{scroll: true}
);
}
});
MailPoet.MP2Migrator.stopLogger();
return false;
@ -143,6 +154,15 @@ define('mp2migrator', ['mailpoet', 'jquery'], function(MailPoet, jQuery) {
}
}).done(function () {
MailPoet.MP2Migrator.gotoWelcomePage();
}).fail(function (response) {
if(response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map(function (error) {
return error.message;
}),
{scroll: true}
);
}
});
return false;
},

View File

@ -15,8 +15,8 @@ define([
contentRegion: '#mailpoet_editor_content',
sidebarRegion: '#mailpoet_editor_sidebar',
bottomRegion: '#mailpoet_editor_bottom',
headingRegion: '#mailpoet_editor_heading',
},
headingRegion: '#mailpoet_editor_heading'
}
});
var EditorApplication = Marionette.Application.extend({

View File

@ -21,6 +21,6 @@ define([
chooseText: MailPoet.I18n.t('selectColor'),
cancelText: MailPoet.I18n.t('cancelColorSelection')
});
},
}
});
});

View File

@ -15,7 +15,7 @@ define([
BehaviorsLookup.ContainerDropZoneBehavior = Marionette.Behavior.extend({
defaults: {
columnLimit: 3,
columnLimit: 3
},
onRender: function() {
var dragAndDropDisabled = _.isObject(this.view.options.renderOptions) && this.view.options.renderOptions.disableDragAndDrop === true;
@ -195,7 +195,7 @@ define([
if (view.model.get('orientation') === 'horizontal' && droppableModel.get('type') !== 'container') {
// Regular blocks always need to be inserted into columns - vertical containers
tempCollection = new (EditorApplication.getBlockTypeModel('container'))({
orientation: 'vertical',
orientation: 'vertical'
});
tempCollection.get('blocks').add(droppableModel);
viewCollection.add(tempCollection, {at: index});
@ -210,7 +210,7 @@ define([
var tempModel = viewCollection.at(dropPosition.index);
tempCollection = new (EditorApplication.getBlockTypeModel('container'))({
orientation: (view.model.get('orientation') === 'vertical') ? 'horizontal' : 'vertical',
orientation: (view.model.get('orientation') === 'vertical') ? 'horizontal' : 'vertical'
});
viewCollection.remove(tempModel);
@ -218,19 +218,19 @@ define([
if (tempCollection.get('orientation') === 'horizontal') {
if (dropPosition.position === 'before') {
tempCollection2 = new (EditorApplication.getBlockTypeModel('container'))({
orientation: 'vertical',
orientation: 'vertical'
});
tempCollection2.get('blocks').add(droppableModel);
tempCollection.get('blocks').add(tempCollection2);
}
tempCollection2 = new (EditorApplication.getBlockTypeModel('container'))({
orientation: 'vertical',
orientation: 'vertical'
});
tempCollection2.get('blocks').add(tempModel);
tempCollection.get('blocks').add(tempCollection2);
if (dropPosition.position === 'after') {
tempCollection2 = new (EditorApplication.getBlockTypeModel('container'))({
orientation: 'vertical',
orientation: 'vertical'
});
tempCollection2.get('blocks').add(droppableModel);
tempCollection.get('blocks').add(tempCollection2);
@ -254,11 +254,11 @@ define([
event.draggable.onDrop({
dropBehavior: that,
droppedModel: droppableModel,
droppedView: droppedView,
droppedView: droppedView
});
that.cleanup();
},
}
});
},
cleanup: function() {
@ -296,7 +296,7 @@ define([
return {
insertionType: 'normal',
index: 0,
position: 'inside',
position: 'inside'
};
}
@ -347,7 +347,7 @@ define([
return {
insertionType: insertionType, // 'normal'|'special'
index: index,
position: position, // 'inside'|'before'|'after'
position: position // 'inside'|'before'|'after'
};
},
_computeNormalIndex: function(eventX, eventY) {
@ -377,13 +377,13 @@ define([
// First half of the element
return {
index: index,
position: 'before',
position: 'before'
};
} else {
// Second half of the element
return {
index: index,
position: 'after',
position: 'after'
};
}
},

View File

@ -28,7 +28,7 @@ define([
},
onDrop: function(model, view) {},
testAttachToInstance: function(model, view) { return true; },
testAttachToInstance: function(model, view) { return true; }
},
onRender: function() {
var that = this,
@ -38,7 +38,7 @@ define([
if (!this.options.testAttachToInstance(this.view.model, this.view)) return;
interactable = interact(this.$el.get(0), {
ignoreFrom: this.options.ignoreSelector,
ignoreFrom: this.options.ignoreSelector
}).draggable({
// allow dragging of multple elements at the same time
max: Infinity,
@ -111,9 +111,10 @@ define([
that.view.$el.removeClass('mailpoet_hidden');
}
}
},
}
})
.preventDefault('auto')
.styleCursor(false)
.actionChecker(function (pointer, event, action) {
// Disable dragging with right click
if (event.button !== 0) {
@ -136,6 +137,6 @@ define([
// Delegate to view's event handler
that.options.onDrop.apply(that, [options]);
};
},
}
});
});

View File

@ -5,19 +5,19 @@
*/
define([
'backbone.marionette',
'newsletter_editor/behaviors/BehaviorsLookup',
'newsletter_editor/behaviors/BehaviorsLookup'
], function(Marionette, BehaviorsLookup) {
BehaviorsLookup.HighlightEditingBehavior = Marionette.Behavior.extend({
modelEvents: {
'startEditing': 'enableHighlight',
'stopEditing': 'disableHighlight',
'stopEditing': 'disableHighlight'
},
enableHighlight: function() {
this.$el.addClass('mailpoet_highlight');
},
disableHighlight: function() {
this.$el.removeClass('mailpoet_highlight');
},
}
});
});

View File

@ -15,11 +15,11 @@ define([
resizeHandleSelector: true, // true will use edges of the element itself
transformationFunction: function(y) { return y; },
minLength: 0,
modelField: 'styles.block.height',
modelField: 'styles.block.height'
},
events: {
"mouseenter": 'showResizeHandle',
"mouseleave": 'hideResizeHandle',
"mouseleave": 'hideResizeHandle'
},
onRender: function() {
this.attachResize();
@ -37,8 +37,8 @@ define([
top: false,
left: 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) {
that.isBeingResized = true;
that.$el.addClass('mailpoet_resize_active');
@ -63,6 +63,6 @@ define([
if (typeof this.options.resizeHandleSelector === 'string') {
this.view.$(this.options.resizeHandleSelector).addClass('mailpoet_hidden');
}
},
}
});
});

View File

@ -6,15 +6,15 @@
define([
'backbone.marionette',
'jquery',
'newsletter_editor/behaviors/BehaviorsLookup',
'newsletter_editor/behaviors/BehaviorsLookup'
], function(Marionette, jQuery, BehaviorsLookup) {
BehaviorsLookup.ShowSettingsBehavior = Marionette.Behavior.extend({
defaults: {
ignoreFrom: '', // selector
ignoreFrom: '' // selector
},
events: {
'click .mailpoet_content': 'showSettings',
'click .mailpoet_content': 'showSettings'
},
showSettings: function(event) {
if(!this.isIgnoredElement(event.target)) {
@ -25,7 +25,7 @@ define([
return this.options.ignoreFrom
&& this.options.ignoreFrom.length > 0
&& jQuery(element).is(this.options.ignoreFrom);
},
}
});
});

View File

@ -32,7 +32,7 @@ define([
collection.remove(model);
collection.add(model, { at: newIndex });
},
items: this.options.items,
items: this.options.items
});
}
}

View File

@ -18,7 +18,7 @@ define([
invalidElements: "script",
blockFormats: 'Paragraph=p',
plugins: "link textcolor colorpicker mailpoet_shortcodes",
configurationFilter: function(originalConfig) { return originalConfig; },
configurationFilter: function(originalConfig) { return originalConfig; }
},
onDomRefresh: function() {
var that = this;
@ -76,7 +76,7 @@ define([
editor.on('blur', function(e) {
that.view.triggerMethod('text:editor:blur');
});
},
}
}));
}
});

View File

@ -53,7 +53,7 @@ define([
});
CommunicationComponent.getBulkTransformedPosts({
blocks: blocks,
blocks: blocks
}).then(_.partial(this.refreshBlocks, models));
},
refreshBlocks: function(models, renderedBlocks) {
@ -65,7 +65,7 @@ define([
model.trigger('refreshPosts', contents);
}
);
},
}
});
Module.AutomatedLatestContentBlockModel = base.BlockModel.extend({
@ -97,14 +97,14 @@ define([
sortBy: 'newest', // 'newest'|'oldest',
showDivider: true, // true|false
divider: {},
_container: new (App.getBlockTypeModel('container'))(),
_container: new (App.getBlockTypeModel('container'))()
}, App.getConfig().get('blockDefaults.automatedLatestContent'));
},
relations: function() {
return {
readMoreButton: App.getBlockTypeModel('button'),
divider: App.getBlockTypeModel('divider'),
_container: App.getBlockTypeModel('container'),
_container: App.getBlockTypeModel('container')
};
},
initialize: function() {
@ -124,7 +124,7 @@ define([
*/
_scheduleFetchPosts: function() {
App.getChannel().trigger('automatedLatestContentRefresh');
},
}
});
Module.AutomatedLatestContentBlockView = base.BlockView.extend({
@ -138,15 +138,15 @@ define([
getTemplate: function() { return templates.automatedLatestContentBlock; },
regions: {
toolsRegion: '.mailpoet_tools',
postsRegion: '.mailpoet_automated_latest_content_block_posts',
postsRegion: '.mailpoet_automated_latest_content_block_posts'
},
modelEvents: _.extend(
_.omit(base.BlockView.prototype.modelEvents, 'change'),
{
'postsChanged': 'render',
'postsChanged': 'render'
}),
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; },
onRender: function() {
@ -154,16 +154,16 @@ define([
renderOptions = {
disableTextEditor: true,
disableDragAndDrop: true,
emptyContainerMessage: MailPoet.I18n.t('noPostsToDisplay'),
emptyContainerMessage: MailPoet.I18n.t('noPostsToDisplay')
};
this.toolsView = new Module.AutomatedLatestContentBlockToolsView({ model: this.model });
this.showChildView('toolsRegion', this.toolsView);
this.showChildView('postsRegion', new ContainerView({ model: this.model.get('_container'), renderOptions: renderOptions }));
},
}
});
Module.AutomatedLatestContentBlockToolsView = base.BlockToolsView.extend({
getSettingsView: function() { return Module.AutomatedLatestContentBlockSettingsView; },
getSettingsView: function() { return Module.AutomatedLatestContentBlockSettingsView; }
});
// Sidebar view container
@ -192,7 +192,7 @@ define([
"input .mailpoet_automated_latest_content_categories": _.partial(this.changeField, "categoriesPrecededBy"),
"input .mailpoet_automated_latest_content_read_more_text": _.partial(this.changeField, "readMoreText"),
"change .mailpoet_automated_latest_content_sort_by": _.partial(this.changeField, "sortBy"),
"click .mailpoet_done_editing": "close",
"click .mailpoet_done_editing": "close"
};
},
onRender: function() {
@ -247,8 +247,8 @@ define([
}
)
};
},
},
}
}
}).on({
'select2:select': function(event) {
var terms = that.model.get('terms');
@ -261,7 +261,7 @@ define([
terms.remove(event.params.data);
// Reset whole model in order for change events to propagate properly
that.model.set('terms', terms.toJSON());
},
}
}).trigger( 'change' );
},
toggleDisplayOptions: function(event) {
@ -282,8 +282,8 @@ define([
renderOptions: {
displayFormat: 'subpanel',
hideLink: true,
hideApplyToAll: true,
},
hideApplyToAll: true
}
})).render();
},
showDividerSettings: function(event) {
@ -292,8 +292,8 @@ define([
model: this.model.get('divider'),
renderOptions: {
displayFormat: 'subpanel',
hideApplyToAll: true,
},
hideApplyToAll: true
}
})).render();
},
changeReadMoreType: function(event) {
@ -356,11 +356,11 @@ define([
_.each(postTypes, function(type) {
select.append(jQuery('<option>', {
value: type.name,
text: type.label,
text: type.label
}));
});
select.val(selectedValue);
},
}
});
Module.AutomatedLatestContentWidgetView = base.WidgetView.extend({
@ -373,21 +373,21 @@ define([
},
onDrop: function(options) {
options.droppedView.triggerMethod('showSettings');
},
}
}
},
}
});
App.on('before:start', function(App, options) {
App.registerBlockType('automatedLatestContent', {
blockModel: Module.AutomatedLatestContentBlockModel,
blockView: Module.AutomatedLatestContentBlockView,
blockView: Module.AutomatedLatestContentBlockView
});
App.registerWidget({
name: 'automatedLatestContent',
widgetView: Module.AutomatedLatestContentWidgetView,
priority: 97,
priority: 97
});
});

View File

@ -42,20 +42,21 @@ define([
},
getChildren: function() {
return [];
},
}
});
Module.BlockView = AugmentedView.extend({
regions: {
toolsRegion: '> .mailpoet_tools',
toolsRegion: '> .mailpoet_tools'
},
modelEvents: {
'change': 'render',
'delete': 'deleteBlock',
'duplicate': 'duplicateBlock'
},
events: {
"mouseenter": "showTools",
"mouseleave": "hideTools",
"mouseleave": "hideTools"
},
behaviors: {
DraggableBehavior: {
@ -78,14 +79,14 @@ define([
WidgetView.destroy();
return node;
}
},
}
},
HighlightEditingBehavior: {},
HighlightEditingBehavior: {}
},
templateContext: function() {
return {
model: this.model.toJSON(),
viewCid: this.cid,
viewCid: this.cid
};
},
constructor: function() {
@ -142,6 +143,9 @@ define([
this.model.destroy();
}.bind(this));
},
duplicateBlock: function() {
this.model.collection.add(this.model.toJSON(), {at: this.model.collection.findIndex(this.model)});
},
transitionIn: function() {
return this._transition('slideDown', 'fadeIn', 'easeOut');
},
@ -158,19 +162,19 @@ define([
easing: easing,
complete: function() {
promise.resolve();
}.bind(this),
}.bind(this)
}
).velocity(
fadeDirection,
{
duration: 250,
easing: easing,
queue: false, // Do not enqueue, trigger animation in parallel
queue: false // Do not enqueue, trigger animation in parallel
}
);
return promise;
},
}
});
Module.BlockToolsView = AugmentedView.extend({
@ -180,12 +184,14 @@ define([
"click .mailpoet_delete_block_activate": "showDeletionConfirmation",
"click .mailpoet_delete_block_cancel": "hideDeletionConfirmation",
"click .mailpoet_delete_block_confirm": "deleteBlock",
"click .mailpoet_duplicate_block": "duplicateBlock"
},
// Markers of whether these particular tools will be used for this instance
tools: {
settings: true,
delete: true,
move: true,
duplicate: true,
move: true
},
getSettingsView: function() { return Module.BlockSettingsView; },
initialize: function(options) {
@ -203,7 +209,7 @@ define([
return {
model: this.model.toJSON(),
viewCid: this.cid,
tools: this.tools,
tools: this.tools
};
},
changeSettings: function(options) {
@ -221,12 +227,17 @@ define([
this.model.trigger('delete');
return false;
},
duplicateBlock: function(event) {
event.preventDefault();
this.model.trigger('duplicate');
return false;
}
});
Module.BlockSettingsView = Marionette.View.extend({
className: 'mailpoet_editor_settings',
behaviors: {
ColorPickerBehavior: {},
ColorPickerBehavior: {}
},
initialize: function(params) {
this.model.trigger('startEditing');
@ -237,7 +248,7 @@ define([
width: App.getConfig().get('sidepanelWidth'),
onCancel: function() {
this.destroy();
}.bind(this),
}.bind(this)
};
this.renderOptions = params.renderOptions || {};
if (this.renderOptions.displayFormat === 'subpanel') {
@ -279,7 +290,7 @@ define([
onBeforeDestroy: function() {
MailPoet.Modal.close();
this.model.trigger('stopEditing');
},
}
});
Module.WidgetView = Marionette.View.extend({
@ -290,7 +301,7 @@ define([
throw "Unsupported operation";
}
}
},
}
});
return Module;

View File

@ -33,11 +33,11 @@ define([
fontFamily: 'Arial',
fontSize: '16px',
fontWeight: 'normal', // 'normal'|'bold'
textAlign: 'center',
},
},
textAlign: 'center'
}
}
}, App.getConfig().get('blockDefaults.button'));
},
}
});
Module.ButtonBlockView = base.BlockView.extend({
@ -45,7 +45,7 @@ define([
getTemplate: function() { return templates.buttonBlock; },
onDragSubstituteBy: function() { return Module.ButtonWidgetView; },
behaviors: _.extend({}, base.BlockView.prototype.behaviors, {
ShowSettingsBehavior: {},
ShowSettingsBehavior: {}
}),
initialize: function() {
base.BlockView.prototype.initialize.apply(this, arguments);
@ -57,11 +57,11 @@ define([
onRender: function() {
this.toolsView = new Module.ButtonBlockToolsView({ model: this.model });
this.showChildView('toolsRegion', this.toolsView);
},
}
});
Module.ButtonBlockToolsView = base.BlockToolsView.extend({
getSettingsView: function() { return Module.ButtonBlockSettingsView; },
getSettingsView: function() { return Module.ButtonBlockSettingsView; }
});
Module.ButtonBlockSettingsView = base.BlockSettingsView.extend({
@ -95,13 +95,13 @@ define([
"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_done_editing": "close",
"click .mailpoet_done_editing": "close"
};
},
templateContext: function() {
return _.extend({}, base.BlockView.prototype.templateContext.apply(this, arguments), {
availableStyles: App.getAvailableStyles().toJSON(),
renderOptions: this.renderOptions,
renderOptions: this.renderOptions
});
},
applyToAll: function() {
@ -127,21 +127,21 @@ define([
cloneOriginal: true,
drop: function() {
return new Module.ButtonBlockModel();
},
}
}
},
}
});
App.on('before:start', function(App, options) {
App.registerBlockType('button', {
blockModel: Module.ButtonBlockModel,
blockView: Module.ButtonBlockView,
blockView: Module.ButtonBlockView
});
App.registerWidget({
name: 'button',
widgetView: Module.ButtonWidgetView,
priority: 92,
priority: 92
});
});

View File

@ -30,12 +30,12 @@ define([
// TODO: If type has no registered model, use a backup one
return new Type(block, {parse: true});
});
},
}
});
Module.ContainerBlockModel = base.BlockModel.extend({
relations: {
blocks: BlockCollection,
blocks: BlockCollection
},
defaults: function() {
return this._getDefaults({
@ -43,10 +43,10 @@ define([
orientation: 'vertical',
styles: {
block: {
backgroundColor: 'transparent',
},
backgroundColor: 'transparent'
}
},
blocks: new BlockCollection(),
blocks: new BlockCollection()
}, App.getConfig().get('blockDefaults.container'));
},
validate: function() {
@ -60,7 +60,7 @@ define([
// If container has any blocks - add them to a collection
if (response.type === 'container' && _.has(response, 'blocks')) {
response.blocks = new BlockCollection(response.blocks, {
parse: true,
parse: true
});
}
return response;
@ -71,7 +71,7 @@ define([
});
return _.flatten(models);
},
}
});
Module.ContainerBlocksView = Marionette.CollectionView.extend({
@ -100,12 +100,12 @@ define([
blocks: {
el: '> .mailpoet_container',
replaceElement: true
},
}
}),
className: 'mailpoet_block mailpoet_container_block mailpoet_droppable_block mailpoet_droppable_layout_block',
getTemplate: function() { return templates.containerBlock; },
events: _.extend({}, base.BlockView.prototype.events, {
"click .mailpoet_newsletter_layer_selector": "toggleEditingLayer",
"click .mailpoet_newsletter_layer_selector": "toggleEditingLayer"
}),
ui: {
tools: '> .mailpoet_tools'
@ -137,8 +137,8 @@ define([
// Attach Draggable only to layout containers and disable it
// for root and column containers.
return view.renderOptions.depth === 1;
},
},
}
}
}),
onDragSubstituteBy: function() {
// For two and three column layouts display their respective widgets,
@ -161,9 +161,10 @@ define([
tools: {
settings: this.renderOptions.depth === 1,
delete: this.renderOptions.depth === 1,
duplicate: true,
move: this.renderOptions.depth === 1,
layerSelector: false,
},
layerSelector: false
}
});
this.showChildView('toolsRegion', this.toolsView);
this.showChildView('blocks', new Module.ContainerBlocksView({
@ -212,7 +213,7 @@ define([
enableContainerLayer();
}
event.stopPropagation();
},
}
});
Module.ContainerBlockEmptyView = Marionette.View.extend({
@ -223,13 +224,13 @@ define([
templateContext: function() {
return {
isRoot: this.renderOptions.depth === 0,
emptyContainerMessage: this.renderOptions.emptyContainerMessage || '',
emptyContainerMessage: this.renderOptions.emptyContainerMessage || ''
};
},
}
});
Module.ContainerBlockToolsView = base.BlockToolsView.extend({
getSettingsView: function() { return Module.ContainerBlockSettingsView; },
getSettingsView: function() { return Module.ContainerBlockSettingsView; }
});
Module.ContainerBlockSettingsView = base.BlockSettingsView.extend({
@ -237,31 +238,31 @@ define([
events: function() {
return {
"change .mailpoet_field_container_background_color": _.partial(this.changeColorField, "styles.block.backgroundColor"),
"click .mailpoet_done_editing": "close",
"click .mailpoet_done_editing": "close"
};
},
regions: {
columnsSettingsRegion: '.mailpoet_container_columns_settings',
columnsSettingsRegion: '.mailpoet_container_columns_settings'
},
initialize: function() {
base.BlockSettingsView.prototype.initialize.apply(this, arguments);
this._columnsSettingsView = new (Module.ContainerBlockColumnsSettingsView)({
collection: this.model.get('blocks'),
collection: this.model.get('blocks')
});
},
onRender: function() {
this.showChildView('columnsSettingsRegion', this._columnsSettingsView);
},
}
});
Module.ContainerBlockColumnsSettingsView = Marionette.CollectionView.extend({
childView: function() { return Module.ContainerBlockColumnSettingsView; },
childViewOptions: function(model, index) {
return {
columnIndex: index,
columnIndex: index
};
},
}
});
Module.ContainerBlockColumnSettingsView = Marionette.View.extend({
@ -272,9 +273,9 @@ define([
templateContext: function() {
return {
model: this.model.toJSON(),
columnNumber: this.columnNumber,
columnNumber: this.columnNumber
};
},
}
});
Module.OneColumnContainerWidgetView = base.WidgetView.extend({
@ -287,12 +288,12 @@ define([
return new Module.ContainerBlockModel({
orientation: 'horizontal',
blocks: [
new Module.ContainerBlockModel(),
new Module.ContainerBlockModel()
]
});
}
}
},
}
});
Module.TwoColumnContainerWidgetView = base.WidgetView.extend({
@ -306,12 +307,12 @@ define([
orientation: 'horizontal',
blocks: [
new Module.ContainerBlockModel(),
new Module.ContainerBlockModel(),
new Module.ContainerBlockModel()
]
});
}
}
},
}
});
Module.ThreeColumnContainerWidgetView = base.WidgetView.extend({
@ -326,36 +327,36 @@ define([
blocks: [
new Module.ContainerBlockModel(),
new Module.ContainerBlockModel(),
new Module.ContainerBlockModel(),
new Module.ContainerBlockModel()
]
});
}
}
},
}
});
App.on('before:start', function(App, options) {
App.registerBlockType('container', {
blockModel: Module.ContainerBlockModel,
blockView: Module.ContainerBlockView,
blockView: Module.ContainerBlockView
});
App.registerLayoutWidget({
name: 'oneColumnLayout',
priority: 100,
widgetView: Module.OneColumnContainerWidgetView,
widgetView: Module.OneColumnContainerWidgetView
});
App.registerLayoutWidget({
name: 'twoColumnLayout',
priority: 100,
widgetView: Module.TwoColumnContainerWidgetView,
widgetView: Module.TwoColumnContainerWidgetView
});
App.registerLayoutWidget({
name: 'threeColumnLayout',
priority: 100,
widgetView: Module.ThreeColumnContainerWidgetView,
widgetView: Module.ThreeColumnContainerWidgetView
});
});

View File

@ -24,11 +24,11 @@ define([
padding: '12px',
borderStyle: 'solid',
borderWidth: '1px',
borderColor: '#000000',
},
},
borderColor: '#000000'
}
}
}, App.getConfig().get('blockDefaults.divider'));
},
}
});
Module.DividerBlockView = base.BlockView.extend({
@ -41,11 +41,11 @@ define([
resizeHandleSelector: '.mailpoet_resize_handle',
transformationFunction: function(y) { return y / 2; },
minLength: 0, // TODO: Move this number to editor configuration
modelField: 'styles.block.padding',
modelField: 'styles.block.padding'
},
ShowSettingsBehavior: {
ignoreFrom: '.mailpoet_resize_handle'
},
}
}, base.BlockView.prototype.behaviors),
onDragSubstituteBy: function() { return Module.DividerWidgetView; },
initialize: function() {
@ -61,7 +61,7 @@ define([
},
templateContext: function() {
return _.extend({
totalHeight: parseInt(this.model.get('styles.block.padding'), 10)*2 + parseInt(this.model.get('styles.block.borderWidth')) + 'px',
totalHeight: parseInt(this.model.get('styles.block.padding'), 10)*2 + parseInt(this.model.get('styles.block.borderWidth')) + 'px'
}, base.BlockView.prototype.templateContext.apply(this));
},
onRender: function() {
@ -76,11 +76,11 @@ define([
this.$('.mailpoet_content').css('padding-top', this.model.get('styles.block.padding'));
this.$('.mailpoet_content').css('padding-bottom', this.model.get('styles.block.padding'));
this.$('.mailpoet_resize_handle_text').text(parseInt(this.model.get('styles.block.padding'), 10)*2 + parseInt(this.model.get('styles.block.borderWidth')) + 'px');
},
}
});
Module.DividerBlockToolsView = base.BlockToolsView.extend({
getSettingsView: function() { return Module.DividerBlockSettingsView; },
getSettingsView: function() { return Module.DividerBlockSettingsView; }
});
Module.DividerBlockSettingsView = base.BlockSettingsView.extend({
@ -96,18 +96,18 @@ define([
"change .mailpoet_field_divider_border_color": _.partial(this.changeColorField, "styles.block.borderColor"),
"change .mailpoet_field_divider_background_color": _.partial(this.changeColorField, "styles.block.backgroundColor"),
"click .mailpoet_button_divider_apply_to_all": "applyToAll",
"click .mailpoet_done_editing": "close",
"click .mailpoet_done_editing": "close"
};
},
modelEvents: function() {
return {
'change:styles.block.borderColor': 'repaintDividerStyleOptions',
'change:styles.block.borderColor': 'repaintDividerStyleOptions'
};
},
templateContext: function() {
return _.extend({}, base.BlockView.prototype.templateContext.apply(this, arguments), {
availableStyles: App.getAvailableStyles().toJSON(),
renderOptions: this.renderOptions,
renderOptions: this.renderOptions
});
},
changeStyle: function(event) {
@ -125,7 +125,7 @@ define([
updateValueAndCall: function(fieldToUpdate, callable, event) {
this.$(fieldToUpdate).val(jQuery(event.target).val());
callable(event);
},
}
});
Module.DividerWidgetView = base.WidgetView.extend({
@ -135,20 +135,20 @@ define([
cloneOriginal: true,
drop: function() {
return new Module.DividerBlockModel();
},
}
}
},
}
});
App.on('before:start', function(App, options) {
App.registerBlockType('divider', {
blockModel: Module.DividerBlockModel,
blockView: Module.DividerBlockView,
blockView: Module.DividerBlockView
});
App.registerWidget({
name: 'divider',
widgetView: Module.DividerWidgetView,
priority: 93,
priority: 93
});
});

View File

@ -19,38 +19,38 @@ define([
text: '<a href="[link:subscription_unsubscribe_url]">Unsubscribe</a> | <a href="[link:subscription_manage_url]">Manage subscription</a><br /><b>Add your postal address here!</b>',
styles: {
block: {
backgroundColor: 'transparent',
backgroundColor: 'transparent'
},
text: {
fontColor: '#000000',
fontFamily: 'Arial',
fontSize: '12px',
textAlign: 'center',
textAlign: 'center'
},
link: {
fontColor: '#0000ff',
textDecoration: 'none',
},
},
textDecoration: 'none'
}
}
}, App.getConfig().get('blockDefaults.footer'));
},
}
});
Module.FooterBlockView = base.BlockView.extend({
className: "mailpoet_block mailpoet_footer_block mailpoet_droppable_block",
getTemplate: function() { return templates.footerBlock; },
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')),
behaviors: _.extend({}, base.BlockView.prototype.behaviors, {
TextEditorBehavior: {
configurationFilter: function(originalSettings) {
return _.extend({}, originalSettings, {
mailpoet_shortcodes: App.getConfig().get('shortcodes').toJSON(),
mailpoet_shortcodes_window_title: MailPoet.I18n.t('shortcodesWindowTitle'),
mailpoet_shortcodes_window_title: MailPoet.I18n.t('shortcodesWindowTitle')
});
}
},
}
}),
onDragSubstituteBy: function() { return Module.FooterWidgetView; },
onRender: function() {
@ -67,11 +67,11 @@ define([
onTextEditorBlur: function() {
this.enableDragging();
this.enableShowingTools();
},
}
});
Module.FooterBlockToolsView = base.BlockToolsView.extend({
getSettingsView: function() { return Module.FooterBlockSettingsView; },
getSettingsView: function() { return Module.FooterBlockSettingsView; }
});
Module.FooterBlockSettingsView = base.BlockSettingsView.extend({
@ -87,14 +87,14 @@ define([
},
"change .mailpoet_field_footer_background_color": _.partial(this.changeColorField, "styles.block.backgroundColor"),
"change .mailpoet_field_footer_alignment": _.partial(this.changeField, "styles.text.textAlign"),
"click .mailpoet_done_editing": "close",
"click .mailpoet_done_editing": "close"
};
},
templateContext: function() {
return _.extend({}, base.BlockView.prototype.templateContext.apply(this, arguments), {
availableStyles: App.getAvailableStyles().toJSON(),
availableStyles: App.getAvailableStyles().toJSON()
});
},
}
});
Module.FooterWidgetView = base.WidgetView.extend({
@ -104,21 +104,21 @@ define([
cloneOriginal: true,
drop: function() {
return new Module.FooterBlockModel();
},
}
}
},
}
});
App.on('before:start', function(App, options) {
App.registerBlockType('footer', {
blockModel: Module.FooterBlockModel,
blockView: Module.FooterBlockView,
blockView: Module.FooterBlockView
});
App.registerWidget({
name: 'footer',
widgetView: Module.FooterWidgetView,
priority: 99,
priority: 99
});
});

View File

@ -19,38 +19,38 @@ define([
text: 'Display problems? <a href="[link:newsletter_view_in_browser_url]">View it in your browser</a>',
styles: {
block: {
backgroundColor: 'transparent',
backgroundColor: 'transparent'
},
text: {
fontColor: '#000000',
fontFamily: 'Arial',
fontSize: '12px',
textAlign: 'center',
textAlign: 'center'
},
link: {
fontColor: '#0000ff',
textDecoration: 'underline',
},
},
textDecoration: 'underline'
}
}
}, App.getConfig().get('blockDefaults.header'));
},
}
});
Module.HeaderBlockView = base.BlockView.extend({
className: "mailpoet_block mailpoet_header_block mailpoet_droppable_block",
getTemplate: function() { return templates.headerBlock; },
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')),
behaviors: _.extend({}, base.BlockView.prototype.behaviors, {
TextEditorBehavior: {
configurationFilter: function(originalSettings) {
return _.extend({}, originalSettings, {
mailpoet_shortcodes: App.getConfig().get('shortcodes').toJSON(),
mailpoet_shortcodes_window_title: MailPoet.I18n.t('shortcodesWindowTitle'),
mailpoet_shortcodes_window_title: MailPoet.I18n.t('shortcodesWindowTitle')
});
}
},
}
}),
onDragSubstituteBy: function() { return Module.HeaderWidgetView; },
onRender: function() {
@ -67,11 +67,11 @@ define([
onTextEditorBlur: function() {
this.enableDragging();
this.enableShowingTools();
},
}
});
Module.HeaderBlockToolsView = base.BlockToolsView.extend({
getSettingsView: function() { return Module.HeaderBlockSettingsView; },
getSettingsView: function() { return Module.HeaderBlockSettingsView; }
});
Module.HeaderBlockSettingsView = base.BlockSettingsView.extend({
@ -87,14 +87,14 @@ define([
},
"change .mailpoet_field_header_background_color": _.partial(this.changeColorField, "styles.block.backgroundColor"),
"change .mailpoet_field_header_alignment": _.partial(this.changeField, "styles.text.textAlign"),
"click .mailpoet_done_editing": "close",
"click .mailpoet_done_editing": "close"
};
},
templateContext: function() {
return _.extend({}, base.BlockView.prototype.templateContext.apply(this, arguments), {
availableStyles: App.getAvailableStyles().toJSON(),
availableStyles: App.getAvailableStyles().toJSON()
});
},
}
});
Module.HeaderWidgetView = base.WidgetView.extend({
@ -104,21 +104,21 @@ define([
cloneOriginal: true,
drop: function() {
return new Module.HeaderBlockModel();
},
}
}
},
}
});
App.on('before:start', function(App, options) {
App.registerBlockType('header', {
blockModel: Module.HeaderBlockModel,
blockView: Module.HeaderBlockView,
blockView: Module.HeaderBlockView
});
App.registerWidget({
name: 'header',
widgetView: Module.HeaderWidgetView,
priority: 98,
priority: 98
});
});

View File

@ -25,11 +25,11 @@ define([
height: '64px',
styles: {
block: {
textAlign: 'center',
},
},
textAlign: 'center'
}
}
}, App.getConfig().get('blockDefaults.image'));
},
}
});
Module.ImageBlockView = base.BlockView.extend({
@ -38,11 +38,11 @@ define([
onDragSubstituteBy: function() { return Module.ImageWidgetView; },
templateContext: function() {
return _.extend({
imageMissingSrc: App.getConfig().get('urls.imageMissing'),
imageMissingSrc: App.getConfig().get('urls.imageMissing')
}, base.BlockView.prototype.templateContext.apply(this));
},
behaviors: _.extend({}, base.BlockView.prototype.behaviors, {
ShowSettingsBehavior: {},
ShowSettingsBehavior: {}
}),
onRender: function() {
this.toolsView = new Module.ImageBlockToolsView({ model: this.model });
@ -53,11 +53,11 @@ define([
} else {
this.$el.removeClass('mailpoet_full_image');
}
},
}
});
Module.ImageBlockToolsView = base.BlockToolsView.extend({
getSettingsView: function() { return Module.ImageBlockSettingsView; },
getSettingsView: function() { return Module.ImageBlockSettingsView; }
});
Module.ImageBlockSettingsView = base.BlockSettingsView.extend({
@ -70,7 +70,7 @@ define([
"change .mailpoet_field_image_full_width": _.partial(this.changeBoolCheckboxField, "fullWidth"),
"change .mailpoet_field_image_alignment": _.partial(this.changeField, "styles.block.textAlign"),
"click .mailpoet_field_image_select_another_image": "showMediaManager",
"click .mailpoet_done_editing": "close",
"click .mailpoet_done_editing": "close"
};
},
initialize: function(options) {
@ -141,7 +141,7 @@ define([
// Update user settings when users adjust the
// attachment display settings.
displayUserSettings: false
}),
})
]);
if(wp.media.view.settings.post.featuredImageId) {
@ -285,8 +285,8 @@ define([
},
displaySettings: false,
button: {
text: 'Select',
},
text: 'Select'
}
}),
that = this;
@ -318,7 +318,7 @@ define([
height: mainSize.height + 'px',
width: mainSize.width + 'px',
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
that.render();
@ -346,7 +346,7 @@ define([
if (typeof this._mediaManager === 'object') {
this._mediaManager.remove();
}
},
}
});
ImageWidgetView = base.WidgetView.extend({
@ -359,22 +359,22 @@ define([
},
onDrop: function(options) {
options.droppedView.triggerMethod('showSettings', { showImageManager: true });
},
}
}
},
}
});
Module.ImageWidgetView = ImageWidgetView;
App.on('before:start', function(App, options) {
App.registerBlockType('image', {
blockModel: Module.ImageBlockModel,
blockView: Module.ImageBlockView,
blockView: Module.ImageBlockView
});
App.registerWidget({
name: 'image',
widgetView: Module.ImageWidgetView,
priority: 91,
priority: 91
});
});

View File

@ -76,7 +76,7 @@ define([
divider: {},
_selectedPosts: [],
_availablePosts: [],
_transformedPosts: new (App.getBlockTypeModel('container'))(),
_transformedPosts: new (App.getBlockTypeModel('container'))()
}, App.getConfig().get('blockDefaults.posts'));
},
relations: function() {
@ -85,7 +85,7 @@ define([
divider: App.getBlockTypeModel('divider'),
_selectedPosts: Backbone.Collection,
_availablePosts: Backbone.Collection,
_transformedPosts: App.getBlockTypeModel('container'),
_transformedPosts: App.getBlockTypeModel('container')
};
},
initialize: function() {
@ -172,7 +172,7 @@ define([
}).fail(function() {
MailPoet.Notice.error(MailPoet.I18n.t('failedToFetchRenderedPosts'));
});
},
}
});
Module.PostsBlockView = base.BlockView.extend({
@ -180,7 +180,7 @@ define([
getTemplate: function() { return templates.postsBlock; },
modelEvents: {}, // Forcefully disable all events
regions: _.extend({
postsRegion: '.mailpoet_posts_block_posts',
postsRegion: '.mailpoet_posts_block_posts'
}, base.BlockView.prototype.regions),
onDragSubstituteBy: function() { return Module.PostsWidgetView; },
initialize: function() {
@ -199,7 +199,7 @@ define([
renderOptions = {
disableTextEditor: true,
disableDragAndDrop: true,
emptyContainerMessage: MailPoet.I18n.t('noPostsToDisplay'),
emptyContainerMessage: MailPoet.I18n.t('noPostsToDisplay')
};
this.showChildView('postsRegion', new ContainerView({ model: this.model.get('_transformedPosts'), renderOptions: renderOptions }));
},
@ -208,27 +208,27 @@ define([
},
onBeforeDestroy: function() {
this.model.stopReplying('blockView', this.notifyAboutSelf, this);
},
}
});
Module.PostsBlockToolsView = base.BlockToolsView.extend({
getSettingsView: function() { return Module.PostsBlockSettingsView; },
getSettingsView: function() { return Module.PostsBlockSettingsView; }
});
Module.PostsBlockSettingsView = base.BlockSettingsView.extend({
getTemplate: function() { return templates.postsBlockSettings; },
regions: {
selectionRegion: '.mailpoet_settings_posts_selection',
displayOptionsRegion: '.mailpoet_settings_posts_display_options',
displayOptionsRegion: '.mailpoet_settings_posts_display_options'
},
events: {
'click .mailpoet_settings_posts_show_display_options': 'switchToDisplayOptions',
'click .mailpoet_settings_posts_show_post_selection': 'switchToPostSelection',
'click .mailpoet_settings_posts_insert_selected': 'insertPosts',
'click .mailpoet_settings_posts_insert_selected': 'insertPosts'
},
templateContext: function() {
return {
model: this.model.toJSON(),
model: this.model.toJSON()
};
},
initialize: function() {
@ -251,7 +251,7 @@ define([
onCancel: function() {
// Self destroy the block if the user closes settings modal
that.model.destroy();
},
}
});
// Inform child views that they have been attached to document
@ -280,7 +280,7 @@ define([
this.model.trigger('insertSelectedPosts');
this.model.destroy();
this.close();
},
}
});
var PostsSelectionCollectionView = Marionette.CollectionView.extend({
@ -289,14 +289,14 @@ define([
emptyView: function() { return EmptyPostSelectionSettingsView; },
childViewOptions: function() {
return {
blockModel: this.blockModel,
blockModel: this.blockModel
};
},
initialize: function(options) {
this.blockModel = options.blockModel;
},
events: {
'scroll': 'onPostsScroll',
'scroll': 'onPostsScroll'
},
onPostsScroll: function(event) {
var $postsBox = jQuery(event.target);
@ -304,19 +304,19 @@ define([
// Load more posts if scrolled to bottom
this.blockModel.trigger('loadMorePosts');
}
},
}
});
var PostSelectionSettingsView = Marionette.View.extend({
getTemplate: function() { return templates.postSelectionPostsBlockSettings; },
regions: {
posts: '.mailpoet_post_selection_container',
posts: '.mailpoet_post_selection_container'
},
events: function() {
return {
'change .mailpoet_settings_posts_content_type': _.partial(this.changeField, 'contentType'),
'change .mailpoet_posts_post_status': _.partial(this.changeField, 'postStatus'),
'input .mailpoet_posts_search_term': _.partial(this.changeField, 'search'),
'input .mailpoet_posts_search_term': _.partial(this.changeField, 'search')
};
},
modelEvents: {
@ -392,8 +392,8 @@ define([
}
)
};
},
},
}
}
}).on({
'select2:select': function(event) {
var terms = that.model.get('terms');
@ -406,7 +406,7 @@ define([
terms.remove(event.params.data);
// Reset whole model in order for change events to propagate properly
that.model.set('terms', terms.toJSON());
},
}
}).trigger( 'change' );
},
changeField: function(field, event) {
@ -420,28 +420,28 @@ define([
_.each(postTypes, function(type) {
select.append(jQuery('<option>', {
value: type.name,
text: type.label,
text: type.label
}));
});
select.val(selectedValue);
},
}
});
var EmptyPostSelectionSettingsView = Marionette.View.extend({
getTemplate: function() { return templates.emptyPostPostsBlockSettings; },
getTemplate: function() { return templates.emptyPostPostsBlockSettings; }
});
var SinglePostSelectionSettingsView = Marionette.View.extend({
getTemplate: function() { return templates.singlePostPostsBlockSettings; },
events: function() {
return {
'change .mailpoet_select_post_checkbox': 'postSelectionChange',
'change .mailpoet_select_post_checkbox': 'postSelectionChange'
};
},
templateContext: function() {
return {
model: this.model.toJSON(),
index: this._index,
index: this._index
};
},
initialize: function(options) {
@ -455,7 +455,7 @@ define([
} else {
selectedPostsCollection.remove(this.model);
}
},
}
});
var PostsDisplayOptionsSettingsView = base.BlockSettingsView.extend({
@ -480,12 +480,12 @@ define([
"change .mailpoet_posts_show_categories": _.partial(this.changeField, "showCategories"),
"input .mailpoet_posts_categories": _.partial(this.changeField, "categoriesPrecededBy"),
"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() {
return {
model: this.model.toJSON(),
model: this.model.toJSON()
};
},
showButtonSettings: function(event) {
@ -495,8 +495,8 @@ define([
renderOptions: {
displayFormat: 'subpanel',
hideLink: true,
hideApplyToAll: true,
},
hideApplyToAll: true
}
})).render();
},
showDividerSettings: function(event) {
@ -505,8 +505,8 @@ define([
model: this.model.get('divider'),
renderOptions: {
displayFormat: 'subpanel',
hideApplyToAll: true,
},
hideApplyToAll: true
}
})).render();
},
changeReadMoreType: function(event) {
@ -560,7 +560,7 @@ define([
this.$('.mailpoet_posts_title_as_link').removeClass('mailpoet_hidden');
}
this.changeField('titleFormat', event);
},
}
});
Module.PostsWidgetView = base.WidgetView.extend({
@ -572,19 +572,19 @@ define([
return new Module.PostsBlockModel({}, { parse: true });
}
}
},
}
});
App.on('before:start', function(App, options) {
App.registerBlockType('posts', {
blockModel: Module.PostsBlockModel,
blockView: Module.PostsBlockView,
blockView: Module.PostsBlockView
});
App.registerWidget({
name: 'posts',
widgetView: Module.PostsWidgetView,
priority: 96,
priority: 96
});
});

View File

@ -30,7 +30,7 @@ define([
image: App.getAvailableStyles().get('socialIconSets.default.custom'),
height: '32px',
width: '32px',
text: defaultValues.get('title'),
text: defaultValues.get('title')
};
},
initialize: function(options) {
@ -42,11 +42,11 @@ define([
this.set({
link: defaultValues.get('defaultLink'),
image: iconSet.get(that.get('iconType')),
text: defaultValues.get('title'),
text: defaultValues.get('title')
});
}, this);
this.on('change', function() { App.getChannel().trigger('autoSave'); });
},
}
});
Module.SocialIconCollectionModel = Backbone.Collection.extend({
@ -59,11 +59,11 @@ define([
return this._getDefaults({
type: 'social',
iconSet: 'default',
icons: new Module.SocialIconCollectionModel(),
icons: new Module.SocialIconCollectionModel()
}, App.getConfig().get('blockDefaults.social'));
},
relations: {
icons: Module.SocialIconCollectionModel,
icons: Module.SocialIconCollectionModel
},
initialize: function() {
this.get('icons').on('add remove change', this._iconsChanged, this);
@ -80,27 +80,27 @@ define([
},
_iconsChanged: function() {
App.getChannel().trigger('autoSave');
},
}
});
var SocialIconView = Marionette.View.extend({
tagName: 'span',
getTemplate: function() { return templates.socialIconBlock; },
modelEvents: {
'change': 'render',
'change': 'render'
},
templateContext: function() {
var allIconSets = App.getAvailableStyles().get('socialIconSets');
return {
model: this.model.toJSON(),
allIconSets: allIconSets.toJSON(),
imageMissingSrc: App.getConfig().get('urls.imageMissing'),
imageMissingSrc: App.getConfig().get('urls.imageMissing')
};
},
}
});
Module.SocialIconCollectionView = Marionette.CollectionView.extend({
childView: SocialIconView,
childView: SocialIconView
});
Module.SocialBlockView = base.BlockView.extend({
@ -113,7 +113,7 @@ define([
tools: '> .mailpoet_tools'
},
behaviors: _.extend({}, base.BlockView.prototype.behaviors, {
ShowSettingsBehavior: {},
ShowSettingsBehavior: {}
}),
onDragSubstituteBy: function() { return Module.SocialWidgetView; },
onRender: function() {
@ -122,11 +122,11 @@ define([
this.showChildView('icons', new Module.SocialIconCollectionView({
collection: this.model.get('icons')
}))
},
}
});
Module.SocialBlockToolsView = base.BlockToolsView.extend({
getSettingsView: function() { return Module.SocialBlockSettingsView; },
getSettingsView: function() { return Module.SocialBlockSettingsView; }
});
// Sidebar view container
@ -134,11 +134,11 @@ define([
getTemplate: function() { return templates.socialBlockSettings; },
regions: {
iconRegion: '#mailpoet_social_icons_selection',
stylesRegion: '#mailpoet_social_icons_styles',
stylesRegion: '#mailpoet_social_icons_styles'
},
events: function() {
return {
"click .mailpoet_done_editing": "close",
"click .mailpoet_done_editing": "close"
};
},
initialize: function() {
@ -162,7 +162,7 @@ define([
"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_link": this.changeLink,
"input .mailpoet_social_icon_field_text": _.partial(this.changeField, "text"),
"input .mailpoet_social_icon_field_text": _.partial(this.changeField, "text")
};
},
modelEvents: {
@ -172,7 +172,7 @@ define([
},
'change:text': function() {
this.$('.mailpoet_social_icon_image').attr('alt', this.model.get('text'));
},
}
},
templateContext: function() {
var icons = App.getConfig().get('socialIcons'),
@ -182,7 +182,7 @@ define([
return _.extend({}, base.BlockView.prototype.templateContext.apply(this, arguments), {
iconTypes: availableIconTypes,
currentType: icons.get(this.model.get('iconType')).toJSON(),
allIconSets: allIconSets.toJSON(),
allIconSets: allIconSets.toJSON()
});
},
deleteIcon: function() {
@ -197,17 +197,17 @@ define([
},
changeField: function(field, event) {
this.model.set(field, jQuery(event.target).val());
},
}
});
SocialBlockSettingsIconCollectionView = Marionette.CollectionView.extend({
behaviors: {
SortableBehavior: {
items: '> div',
},
items: '> div'
}
},
childViewContainer: '#mailpoet_social_icon_selector_contents',
childView: SocialBlockSettingsIconView,
childView: SocialBlockSettingsIconView
});
// Select icons section container view
@ -217,10 +217,10 @@ define([
'icons': '#mailpoet_social_icon_selector_contents'
},
events: {
'click .mailpoet_add_social_icon': 'addSocialIcon',
'click .mailpoet_add_social_icon': 'addSocialIcon'
},
modelEvents: {
'change:iconSet': 'render',
'change:iconSet': 'render'
},
addSocialIcon: function() {
// Add a social icon with default values
@ -237,10 +237,10 @@ define([
SocialBlockSettingsStylesView = Marionette.View.extend({
getTemplate: function() { return templates.socialSettingsStyles; },
modelEvents: {
'change': 'render',
'change': 'render'
},
events: {
'click .mailpoet_social_icon_set': 'changeSocialIconSet',
'click .mailpoet_social_icon_set': 'changeSocialIconSet'
},
initialize: function() {
this.listenTo(this.model.get('icons'), 'add remove change', this.render);
@ -251,7 +251,7 @@ define([
activeSet: this.model.get('iconSet'),
socialIconSets: allIconSets.toJSON(),
availableSets: _.keys(allIconSets.toJSON()),
availableSocialIcons: this.model.get('icons').pluck('iconType'),
availableSocialIcons: this.model.get('icons').pluck('iconType')
};
},
changeSocialIconSet: function(event) {
@ -259,7 +259,7 @@ define([
},
onBeforeDestroy: function() {
this.model.get('icons').off('add remove', this.render, this);
},
}
});
Module.SocialWidgetView = base.WidgetView.extend({
@ -279,7 +279,7 @@ define([
image: App.getAvailableStyles().get('socialIconSets.default.facebook'),
height: '32px',
width: '32px',
text: 'Facebook',
text: 'Facebook'
},
{
type: 'socialIcon',
@ -288,25 +288,25 @@ define([
image: App.getAvailableStyles().get('socialIconSets.default.twitter'),
height: '32px',
width: '32px',
text: 'Twitter',
},
],
text: 'Twitter'
}
]
}, { parse: true });
}
}
},
}
});
App.on('before:start', function(App, options) {
App.registerBlockType('social', {
blockModel: Module.SocialBlockModel,
blockView: Module.SocialBlockView,
blockView: Module.SocialBlockView
});
App.registerWidget({
name: 'social',
widgetView: Module.SocialWidgetView,
priority: 95,
priority: 95
});
});

View File

@ -19,11 +19,11 @@ define([
styles: {
block: {
backgroundColor: 'transparent',
height: '40px',
},
},
height: '40px'
}
}
}, App.getConfig().get('blockDefaults.spacer'));
},
}
});
Module.SpacerBlockView = base.BlockView.extend({
@ -34,11 +34,11 @@ define([
elementSelector: '.mailpoet_spacer',
resizeHandleSelector: '.mailpoet_resize_handle',
minLength: 20, // TODO: Move this number to editor configuration
modelField: 'styles.block.height',
modelField: 'styles.block.height'
},
ShowSettingsBehavior: {
ignoreFrom: '.mailpoet_resize_handle'
},
}
}, base.BlockView.prototype.behaviors),
modelEvents: _.omit(base.BlockView.prototype.modelEvents, 'change'),
onDragSubstituteBy: function() { return Module.SpacerWidgetView; },
@ -58,11 +58,11 @@ define([
},
onBeforeDestroy: function() {
this.stopListening(this.model);
},
}
});
Module.SpacerBlockToolsView = base.BlockToolsView.extend({
getSettingsView: function() { return Module.SpacerBlockSettingsView; },
getSettingsView: function() { return Module.SpacerBlockSettingsView; }
});
Module.SpacerBlockSettingsView = base.BlockSettingsView.extend({
@ -70,9 +70,9 @@ define([
events: function() {
return {
"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({
@ -82,21 +82,21 @@ define([
cloneOriginal: true,
drop: function() {
return new Module.SpacerBlockModel();
},
}
}
},
}
});
App.on('before:start', function(App, options) {
App.registerBlockType('spacer', {
blockModel: Module.SpacerBlockModel,
blockView: Module.SpacerBlockView,
blockView: Module.SpacerBlockView
});
App.registerWidget({
name: 'spacer',
widgetView: Module.SpacerWidgetView,
priority: 94,
priority: 94
});
});

View File

@ -16,9 +16,9 @@ define([
defaults: function() {
return this._getDefaults({
type: 'text',
text: 'Edit this to insert text',
text: 'Edit this to insert text'
}, App.getConfig().get('blockDefaults.text'));
},
}
});
Module.TextBlockView = base.BlockView.extend({
@ -36,16 +36,16 @@ define([
configurationFilter: function(originalSettings) {
return _.extend({}, originalSettings, {
mailpoet_shortcodes: App.getConfig().get('shortcodes').toJSON(),
mailpoet_shortcodes_window_title: MailPoet.I18n.t('shortcodesWindowTitle'),
mailpoet_shortcodes_window_title: MailPoet.I18n.t('shortcodesWindowTitle')
});
}
},
}
}),
initialize: function(options) {
base.BlockView.prototype.initialize.apply(this, arguments);
this.renderOptions = _.defaults(options.renderOptions || {}, {
disableTextEditor: false,
disableTextEditor: false
});
this.disableTextEditor = this.renderOptions.disableTextEditor;
@ -55,8 +55,8 @@ define([
this.toolsView = new Module.TextBlockToolsView({
model: this.model,
tools: {
settings: false,
},
settings: false
}
});
this.showChildView('toolsRegion', this.toolsView);
},
@ -70,15 +70,15 @@ define([
onTextEditorBlur: function() {
this.enableDragging();
this.enableShowingTools();
},
}
});
Module.TextBlockToolsView = base.BlockToolsView.extend({
getSettingsView: function() { return Module.TextBlockSettingsView; },
getSettingsView: function() { return Module.TextBlockSettingsView; }
});
Module.TextBlockSettingsView = base.BlockSettingsView.extend({
getTemplate: function() { return templates.textBlockSettings; },
getTemplate: function() { return templates.textBlockSettings; }
});
Module.TextWidgetView = base.WidgetView.extend({
@ -88,21 +88,21 @@ define([
cloneOriginal: true,
drop: function() {
return new Module.TextBlockModel();
},
}
}
},
}
});
App.on('before:start', function(App, options) {
App.registerBlockType('text', {
blockModel: Module.TextBlockModel,
blockView: Module.TextBlockView,
blockView: Module.TextBlockView
});
App.registerWidget({
name: 'text',
widgetView: Module.TextWidgetView,
priority: 90,
priority: 90
});
});

View File

@ -12,8 +12,8 @@ define([
blockDefaults: {},
sidepanelWidth: '331px',
validation: {},
urls: {},
},
urls: {}
}
});
// Global and available styles for access in blocks and their settings

View File

@ -22,7 +22,7 @@ define([
// Use only whitelisted properties to ensure properties editor
// doesn't control don't change.
return _.pick(SuperModel.prototype.toJSON.call(this), this.whitelisted);
},
}
});
// Content block view and model handlers for different content types
@ -48,13 +48,13 @@ define([
Module.getBody = function() {
return {
content: App._contentContainer.toJSON(),
globalStyles: App.getGlobalStyles().toJSON(),
globalStyles: App.getGlobalStyles().toJSON()
};
};
Module.toJSON = function() {
return _.extend({
body: Module.getBody(),
body: Module.getBody()
}, App.getNewsletter().toJSON());
};
@ -94,7 +94,7 @@ define([
App._contentContainer = new (App.getBlockTypeModel('container'))(content, {parse: true});
App._contentContainerView = new (App.getBlockTypeView('container'))({
model: App._contentContainer,
renderOptions: { depth: 0 },
renderOptions: { depth: 0 }
});
App._appView.showChildView('contentRegion', App._contentContainerView);

View File

@ -14,18 +14,18 @@ define([
getTemplate: function() { return templates.heading; },
templateContext: function() {
return {
model: this.model.toJSON(),
model: this.model.toJSON()
};
},
events: function() {
return {
'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) {
this.model.set(field, jQuery(event.target).val());
},
}
});
App.on('start', function(App, options) {

View File

@ -49,7 +49,7 @@ define([
MailPoet.Notice.error(
MailPoet.I18n.t('templateSaveFailed'),
{
scroll: true,
scroll: true
}
);
} else {
@ -105,7 +105,7 @@ define([
promise.then(function(thumbnail) {
var data = _.extend(options || {}, {
thumbnail: thumbnail.toDataURL('image/jpeg'),
body: JSON.stringify(App.getBody()),
body: JSON.stringify(App.getBody())
});
return MailPoet.Ajax.post({
@ -132,7 +132,7 @@ define([
).then(function(thumbnail) {
var data = _.extend(options || {}, {
thumbnail: thumbnail.toDataURL('image/jpeg'),
body: App.getBody(),
body: App.getBody()
});
var blob = new Blob(
[JSON.stringify(data)],
@ -154,7 +154,7 @@ define([
'click .mailpoet_save_as_template': 'saveAsTemplate',
/* Export template */
'click .mailpoet_save_export': 'toggleExportTemplate',
'click .mailpoet_export_template': 'exportTemplate',
'click .mailpoet_export_template': 'exportTemplate'
},
initialize: function(options) {
App.getChannel().on('beforeEditorSave', this.beforeSave, this);
@ -202,7 +202,7 @@ define([
MailPoet.I18n.t('templateNameMissing'),
{
positionAfter: that.$el,
scroll: true,
scroll: true
}
);
} else if (templateDescription === '') {
@ -210,19 +210,19 @@ define([
MailPoet.I18n.t('templateDescriptionMissing'),
{
positionAfter: that.$el,
scroll: true,
scroll: true
}
);
} else {
Module.saveTemplate({
name: templateName,
description: templateDescription,
description: templateDescription
}).done(function() {
MailPoet.Notice.success(
MailPoet.I18n.t('templateSaved'),
{
positionAfter: that.$el,
scroll: true,
scroll: true
}
);
}).fail(function() {
@ -230,7 +230,7 @@ define([
MailPoet.I18n.t('templateSaveFailed'),
{
positionAfter: that.$el,
scroll: true,
scroll: true
}
);
});
@ -255,7 +255,7 @@ define([
MailPoet.I18n.t('templateNameMissing'),
{
positionAfter: that.$el,
scroll: true,
scroll: true
}
);
} else if (templateDescription === '') {
@ -263,13 +263,13 @@ define([
MailPoet.I18n.t('templateDescriptionMissing'),
{
positionAfter: that.$el,
scroll: true,
scroll: true
}
);
} else {
Module.exportTemplate({
name: templateName,
description: templateDescription,
description: templateDescription
});
this.hideExportTemplate();
}
@ -311,7 +311,7 @@ define([
hideValidationError: function() {
this.$('.mailpoet_save_error').addClass('mailpoet_hidden');
this.$('.mailpoet_save_next').removeClass('button-disabled');
},
}
});
Module.autoSave = function() {

View File

@ -30,10 +30,10 @@ define([
defaults: {
name: '',
priority: 100,
widgetView: undefined,
},
widgetView: undefined
}
}),
comparator: 'priority',
comparator: 'priority'
}))();
Module.registerWidget = function(widget) { return Module._contentWidgets.add(widget); };
Module.getWidgets = function() { return Module._contentWidgets; };
@ -44,10 +44,10 @@ define([
defaults: {
name: '',
priority: 100,
widgetView: undefined,
},
widgetView: undefined
}
}),
comparator: 'priority',
comparator: 'priority'
}))();
Module.registerLayoutWidget = function(widget) { return Module._layoutWidgets.add(widget); };
Module.getLayoutWidgets = function() { return Module._layoutWidgets; };
@ -58,7 +58,7 @@ define([
contentRegion: '.mailpoet_content_region',
layoutRegion: '.mailpoet_layout_region',
stylesRegion: '.mailpoet_styles_region',
previewRegion: '.mailpoet_preview_region',
previewRegion: '.mailpoet_preview_region'
},
events: {
'click .mailpoet_sidebar_region h3, .mailpoet_sidebar_region .handlediv': function(event) {
@ -84,11 +84,11 @@ define([
easing: "easeIn",
complete: function() {
$targetRegion.removeClass('closed');
},
}
}
);
}
},
}
},
initialize: function(options) {
jQuery(window)
@ -104,7 +104,7 @@ define([
));
this.showChildView('stylesRegion', new Module.SidebarStylesView({
model: App.getGlobalStyles(),
availableStyles: App.getAvailableStyles(),
availableStyles: App.getAvailableStyles()
}));
this.showChildView('previewRegion', new Module.SidebarPreviewView());
},
@ -127,13 +127,13 @@ define([
},
onDomRefresh: function() {
this.$el.parent().stick_in_parent({
offset_top: 32,
offset_top: 32
});
this.$el.parent().on('sticky_kit:stick', this.updateHorizontalScroll.bind(this));
this.$el.parent().on('sticky_kit:unstick', this.updateHorizontalScroll.bind(this));
this.$el.parent().on('sticky_kit:bottom', this.updateHorizontalScroll.bind(this));
this.$el.parent().on('sticky_kit:unbottom', this.updateHorizontalScroll.bind(this));
},
}
});
/**
@ -167,7 +167,7 @@ define([
* Responsible for rendering draggable layout widgets
*/
Module.SidebarLayoutWidgetsView = Module.SidebarWidgetsView.extend({
getTemplate: function() { return templates.sidebarLayout; },
getTemplate: function() { return templates.sidebarLayout; }
});
/**
@ -176,7 +176,7 @@ define([
Module.SidebarStylesView = Marionette.View.extend({
getTemplate: function() { return templates.sidebarStyles; },
behaviors: {
ColorPickerBehavior: {},
ColorPickerBehavior: {}
},
events: function() {
return {
@ -213,13 +213,13 @@ define([
this.model.set('link.textDecoration', (event.target.checked) ? event.target.value : 'none');
},
"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() {
return {
model: this.model.toJSON(),
availableStyles: this.availableStyles.toJSON(),
availableStyles: this.availableStyles.toJSON()
};
},
initialize: function(options) {
@ -234,14 +234,14 @@ define([
value = 'transparent';
}
this.model.set(field, value);
},
}
});
Module.SidebarPreviewView = Marionette.View.extend({
getTemplate: function() { return templates.sidebarPreview; },
events: {
'click .mailpoet_show_preview': 'showPreview',
'click #mailpoet_send_preview': 'sendPreview',
'click #mailpoet_send_preview': 'sendPreview'
},
onBeforeDestroy: function() {
if (this.previewView) {
@ -263,7 +263,7 @@ define([
api_version: window.mailpoet_api_version,
endpoint: 'newsletters',
action: 'showPreview',
data: json,
data: json
}).always(function() {
MailPoet.Modal.loading(false);
}).done(function(response) {
@ -296,7 +296,7 @@ define([
var $emailField = this.$('#mailpoet_preview_to_email');
var data = {
subscriber: $emailField.val(),
id: App.getNewsletter().get('id'),
id: App.getNewsletter().get('id')
};
if (data.subscriber.length <= 0) {
@ -304,7 +304,7 @@ define([
MailPoet.I18n.t('newsletterPreviewEmailMissing'),
{
positionAfter: $emailField,
scroll: true,
scroll: true
}
);
return false;
@ -333,7 +333,7 @@ define([
}
});
});
},
}
});
Module.NewsletterPreviewView = Marionette.View.extend({
@ -347,7 +347,7 @@ define([
return {
previewUrl: this.previewUrl,
width: this.width,
height: this.height,
height: this.height
};
}
});

View File

@ -13,7 +13,7 @@ define([
text: {
fontColor: '#000000',
fontFamily: 'Arial',
fontSize: '16px',
fontSize: '16px'
},
h1: {
fontColor: '#111111',
@ -23,33 +23,33 @@ define([
h2: {
fontColor: '#222222',
fontFamily: 'Tahoma',
fontSize: '32px',
fontSize: '32px'
},
h3: {
fontColor: '#333333',
fontFamily: 'Verdana',
fontSize: '24px',
fontSize: '24px'
},
link: {
fontColor: '#21759B',
textDecoration: 'underline',
textDecoration: 'underline'
},
wrapper: {
backgroundColor: '#ffffff',
backgroundColor: '#ffffff'
},
body: {
backgroundColor: '#cccccc',
},
backgroundColor: '#cccccc'
}
},
initialize: function() {
this.on('change', function() { App.getChannel().trigger('autoSave'); });
},
}
});
Module.StylesView = Marionette.View.extend({
getTemplate: function() { return templates.styles; },
modelEvents: {
'change': 'render',
'change': 'render'
},
serializeData: function() {
return this.model.toJSON();

View File

@ -31,7 +31,7 @@ tinymce.PluginManager.add('mailpoet_shortcodes', function(editor, url) {
if (configShortcodes.hasOwnProperty(segment)) {
shortcodes.push({
type: 'label',
text: segment,
text: segment
});
for (var i = 0; i < configShortcodes[segment].length; i += 1) {
@ -51,8 +51,8 @@ tinymce.PluginManager.add('mailpoet_shortcodes', function(editor, url) {
autoScroll: true,
title: editor.settings.mailpoet_shortcodes_window_title,
body: shortcodes,
buttons: [],
buttons: []
});
},
}
});
});

View File

@ -13,15 +13,15 @@ ImageAndTextTemplateWidgetView = EditorApplication.module('blocks.base').WidgetV
orientation: 'horizontal',
blocks: [
{
type: 'image',
type: 'image'
},
{
type: 'text',
text: 'Some random text',
},
],
text: 'Some random text'
}
]
}, {parse: true});
},
}
}
},
}
});

View File

@ -1,6 +1,6 @@
import React from 'react'
import classNames from 'classnames'
import ReactTooltip from 'react-tooltip'
import React from 'react';
import classNames from 'classnames';
import ReactTooltip from 'react-tooltip';
class Badge extends React.Component {
render() {

View File

@ -1,21 +1,21 @@
import MailPoet from 'mailpoet'
import React from 'react'
import MailPoet from 'mailpoet';
import React from 'react';
import Badge from './badge.jsx'
import Badge from './badge.jsx';
const badges = {
excellent: {
name: MailPoet.I18n.t('excellentBadgeName'),
tooltipTitle: MailPoet.I18n.t('excellentBadgeTooltip')
tooltipTitle: MailPoet.I18n.t('excellentBadgeTooltip'),
},
good: {
name: MailPoet.I18n.t('goodBadgeName'),
tooltipTitle: MailPoet.I18n.t('goodBadgeTooltip')
tooltipTitle: MailPoet.I18n.t('goodBadgeTooltip'),
},
bad: {
name: MailPoet.I18n.t('badBadgeName'),
tooltipTitle: MailPoet.I18n.t('badBadgeTooltip')
}
tooltipTitle: MailPoet.I18n.t('badBadgeTooltip'),
},
};
const stats = {
@ -24,7 +24,7 @@ const stats = {
badgeTypes: [
'excellent',
'good',
'bad'
'bad',
],
tooltipText: MailPoet.I18n.t('openedStatTooltip'),
},
@ -33,25 +33,25 @@ const stats = {
badgeTypes: [
'excellent',
'good',
'bad'
'bad',
],
tooltipText: MailPoet.I18n.t('clickedStatTooltip')
tooltipText: MailPoet.I18n.t('clickedStatTooltip'),
},
unsubscribed: {
badgeRanges: [3, 1, 0],
badgeTypes: [
'bad',
'good',
'excellent'
'excellent',
],
tooltipText: MailPoet.I18n.t('unsubscribedStatTooltip')
tooltipText: MailPoet.I18n.t('unsubscribedStatTooltip'),
},
};
class StatsBadge extends React.Component {
getBadgeType(stat, rate) {
const len = stat.badgeRanges.length;
for (var i = 0; i < len; i++) {
for (let i = 0; i < len; i += 1) {
if (rate > stat.badgeRanges[i]) {
return stat.badgeTypes[i];
}

View File

@ -3,48 +3,48 @@ define(
'react',
'react-router',
'classnames',
'mailpoet'
'mailpoet',
],
function(
(
React,
Router,
classNames,
MailPoet
) {
var Link = Router.Link;
) => {
const Link = Router.Link;
var Breadcrumb = React.createClass({
getInitialState: function() {
const Breadcrumb = React.createClass({
getInitialState: function () {
return {
step: null,
steps: [
{
name: 'type',
label: MailPoet.I18n.t('selectType'),
link: '/new'
link: '/new',
},
{
name: 'template',
label: MailPoet.I18n.t('template')
label: MailPoet.I18n.t('template'),
},
{
name: 'editor',
label: MailPoet.I18n.t('designer')
label: MailPoet.I18n.t('designer'),
},
{
name: 'send',
label: MailPoet.I18n.t('send')
}
]
label: MailPoet.I18n.t('send'),
},
],
};
},
render: function() {
var steps = this.state.steps.map(function(step, index) {
var stepClasses = classNames(
render: function () {
const steps = this.state.steps.map((step, index) => {
const stepClasses = classNames(
{ 'mailpoet_current': (this.props.step === step.name) }
);
var label = step.label;
let label = step.label;
if(step['link'] !== undefined && this.props.step !== step.name) {
label = (
@ -60,14 +60,14 @@ define(
{ (index < (this.state.steps.length - 1) ) ? ' > ' : '' }
</span>
);
}.bind(this));
});
return (
<p className="mailpoet_breadcrumb">
{ steps }
</p>
);
}
},
});
return Breadcrumb;

View File

@ -1,56 +1,56 @@
import React from 'react'
import ReactDOM from 'react-dom'
import ReactStringReplace from 'react-string-replace'
import { Link } from 'react-router'
import MailPoet from 'mailpoet'
import classNames from 'classnames'
import moment from 'moment'
import jQuery from 'jquery'
import Hooks from 'wp-js-hooks'
import StatsBadge from 'newsletters/badges/stats.jsx'
import React from 'react';
import ReactDOM from 'react-dom';
import ReactStringReplace from 'react-string-replace';
import { Link } from 'react-router';
import MailPoet from 'mailpoet';
import classNames from 'classnames';
import moment from 'moment';
import jQuery from 'jquery';
import Hooks from 'wp-js-hooks';
import StatsBadge from 'newsletters/badges/stats.jsx';
const _QueueMixin = {
pauseSending: function(newsletter) {
pauseSending: function (newsletter) {
MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: 'sendingQueue',
action: 'pause',
data: {
newsletter_id: newsletter.id
}
}).done(function() {
newsletter_id: newsletter.id,
},
}).done(() => {
jQuery('#resume_'+newsletter.id).show();
jQuery('#pause_'+newsletter.id).hide();
}).fail((response) => {
if (response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
}
});
},
resumeSending: function(newsletter) {
resumeSending: function (newsletter) {
MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: 'sendingQueue',
action: 'resume',
data: {
newsletter_id: newsletter.id
}
}).done(function() {
newsletter_id: newsletter.id,
},
}).done(() => {
jQuery('#pause_'+newsletter.id).show();
jQuery('#resume_'+newsletter.id).hide();
}).fail((response) => {
if (response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
}
});
},
renderQueueStatus: function(newsletter, mailer_log) {
renderQueueStatus: function (newsletter, mailer_log) {
if (!newsletter.queue) {
return (
<span>{MailPoet.I18n.t('notSentYet')}</span>
@ -58,18 +58,18 @@ const _QueueMixin = {
} else if (mailer_log.status === 'paused' && newsletter.queue.status !== 'completed') {
return (
<span>{MailPoet.I18n.t('paused')}</span>
)
);
} else {
if (newsletter.queue.status === 'scheduled') {
return (
<span>
{ MailPoet.I18n.t('scheduledFor') } { MailPoet.Date.format(newsletter.queue.scheduled_at) }
</span>
)
);
}
const progressClasses = classNames(
'mailpoet_progress',
{ 'mailpoet_progress_complete': newsletter.queue.status === 'completed'}
{ 'mailpoet_progress_complete': newsletter.queue.status === 'completed' }
);
// calculate percentage done
@ -84,7 +84,7 @@ const _QueueMixin = {
<span>
{
MailPoet.I18n.t('newsletterQueueCompleted')
.replace("%$1d",newsletter.queue.count_processed)
.replace("%$1d", newsletter.queue.count_processed)
.replace("%$2d", newsletter.queue.count_total)
}
</span>
@ -128,7 +128,7 @@ const _QueueMixin = {
<div className={ progressClasses }>
<span
className="mailpoet_progress_bar"
style={ { width: progress_bar_width + "%"} }
style={ { width: progress_bar_width + "%" } }
></span>
<span className="mailpoet_progress_label">
{ percentage }
@ -144,12 +144,12 @@ const _QueueMixin = {
};
const _StatisticsMixin = {
renderStatistics: function(newsletter, is_sent, current_time) {
renderStatistics: function (newsletter, is_sent, current_time) {
if (is_sent === undefined) {
// condition for standard and post notification listings
is_sent = newsletter.statistics
&& newsletter.queue
&& newsletter.queue.status !== 'scheduled'
&& newsletter.queue.status !== 'scheduled';
}
if (!is_sent) {
return (
@ -286,6 +286,7 @@ const _StatisticsMixin = {
<Link
key={ `stats-${newsletter.id}` }
to={ params.link }
onClick={ params.onClick || null }
>
{content}
</Link>
@ -300,11 +301,11 @@ const _StatisticsMixin = {
{after_content}
</div>
);
}
}
},
};
const _MailerMixin = {
checkMailerStatus: function(state) {
checkMailerStatus: function (state) {
if (state.meta.mta_log.error && state.meta.mta_log.status === 'paused') {
MailPoet.Notice.error(
'',
@ -321,10 +322,10 @@ const _MailerMixin = {
},
getMailerError(state) {
let mailer_error_notice;
let mailer_check_settings_notice = ReactStringReplace(
const mailer_check_settings_notice = ReactStringReplace(
MailPoet.I18n.t('mailerCheckSettingsNotice'),
/\[link\](.*?)\[\/link\]/g,
(match, i) => (
match => (
<a href={`?page=mailpoet-settings#mta`}>{ match }</a>
)
);
@ -355,25 +356,25 @@ const _MailerMixin = {
MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: 'mailer',
action: 'resumeSending'
}).done(function() {
action: 'resumeSending',
}).done(() => {
MailPoet.Notice.hide('mailpoet_mailer_error');
MailPoet.Notice.success(MailPoet.I18n.t('mailerSendingResumedNotice'));
window.mailpoet_listing.forceUpdate();
}).fail((response) => {
if (response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
}
});
}
}
},
};
export { _QueueMixin as QueueMixin };
export { _StatisticsMixin as StatisticsMixin };
export { _MailerMixin as MailerMixin };
export { _MailerMixin as MailerMixin };

View File

@ -1,24 +1,20 @@
import React from 'react'
import { Router, Route, IndexRoute, Link, useRouterHistory } from 'react-router'
import { createHashHistory } from 'history'
import React from 'react';
import { Link } from 'react-router';
import Listing from 'listing/listing.jsx'
import ListingTabs from 'newsletters/listings/tabs.jsx'
import Listing from 'listing/listing.jsx';
import ListingTabs from 'newsletters/listings/tabs.jsx';
import { MailerMixin } from 'newsletters/listings/mixins.jsx'
import { MailerMixin } from 'newsletters/listings/mixins.jsx';
import classNames from 'classnames'
import jQuery from 'jquery'
import MailPoet from 'mailpoet'
import classNames from 'classnames';
import MailPoet from 'mailpoet';
import {
timeOfDayValues,
weekDayValues,
monthDayValues,
nthWeekDayValues
} from 'newsletters/scheduling/common.jsx'
const mailpoet_settings = window.mailpoet_settings || {};
nthWeekDayValues,
} from 'newsletters/scheduling/common.jsx';
const messages = {
onTrash: (response) => {
@ -65,76 +61,76 @@ const messages = {
).replace('%$1d', count.toLocaleString());
}
MailPoet.Notice.success(message);
}
},
};
const columns = [
{
name: 'subject',
label: MailPoet.I18n.t('subject'),
sortable: true
sortable: true,
},
{
name: 'status',
label: MailPoet.I18n.t('status'),
width: 100
width: 100,
},
{
name: 'settings',
label: MailPoet.I18n.t('settings')
label: MailPoet.I18n.t('settings'),
},
{
name: 'history',
label: MailPoet.I18n.t('history'),
width: 100
width: 100,
},
{
name: 'updated_at',
label: MailPoet.I18n.t('lastModifiedOn'),
sortable: true
}
sortable: true,
},
];
const bulk_actions = [
{
name: 'trash',
label: MailPoet.I18n.t('moveToTrash'),
onSuccess: messages.onTrash
}
onSuccess: messages.onTrash,
},
];
const newsletter_actions = [
{
name: 'view',
link: function(newsletter) {
link: function (newsletter) {
return (
<a href={ newsletter.preview_url } target="_blank">
{MailPoet.I18n.t('preview')}
</a>
);
}
},
},
{
name: 'edit',
link: function(newsletter) {
link: function (newsletter) {
return (
<a href={ `?page=mailpoet-newsletter-editor&id=${ newsletter.id }` }>
{MailPoet.I18n.t('edit')}
</a>
);
}
},
},
{
name: 'duplicate',
label: MailPoet.I18n.t('duplicate'),
onClick: function(newsletter, refresh) {
onClick: function (newsletter, refresh) {
return MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: 'newsletters',
action: 'duplicate',
data: {
id: newsletter.id
}
id: newsletter.id,
},
}).done((response) => {
MailPoet.Notice.success(
(MailPoet.I18n.t('newsletterDuplicated')).replace(
@ -145,21 +141,21 @@ const newsletter_actions = [
}).fail((response) => {
if (response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
}
});
}
},
},
{
name: 'trash'
}
name: 'trash',
},
];
const NewsletterListNotification = React.createClass({
mixins: [ MailerMixin ],
updateStatus: function(e) {
updateStatus: function (e) {
// make the event persist so that we can still override the selected value
// in the ajax callback
e.persist();
@ -170,8 +166,8 @@ const NewsletterListNotification = React.createClass({
action: 'setStatus',
data: {
id: ~~(e.target.getAttribute('data-id')),
status: e.target.value
}
status: e.target.value,
},
}).done((response) => {
if (response.data.status === 'active') {
MailPoet.Notice.success(MailPoet.I18n.t('postNotificationActivated'));
@ -185,7 +181,7 @@ const NewsletterListNotification = React.createClass({
e.target.value = response.status;
});
},
renderStatus: function(newsletter) {
renderStatus: function (newsletter) {
return (
<select
data-id={ newsletter.id }
@ -197,13 +193,13 @@ const NewsletterListNotification = React.createClass({
</select>
);
},
renderSettings: function(newsletter) {
renderSettings: function (newsletter) {
let sendingFrequency;
let sendingToSegments;
// get list of segments' name
const segments = newsletter.segments.map(function(segment) {
return segment.name
const segments = newsletter.segments.map((segment) => {
return segment.name;
});
// check if the user has specified segments to send to
@ -224,7 +220,7 @@ const NewsletterListNotification = React.createClass({
sendingFrequency = MailPoet.I18n.t('sendDaily').replace(
'%$1s', timeOfDayValues[newsletter.options.timeOfDay]
);
break;
break;
case 'weekly':
sendingFrequency = MailPoet.I18n.t('sendWeekly').replace(
@ -232,7 +228,7 @@ const NewsletterListNotification = React.createClass({
).replace(
'%$2s', timeOfDayValues[newsletter.options.timeOfDay]
);
break;
break;
case 'monthly':
sendingFrequency = MailPoet.I18n.t('sendMonthly').replace(
@ -240,7 +236,7 @@ const NewsletterListNotification = React.createClass({
).replace(
'%$2s', timeOfDayValues[newsletter.options.timeOfDay]
);
break;
break;
case 'nthWeekDay':
sendingFrequency = MailPoet.I18n.t('sendNthWeekDay').replace(
@ -250,11 +246,11 @@ const NewsletterListNotification = React.createClass({
).replace(
'%$3s', timeOfDayValues[newsletter.options.timeOfDay]
);
break;
break;
case 'immediately':
sendingFrequency = MailPoet.I18n.t('sendImmediately');
break;
break;
}
}
@ -264,7 +260,7 @@ const NewsletterListNotification = React.createClass({
</span>
);
},
renderHistoryLink: function(newsletter) {
renderHistoryLink: function (newsletter) {
const childrenCount = ~~(newsletter.children_count);
if (childrenCount === 0) {
return (
@ -278,7 +274,7 @@ const NewsletterListNotification = React.createClass({
);
}
},
renderItem: function(newsletter, actions) {
renderItem: function (newsletter, actions) {
const rowClasses = classNames(
'manage-column',
'column-primary',
@ -311,7 +307,7 @@ const NewsletterListNotification = React.createClass({
</div>
);
},
render: function() {
render: function () {
return (
<div>
<h1 className="title">
@ -339,7 +335,7 @@ const NewsletterListNotification = React.createClass({
/>
</div>
);
}
},
});
module.exports = NewsletterListNotification;

View File

@ -1,21 +1,19 @@
import React from 'react'
import { Router, Link } from 'react-router'
import classNames from 'classnames'
import jQuery from 'jquery'
import MailPoet from 'mailpoet'
import Hooks from 'wp-js-hooks'
import React from 'react';
import { Link } from 'react-router';
import classNames from 'classnames';
import MailPoet from 'mailpoet';
import Hooks from 'wp-js-hooks';
import Listing from 'listing/listing.jsx'
import ListingTabs from 'newsletters/listings/tabs.jsx'
import Listing from 'listing/listing.jsx';
import ListingTabs from 'newsletters/listings/tabs.jsx';
import {
QueueMixin,
StatisticsMixin,
MailerMixin
} from 'newsletters/listings/mixins.jsx'
MailerMixin,
} from 'newsletters/listings/mixins.jsx';
const mailpoet_tracking_enabled = (!!(window['mailpoet_tracking_enabled']));
const mailpoet_settings = window.mailpoet_settings || {};
const columns = [
{
@ -24,58 +22,51 @@ const columns = [
},
{
name: 'status',
label: MailPoet.I18n.t('status')
label: MailPoet.I18n.t('status'),
},
{
name: 'segments',
label: MailPoet.I18n.t('lists')
label: MailPoet.I18n.t('lists'),
},
{
name: 'statistics',
label: MailPoet.I18n.t('statistics'),
display: mailpoet_tracking_enabled
display: mailpoet_tracking_enabled,
},
{
name: 'processed_at',
name: 'sent_at',
label: MailPoet.I18n.t('sentOn'),
}
},
];
let newsletter_actions = [
{
name: 'view',
link: function(newsletter) {
link: function (newsletter) {
return (
<a href={ newsletter.preview_url } target="_blank">
{MailPoet.I18n.t('preview')}
</a>
);
}
}
},
},
];
newsletter_actions = Hooks.applyFilters('mailpoet_newsletters_listings_notification_history_actions', newsletter_actions);
const NewsletterListNotificationHistory = React.createClass({
mixins: [ QueueMixin, StatisticsMixin, MailerMixin ],
renderSentDate: function(newsletter) {
return (newsletter.queue.status === 'completed')
? ( <abbr>{ MailPoet.Date.format(newsletter.updated_at) }</abbr> )
: MailPoet.I18n.t('notSentYet')
},
renderItem: function(newsletter, actions, meta) {
renderItem: function (newsletter, actions, meta) {
const rowClasses = classNames(
'manage-column',
'column-primary',
'has-row-actions'
);
const segments = newsletter.segments.map(function(segment) {
return segment.name
const segments = newsletter.segments.map((segment) => {
return segment.name;
}).join(', ');
const mailer_log = window.mailpoet_settings.mta_log || {};
return (
<div>
<td className={ rowClasses }>
@ -98,13 +89,13 @@ const NewsletterListNotificationHistory = React.createClass({
{ this.renderStatistics(newsletter, undefined, meta.current_time) }
</td>
) : null }
<td className="column-date" data-colname={ MailPoet.I18n.t('lastModifiedOn') }>
{ this.renderSentDate(newsletter) }
<td className="column-date" data-colname={ MailPoet.I18n.t('sentOn') }>
{ (newsletter.sent_at) ? MailPoet.Date.format(newsletter.sent_at) : MailPoet.I18n.t('notSentYet') }
</td>
</div>
);
},
render: function() {
render: function () {
return (
<div>
<h1 className="title">
@ -129,13 +120,13 @@ const NewsletterListNotificationHistory = React.createClass({
columns={columns}
item_actions={ newsletter_actions }
auto_refresh={ true }
sort_by="updated_at"
sort_by="sent_at"
sort_order="desc"
afterGetItems={ this.checkMailerStatus }
/>
</div>
);
}
},
});
module.exports = NewsletterListNotificationHistory;
module.exports = NewsletterListNotificationHistory;

View File

@ -1,20 +1,19 @@
import React from 'react'
import { Link } from 'react-router'
import classNames from 'classnames'
import MailPoet from 'mailpoet'
import Hooks from 'wp-js-hooks'
import React from 'react';
import { Link } from 'react-router';
import classNames from 'classnames';
import MailPoet from 'mailpoet';
import Hooks from 'wp-js-hooks';
import Listing from 'listing/listing.jsx'
import ListingTabs from 'newsletters/listings/tabs.jsx'
import Listing from 'listing/listing.jsx';
import ListingTabs from 'newsletters/listings/tabs.jsx';
import {
QueueMixin,
StatisticsMixin,
MailerMixin
} from 'newsletters/listings/mixins.jsx'
MailerMixin,
} from 'newsletters/listings/mixins.jsx';
const mailpoet_tracking_enabled = (!!(window['mailpoet_tracking_enabled']));
const mailpoet_settings = window.mailpoet_settings || {};
const messages = {
onTrash: (response) => {
@ -61,75 +60,75 @@ const messages = {
).replace('%$1d', count.toLocaleString());
}
MailPoet.Notice.success(message);
}
},
};
const columns = [
{
name: 'subject',
label: MailPoet.I18n.t('subject'),
sortable: true
sortable: true,
},
{
name: 'status',
label: MailPoet.I18n.t('status')
label: MailPoet.I18n.t('status'),
},
{
name: 'segments',
label: MailPoet.I18n.t('lists')
label: MailPoet.I18n.t('lists'),
},
{
name: 'statistics',
label: MailPoet.I18n.t('statistics'),
display: mailpoet_tracking_enabled
display: mailpoet_tracking_enabled,
},
{
name: 'updated_at',
label: MailPoet.I18n.t('lastModifiedOn'),
sortable: true
}
name: 'sent_at',
label: MailPoet.I18n.t('sentOn'),
sortable: true,
},
];
const bulk_actions = [
{
name: 'trash',
label: MailPoet.I18n.t('moveToTrash'),
onSuccess: messages.onTrash
}
onSuccess: messages.onTrash,
},
];
let newsletter_actions = [
{
name: 'view',
link: function(newsletter) {
link: function (newsletter) {
return (
<a href={ newsletter.preview_url } target="_blank">
{MailPoet.I18n.t('preview')}
</a>
);
}
},
},
{
name: 'edit',
link: function(newsletter) {
link: function (newsletter) {
return (
<a href={ `?page=mailpoet-newsletter-editor&id=${ newsletter.id }` }>
{MailPoet.I18n.t('edit')}
</a>
);
}
},
},
{
name: 'duplicate',
label: MailPoet.I18n.t('duplicate'),
onClick: function(newsletter, refresh) {
onClick: function (newsletter, refresh) {
return MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: 'newsletters',
action: 'duplicate',
data: {
id: newsletter.id
}
id: newsletter.id,
},
}).done((response) => {
MailPoet.Notice.success(
(MailPoet.I18n.t('newsletterDuplicated')).replace(
@ -140,31 +139,31 @@ let newsletter_actions = [
}).fail((response) => {
if (response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
}
});
}
},
},
{
name: 'trash'
}
name: 'trash',
},
];
newsletter_actions = Hooks.applyFilters('mailpoet_newsletters_listings_standard_actions', newsletter_actions);
const NewsletterListStandard = React.createClass({
mixins: [ QueueMixin, StatisticsMixin, MailerMixin ],
renderItem: function(newsletter, actions, meta) {
renderItem: function (newsletter, actions, meta) {
const rowClasses = classNames(
'manage-column',
'column-primary',
'has-row-actions'
);
const segments = newsletter.segments.map(function(segment) {
return segment.name
const segments = newsletter.segments.map((segment) => {
return segment.name;
}).join(', ');
return (
@ -189,13 +188,13 @@ const NewsletterListStandard = React.createClass({
{ this.renderStatistics(newsletter, undefined, meta.current_time) }
</td>
) : null }
<td className="column-date" data-colname={ MailPoet.I18n.t('lastModifiedOn') }>
<abbr>{ MailPoet.Date.format(newsletter.updated_at) }</abbr>
<td className="column-date" data-colname={ MailPoet.I18n.t('sentOn') }>
<abbr>{ (newsletter.sent_at) ? MailPoet.Date.format(newsletter.sent_at) : MailPoet.I18n.t('notSentYet') }</abbr>
</td>
</div>
);
},
render: function() {
render: function () {
return (
<div>
<h1 className="title">
@ -217,13 +216,13 @@ const NewsletterListStandard = React.createClass({
item_actions={ newsletter_actions }
messages={ messages }
auto_refresh={ true }
sort_by="updated_at"
sort_by="sent_at"
sort_order="desc"
afterGetItems={ this.checkMailerStatus }
/>
</div>
);
}
},
});
module.exports = NewsletterListStandard;

View File

@ -1,7 +1,7 @@
import React from 'react'
import { Link } from 'react-router'
import classNames from 'classnames'
import MailPoet from 'mailpoet'
import React from 'react';
import { Link } from 'react-router';
import classNames from 'classnames';
import MailPoet from 'mailpoet';
const ListingTabs = React.createClass({
getInitialState() {
@ -11,19 +11,19 @@ const ListingTabs = React.createClass({
{
name: 'standard',
label: MailPoet.I18n.t('tabStandardTitle'),
link: '/standard'
link: '/standard',
},
{
name: 'welcome',
label: MailPoet.I18n.t('tabWelcomeTitle'),
link: '/welcome'
link: '/welcome',
},
{
name: 'notification',
label: MailPoet.I18n.t('tabNotificationTitle'),
link: '/notification'
}
]
link: '/notification',
},
],
};
},
render() {
@ -47,7 +47,7 @@ const ListingTabs = React.createClass({
{ tabs }
</h2>
);
}
},
});
module.exports = ListingTabs;
module.exports = ListingTabs;

View File

@ -1,22 +1,19 @@
import React from 'react'
import { Router, Route, IndexRoute, Link, useRouterHistory } from 'react-router'
import { createHashHistory } from 'history'
import React from 'react';
import { Link } from 'react-router';
import Listing from 'listing/listing.jsx'
import ListingTabs from 'newsletters/listings/tabs.jsx'
import Listing from 'listing/listing.jsx';
import ListingTabs from 'newsletters/listings/tabs.jsx';
import { StatisticsMixin, MailerMixin } from 'newsletters/listings/mixins.jsx'
import { StatisticsMixin, MailerMixin } from 'newsletters/listings/mixins.jsx';
import classNames from 'classnames'
import jQuery from 'jquery'
import MailPoet from 'mailpoet'
import _ from 'underscore'
import Hooks from 'wp-js-hooks'
import classNames from 'classnames';
import MailPoet from 'mailpoet';
import _ from 'underscore';
import Hooks from 'wp-js-hooks';
const mailpoet_roles = window.mailpoet_roles || {};
const mailpoet_segments = window.mailpoet_segments || {};
const mailpoet_tracking_enabled = (!!(window['mailpoet_tracking_enabled']));
const mailpoet_settings = window.mailpoet_settings || {};
const messages = {
onTrash: (response) => {
@ -63,75 +60,75 @@ const messages = {
).replace('%$1d', count.toLocaleString());
}
MailPoet.Notice.success(message);
}
},
};
const columns = [
{
name: 'subject',
label: MailPoet.I18n.t('subject'),
sortable: true
sortable: true,
},
{
name: 'status',
label: MailPoet.I18n.t('status'),
width: 145
width: 145,
},
{
name: 'settings',
label: MailPoet.I18n.t('settings')
label: MailPoet.I18n.t('settings'),
},
{
name: 'statistics',
label: MailPoet.I18n.t('statistics'),
display: mailpoet_tracking_enabled
display: mailpoet_tracking_enabled,
},
{
name: 'updated_at',
label: MailPoet.I18n.t('lastModifiedOn'),
sortable: true
}
sortable: true,
},
];
const bulk_actions = [
{
name: 'trash',
label: MailPoet.I18n.t('moveToTrash'),
onSuccess: messages.onTrash
}
onSuccess: messages.onTrash,
},
];
let newsletter_actions = [
{
name: 'view',
link: function(newsletter) {
link: function (newsletter) {
return (
<a href={ newsletter.preview_url } target="_blank">
{MailPoet.I18n.t('preview')}
</a>
);
}
},
},
{
name: 'edit',
link: function(newsletter) {
link: function (newsletter) {
return (
<a href={ `?page=mailpoet-newsletter-editor&id=${ newsletter.id }` }>
{MailPoet.I18n.t('edit')}
</a>
);
}
},
},
{
name: 'trash'
}
name: 'trash',
},
];
newsletter_actions = Hooks.applyFilters('mailpoet_newsletters_listings_welcome_notification_actions', newsletter_actions);
const NewsletterListWelcome = React.createClass({
mixins: [ StatisticsMixin, MailerMixin ],
updateStatus: function(e) {
updateStatus: function (e) {
// make the event persist so that we can still override the selected value
// in the ajax callback
e.persist();
@ -142,8 +139,8 @@ const NewsletterListWelcome = React.createClass({
action: 'setStatus',
data: {
id: ~~(e.target.getAttribute('data-id')),
status: e.target.value
}
status: e.target.value,
},
}).done((response) => {
if (response.data.status === 'active') {
MailPoet.Notice.success(MailPoet.I18n.t('welcomeEmailActivated'));
@ -157,9 +154,8 @@ const NewsletterListWelcome = React.createClass({
e.target.value = response.status;
});
},
renderStatus: function(newsletter) {
let total_sent;
total_sent = (
renderStatus: function (newsletter) {
const total_sent = (
MailPoet.I18n.t('sentToXSubscribers')
.replace('%$1d', newsletter.total_sent.toLocaleString())
);
@ -180,7 +176,7 @@ const NewsletterListWelcome = React.createClass({
</div>
);
},
renderSettings: function(newsletter) {
renderSettings: function (newsletter) {
let sendingEvent;
let sendingDelay;
@ -195,11 +191,11 @@ const NewsletterListWelcome = React.createClass({
'%$1s', mailpoet_roles[newsletter.options.role]
);
}
break;
break;
case 'segment':
// get segment
const segment = _.find(mailpoet_segments, function(segment) {
const segment = _.find(mailpoet_segments, (segment) => {
return (~~(segment.id) === ~~(newsletter.options.segment));
});
@ -214,7 +210,7 @@ const NewsletterListWelcome = React.createClass({
'%$1s', segment.name
);
}
break;
break;
}
// set sending delay
@ -225,19 +221,19 @@ const NewsletterListWelcome = React.createClass({
sendingDelay = MailPoet.I18n.t('sendingDelayHours').replace(
'%$1d', newsletter.options.afterTimeNumber
);
break;
break;
case 'days':
sendingDelay = MailPoet.I18n.t('sendingDelayDays').replace(
'%$1d', newsletter.options.afterTimeNumber
);
break;
break;
case 'weeks':
sendingDelay = MailPoet.I18n.t('sendingDelayWeeks').replace(
'%$1d', newsletter.options.afterTimeNumber
);
break;
break;
}
sendingEvent += ' [' + sendingDelay + ']';
}
@ -251,7 +247,7 @@ const NewsletterListWelcome = React.createClass({
</span>
);
},
renderItem: function(newsletter, actions) {
renderItem: function (newsletter, actions) {
const rowClasses = classNames(
'manage-column',
'column-primary',
@ -289,7 +285,7 @@ const NewsletterListWelcome = React.createClass({
</div>
);
},
render: function() {
render: function () {
return (
<div>
<h1 className="title">
@ -317,7 +313,7 @@ const NewsletterListWelcome = React.createClass({
/>
</div>
);
}
},
});
module.exports = NewsletterListWelcome;

View File

@ -1,27 +1,27 @@
import React from 'react'
import ReactDOM from 'react-dom'
import { Router, Route, IndexRedirect, Link, useRouterHistory } from 'react-router'
import { createHashHistory } from 'history'
import Hooks from 'wp-js-hooks'
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, IndexRedirect, useRouterHistory } from 'react-router';
import { createHashHistory } from 'history';
import Hooks from 'wp-js-hooks';
import NewsletterTypes from 'newsletters/types.jsx'
import NewsletterTemplates from 'newsletters/templates.jsx'
import NewsletterSend from 'newsletters/send.jsx'
import NewsletterTypes from 'newsletters/types.jsx';
import NewsletterTemplates from 'newsletters/templates.jsx';
import NewsletterSend from 'newsletters/send.jsx';
import NewsletterTypeStandard from 'newsletters/types/standard.jsx'
import NewsletterTypeNotification from 'newsletters/types/notification/notification.jsx'
import NewsletterTypeStandard from 'newsletters/types/standard.jsx';
import NewsletterTypeNotification from 'newsletters/types/notification/notification.jsx';
import NewsletterListStandard from 'newsletters/listings/standard.jsx'
import NewsletterListWelcome from 'newsletters/listings/welcome.jsx'
import NewsletterListNotification from 'newsletters/listings/notification.jsx'
import NewsletterListNotificationHistory from 'newsletters/listings/notification_history.jsx'
import NewsletterListStandard from 'newsletters/listings/standard.jsx';
import NewsletterListWelcome from 'newsletters/listings/welcome.jsx';
import NewsletterListNotification from 'newsletters/listings/notification.jsx';
import NewsletterListNotificationHistory from 'newsletters/listings/notification_history.jsx';
const history = useRouterHistory(createHashHistory)({ queryKey: false });
const App = React.createClass({
render() {
return this.props.children;
}
},
});
const container = document.getElementById('newsletters_container');

View File

@ -1,5 +1,5 @@
import _ from 'underscore'
import MailPoet from 'mailpoet'
import _ from 'underscore';
import MailPoet from 'mailpoet';
const timeFormat = window.mailpoet_time_format || 'H:i';
@ -8,7 +8,7 @@ const _timeDelayValues = {
'immediate': MailPoet.I18n.t('delayImmediately'),
'hours': MailPoet.I18n.t('delayHoursAfter'),
'days': MailPoet.I18n.t('delayDaysAfter'),
'weeks': MailPoet.I18n.t('delayWeeksAfter')
'weeks': MailPoet.I18n.t('delayWeeksAfter'),
};
const _intervalValues = {
@ -16,7 +16,7 @@ const _intervalValues = {
'weekly': MailPoet.I18n.t('weekly'),
'monthly': MailPoet.I18n.t('monthly'),
'nthWeekDay': MailPoet.I18n.t('monthlyEvery'),
'immediately': MailPoet.I18n.t('immediately')
'immediately': MailPoet.I18n.t('immediately'),
};
// notification emails
@ -25,14 +25,14 @@ const TIME_STEP_SECONDS = 3600;
const numberOfTimeSteps = SECONDS_IN_DAY / TIME_STEP_SECONDS;
const _timeOfDayValues = _.object(_.map(
_.times(numberOfTimeSteps,function(step) {
_.times(numberOfTimeSteps, (step) => {
return step * TIME_STEP_SECONDS;
}), function(seconds) {
let date = new Date(null);
date.setSeconds(seconds);
const timeLabel = MailPoet.Date.format(date, { format: timeFormat, offset: 0 });
return [seconds, timeLabel];
})
}), (seconds) => {
const date = new Date(null);
date.setSeconds(seconds);
const timeLabel = MailPoet.Date.format(date, { format: timeFormat, offset: 0 });
return [seconds, timeLabel];
})
);
const _weekDayValues = {
@ -42,28 +42,28 @@ const _weekDayValues = {
3: MailPoet.I18n.t('wednesday'),
4: MailPoet.I18n.t('thursday'),
5: MailPoet.I18n.t('friday'),
6: MailPoet.I18n.t('saturday')
6: MailPoet.I18n.t('saturday'),
};
const NUMBER_OF_DAYS_IN_MONTH = 28;
const _monthDayValues = _.object(
_.map(
_.times(NUMBER_OF_DAYS_IN_MONTH, function(day) {
_.times(NUMBER_OF_DAYS_IN_MONTH, (day) => {
return day;
}), function(day) {
const labels = {
0: MailPoet.I18n.t('first'),
1: MailPoet.I18n.t('second'),
2: MailPoet.I18n.t('third')
};
let label;
if (labels[day] !== undefined) {
label = labels[day];
} else {
label = MailPoet.I18n.t('nth').replace("%$1d", day + 1);
}
return [day + 1, label];
}), (day) => {
const labels = {
0: MailPoet.I18n.t('first'),
1: MailPoet.I18n.t('second'),
2: MailPoet.I18n.t('third'),
};
let label;
if (labels[day] !== undefined) {
label = labels[day];
} else {
label = MailPoet.I18n.t('nth').replace("%$1d", day + 1);
}
return [day + 1, label];
}
)
);
@ -71,7 +71,7 @@ const _nthWeekDayValues = {
'1': MailPoet.I18n.t('first'),
'2': MailPoet.I18n.t('second'),
'3': MailPoet.I18n.t('third'),
'L': MailPoet.I18n.t('last')
'L': MailPoet.I18n.t('last'),
};
export { _timeDelayValues as timeDelayValues };

View File

@ -8,9 +8,9 @@ define(
'newsletters/send/standard.jsx',
'newsletters/send/notification.jsx',
'newsletters/send/welcome.jsx',
'newsletters/breadcrumb.jsx'
'newsletters/breadcrumb.jsx',
],
function(
(
React,
Router,
_,
@ -20,47 +20,47 @@ define(
NotificationNewsletterFields,
WelcomeNewsletterFields,
Breadcrumb
) {
) => {
var NewsletterSend = React.createClass({
const NewsletterSend = React.createClass({
contextTypes: {
router: React.PropTypes.object.isRequired
router: React.PropTypes.object.isRequired,
},
getInitialState: function() {
getInitialState: function () {
return {
fields: [],
item: {},
loading: false,
};
},
getFieldsByNewsletter: function(newsletter) {
var type = this.getSubtype(newsletter);
getFieldsByNewsletter: function (newsletter) {
const type = this.getSubtype(newsletter);
return type.getFields(newsletter);
},
getSendButtonOptions: function() {
var type = this.getSubtype(this.state.item);
getSendButtonOptions: function () {
const type = this.getSubtype(this.state.item);
return type.getSendButtonOptions(this.state.item);
},
getSubtype: function(newsletter) {
getSubtype: function (newsletter) {
switch(newsletter.type) {
case 'notification': return NotificationNewsletterFields;
case 'welcome': return WelcomeNewsletterFields;
default: return StandardNewsletterFields;
}
},
isValid: function() {
isValid: function () {
return jQuery('#mailpoet_newsletter').parsley().isValid();
},
componentDidMount: function() {
componentDidMount: function () {
if(this.isMounted()) {
this.loadItem(this.props.params.id);
}
jQuery('#mailpoet_newsletter').parsley();
},
componentWillReceiveProps: function(props) {
componentWillReceiveProps: function (props) {
this.loadItem(props.params.id);
},
loadItem: function(id) {
loadItem: function (id) {
this.setState({ loading: true });
MailPoet.Ajax.post({
@ -68,24 +68,24 @@ define(
endpoint: 'newsletters',
action: 'get',
data: {
id: id
}
id: id,
},
}).done((response) => {
this.setState({
loading: false,
item: response.data,
fields: this.getFieldsByNewsletter(response.data)
fields: this.getFieldsByNewsletter(response.data),
});
}).fail((response) => {
}).fail(() => {
this.setState({
loading: false,
item: {}
item: {},
}, () => {
this.context.router.push('/new');
});
});
},
handleSend: function(e) {
handleSend: function (e) {
e.preventDefault();
if(!this.isValid()) {
@ -103,8 +103,8 @@ define(
action: 'setStatus',
data: {
id: this.props.params.id,
status: 'active'
}
status: 'active',
},
}).done((response) => {
// redirect to listing based on newsletter type
this.context.router.push(`/${ this.state.item.type || '' }`);
@ -126,8 +126,8 @@ define(
endpoint: 'sendingQueue',
action: 'add',
data: {
newsletter_id: this.props.params.id
}
newsletter_id: this.props.params.id,
},
}).done((response) => {
// redirect to listing based on newsletter type
this.context.router.push(`/${ this.state.item.type || '' }`);
@ -149,10 +149,10 @@ define(
}
return false;
},
handleSave: function(e) {
handleSave: function (e) {
e.preventDefault();
this._save(e).done((response) => {
this._save(e).done(() => {
MailPoet.Notice.success(
MailPoet.I18n.t('newsletterUpdated')
);
@ -160,11 +160,11 @@ define(
this.context.router.push(`/${ this.state.item.type || '' }`);
}).fail(this._showError);
},
handleRedirectToDesign: function(e) {
handleRedirectToDesign: function (e) {
e.preventDefault();
var redirectTo = e.target.href;
const redirectTo = e.target.href;
this._save(e).done((response) => {
this._save(e).done(() => {
MailPoet.Notice.success(
MailPoet.I18n.t('newsletterUpdated')
);
@ -172,14 +172,14 @@ define(
window.location = redirectTo;
}).fail(this._showError);
},
_save: function(e) {
var data = this.state.item;
_save: function () {
const data = this.state.item;
this.setState({ loading: true });
// Store only properties that can be changed on this page
const IGNORED_NEWSLETTER_PROPERTIES = [
'preheader', 'body', 'created_at', 'deleted_at', 'hash',
'status', 'updated_at', 'type'
'preheader', 'body', 'created_at', 'deleted_at', 'hash',
'status', 'updated_at', 'type',
];
const newsletterData = _.omit(
data,
@ -198,23 +198,23 @@ define(
_showError: (response) => {
if (response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
}
},
handleFormChange: function(e) {
var item = this.state.item,
field = e.target.name;
handleFormChange: function (e) {
const item = this.state.item;
const field = e.target.name;
item[field] = e.target.value;
this.setState({
item: item
item: item,
});
return true;
},
render: function() {
render: function () {
return (
<div>
<h1>{MailPoet.I18n.t('finalNewsletterStep')}</h1>
@ -254,7 +254,7 @@ define(
</Form>
</div>
);
}
},
});
return NewsletterSend;

View File

@ -3,18 +3,16 @@ define(
'mailpoet',
'wp-js-hooks',
'newsletters/types/notification/scheduling.jsx',
'underscore'
'underscore',
],
function(
(
MailPoet,
Hooks,
Scheduling,
_
) {
) => {
var settings = window.mailpoet_settings || {};
var fields = [
let fields = [
{
name: 'subject',
label: MailPoet.I18n.t('subjectLine'),
@ -22,8 +20,8 @@ define(
type: 'text',
validation: {
'data-parsley-required': true,
'data-parsley-required-message': MailPoet.I18n.t('emptySubjectLineError')
}
'data-parsley-required-message': MailPoet.I18n.t('emptySubjectLineError'),
},
},
{
name: 'options',
@ -41,24 +39,24 @@ define(
api_version: window.mailpoet_api_version,
endpoint: 'segments',
multiple: true,
filter: function(segment) {
filter: function (segment) {
return !!(!segment.deleted_at);
},
getLabel: function(segment) {
return segment.name + ' (' + parseInt(segment.subscribers).toLocaleString() + ')';
getLabel: function (segment) {
return segment.name + ' (' + parseInt(segment.subscribers, 10).toLocaleString() + ')';
},
transformChangedValue: function(segment_ids) {
var all_segments = this.state.items;
return _.map(segment_ids, function(id) {
return _.find(all_segments, function(segment) {
transformChangedValue: function (segment_ids) {
const all_segments = this.state.items;
return _.map(segment_ids, (id) => {
return _.find(all_segments, (segment) => {
return segment.id === id;
});
});
},
validation: {
'data-parsley-required': true,
'data-parsley-required-message': MailPoet.I18n.t('noSegmentsSelectedError')
}
'data-parsley-required-message': MailPoet.I18n.t('noSegmentsSelectedError'),
},
},
{
name: 'sender',
@ -70,8 +68,8 @@ define(
type: 'text',
placeholder: MailPoet.I18n.t('senderNamePlaceholder'),
validation: {
'data-parsley-required': true
}
'data-parsley-required': true,
},
},
{
name: 'sender_address',
@ -79,10 +77,10 @@ define(
placeholder: MailPoet.I18n.t('senderAddressPlaceholder'),
validation: {
'data-parsley-required': true,
'data-parsley-type': 'email'
}
}
]
'data-parsley-type': 'email',
},
},
],
},
{
name: 'reply-to',
@ -93,26 +91,26 @@ define(
{
name: 'reply_to_name',
type: 'text',
placeholder: MailPoet.I18n.t('replyToNamePlaceholder')
placeholder: MailPoet.I18n.t('replyToNamePlaceholder'),
},
{
name: 'reply_to_address',
type: 'text',
placeholder: MailPoet.I18n.t('replyToAddressPlaceholder')
}
]
}
placeholder: MailPoet.I18n.t('replyToAddressPlaceholder'),
},
],
},
];
fields = Hooks.applyFilters('mailpoet_newsletters_3rd_step_fields', fields);
return {
getFields: function(newsletter) {
getFields: function () {
return fields;
},
getSendButtonOptions: function(newsletter) {
getSendButtonOptions: function () {
return {
value: MailPoet.I18n.t('activate')
value: MailPoet.I18n.t('activate'),
};
},
};

View File

@ -5,29 +5,22 @@ define(
'underscore',
'mailpoet',
'wp-js-hooks',
'form/fields/checkbox.jsx',
'form/fields/select.jsx',
'form/fields/text.jsx',
],
function(
(
React,
jQuery,
_,
MailPoet,
Hooks,
Checkbox,
Select,
Text
) {
Hooks
) => {
var settings = window.mailpoet_settings || {},
currentTime = window.mailpoet_current_time || '00:00',
defaultDateTime = window.mailpoet_current_date + ' ' + '00:00:00';
timeOfDayItems = window.mailpoet_schedule_time_of_day,
dateDisplayFormat = window.mailpoet_date_display_format,
dateStorageFormat = window.mailpoet_date_storage_format;
const currentTime = window.mailpoet_current_time || '00:00';
const defaultDateTime = window.mailpoet_current_date + ' ' + '00:00:00';
const timeOfDayItems = window.mailpoet_schedule_time_of_day;
const dateDisplayFormat = window.mailpoet_date_display_format;
const dateStorageFormat = window.mailpoet_date_storage_format;
var datepickerTranslations = {
const datepickerTranslations = {
closeText: MailPoet.I18n.t('close'),
currentText: MailPoet.I18n.t('today'),
nextText: MailPoet.I18n.t('next'),
@ -44,7 +37,7 @@ define(
MailPoet.I18n.t('september'),
MailPoet.I18n.t('october'),
MailPoet.I18n.t('november'),
MailPoet.I18n.t('december')
MailPoet.I18n.t('december'),
],
monthNamesShort: [
MailPoet.I18n.t('januaryShort'),
@ -58,7 +51,7 @@ define(
MailPoet.I18n.t('septemberShort'),
MailPoet.I18n.t('octoberShort'),
MailPoet.I18n.t('novemberShort'),
MailPoet.I18n.t('decemberShort')
MailPoet.I18n.t('decemberShort'),
],
dayNames: [
MailPoet.I18n.t('sunday'),
@ -67,7 +60,7 @@ define(
MailPoet.I18n.t('wednesday'),
MailPoet.I18n.t('thursday'),
MailPoet.I18n.t('friday'),
MailPoet.I18n.t('saturday')
MailPoet.I18n.t('saturday'),
],
dayNamesShort: [
MailPoet.I18n.t('sundayShort'),
@ -76,7 +69,7 @@ define(
MailPoet.I18n.t('wednesdayShort'),
MailPoet.I18n.t('thursdayShort'),
MailPoet.I18n.t('fridayShort'),
MailPoet.I18n.t('saturdayShort')
MailPoet.I18n.t('saturdayShort'),
],
dayNamesMin: [
MailPoet.I18n.t('sundayMin'),
@ -85,35 +78,35 @@ define(
MailPoet.I18n.t('wednesdayMin'),
MailPoet.I18n.t('thursdayMin'),
MailPoet.I18n.t('fridayMin'),
MailPoet.I18n.t('saturdayMin')
MailPoet.I18n.t('saturdayMin'),
],
};
var DateText = React.createClass({
onChange: function(event) {
const DateText = React.createClass({
onChange: function (event) {
// Swap display format to storage format
var displayDate = event.target.value,
storageDate = this.getStorageDate(displayDate);
const displayDate = event.target.value;
const storageDate = this.getStorageDate(displayDate);
event.target.value = storageDate;
this.props.onChange(event);
},
componentDidMount: function() {
var $element = jQuery(this.refs.dateInput),
that = this;
componentDidMount: function () {
const $element = jQuery(this.refs.dateInput);
const that = this;
if ($element.datepicker) {
// Override jQuery UI datepicker Date parsing and formatting
jQuery.datepicker.parseDate = function(format, value) {
jQuery.datepicker.parseDate = function (format, value) {
// Transform string format to Date object
return MailPoet.Date.toDate(value, {
parseFormat: dateDisplayFormat,
format: format
format: format,
});
};
jQuery.datepicker.formatDate = function(format, value) {
jQuery.datepicker.formatDate = function (format, value) {
// Transform Date object to string format
var newValue = MailPoet.Date.format(value, {
format: format
const newValue = MailPoet.Date.format(value, {
format: format,
});
return newValue;
};
@ -121,7 +114,7 @@ define(
$element.datepicker(_.extend({
dateFormat: this.props.displayFormat,
isRTL: false,
onSelect: function(value) {
onSelect: function (value) {
that.onChange({
target: {
name: that.getFieldName(),
@ -134,27 +127,27 @@ define(
this.datepickerInitialized = true;
}
},
componentWillUnmount: function() {
componentWillUnmount: function () {
if (this.datepickerInitialized) {
jQuery(this.refs.dateInput).datepicker('destroy');
}
},
getFieldName: function() {
getFieldName: function () {
return this.props.name || 'date';
},
getDisplayDate: function(date) {
getDisplayDate: function (date) {
return MailPoet.Date.format(date, {
parseFormat: this.props.storageFormat,
format: this.props.displayFormat
format: this.props.displayFormat,
});
},
getStorageDate: function(date) {
getStorageDate: function (date) {
return MailPoet.Date.format(date, {
parseFormat: this.props.displayFormat,
format: this.props.storageFormat
format: this.props.storageFormat,
});
},
render: function() {
render: function () {
return (
<input
type="text"
@ -169,8 +162,8 @@ define(
},
});
var TimeSelect = React.createClass({
render: function() {
const TimeSelect = React.createClass({
render: function () {
const options = Object.keys(timeOfDayItems).map(
(value, index) => {
return (
@ -193,47 +186,47 @@ define(
{options}
</select>
);
}
},
});
var DateTime = React.createClass({
const DateTime = React.createClass({
_DATE_TIME_SEPARATOR: " ",
getInitialState: function() {
getInitialState: function () {
return this._buildStateFromProps(this.props);
},
componentWillReceiveProps: function(nextProps) {
componentWillReceiveProps: function (nextProps) {
this.setState(this._buildStateFromProps(nextProps));
},
_buildStateFromProps: function(props) {
let value = props.value || defaultDateTime;
const [date, time] = value.split(this._DATE_TIME_SEPARATOR)
_buildStateFromProps: function (props) {
const value = props.value || defaultDateTime;
const [date, time] = value.split(this._DATE_TIME_SEPARATOR);
return {
date: date,
time: time,
};
},
handleChange: function(event) {
var newState = {};
handleChange: function (event) {
const newState = {};
newState[event.target.name] = event.target.value;
this.setState(newState, function() {
this.setState(newState, function () {
this.propagateChange();
});
},
propagateChange: function() {
propagateChange: function () {
if (this.props.onChange) {
return this.props.onChange({
target: {
name: this.props.name || '',
value: this.getDateTime(),
}
})
},
});
}
},
getDateTime: function() {
getDateTime: function () {
return [this.state.date, this.state.time].join(this._DATE_TIME_SEPARATOR);
},
render: function() {
render: function () {
return (
<span>
<DateText
@ -250,47 +243,47 @@ define(
validation={this.props.timeValidation} />
</span>
);
}
},
});
var StandardScheduling = React.createClass({
_getCurrentValue: function() {
const StandardScheduling = React.createClass({
_getCurrentValue: function () {
return _.defaults(
this.props.item[this.props.field.name] || {},
{
isScheduled: '0',
scheduledAt: defaultDateTime
scheduledAt: defaultDateTime,
}
);
},
handleValueChange: function(event) {
var oldValue = this._getCurrentValue(),
newValue = {};
handleValueChange: function (event) {
const oldValue = this._getCurrentValue();
const newValue = {};
newValue[event.target.name] = event.target.value;
return this.props.onValueChange({
target: {
name: this.props.field.name,
value: _.extend({}, oldValue, newValue)
}
value: _.extend({}, oldValue, newValue),
},
});
},
handleCheckboxChange: function(event) {
handleCheckboxChange: function (event) {
event.target.value = this.refs.isScheduled.checked ? '1' : '0';
return this.handleValueChange(event);
},
isScheduled: function() {
isScheduled: function () {
return this._getCurrentValue().isScheduled === '1';
},
getDateValidation: function() {
getDateValidation: function () {
return {
'data-parsley-required': true,
'data-parsley-required-message': MailPoet.I18n.t('noScheduledDateError'),
'data-parsley-errors-container': '#mailpoet_scheduling',
};
},
render: function() {
var schedulingOptions;
render: function () {
let schedulingOptions;
if (this.isScheduled()) {
schedulingOptions = (
@ -324,7 +317,7 @@ define(
},
});
var fields = [
let fields = [
{
name: 'subject',
label: MailPoet.I18n.t('subjectLine'),
@ -332,8 +325,8 @@ define(
type: 'text',
validation: {
'data-parsley-required': true,
'data-parsley-required-message': MailPoet.I18n.t('emptySubjectLineError')
}
'data-parsley-required-message': MailPoet.I18n.t('emptySubjectLineError'),
},
},
{
name: 'segments',
@ -345,24 +338,24 @@ define(
api_version: window.mailpoet_api_version,
endpoint: 'segments',
multiple: true,
filter: function(segment) {
filter: function (segment) {
return !!(!segment.deleted_at);
},
getLabel: function(segment) {
return segment.name + ' (' + parseInt(segment.subscribers).toLocaleString() + ')';
getLabel: function (segment) {
return segment.name + ' (' + parseInt(segment.subscribers, 10).toLocaleString() + ')';
},
transformChangedValue: function(segment_ids) {
var all_segments = this.state.items;
return _.map(segment_ids, function(id) {
return _.find(all_segments, function(segment) {
transformChangedValue: function (segment_ids) {
const all_segments = this.state.items;
return _.map(segment_ids, (id) => {
return _.find(all_segments, (segment) => {
return segment.id === id;
});
});
},
validation: {
'data-parsley-required': true,
'data-parsley-required-message': MailPoet.I18n.t('noSegmentsSelectedError')
}
'data-parsley-required-message': MailPoet.I18n.t('noSegmentsSelectedError'),
},
},
{
name: 'sender',
@ -374,8 +367,8 @@ define(
type: 'text',
placeholder: MailPoet.I18n.t('senderNamePlaceholder'),
validation: {
'data-parsley-required': true
}
'data-parsley-required': true,
},
},
{
name: 'sender_address',
@ -383,10 +376,10 @@ define(
placeholder: MailPoet.I18n.t('senderAddressPlaceholder'),
validation: {
'data-parsley-required': true,
'data-parsley-type': 'email'
}
}
]
'data-parsley-type': 'email',
},
},
],
},
{
name: 'reply-to',
@ -397,40 +390,40 @@ define(
{
name: 'reply_to_name',
type: 'text',
placeholder: MailPoet.I18n.t('replyToNamePlaceholder')
placeholder: MailPoet.I18n.t('replyToNamePlaceholder'),
},
{
name: 'reply_to_address',
type: 'text',
placeholder: MailPoet.I18n.t('replyToAddressPlaceholder')
}
]
placeholder: MailPoet.I18n.t('replyToAddressPlaceholder'),
},
],
},
{
name: 'options',
label: MailPoet.I18n.t('scheduleIt'),
type: 'reactComponent',
component: StandardScheduling,
}
},
];
fields = Hooks.applyFilters('mailpoet_newsletters_3rd_step_fields', fields);
return {
getFields: function(newsletter) {
getFields: function () {
return fields;
},
getSendButtonOptions: function(newsletter) {
getSendButtonOptions: function (newsletter) {
newsletter = newsletter || {};
let isScheduled = (
const isScheduled = (
typeof newsletter.options === 'object'
&& newsletter.options.isScheduled === '1'
);
let options = {
const options = {
value: (isScheduled
? MailPoet.I18n.t('schedule')
: MailPoet.I18n.t('send'))
: MailPoet.I18n.t('send')),
};
if (newsletter.status === 'sent'

View File

@ -2,17 +2,16 @@ define(
[
'mailpoet',
'wp-js-hooks',
'newsletters/types/welcome/scheduling.jsx'
'newsletters/types/welcome/scheduling.jsx',
],
function(
(
MailPoet,
Hooks,
Scheduling
) {
) => {
var settings = window.mailpoet_settings || {};
var fields = [
let fields = [
{
name: 'subject',
label: MailPoet.I18n.t('subjectLine'),
@ -20,8 +19,8 @@ define(
type: 'text',
validation: {
'data-parsley-required': true,
'data-parsley-required-message': MailPoet.I18n.t('emptySubjectLineError')
}
'data-parsley-required-message': MailPoet.I18n.t('emptySubjectLineError'),
},
},
{
name: 'options',
@ -39,8 +38,8 @@ define(
type: 'text',
placeholder: MailPoet.I18n.t('senderNamePlaceholder'),
validation: {
'data-parsley-required': true
}
'data-parsley-required': true,
},
},
{
name: 'sender_address',
@ -48,10 +47,10 @@ define(
placeholder: MailPoet.I18n.t('senderAddressPlaceholder'),
validation: {
'data-parsley-required': true,
'data-parsley-type': 'email'
}
}
]
'data-parsley-type': 'email',
},
},
],
},
{
name: 'reply-to',
@ -62,26 +61,26 @@ define(
{
name: 'reply_to_name',
type: 'text',
placeholder: MailPoet.I18n.t('replyToNamePlaceholder')
placeholder: MailPoet.I18n.t('replyToNamePlaceholder'),
},
{
name: 'reply_to_address',
type: 'text',
placeholder: MailPoet.I18n.t('replyToAddressPlaceholder')
}
]
}
placeholder: MailPoet.I18n.t('replyToAddressPlaceholder'),
},
],
},
];
fields = Hooks.applyFilters('mailpoet_newsletters_3rd_step_fields', fields);
return {
getFields: function(newsletter) {
getFields: function () {
return fields;
},
getSendButtonOptions: function(newsletter) {
getSendButtonOptions: function () {
return {
value: MailPoet.I18n.t('activate')
value: MailPoet.I18n.t('activate'),
};
},
};

View File

@ -5,19 +5,19 @@ define(
'mailpoet',
'react-router',
'classnames',
'newsletters/breadcrumb.jsx'
'newsletters/breadcrumb.jsx',
],
function(
(
React,
_,
MailPoet,
Router,
classNames,
Breadcrumb
) {
) => {
var ImportTemplate = React.createClass({
saveTemplate: function(template) {
const ImportTemplate = React.createClass({
saveTemplate: function (template) {
// Stringify to enable transmission of primitive non-string value types
if (!_.isUndefined(template.body)) {
@ -30,28 +30,28 @@ define(
api_version: window.mailpoet_api_version,
endpoint: 'newsletterTemplates',
action: 'save',
data: template
}).always(function() {
data: template,
}).always(() => {
MailPoet.Modal.loading(false);
}).done((response) => {
this.props.onImport(response.data);
}).fail((response) => {
if (response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
}
});
},
handleSubmit: function(e) {
handleSubmit: function (e) {
e.preventDefault();
if (_.size(this.refs.templateFile.files) <= 0) return false;
var file = _.first(this.refs.templateFile.files);
var reader = new FileReader();
var saveTemplate = this.saveTemplate;
const file = _.first(this.refs.templateFile.files);
const reader = new FileReader();
const saveTemplate = this.saveTemplate;
reader.onload = (e) => {
try {
@ -63,7 +63,7 @@ define(
reader.readAsText(file);
},
render: function() {
render: function () {
return (
<div>
<h2>{MailPoet.I18n.t('importTemplateTitle')}</h2>
@ -82,17 +82,17 @@ define(
},
});
var NewsletterTemplates = React.createClass({
getInitialState: function() {
const NewsletterTemplates = React.createClass({
getInitialState: function () {
return {
loading: false,
templates: []
templates: [],
};
},
componentDidMount: function() {
componentDidMount: function () {
this.getTemplates();
},
getTemplates: function() {
getTemplates: function () {
this.setState({ loading: true });
MailPoet.Modal.loading(true);
@ -112,19 +112,26 @@ define(
MailPoet.I18n.t('mailpoetGuideTemplateTitle'),
description:
MailPoet.I18n.t('mailpoetGuideTemplateDescription'),
readonly: "1"
}
readonly: "1",
},
];
}
this.setState({
templates: response.data,
loading: false
loading: false,
});
}
}).fail((response) => {
if(response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
}
});
},
handleSelectTemplate: function(template) {
var body = template.body;
handleSelectTemplate: function (template) {
let body = template.body;
// Stringify to enable transmission of primitive non-string value types
if (!_.isUndefined(body)) {
@ -137,21 +144,21 @@ define(
action: 'save',
data: {
id: this.props.params.id,
body: body
}
body: body,
},
}).done((response) => {
// TODO: Move this URL elsewhere
window.location = 'admin.php?page=mailpoet-newsletter-editor&id=' + response.data.id;
}).fail((response) => {
if (response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
}
});
},
handleDeleteTemplate: function(template) {
handleDeleteTemplate: function (template) {
this.setState({ loading: true });
if(
window.confirm(
@ -165,28 +172,35 @@ define(
endpoint: 'newsletterTemplates',
action: 'delete',
data: {
id: template.id
}
}).done((response) => {
id: template.id,
},
}).done(() => {
this.getTemplates();
}).fail((response) => {
if (response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
}
});
} else {
this.setState({ loading: false });
this.setState({ loading: false });
}
},
handleShowTemplate: function(template) {
handleShowTemplate: function (template) {
MailPoet.Modal.popup({
title: template.name,
template: '<div class="mailpoet_boxes_preview" style="background-color: {{ body.globalStyles.body.backgroundColor }}"><img src="{{ thumbnail }}" /></div>',
data: template
data: template,
});
},
handleTemplateImport: function() {
handleTemplateImport: function () {
this.getTemplates();
},
render: function() {
var templates = this.state.templates.map(function(template, index) {
var deleteLink = (
render: function () {
const templates = this.state.templates.map((template, index) => {
const deleteLink = (
<div className="mailpoet_delete">
<a
href="javascript:;"
@ -195,7 +209,8 @@ define(
{MailPoet.I18n.t('delete')}
</a>
</div>
), thumbnail = '';
);
let thumbnail = '';
if (typeof template.thumbnail === 'string'
&& template.thumbnail.length > 0) {
@ -236,9 +251,9 @@ define(
{ (template.readonly === "1") ? false : deleteLink }
</li>
);
}.bind(this));
});
var boxClasses = classNames(
const boxClasses = classNames(
'mailpoet_boxes',
'clearfix',
{ 'mailpoet_boxes_loading': this.state.loading }
@ -257,7 +272,7 @@ define(
<ImportTemplate onImport={this.handleTemplateImport} />
</div>
);
}
},
});
return NewsletterTemplates;

View File

@ -4,25 +4,25 @@ define(
'mailpoet',
'wp-js-hooks',
'react-router',
'newsletters/breadcrumb.jsx'
'newsletters/breadcrumb.jsx',
],
function(
(
React,
MailPoet,
Hooks,
Router,
Breadcrumb
) {
var NewsletterTypes = React.createClass({
) => {
const NewsletterTypes = React.createClass({
contextTypes: {
router: React.PropTypes.object.isRequired
router: React.PropTypes.object.isRequired,
},
setupNewsletter: function(type) {
setupNewsletter: function (type) {
if(type !== undefined) {
this.context.router.push(`/new/${type}`);
}
},
createNewsletter: function(type) {
createNewsletter: function (type) {
MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: 'newsletters',
@ -30,58 +30,58 @@ define(
data: {
type: type,
subject: MailPoet.I18n.t('draftNewsletterTitle'),
}
},
}).done((response) => {
this.context.router.push(`/template/${response.data.id}`);
}).fail((response) => {
if (response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
}
});
},
render: function() {
var types = [
render: function () {
let types = [
{
'id': 'standard',
'title': MailPoet.I18n.t('regularNewsletterTypeTitle'),
'description': MailPoet.I18n.t('regularNewsletterTypeDescription'),
'action': function() {
'action': function () {
return (
<a className="button button-primary" onClick={ this.createNewsletter.bind(null, 'standard') }>
{MailPoet.I18n.t('create')}
</a>
)
}.bind(this)()
);
}.bind(this)(),
},
{
'id': 'welcome',
'title': MailPoet.I18n.t('welcomeNewsletterTypeTitle'),
'description': MailPoet.I18n.t('welcomeNewsletterTypeDescription'),
'action': function() {
'action': function () {
return (
<div>
<a href="?page=mailpoet-premium" target="_blank">
{MailPoet.I18n.t('getPremiumVersion')}
</a>
</div>
)
}()
);
}(),
},
{
'id': 'notification',
'title': MailPoet.I18n.t('postNotificationNewsletterTypeTitle'),
'description': MailPoet.I18n.t('postNotificationNewsletterTypeDescription'),
'action': function() {
'action': function () {
return (
<a className="button button-primary" onClick={ this.setupNewsletter.bind(null, 'notification') }>
{MailPoet.I18n.t('setUp')}
</a>
)
}.bind(this)()
}
);
}.bind(this)(),
},
];
types = Hooks.applyFilters('mailpoet_newsletters_types', types, this);
@ -93,7 +93,7 @@ define(
<Breadcrumb step="type" />
<ul className="mailpoet_boxes clearfix">
{types.map(function(type, index) {
{types.map((type, index) => {
return (
<li key={index} data-type={type.id}>
<div>
@ -109,12 +109,12 @@ define(
</div>
</div>
</li>
)
);
}, this)}
</ul>
</div>
);
}
},
});
return NewsletterTypes;

View File

@ -5,28 +5,28 @@ define(
'react-router',
'mailpoet',
'newsletters/types/notification/scheduling.jsx',
'newsletters/breadcrumb.jsx'
'newsletters/breadcrumb.jsx',
],
function(
(
_,
React,
Router,
MailPoet,
Scheduling,
Breadcrumb
) {
) => {
var field = {
const field = {
name: 'options',
type: 'reactComponent',
component: Scheduling,
};
var NewsletterNotification = React.createClass({
const NewsletterNotification = React.createClass({
contextTypes: {
router: React.PropTypes.object.isRequired
router: React.PropTypes.object.isRequired,
},
getInitialState: function() {
getInitialState: function () {
return {
options: {
intervalType: 'daily',
@ -34,15 +34,15 @@ define(
weekDay: 1,
monthDay: 0,
nthWeekDay: 1,
}
},
};
},
handleValueChange: function(event) {
var state = this.state;
handleValueChange: function (event) {
const state = this.state;
state[event.target.name] = event.target.value;
this.setState(state);
},
handleNext: function() {
handleNext: function () {
MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: 'newsletters',
@ -56,16 +56,16 @@ define(
}).fail((response) => {
if (response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
}
});
},
showTemplateSelection: function(newsletterId) {
showTemplateSelection: function (newsletterId) {
this.context.router.push(`/template/${newsletterId}`);
},
render: function() {
render: function () {
return (
<div>
<h1>{MailPoet.I18n.t('postNotificationNewsletterTypeTitle')}</h1>

View File

@ -1,87 +1,87 @@
import _ from 'underscore'
import React from 'react'
import Select from 'form/fields/select.jsx'
import _ from 'underscore';
import React from 'react';
import Select from 'form/fields/select.jsx';
import {
intervalValues,
timeOfDayValues,
weekDayValues,
monthDayValues,
nthWeekDayValues
} from 'newsletters/scheduling/common.jsx'
nthWeekDayValues,
} from 'newsletters/scheduling/common.jsx';
const intervalField = {
name: 'intervalType',
values: intervalValues
values: intervalValues,
};
const timeOfDayField = {
name: 'timeOfDay',
values: timeOfDayValues
values: timeOfDayValues,
};
const weekDayField = {
name: 'weekDay',
values: weekDayValues
values: weekDayValues,
};
const monthDayField = {
name: 'monthDay',
values: monthDayValues
values: monthDayValues,
};
const nthWeekDayField = {
name: 'nthWeekDay',
values: nthWeekDayValues
values: nthWeekDayValues,
};
const NotificationScheduling = React.createClass({
_getCurrentValue: function() {
_getCurrentValue: function () {
return (this.props.item[this.props.field.name] || {});
},
handleValueChange: function(name, value) {
handleValueChange: function (name, value) {
const oldValue = this._getCurrentValue();
let newValue = {};
const newValue = {};
newValue[name] = value;
return this.props.onValueChange({
target: {
name: this.props.field.name,
value: _.extend({}, oldValue, newValue)
}
value: _.extend({}, oldValue, newValue),
},
});
},
handleIntervalChange: function(event) {
handleIntervalChange: function (event) {
return this.handleValueChange(
'intervalType',
event.target.value
);
},
handleTimeOfDayChange: function(event) {
handleTimeOfDayChange: function (event) {
return this.handleValueChange(
'timeOfDay',
event.target.value
);
},
handleWeekDayChange: function(event) {
handleWeekDayChange: function (event) {
return this.handleValueChange(
'weekDay',
event.target.value
);
},
handleMonthDayChange: function(event) {
handleMonthDayChange: function (event) {
return this.handleValueChange(
'monthDay',
event.target.value
);
},
handleNthWeekDayChange: function(event) {
handleNthWeekDayChange: function (event) {
return this.handleValueChange(
'nthWeekDay',
event.target.value
);
},
render: function() {
render: function () {
const value = this._getCurrentValue();
let timeOfDaySelection;
let weekDaySelection;
@ -137,7 +137,7 @@ const NotificationScheduling = React.createClass({
{timeOfDaySelection}
</div>
);
}
},
});
module.exports = NotificationScheduling;

View File

@ -3,43 +3,43 @@ define(
'react',
'react-router',
'mailpoet',
'newsletters/breadcrumb.jsx'
'newsletters/breadcrumb.jsx',
],
function(
(
React,
Router,
MailPoet,
Breadcrumb
) {
) => {
var NewsletterStandard = React.createClass({
const NewsletterStandard = React.createClass({
contextTypes: {
router: React.PropTypes.object.isRequired
router: React.PropTypes.object.isRequired,
},
showTemplateSelection: function(newsletterId) {
showTemplateSelection: function (newsletterId) {
this.context.router.push(`/template/${newsletterId}`);
},
componentDidMount: function() {
componentDidMount: function () {
// No options for this type, create a newsletter upon mounting
MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: 'newsletters',
action: 'create',
data: {
type: 'standard'
}
type: 'standard',
},
}).done((response) => {
this.showTemplateSelection(response.data.id);
}).fail((response) => {
if (response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
}
});
},
render: function() {
render: function () {
return (
<div>
<h1>{MailPoet.I18n.t('regularNewsletterTypeTitle')}</h1>

View File

@ -1,17 +1,14 @@
import _ from 'underscore'
import React from 'react'
import MailPoet from 'mailpoet'
import Select from 'form/fields/select.jsx'
import Text from 'form/fields/text.jsx'
import {
timeDelayValues,
intervalValues
} from 'newsletters/scheduling/common.jsx'
import _ from 'underscore';
import React from 'react';
import MailPoet from 'mailpoet';
import Select from 'form/fields/select.jsx';
import Text from 'form/fields/text.jsx';
import { timeDelayValues } from 'newsletters/scheduling/common.jsx';
const availableRoles = window.mailpoet_roles || {};
const availableSegments = _.filter(
window.mailpoet_segments || [],
function (segment) {
(segment) => {
return segment.type === 'default';
}
);
@ -21,111 +18,111 @@ const events = {
values: {
'segment': MailPoet.I18n.t('onSubscriptionToList'),
'user': MailPoet.I18n.t('onWPUserRegistration'),
}
},
};
const availableSegmentValues = _.object(_.map(
availableSegments,
function(segment) {
let name = segment.name + ' (' + parseInt(segment.subscribers).toLocaleString() + ')';
(segment) => {
const name = segment.name + ' (' + parseInt(segment.subscribers, 10).toLocaleString() + ')';
return [segment.id, name];
}
));
const segmentField = {
name: 'segment',
values: availableSegmentValues,
sortBy: (key, value) => value.toLowerCase()
sortBy: (key, value) => value.toLowerCase(),
};
const roleField = {
name: 'role',
values: availableRoles
values: availableRoles,
};
const afterTimeNumberField = {
name: 'afterTimeNumber',
size: 3
size: 3,
};
const afterTimeTypeField = {
name: 'afterTimeType',
values: timeDelayValues
values: timeDelayValues,
};
const WelcomeScheduling = React.createClass({
contextTypes: {
router: React.PropTypes.object.isRequired
router: React.PropTypes.object.isRequired,
},
_getCurrentValue: function() {
_getCurrentValue: function () {
return (this.props.item[this.props.field.name] || {});
},
handleValueChange: function(name, value) {
handleValueChange: function (name, value) {
const oldValue = this._getCurrentValue();
let newValue = {};
const newValue = {};
newValue[name] = value;
return this.props.onValueChange({
target: {
name: this.props.field.name,
value: _.extend({}, oldValue, newValue)
}
value: _.extend({}, oldValue, newValue),
},
});
},
handleEventChange: function(event) {
handleEventChange: function (event) {
return this.handleValueChange(
'event',
event.target.value
);
},
handleSegmentChange: function(event) {
handleSegmentChange: function (event) {
return this.handleValueChange(
'segment',
event.target.value
);
},
handleRoleChange: function(event) {
handleRoleChange: function (event) {
return this.handleValueChange(
'role',
event.target.value
);
},
handleAfterTimeNumberChange: function(event) {
handleAfterTimeNumberChange: function (event) {
return this.handleValueChange(
'afterTimeNumber',
event.target.value
);
},
handleAfterTimeTypeChange: function(event) {
handleAfterTimeTypeChange: function (event) {
return this.handleValueChange(
'afterTimeType',
event.target.value
);
},
handleNext: function() {
handleNext: function () {
MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: 'newsletters',
action: 'create',
data: {
type: 'welcome',
options: this.state
}
options: this.state,
},
}).done((response) => {
this.showTemplateSelection(response.data.id);
}).fail((response) => {
if (response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
this.showTemplateSelection(response.data.id);
}).fail((response) => {
if (response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
}
});
}
});
},
showTemplateSelection: function(newsletterId) {
showTemplateSelection: function (newsletterId) {
this.context.router.push(`/template/${ newsletterId }`);
},
render: function() {
render: function () {
const value = this._getCurrentValue();
let roleSegmentSelection;
let timeNumber;

View File

@ -3,42 +3,42 @@ define(
'react',
'react-router',
'mailpoet',
'form/form.jsx'
'form/form.jsx',
],
function(
(
React,
Router,
MailPoet,
Form
) {
) => {
let fields = [
const fields = [
{
name: 'name',
label: MailPoet.I18n.t('name'),
type: 'text'
type: 'text',
},
{
name: 'description',
label: MailPoet.I18n.t('description'),
type: 'textarea',
tip: MailPoet.I18n.t('segmentDescriptionTip')
}
tip: MailPoet.I18n.t('segmentDescriptionTip'),
},
];
const messages = {
onUpdate: function() {
onUpdate: function () {
MailPoet.Notice.success(MailPoet.I18n.t('segmentUpdated'));
},
onCreate: function() {
onCreate: function () {
MailPoet.Notice.success(MailPoet.I18n.t('segmentAdded'));
}
},
};
var Link = Router.Link;
const Link = Router.Link;
const SegmentForm = React.createClass({
render: function() {
render: function () {
return (
<div>
<h1 className="title">
@ -54,7 +54,7 @@ define(
/>
</div>
);
}
},
});
return SegmentForm;

View File

@ -1,42 +1,41 @@
import React from 'react'
import { Router, Link } from 'react-router'
import jQuery from 'jquery'
import MailPoet from 'mailpoet'
import classNames from 'classnames'
import React from 'react';
import { Link } from 'react-router';
import MailPoet from 'mailpoet';
import classNames from 'classnames';
import Listing from 'listing/listing.jsx'
import Listing from 'listing/listing.jsx';
var columns = [
const columns = [
{
name: 'name',
label: MailPoet.I18n.t('name'),
sortable: true
sortable: true,
},
{
name: 'description',
label: MailPoet.I18n.t('description')
label: MailPoet.I18n.t('description'),
},
{
name: 'subscribed',
label: MailPoet.I18n.t('subscribed')
label: MailPoet.I18n.t('subscribed'),
},
{
name: 'unconfirmed',
label: MailPoet.I18n.t('unconfirmed')
label: MailPoet.I18n.t('unconfirmed'),
},
{
name: 'unsubscribed',
label: MailPoet.I18n.t('unsubscribed')
label: MailPoet.I18n.t('unsubscribed'),
},
{
name: 'bounced',
label: MailPoet.I18n.t('bounced')
label: MailPoet.I18n.t('bounced'),
},
{
name: 'created_at',
label: MailPoet.I18n.t('createdOn'),
sortable: true
}
sortable: true,
},
];
const messages = {
@ -84,28 +83,28 @@ const messages = {
).replace('%$1d', count.toLocaleString());
}
MailPoet.Notice.success(message);
}
},
};
const bulk_actions = [
{
name: 'trash',
label: MailPoet.I18n.t('moveToTrash'),
onSuccess: messages.onTrash
}
onSuccess: messages.onTrash,
},
];
const item_actions = [
{
name: 'edit',
link: function(item) {
link: function (item) {
return (
<Link to={ `/edit/${item.id}` }>{MailPoet.I18n.t('edit')}</Link>
);
},
display: function(segment) {
display: function (segment) {
return (segment.type !== 'wp_users');
}
},
},
{
name: 'duplicate_segment',
@ -116,8 +115,8 @@ const item_actions = [
endpoint: 'segments',
action: 'duplicate',
data: {
id: item.id
}
id: item.id,
},
}).done((response) => {
MailPoet.Notice.success(
MailPoet.I18n.t('listDuplicated').replace('%$1s', response.data.name)
@ -125,18 +124,18 @@ const item_actions = [
refresh();
}).fail((response) => {
MailPoet.Notice.error(
response.errors.map(function(error) { return error.message; }),
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
});
},
display: function(segment) {
display: function (segment) {
return (segment.type !== 'wp_users');
}
},
},
{
name: 'read_more',
link: function(item) {
link: function () {
return (
<a
href="http://docs.mailpoet.com/article/133-the-wordpress-users-list"
@ -144,52 +143,58 @@ const item_actions = [
>{MailPoet.I18n.t('readMore')}</a>
);
},
display: function(segment) {
display: function (segment) {
return (segment.type === 'wp_users');
}
},
},
{
name: 'synchronize_segment',
label: MailPoet.I18n.t('forceSync'),
onClick: function(item, refresh) {
onClick: function (item, refresh) {
MailPoet.Modal.loading(true);
MailPoet.Ajax.post({
api_version: window.mailpoet_api_version,
endpoint: 'segments',
action: 'synchronize'
}).done(function(response) {
action: 'synchronize',
}).done(() => {
MailPoet.Modal.loading(false);
if(response === true) {
MailPoet.Notice.success(
(MailPoet.I18n.t('listSynchronized')).replace('%$1s', item.name)
MailPoet.Notice.success(
(MailPoet.I18n.t('listSynchronized')).replace('%$1s', item.name)
);
refresh();
}).fail((response) => {
MailPoet.Modal.loading(false);
if(response.errors.length > 0) {
MailPoet.Notice.error(
response.errors.map((error) => { return error.message; }),
{ scroll: true }
);
refresh();
}
});
},
display: function(segment) {
display: function (segment) {
return (segment.type === 'wp_users');
}
},
},
{
name: 'view_subscribers',
link: function(item) {
link: function (item) {
return (
<a href={ item.subscribers_url }>{MailPoet.I18n.t('viewSubscribers')}</a>
);
}
},
},
{
name: 'trash',
display: function(segment) {
display: function (segment) {
return (segment.type !== 'wp_users');
}
}
},
},
];
const SegmentList = React.createClass({
renderItem: function(segment, actions) {
var rowClasses = classNames(
renderItem: function (segment, actions) {
const rowClasses = classNames(
'manage-column',
'column-primary',
'has-row-actions'
@ -245,7 +250,7 @@ const SegmentList = React.createClass({
</div>
);
},
render: function() {
render: function () {
return (
<div>
<h1 className="title">
@ -268,7 +273,7 @@ const SegmentList = React.createClass({
/>
</div>
);
}
},
});
module.exports = SegmentList;

View File

@ -1,17 +1,17 @@
import React from 'react'
import ReactDOM from 'react-dom'
import { Router, Route, IndexRoute, Link, useRouterHistory } from 'react-router'
import { createHashHistory } from 'history'
import React from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, IndexRoute, useRouterHistory } from 'react-router';
import { createHashHistory } from 'history';
import SegmentList from 'segments/list.jsx'
import SegmentForm from 'segments/form.jsx'
import SegmentList from 'segments/list.jsx';
import SegmentForm from 'segments/form.jsx';
const history = useRouterHistory(createHashHistory)({ queryKey: false });
const App = React.createClass({
render() {
return this.props.children
}
return this.props.children;
},
});
const container = document.getElementById('segments_container');
@ -27,4 +27,4 @@ if(container) {
</Route>
</Router>
), container);
}
}

View File

@ -17,7 +17,7 @@ define(
routes: {
'': 'sendingMethodGroup', // the default tab is currently mta, needs its own method
'mta(/:group)': 'sendingMethodGroup',
'(:tab)': 'tabs',
'(:tab)': 'tabs'
},
sendingMethodGroup: function(group) {
// display mta tab
@ -70,6 +70,14 @@ define(
// show "save settings" button
jQuery('.mailpoet_settings_submit').show();
MailPoet.trackEvent(
'User has clicked a tab in Settings',
{
'MailPoet Free version': window.mailpoet_version,
'Tab ID': tab
}
);
}
}));

View File

@ -4,39 +4,39 @@ define(
'react-router',
'mailpoet',
'form/form.jsx',
'react-string-replace'
'react-string-replace',
],
function(
(
React,
Router,
MailPoet,
Form,
ReactStringReplace
) {
var fields = [
) => {
const fields = [
{
name: 'email',
label: MailPoet.I18n.t('email'),
type: 'text',
disabled: function(subscriber) {
disabled: function (subscriber) {
return ~~(subscriber.wp_user_id > 0);
}
},
},
{
name: 'first_name',
label: MailPoet.I18n.t('firstname'),
type: 'text',
disabled: function(subscriber) {
disabled: function (subscriber) {
return ~~(subscriber.wp_user_id > 0);
}
},
},
{
name: 'last_name',
label: MailPoet.I18n.t('lastname'),
type: 'text',
disabled: function(subscriber) {
disabled: function (subscriber) {
return ~~(subscriber.wp_user_id > 0);
}
},
},
{
name: 'status',
@ -46,14 +46,14 @@ define(
'subscribed': MailPoet.I18n.t('subscribed'),
'unconfirmed': MailPoet.I18n.t('unconfirmed'),
'unsubscribed': MailPoet.I18n.t('unsubscribed'),
'bounced': MailPoet.I18n.t('bounced')
'bounced': MailPoet.I18n.t('bounced'),
},
filter: function(subscriber, value) {
filter: function (subscriber, value) {
if (~~(subscriber.wp_user_id) > 0 && value === 'unconfirmed') {
return false;
}
return true;
}
},
},
{
name: 'segments',
@ -63,28 +63,28 @@ define(
api_version: window.mailpoet_api_version,
endpoint: 'segments',
multiple: true,
selected: function(subscriber) {
selected: function (subscriber) {
if (Array.isArray(subscriber.subscriptions) === false) {
return null;
}
return subscriber.subscriptions.map(function(subscription) {
return subscriber.subscriptions.map((subscription) => {
if (subscription.status === 'subscribed') {
return subscription.segment_id;
}
});
},
filter: function(segment) {
filter: function (segment) {
return !!(!segment.deleted_at && segment.type === 'default');
},
getLabel: function(segment) {
getLabel: function (segment) {
return segment.name + ' ('+ segment.subscribers +')';
},
getSearchLabel: function(segment, subscriber) {
getSearchLabel: function (segment, subscriber) {
let label = '';
if (subscriber.subscriptions !== undefined) {
subscriber.subscriptions.map(function(subscription) {
subscriber.subscriptions.map((subscription) => {
if (segment.id === subscription.segment_id) {
label = segment.name;
@ -103,16 +103,16 @@ define(
});
}
return label;
}
}
},
},
];
var custom_fields = window.mailpoet_custom_fields || [];
custom_fields.map(custom_field => {
let field = {
const custom_fields = window.mailpoet_custom_fields || [];
custom_fields.map((custom_field) => {
const field = {
name: 'cf_' + custom_field.id,
label: custom_field.name,
type: custom_field.type
type: custom_field.type,
};
if (custom_field.params) {
field.params = custom_field.params;
@ -128,26 +128,26 @@ define(
field.year_placeholder = MailPoet.I18n.t('year');
field.month_placeholder = MailPoet.I18n.t('month');
field.day_placeholder = MailPoet.I18n.t('day');
break;
break;
case 'select':
field.placeholder = '-';
break;
break;
}
fields.push(field);
});
var messages = {
onUpdate: function() {
const messages = {
onUpdate: function () {
MailPoet.Notice.success(MailPoet.I18n.t('subscriberUpdated'));
},
onCreate: function() {
onCreate: function () {
MailPoet.Notice.success(MailPoet.I18n.t('subscriberAdded'));
}
},
};
var beforeFormContent = function(subscriber) {
const beforeFormContent = function (subscriber) {
if (~~(subscriber.wp_user_id) > 0) {
return (
<p className="description">
@ -167,7 +167,7 @@ define(
}
};
var afterFormContent = function(subscriber) {
const afterFormContent = function () {
return (
<p className="description">
<strong>
@ -175,12 +175,12 @@ define(
</strong> { MailPoet.I18n.t('customFieldsTip') }
</p>
);
}
};
var Link = Router.Link;
const Link = Router.Link;
var SubscriberForm = React.createClass({
render: function() {
const SubscriberForm = React.createClass({
render: function () {
return (
<div>
<h1 className="title">
@ -198,7 +198,7 @@ define(
/>
</div>
);
}
},
});
return SubscriberForm;

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