diff --git a/assets/css/src/admin.styl b/assets/css/src/admin.styl index a93a030583..b1ef9c2cfe 100644 --- a/assets/css/src/admin.styl +++ b/assets/css/src/admin.styl @@ -29,3 +29,5 @@ @require 'mp2migrator' @require '../../../node_modules/react-confirm-alert/src/react-confirm-alert.css' + +@require 'newsletter_templates' \ No newline at end of file diff --git a/assets/css/src/newsletter_templates.styl b/assets/css/src/newsletter_templates.styl new file mode 100644 index 0000000000..f03c5287ca --- /dev/null +++ b/assets/css/src/newsletter_templates.styl @@ -0,0 +1,7 @@ +@require 'newsletter_editor/variables' + +.mailpoet_template_iframe + position: absolute + z-index: -9999 + width: $newsletter-width + max-width: $newsletter-width \ No newline at end of file diff --git a/assets/js/src/newsletter_editor/components/content.js b/assets/js/src/newsletter_editor/components/content.js index 7efc8592a3..31c3ce4533 100644 --- a/assets/js/src/newsletter_editor/components/content.js +++ b/assets/js/src/newsletter_editor/components/content.js @@ -12,7 +12,7 @@ define([ // Does not hold newsletter content nor newsletter styles, those are // handled by other components. Module.NewsletterModel = SuperModel.extend({ - whitelisted: ['id', 'subject', 'preheader'], + whitelisted: ['id', 'subject', 'preheader', 'type'], initialize: function () { // eslint-disable-line func-names this.on('change', function () { // eslint-disable-line func-names App.getChannel().trigger('autoSave'); diff --git a/assets/js/src/newsletter_editor/components/save.js b/assets/js/src/newsletter_editor/components/save.js index 0efa7aa3be..7c122aedd7 100644 --- a/assets/js/src/newsletter_editor/components/save.js +++ b/assets/js/src/newsletter_editor/components/save.js @@ -98,7 +98,11 @@ define([ promise.then(function (thumbnail) { var data = _.extend(options || {}, { thumbnail: thumbnail.toDataURL('image/jpeg'), - body: JSON.stringify(App.getBody()) + body: JSON.stringify(App.getBody()), + categories: JSON.stringify([ + 'saved', + App.getNewsletter().get('type') + ]) }); return MailPoet.Ajax.post({ @@ -124,7 +128,8 @@ define([ ).then(function (thumbnail) { var data = _.extend(options || {}, { thumbnail: thumbnail.toDataURL('image/jpeg'), - body: App.getBody() + body: App.getBody(), + categories: JSON.stringify([App.getNewsletter().get('type')]) }); var blob = new Blob( [JSON.stringify(data)], diff --git a/assets/js/src/newsletters/send.jsx b/assets/js/src/newsletters/send.jsx index 0f58a0f84e..ececc4fbb0 100644 --- a/assets/js/src/newsletters/send.jsx +++ b/assets/js/src/newsletters/send.jsx @@ -11,6 +11,7 @@ define( 'newsletters/breadcrumb.jsx', 'help-tooltip.jsx', 'jquery', + 'html2canvas', ], ( React, @@ -23,7 +24,8 @@ define( WelcomeNewsletterFields, Breadcrumb, HelpTooltip, - jQuery + jQuery, + html2canvas ) => { const NewsletterSend = React.createClass({ contextTypes: { @@ -88,12 +90,38 @@ define( }); }); }, + saveTemplate: function (response, done) { + const iframe = document.createElement('iframe'); + iframe.src = response.meta.preview_url; + iframe.onload = () => { + html2canvas(iframe.contentDocument.documentElement).then((thumbnail) => { + document.body.removeChild(iframe); + MailPoet.Ajax.post({ + api_version: window.mailpoet_api_version, + endpoint: 'newsletterTemplates', + action: 'save', + data: { + newsletter_id: response.data.id, + name: response.data.subject, + description: response.data.preheader, + thumbnail: thumbnail.toDataURL('image/jpeg'), + body: JSON.stringify(response.data.body), + categories: '["recent"]', + }, + }).then(done).fail(this.showError); + }); + }; + // just to hide the iframe + iframe.className ='mailpoet_template_iframe'; + document.body.appendChild(iframe); + }, handleSend: function (e) { e.preventDefault(); if (!this.isValid()) { jQuery('#mailpoet_newsletter').parsley().validate(); } else { + MailPoet.Modal.loading(true); this.saveNewsletter(e).done(() => { this.setState({ loading: true }); }).done((response) => { @@ -109,29 +137,37 @@ define( status: 'active', }, }).done((response2) => { - // redirect to listing based on newsletter type - this.context.router.push(`/${this.state.item.type || ''}`); - const opts = this.state.item.options; - // display success message depending on newsletter type - if (response2.data.type === 'welcome') { - MailPoet.Notice.success( - MailPoet.I18n.t('welcomeEmailActivated') - ); - MailPoet.trackEvent('Emails > Welcome email activated', { - 'MailPoet Free version': window.mailpoet_version, - 'List type': opts.event, - Delay: `${opts.afterTimeNumber} ${opts.afterTimeType}`, - }); - } else if (response2.data.type === 'notification') { - MailPoet.Notice.success( - MailPoet.I18n.t('postNotificationActivated') - ); - MailPoet.trackEvent('Emails > Post notifications activated', { - 'MailPoet Free version': window.mailpoet_version, - Frequency: opts.intervalType, - }); - } - }).fail(this.showError); + // save template in recently sent category + this.saveTemplate(response, () => { + // redirect to listing based on newsletter type + this.context.router.push(`/${this.state.item.type || ''}`); + const opts = this.state.item.options; + // display success message depending on newsletter type + if (response2.data.type === 'welcome') { + MailPoet.Notice.success( + MailPoet.I18n.t('welcomeEmailActivated') + ); + MailPoet.trackEvent('Emails > Welcome email activated', { + 'MailPoet Free version': window.mailpoet_version, + 'List type': opts.event, + Delay: `${opts.afterTimeNumber} ${opts.afterTimeType}`, + }); + } else if (response2.data.type === 'notification') { + MailPoet.Notice.success( + MailPoet.I18n.t('postNotificationActivated') + ); + MailPoet.trackEvent('Emails > Post notifications activated', { + 'MailPoet Free version': window.mailpoet_version, + Frequency: opts.intervalType, + }); + } + MailPoet.Modal.loading(false); + }); + }).fail((err) => { + this.showError(err); + this.setState({ loading: false }); + MailPoet.Modal.loading(false); + }); default: return MailPoet.Ajax.post({ api_version: window.mailpoet_api_version, @@ -141,32 +177,42 @@ define( newsletter_id: this.props.params.id, }, }).done((response2) => { - // redirect to listing based on newsletter type - this.context.router.push(`/${this.state.item.type || ''}`); + // save template in recently sent category + this.saveTemplate(response, () => { + // redirect to listing based on newsletter type + this.context.router.push(`/${this.state.item.type || ''}`); - if (response2.data.status === 'scheduled') { - MailPoet.Notice.success( - MailPoet.I18n.t('newsletterHasBeenScheduled') - ); - MailPoet.trackEvent('Emails > Newsletter sent', { - scheduled: true, - 'MailPoet Free version': window.mailpoet_version, - }); - } else { - MailPoet.Notice.success( - MailPoet.I18n.t('newsletterBeingSent') - ); - MailPoet.trackEvent('Emails > Newsletter sent', { - scheduled: false, - 'MailPoet Free version': window.mailpoet_version, - }); - } - }).fail(this.showError); + if (response2.data.status === 'scheduled') { + MailPoet.Notice.success( + MailPoet.I18n.t('newsletterHasBeenScheduled') + ); + MailPoet.trackEvent('Emails > Newsletter sent', { + scheduled: true, + 'MailPoet Free version': window.mailpoet_version, + }); + } else { + MailPoet.Notice.success( + MailPoet.I18n.t('newsletterBeingSent') + ); + MailPoet.trackEvent('Emails > Newsletter sent', { + scheduled: false, + 'MailPoet Free version': window.mailpoet_version, + }); + } + MailPoet.Modal.loading(false); + }); + }) + .fail((err) => { + this.showError(err); + this.setState({ loading: false }); + MailPoet.Modal.loading(false); + }); } }) - .fail(this.showError) - .always(() => { + .fail((err) => { + this.showError(err); this.setState({ loading: false }); + MailPoet.Modal.loading(false); }); } return false; diff --git a/assets/js/src/newsletters/templates.jsx b/assets/js/src/newsletters/templates.jsx index b818a4957f..7166b6dd25 100644 --- a/assets/js/src/newsletters/templates.jsx +++ b/assets/js/src/newsletters/templates.jsx @@ -15,6 +15,9 @@ const ImportTemplate = React.createClass({ template.body = JSON.stringify(template.body); } + if (undefined === template.categories) { + template.categories = '["saved"]'; + } MailPoet.Modal.loading(true); MailPoet.Ajax.post({ @@ -81,11 +84,52 @@ const ImportTemplate = React.createClass({ }, }); +const templatesCategories = [ + { + name: 'standard', + label: MailPoet.I18n.t('tabStandardTitle'), + }, + { + name: 'welcome', + label: MailPoet.I18n.t('tabWelcomeTitle'), + }, + { + name: 'notification', + label: MailPoet.I18n.t('tabNotificationTitle'), + }, + { + name: 'sample', + label: MailPoet.I18n.t('sample'), + }, + { + name: 'blank', + label: MailPoet.I18n.t('blank'), + }, + { + name: 'recent', + label: MailPoet.I18n.t('recentlySent'), + }, + { + name: 'saved', + label: MailPoet.I18n.t('savedTemplates'), + }, +]; + +const CategoryTab = ({ name, label, selected, select }) => ( +
  • select(name)} + > {label} +
  • +); + const NewsletterTemplates = React.createClass({ getInitialState: function () { return { loading: false, - templates: [], + templates: {}, + selectedCategory: '', }; }, componentDidMount: function () { @@ -100,8 +144,6 @@ const NewsletterTemplates = React.createClass({ api_version: window.mailpoet_api_version, endpoint: 'newsletterTemplates', action: 'getAll', - }).always(() => { - MailPoet.Modal.loading(false); }).done((response) => { if (this.isMounted()) { if (response.data.length === 0) { @@ -111,15 +153,53 @@ const NewsletterTemplates = React.createClass({ MailPoet.I18n.t('mailpoetGuideTemplateTitle'), description: MailPoet.I18n.t('mailpoetGuideTemplateDescription'), + categories: '["welcome", "notification", "standard"]', readonly: '1', }, ]; } - this.setState({ - templates: response.data, - loading: false, - }); + + let templates = templatesCategories.reduce((result, { name }) => { + const obj = result; + obj[name] = []; + return obj; + }, {}); + + templates = response.data.reduce((result, item) => { + JSON.parse(item.categories).forEach((category) => { + result[category].push(item); + }); + return result; + }, templates); + + this.selectInitialCategory(templates); } + }).fail((response) => { + if (response.errors.length > 0) { + MailPoet.Notice.error( + response.errors.map(error => error.message), + { scroll: true } + ); + } + MailPoet.Modal.loading(false); + }); + }, + selectInitialCategory: function (templates) { + MailPoet.Ajax.post({ + api_version: window.mailpoet_api_version, + endpoint: 'newsletters', + action: 'get', + data: { + id: this.props.params.id, + }, + }).always(() => { + MailPoet.Modal.loading(false); + }).done((response) => { + this.setState({ + templates: templates, + selectedCategory: response.data.type, + loading: false, + }); }).fail((response) => { if (response.errors.length > 0) { MailPoet.Notice.error( @@ -206,7 +286,9 @@ const NewsletterTemplates = React.createClass({ this.getTemplates(); }, render: function () { - const templates = this.state.templates.map((template, index) => { + let templates = this.state.templates[this.state.selectedCategory] || []; + + templates = templates.map((template, index) => { const deleteLink = (
    {MailPoet.I18n.t('noTemplates')}

    ; + } + const boxClasses = classNames( 'mailpoet_boxes', 'clearfix', @@ -273,6 +359,19 @@ const NewsletterTemplates = React.createClass({ +
    +
      + {templatesCategories.map(({ name, label }) => ( + this.setState({ selectedCategory: category })} /> + ))} +
    +
    +
      { templates }
    diff --git a/lib/API/JSON/v1/NewsletterTemplates.php b/lib/API/JSON/v1/NewsletterTemplates.php index 96a78956de..c1e9b9ada4 100644 --- a/lib/API/JSON/v1/NewsletterTemplates.php +++ b/lib/API/JSON/v1/NewsletterTemplates.php @@ -38,6 +38,13 @@ class NewsletterTemplates extends APIEndpoint { } function save($data = array()) { + if(!empty($data['newsletter_id'])) { + $template = NewsletterTemplate::whereEqual('newsletter_id', $data['newsletter_id'])->findOne(); + if(!empty($template)) { + $template = $template->asArray(); + $data['id'] = $template['id']; + } + } $template = NewsletterTemplate::createOrUpdate($data); $errors = $template->getErrors(); diff --git a/lib/API/JSON/v1/Newsletters.php b/lib/API/JSON/v1/Newsletters.php index 72f6047b04..67529df4ba 100644 --- a/lib/API/JSON/v1/Newsletters.php +++ b/lib/API/JSON/v1/Newsletters.php @@ -129,7 +129,13 @@ class Newsletters extends APIEndpoint { Hooks::doAction('mailpoet_api_newsletters_save_after', $newsletter); - return $this->successResponse($newsletter->asArray()); + $preview_url = NewsletterUrl::getViewInBrowserUrl( + NewsletterUrl::TYPE_LISTING_EDITOR, + $newsletter, + Subscriber::getCurrentWPUser() + ); + + return $this->successResponse($newsletter->asArray(), array('preview_url' => $preview_url)); } function setStatus($data = array()) { diff --git a/lib/Config/Migrator.php b/lib/Config/Migrator.php index 34d30aa5e4..d86cc270cd 100644 --- a/lib/Config/Migrator.php +++ b/lib/Config/Migrator.php @@ -244,7 +244,9 @@ class Migrator { function newsletterTemplates() { $attributes = array( 'id int(11) unsigned NOT NULL AUTO_INCREMENT,', + 'newsletter_id int NULL DEFAULT 0,', 'name varchar(250) NOT NULL,', + 'categories varchar(250) NOT NULL DEFAULT "[]",', 'description varchar(250) NOT NULL,', 'body LONGTEXT,', 'thumbnail LONGTEXT,', diff --git a/lib/Config/PopulatorData/Templates/AppWelcome.php b/lib/Config/PopulatorData/Templates/AppWelcome.php index b6a921ddeb..18732b85c6 100644 --- a/lib/Config/PopulatorData/Templates/AppWelcome.php +++ b/lib/Config/PopulatorData/Templates/AppWelcome.php @@ -16,6 +16,7 @@ class AppWelcome { return array( 'name' => __("App Welcome", 'mailpoet'), 'description' => __("A welcome email template for your app.", 'mailpoet'), + 'categories' => json_encode(array('welcome', 'sample')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/BurgerJoint.php b/lib/Config/PopulatorData/Templates/BurgerJoint.php index c04e031c52..0031a3b32d 100644 --- a/lib/Config/PopulatorData/Templates/BurgerJoint.php +++ b/lib/Config/PopulatorData/Templates/BurgerJoint.php @@ -16,6 +16,7 @@ class BurgerJoint { return array( 'name' => __("Burger Joint", 'mailpoet'), 'description' => __("Add more or less ketchup or mayo to this restaurant template.", 'mailpoet'), + 'categories' => json_encode(array('standard', 'sample')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/ChocolateStore.php b/lib/Config/PopulatorData/Templates/ChocolateStore.php index d036e10be1..d8d28b1d45 100644 --- a/lib/Config/PopulatorData/Templates/ChocolateStore.php +++ b/lib/Config/PopulatorData/Templates/ChocolateStore.php @@ -16,6 +16,7 @@ class ChocolateStore { return array( 'name' => __("Chocolate Store", 'mailpoet'), 'description' => __("A classy black store template.", 'mailpoet'), + 'categories' => json_encode(array('standard', 'sample')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/CoffeeShop.php b/lib/Config/PopulatorData/Templates/CoffeeShop.php index 1d17daa1f2..8a251475e3 100644 --- a/lib/Config/PopulatorData/Templates/CoffeeShop.php +++ b/lib/Config/PopulatorData/Templates/CoffeeShop.php @@ -16,6 +16,7 @@ class CoffeeShop { return array( 'name' => __("Coffee Shop", 'mailpoet'), 'description' => __("Coffee and sugar in your coffee?", 'mailpoet'), + 'categories' => json_encode(array('standard', 'sample')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/Discount.php b/lib/Config/PopulatorData/Templates/Discount.php index 81d1439849..f54e31530e 100644 --- a/lib/Config/PopulatorData/Templates/Discount.php +++ b/lib/Config/PopulatorData/Templates/Discount.php @@ -16,6 +16,7 @@ class Discount { return array( 'name' => __("Discount", 'mailpoet'), 'description' => __("A useful layout for a simple discount email.", 'mailpoet'), + 'categories' => json_encode(array('standard', 'sample')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/Faith.php b/lib/Config/PopulatorData/Templates/Faith.php index 30270cd859..d68a5e2854 100644 --- a/lib/Config/PopulatorData/Templates/Faith.php +++ b/lib/Config/PopulatorData/Templates/Faith.php @@ -16,6 +16,7 @@ class Faith { return array( 'name' => __("Faith", 'mailpoet'), 'description' => __("A calm and muted faith template.", 'mailpoet'), + 'categories' => json_encode(array('standard', 'sample')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/FestivalEvent.php b/lib/Config/PopulatorData/Templates/FestivalEvent.php index 11fa10f502..9b077d9c6f 100644 --- a/lib/Config/PopulatorData/Templates/FestivalEvent.php +++ b/lib/Config/PopulatorData/Templates/FestivalEvent.php @@ -16,6 +16,7 @@ class FestivalEvent { return array( 'name' => __("Festival Event", 'mailpoet'), 'description' => __("A colourful festival event template.", 'mailpoet'), + 'categories' => json_encode(array('standard', 'sample')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/FoodBox.php b/lib/Config/PopulatorData/Templates/FoodBox.php index 55afe23dde..dfff3008af 100644 --- a/lib/Config/PopulatorData/Templates/FoodBox.php +++ b/lib/Config/PopulatorData/Templates/FoodBox.php @@ -17,6 +17,7 @@ class FoodBox { return array( 'name' => __("Welcome to FoodBox", 'mailpoet'), 'description' => __("A welcome email template for your takeaway.", 'mailpoet'), + 'categories' => json_encode(array('standard', 'sample')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/KickOff.php b/lib/Config/PopulatorData/Templates/KickOff.php index 7664c39cc9..70c8d4c863 100644 --- a/lib/Config/PopulatorData/Templates/KickOff.php +++ b/lib/Config/PopulatorData/Templates/KickOff.php @@ -16,6 +16,7 @@ class KickOff { return array( 'name' => __("Kick-Off", 'mailpoet'), 'description' => __("Sporty green template for your team or sport event.", 'mailpoet'), + 'categories' => json_encode(array('standard', 'sample')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/NewsDay.php b/lib/Config/PopulatorData/Templates/NewsDay.php index 52ae6ee247..55d263c5ee 100644 --- a/lib/Config/PopulatorData/Templates/NewsDay.php +++ b/lib/Config/PopulatorData/Templates/NewsDay.php @@ -16,6 +16,7 @@ class NewsDay { return array( 'name' => __("News Day", 'mailpoet'), 'description' => __("Media ready template.", 'mailpoet'), + 'categories' => json_encode(array('standard', 'sample')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/NewsletterBlank121Column.php b/lib/Config/PopulatorData/Templates/NewsletterBlank121Column.php index 3ae36b2633..f4a98fc127 100644 --- a/lib/Config/PopulatorData/Templates/NewsletterBlank121Column.php +++ b/lib/Config/PopulatorData/Templates/NewsletterBlank121Column.php @@ -16,6 +16,7 @@ class NewsletterBlank121Column { return array( 'name' => __("Newsletter: Blank 1:2:1 Column", 'mailpoet'), 'description' => __("A blank Newsletter template with a 1:2:1 column layout.", 'mailpoet'), + 'categories' => json_encode(array('standard', 'blank')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/NewsletterBlank12Column.php b/lib/Config/PopulatorData/Templates/NewsletterBlank12Column.php index 5625d99b3c..f48be0e9d5 100644 --- a/lib/Config/PopulatorData/Templates/NewsletterBlank12Column.php +++ b/lib/Config/PopulatorData/Templates/NewsletterBlank12Column.php @@ -16,6 +16,7 @@ class NewsletterBlank12Column { return array( 'name' => __("Newsletter: Blank 1:2 Column", 'mailpoet'), 'description' => __("A blank Newsletter template with a 1:2 column layout.", 'mailpoet'), + 'categories' => json_encode(array('standard', 'blank')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/NewsletterBlank13Column.php b/lib/Config/PopulatorData/Templates/NewsletterBlank13Column.php index e7118670cf..653657b180 100644 --- a/lib/Config/PopulatorData/Templates/NewsletterBlank13Column.php +++ b/lib/Config/PopulatorData/Templates/NewsletterBlank13Column.php @@ -16,6 +16,7 @@ class NewsletterBlank13Column { return array( 'name' => __("Newsletter: Blank 1:3 Column", 'mailpoet'), 'description' => __("A blank Newsletter template with a 1:3 column layout.", 'mailpoet'), + 'categories' => json_encode(array('standard', 'blank')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/NewsletterBlank1Column.php b/lib/Config/PopulatorData/Templates/NewsletterBlank1Column.php index 70fb65767e..c3beeb3a75 100644 --- a/lib/Config/PopulatorData/Templates/NewsletterBlank1Column.php +++ b/lib/Config/PopulatorData/Templates/NewsletterBlank1Column.php @@ -16,6 +16,7 @@ class NewsletterBlank1Column { return array( 'name' => __("Newsletter: Blank 1 Column", 'mailpoet'), 'description' => __("A blank Newsletter template with a 1 column layout.", 'mailpoet'), + 'categories' => json_encode(array('standard', 'blank')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/PieceOfCake.php b/lib/Config/PopulatorData/Templates/PieceOfCake.php index aee3fd6450..28eafd1873 100644 --- a/lib/Config/PopulatorData/Templates/PieceOfCake.php +++ b/lib/Config/PopulatorData/Templates/PieceOfCake.php @@ -16,6 +16,7 @@ class PieceOfCake { return array( 'name' => __("Piece of cake", 'mailpoet'), 'description' => __("Baked with plenty of images.", 'mailpoet'), + 'categories' => json_encode(array('standard', 'sample')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/PostNotificationsBlank1Column.php b/lib/Config/PopulatorData/Templates/PostNotificationsBlank1Column.php index 02aeef76b0..fcdf4e5f7c 100644 --- a/lib/Config/PopulatorData/Templates/PostNotificationsBlank1Column.php +++ b/lib/Config/PopulatorData/Templates/PostNotificationsBlank1Column.php @@ -16,6 +16,7 @@ class PostNotificationsBlank1Column { return array( 'name' => __("Post Notifications: Blank 1 Column", 'mailpoet'), 'description' => __("A blank Post Notifications template with a 1 column layout.", 'mailpoet'), + 'categories' => json_encode(array('notification', 'blank')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/ScienceWeekly.php b/lib/Config/PopulatorData/Templates/ScienceWeekly.php index ec175424ed..1cc71e69fd 100644 --- a/lib/Config/PopulatorData/Templates/ScienceWeekly.php +++ b/lib/Config/PopulatorData/Templates/ScienceWeekly.php @@ -16,6 +16,7 @@ class ScienceWeekly { return array( 'name' => __("Science Weekly", 'mailpoet'), 'description' => __("The right chemistry to send your weekly posts.", 'mailpoet'), + 'categories' => json_encode(array('standard', 'sample')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/Shoes.php b/lib/Config/PopulatorData/Templates/Shoes.php index 59bc712836..1e96318704 100644 --- a/lib/Config/PopulatorData/Templates/Shoes.php +++ b/lib/Config/PopulatorData/Templates/Shoes.php @@ -16,6 +16,7 @@ class Shoes { return array( 'name' => __("Shoes", 'mailpoet'), 'description' => __("Nothing like a pair that fits perfectly.", 'mailpoet'), + 'categories' => json_encode(array('standard', 'sample')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/SimpleText.php b/lib/Config/PopulatorData/Templates/SimpleText.php index 245562cef3..c2a5d5e83c 100644 --- a/lib/Config/PopulatorData/Templates/SimpleText.php +++ b/lib/Config/PopulatorData/Templates/SimpleText.php @@ -16,6 +16,7 @@ class SimpleText { return array( 'name' => __("Simple Text", 'mailpoet'), 'description' => __("A simple plain text template - just like a regular email.", 'mailpoet'), + 'categories' => json_encode(array('standard', 'sample')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/TakeAHike.php b/lib/Config/PopulatorData/Templates/TakeAHike.php index e926b61d3e..176f1030db 100644 --- a/lib/Config/PopulatorData/Templates/TakeAHike.php +++ b/lib/Config/PopulatorData/Templates/TakeAHike.php @@ -16,6 +16,7 @@ class TakeAHike { return array( 'name' => __("Take a Hike", 'mailpoet'), 'description' => __("Can you climb to the top?", 'mailpoet'), + 'categories' => json_encode(array('standard', 'sample')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/TravelNomads.php b/lib/Config/PopulatorData/Templates/TravelNomads.php index 9f00e4d196..82af9747cc 100644 --- a/lib/Config/PopulatorData/Templates/TravelNomads.php +++ b/lib/Config/PopulatorData/Templates/TravelNomads.php @@ -16,6 +16,7 @@ class TravelNomads { return array( 'name' => __("Travel Nomads", 'mailpoet'), 'description' => __("Ideal for sharing your travel adventures.", 'mailpoet'), + 'categories' => json_encode(array('standard', 'sample')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/WelcomeBlank12Column.php b/lib/Config/PopulatorData/Templates/WelcomeBlank12Column.php index afd620706b..3e79611408 100644 --- a/lib/Config/PopulatorData/Templates/WelcomeBlank12Column.php +++ b/lib/Config/PopulatorData/Templates/WelcomeBlank12Column.php @@ -16,6 +16,7 @@ class WelcomeBlank12Column { return array( 'name' => __("Welcome Email: Blank 1:2 Column", 'mailpoet'), 'description' => __("A blank Welcome Email template with a 1:2 column layout.", 'mailpoet'), + 'categories' => json_encode(array('welcome', 'blank')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/WelcomeBlank1Column.php b/lib/Config/PopulatorData/Templates/WelcomeBlank1Column.php index f35ba6f133..6421ef6919 100644 --- a/lib/Config/PopulatorData/Templates/WelcomeBlank1Column.php +++ b/lib/Config/PopulatorData/Templates/WelcomeBlank1Column.php @@ -16,6 +16,7 @@ class WelcomeBlank1Column { return array( 'name' => __("Welcome Email: Blank 1 Column", 'mailpoet'), 'description' => __("A blank Welcome Email template with a 1 column layout.", 'mailpoet'), + 'categories' => json_encode(array('welcome', 'blank')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/WorldCup.php b/lib/Config/PopulatorData/Templates/WorldCup.php index b14d669fbf..d4e601af73 100644 --- a/lib/Config/PopulatorData/Templates/WorldCup.php +++ b/lib/Config/PopulatorData/Templates/WorldCup.php @@ -16,6 +16,7 @@ class WorldCup { return array( 'name' => __("World Cup", 'mailpoet'), 'description' => __("Always a winner.", 'mailpoet'), + 'categories' => json_encode(array('standard', 'sample')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/lib/Config/PopulatorData/Templates/YogaStudio.php b/lib/Config/PopulatorData/Templates/YogaStudio.php index 5e83e288ff..319d7b1000 100644 --- a/lib/Config/PopulatorData/Templates/YogaStudio.php +++ b/lib/Config/PopulatorData/Templates/YogaStudio.php @@ -16,6 +16,7 @@ class YogaStudio { return array( 'name' => __("Yoga Studio", 'mailpoet'), 'description' => __("Salute the sun and your subscribers.", 'mailpoet'), + 'categories' => json_encode(array('standard', 'sample')), 'readonly' => 1, 'thumbnail' => $this->getThumbnail(), 'body' => json_encode($this->getBody()), diff --git a/package-lock.json b/package-lock.json index b093372321..aa6590d38b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha1-+PLIh60Qv2f2NPAFtph/7TF5qsg=", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", "dev": true }, "acorn": { @@ -129,7 +129,7 @@ "anymatch": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-1.3.2.tgz", - "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", + "integrity": "sha512-0XNayC8lTHQ2OI8aljNCN3sSx6hsr/1+rlcDAotXJR7C1oZZHCNsfpbKwMjRA3Uqb5tF1Rae2oloTr4xpq+WjA==", "dev": true, "requires": { "micromatch": "2.3.11", @@ -148,7 +148,7 @@ "aria-query": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-0.7.0.tgz", - "integrity": "sha1-SvEKHmFXPd6gzzuZtRxSwFtCTSQ=", + "integrity": "sha512-/r2lHl09V3o74+2MLKEdewoj37YZqiQZnfen1O4iNlrOjUgeKuu1U2yF3iKh6HJxqF+OXkLMfQv65Z/cvxD6vA==", "dev": true, "requires": { "ast-types-flow": "0.0.7" @@ -166,7 +166,7 @@ "arr-flatten": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", "dev": true }, "array-find": { @@ -565,7 +565,7 @@ "base64-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.2.1.tgz", - "integrity": "sha1-qRlH2h9KUW6jjltOwOw3c2deCIY=", + "integrity": "sha512-dwVUVIXsBZXwTuwnXI9RK8sBmgq09NDHzyR9SAph9eqk76gKK2JSQmZARC2zRC81JC2QTtxD0ARU5qTS25gIGw==", "dev": true }, "bcrypt-pbkdf": { @@ -581,7 +581,7 @@ "big.js": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", - "integrity": "sha1-pfwpi4G54Nyi5FiCR4S2XFK6WI4=", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", "dev": true }, "binary-extensions": { @@ -593,7 +593,7 @@ "bindings": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", - "integrity": "sha1-s0b27PapX1qBXFg5/HzbIlAvHtc=", + "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==", "dev": true }, "blob-tmp": { @@ -610,7 +610,7 @@ "bn.js": { "version": "4.11.8", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz", - "integrity": "sha1-LN4J617jQfSEdGuwMJsyU7GxRC8=", + "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA==", "dev": true }, "boom": { @@ -664,7 +664,7 @@ "browserify-aes": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.1.1.tgz", - "integrity": "sha1-OLerVe24Bv8tzaGn8WIHc6R3xJ8=", + "integrity": "sha512-UGnTYAnB2a3YuYKIRy1/4FB2HdM866E0qC46JXvVTYKlBlZlnvfpSfY6OKfXZAkv70eJ2a1SqzpAo5CRhZGDFg==", "dev": true, "requires": { "buffer-xor": "1.0.3", @@ -838,6 +838,7 @@ "requires": { "anymatch": "1.3.2", "async-each": "1.0.1", + "fsevents": "1.1.3", "glob-parent": "2.0.0", "inherits": "2.0.3", "is-binary-path": "1.0.1", @@ -849,7 +850,7 @@ "cipher-base": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha1-h2Dk7MJy9MNjUy+SbYdKriwTl94=", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", "dev": true, "requires": { "inherits": "2.0.3", @@ -859,7 +860,7 @@ "circular-json": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha1-gVyZ6oT2gJUp0vRXkb34JxE1LWY=", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", "dev": true }, "classnames": { @@ -1138,7 +1139,7 @@ "boom": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha1-XdnabuOl8wIHdDYpDLcX0/SlTgI=", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", "dev": true, "requires": { "hoek": "4.2.0" @@ -1218,7 +1219,7 @@ "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8=", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { "ms": "2.0.0" @@ -1442,7 +1443,7 @@ "emoji-regex": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-6.5.1.tgz", - "integrity": "sha1-m66pKbFVVlwR6kHGYm6qZc75ksI=", + "integrity": "sha512-PAHp6TxrCy7MGMFidro8uikr+zlJJKJ/Q6mm2ExZ7HwkyR9lSVFfE3kt36qcwa24BQL7y0G9axycGjK1A/0uNQ==", "dev": true }, "emojis-list": { @@ -1592,7 +1593,7 @@ "escodegen": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.9.0.tgz", - "integrity": "sha1-mBGi8mXcHNOJRCDuNxcGS2MriFI=", + "integrity": "sha512-v0MYvNQ32bzwoG2OSFzWAkuahDQHK92JBN0pTAALJ4RIxEZe766QJPDR8Hqy7XNUy5K3fnVL76OqYAdc4TZEIw==", "dev": true, "requires": { "esprima": "3.1.3", @@ -1675,7 +1676,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -1689,7 +1690,7 @@ "globals": { "version": "9.18.0", "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha1-qjiWs+abSH8X4x7SFD1pqOMMLYo=", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", "dev": true }, "lodash": { @@ -1701,7 +1702,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -1721,7 +1722,7 @@ "eslint-config-airbnb": { "version": "15.1.0", "resolved": "https://registry.npmjs.org/eslint-config-airbnb/-/eslint-config-airbnb-15.1.0.tgz", - "integrity": "sha1-/UMpZakG4wE5ABuoMPWPc67dro4=", + "integrity": "sha512-m0q9fiMBzDAIbirlGnpJNWToIhdhJmXXnMG+IFflYzzod9231ZhtmGKegKg8E9T8F1YuVaDSU1FnCm5b9iXVhQ==", "dev": true, "requires": { "eslint-config-airbnb-base": "11.3.2" @@ -1730,7 +1731,7 @@ "eslint-config-airbnb-base": { "version": "11.3.2", "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-11.3.2.tgz", - "integrity": "sha1-hwOxGr48iKx+wrdFt/31LgCuaAo=", + "integrity": "sha512-/fhjt/VqzBA2SRsx7ErDtv6Ayf+XLw9LIOqmpBuHFCVwyJo2EtzGWMB9fYRFBoWWQLxmNmCpenNiH0RxyeS41w==", "dev": true, "requires": { "eslint-restricted-globals": "0.1.1" @@ -1768,7 +1769,7 @@ "eslint-module-utils": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz", - "integrity": "sha1-q67IJBd2E7ipWymWOeG2+s9HNEk=", + "integrity": "sha512-jDI/X5l/6D1rRD/3T43q8Qgbls2nq5km5KSqiwlyUbGo5+04fXhMKdCPhjwbqAa6HXWaMxj8Q4hQDIh7IadJQw==", "dev": true, "requires": { "debug": "2.6.9", @@ -1778,7 +1779,7 @@ "eslint-plugin-import": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.8.0.tgz", - "integrity": "sha1-+htu8x/LPFAcCYWcG4bx/FuYaJQ=", + "integrity": "sha512-Rf7dfKJxZ16QuTgVv1OYNxkZcsu/hULFnC+e+w0Gzi6jMC3guQoWQgxYxc54IDRinlb6/0v5z/PxxIKmVctN+g==", "dev": true, "requires": { "builtin-modules": "1.1.1", @@ -1806,7 +1807,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -1817,7 +1818,7 @@ "eslint-plugin-jsx-a11y": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-5.1.1.tgz", - "integrity": "sha1-XJa7UYbKFOlNsQlf9Zs+K9lAabE=", + "integrity": "sha512-5I9SpoP7gT4wBFOtXT8/tXNPYohHBVfyVfO17vkbC7r9kEIxYJF12D3pKqhk8+xnk12rfxKClS3WCFpVckFTPQ==", "dev": true, "requires": { "aria-query": "0.7.0", @@ -1932,7 +1933,7 @@ "evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha1-f8vbGY3HGVlDLv4ThCaE4FJaywI=", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", "dev": true, "requires": { "md5.js": "1.3.4", @@ -2215,10 +2216,914 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "fsevents": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", + "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", + "dev": true, + "optional": true, + "requires": { + "nan": "2.7.0", + "node-pre-gyp": "0.6.39" + }, + "dependencies": { + "abbrev": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true + }, + "ajv": { + "version": "4.11.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "1.0.0", + "readable-stream": "2.2.9" + } + }, + "asn1": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "asynckit": { + "version": "0.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws-sign2": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "0.4.2", + "bundled": true, + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "block-stream": { + "version": "0.0.9", + "bundled": true, + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, + "boom": { + "version": "2.10.1", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "brace-expansion": { + "version": "1.1.7", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "0.4.2", + "concat-map": "0.0.1" + } + }, + "buffer-shims": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "caseless": { + "version": "0.12.0", + "bundled": true, + "dev": true, + "optional": true + }, + "co": { + "version": "4.6.0", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1" + } + }, + "dashdash": { + "version": "1.14.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "debug": { + "version": "2.6.8", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.4.2", + "bundled": true, + "dev": true, + "optional": true + }, + "delayed-stream": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "ecc-jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "extend": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "extsprintf": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "bundled": true, + "dev": true, + "optional": true + }, + "form-data": { + "version": "2.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.15" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "fstream": { + "version": "1.0.11", + "bundled": true, + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "inherits": "2.0.3", + "mkdirp": "0.5.1", + "rimraf": "2.6.1" + } + }, + "fstream-ignore": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fstream": "1.0.11", + "inherits": "2.0.3", + "minimatch": "3.0.4" + } + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "1.1.1", + "console-control-strings": "1.1.0", + "has-unicode": "2.0.1", + "object-assign": "4.1.1", + "signal-exit": "3.0.2", + "string-width": "1.0.2", + "strip-ansi": "3.0.1", + "wide-align": "1.1.2" + } + }, + "getpass": { + "version": "0.1.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "bundled": true, + "dev": true + }, + "har-schema": { + "version": "1.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "hawk": { + "version": "3.1.3", + "bundled": true, + "dev": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "bundled": true, + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.0", + "sshpk": "1.13.0" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.4", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "isstream": { + "version": "0.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "jodid25519": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "jsbn": { + "version": "0.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "bundled": true, + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "jsonify": { + "version": "0.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.0.2", + "json-schema": "0.2.3", + "verror": "1.3.6" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "mime-db": { + "version": "1.27.0", + "bundled": true, + "dev": true + }, + "mime-types": { + "version": "2.1.15", + "bundled": true, + "dev": true, + "requires": { + "mime-db": "1.27.0" + } + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "node-pre-gyp": { + "version": "0.6.39", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "1.0.2", + "hawk": "3.1.3", + "mkdirp": "0.5.1", + "nopt": "4.0.1", + "npmlog": "4.1.0", + "rc": "1.2.1", + "request": "2.81.0", + "rimraf": "2.6.1", + "semver": "5.3.0", + "tar": "2.2.1", + "tar-pack": "3.4.0" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1.1.0", + "osenv": "0.1.4" + } + }, + "npmlog": { + "version": "4.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "1.1.4", + "console-control-strings": "1.1.0", + "gauge": "2.7.4", + "set-blocking": "2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "bundled": true, + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "performance-now": { + "version": "0.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "1.0.7", + "bundled": true, + "dev": true + }, + "punycode": { + "version": "1.4.1", + "bundled": true, + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "0.4.2", + "ini": "1.3.4", + "minimist": "1.2.0", + "strip-json-comments": "2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.2.9", + "bundled": true, + "dev": true, + "requires": { + "buffer-shims": "1.0.0", + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "string_decoder": "1.0.1", + "util-deprecate": "1.0.2" + } + }, + "request": { + "version": "2.81.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.15", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.0.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.2", + "tunnel-agent": "0.6.0", + "uuid": "3.0.1" + } + }, + "rimraf": { + "version": "2.6.1", + "bundled": true, + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.0.1", + "bundled": true, + "dev": true + }, + "semver": { + "version": "5.3.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sntp": { + "version": "1.0.9", + "bundled": true, + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "sshpk": { + "version": "1.13.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jodid25519": "1.0.2", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "string_decoder": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "stringstream": { + "version": "0.0.5", + "bundled": true, + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "2.2.1", + "bundled": true, + "dev": true, + "requires": { + "block-stream": "0.0.9", + "fstream": "1.0.11", + "inherits": "2.0.3" + } + }, + "tar-pack": { + "version": "3.4.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "2.6.8", + "fstream": "1.0.11", + "fstream-ignore": "1.0.5", + "once": "1.4.0", + "readable-stream": "2.2.9", + "rimraf": "2.6.1", + "tar": "2.2.1", + "uid-number": "0.0.6" + } + }, + "tough-cookie": { + "version": "2.3.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "tunnel-agent": { + "version": "0.6.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "bundled": true, + "dev": true, + "optional": true + }, + "uid-number": { + "version": "0.0.6", + "bundled": true, + "dev": true, + "optional": true + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "uuid": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "verror": { + "version": "1.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "extsprintf": "1.0.2" + } + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + } + } + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0=", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, "generate-function": { @@ -2306,7 +3211,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -2320,7 +3225,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -2453,7 +3358,7 @@ "hash.js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha1-NA3tvmKQGHFRweodd3o0SJNd+EY=", + "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", "dev": true, "requires": { "inherits": "2.0.3", @@ -2463,7 +3368,7 @@ "hawk": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha1-r02RTrBl+bXOTZ0RwcshJu7MMDg=", + "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", "dev": true, "requires": { "boom": "4.3.1", @@ -2497,7 +3402,7 @@ "hoek": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", - "integrity": "sha1-ctnQdU9/4lyi0BrY+PmpRJqJUm0=", + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==", "dev": true }, "hoist-non-react-statics": { @@ -2518,7 +3423,7 @@ "hosted-git-info": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha1-bWDjSzq7yDEwYsO3mO+NkBoHrzw=", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", "dev": true }, "html2canvas": { @@ -2572,7 +3477,7 @@ "iconv-lite": { "version": "0.4.19", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", - "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=" + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" }, "ieee754": { "version": "1.1.8", @@ -3023,7 +3928,7 @@ "js-yaml": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", - "integrity": "sha1-LnhEFka9RoLpY/IrbpKCPDCcYtw=", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", "dev": true, "requires": { "argparse": "1.0.9", @@ -3033,7 +3938,7 @@ "esprima": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", - "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", "dev": true } } @@ -3083,7 +3988,7 @@ "json-loader": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/json-loader/-/json-loader-0.5.7.tgz", - "integrity": "sha1-3KFKcCNf+C8KyaOr62DTN6NlGF0=", + "integrity": "sha512-QLPs8Dj7lnf3e3QYS1zkCo+4ZwqOiF9d/nZnYozTISxXWCfNs9yuky5rJw4/W34s7POaNlbZmQGaB5NiXCbP4w==", "dev": true }, "json-schema": { @@ -3410,7 +4315,7 @@ "miller-rabin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", - "integrity": "sha1-8IA1HIZbDcViqEYpZtqlNUPHik0=", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", "dev": true, "requires": { "bn.js": "4.11.8", @@ -3616,7 +4521,7 @@ "node-fetch": { "version": "1.7.3", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha1-mA9vcthSEaU0fGsrwYxbhMPrR+8=", + "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", "requires": { "encoding": "0.1.12", "is-stream": "1.1.0" @@ -3673,7 +4578,7 @@ "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "dev": true, "requires": { "hosted-git-info": "2.5.0", @@ -3700,7 +4605,7 @@ "nwmatcher": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/nwmatcher/-/nwmatcher-1.4.3.tgz", - "integrity": "sha1-ZDSOOz2A8DW0CsEVY9J4+LctuJw=", + "integrity": "sha512-IKdSTiDWCarf2JTS5e9e2+5tPZGdkRJ79XjYV0pzK8Q9BpsFyBq1RGKxzs7Q8UBushGw7m6TzVKz6fcY99iSWw==", "dev": true }, "oauth-sign": { @@ -3937,7 +4842,7 @@ "pbkdf2": { "version": "3.0.14", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.0.14.tgz", - "integrity": "sha1-o14TxkeZsGzhUyD0WcIw5o5zut4=", + "integrity": "sha512-gjsZW9O34fm0R7PaLHRJmLLVfSoesxztjPjE9o6R+qtVJij90ltg1joIovN9GKrRW3t1PzhDDG3UMEMFfZ+1wA==", "dev": true, "requires": { "create-hash": "1.1.3", @@ -4010,7 +4915,7 @@ "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", - "integrity": "sha1-I4Hts2ifelPWUxkAYPz4ItLzaP8=", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==", "dev": true }, "process": { @@ -4033,7 +4938,7 @@ "promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", "requires": { "asap": "2.0.6" } @@ -4108,7 +5013,7 @@ "randomatic": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", "dev": true, "requires": { "is-number": "3.0.0", @@ -4278,7 +5183,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", @@ -4304,7 +5209,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -4361,7 +5266,7 @@ "regenerate": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", - "integrity": "sha1-DDNtOYBVPXVcObWGrjsgqknIK38=", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", "dev": true }, "regenerator": { @@ -4381,7 +5286,7 @@ "regex-cache": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", "dev": true, "requires": { "is-equal-shallow": "0.1.3" @@ -4452,7 +5357,7 @@ "request": { "version": "2.83.0", "resolved": "https://registry.npmjs.org/request/-/request-2.83.0.tgz", - "integrity": "sha1-ygtl2gLtYpNYh4COb1EDgQNOM1Y=", + "integrity": "sha512-lR3gD69osqm6EYLk9wB/G1W/laGWjzH90t1vEa2xuxHD5KUrSzp9pUSfTm+YC5Nxt2T8nMPEvKlhbQayU7bgFw==", "dev": true, "requires": { "aws-sign2": "0.7.0", @@ -4482,7 +5387,7 @@ "qs": { "version": "6.5.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha1-NJzfbu+J7EXBLX1es/wMhwNDptg=", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", "dev": true } } @@ -4533,7 +5438,7 @@ "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { "glob": "7.1.2" @@ -4542,7 +5447,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -4556,7 +5461,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -4592,7 +5497,7 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=" + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, "samsam": { "version": "1.1.3", @@ -4671,7 +5576,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -4685,7 +5590,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -4880,7 +5785,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "requires": { "safe-buffer": "5.1.1" } @@ -4955,7 +5860,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -5004,7 +5909,7 @@ "string-width": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { "is-fullwidth-code-point": "2.0.0", @@ -5145,7 +6050,7 @@ "ua-parser-js": { "version": "0.7.17", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.17.tgz", - "integrity": "sha1-6exflJi57JEOeuOsYmqAXE0J7Kw=" + "integrity": "sha512-uRdSdu1oA1rncCQL7sCj8vSyZkgtL7faaw9Tc9rZ3mGgraQ7+Pdx7w5mnOSF3gw9ZNG6oc+KXfkon3bKuROm0g==" }, "uglify-js": { "version": "2.8.29", @@ -5576,7 +6481,7 @@ "webpack-manifest-plugin": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/webpack-manifest-plugin/-/webpack-manifest-plugin-1.3.2.tgz", - "integrity": "sha1-XqjuV1Y1ndwdmIFDJP5DSWNJp9Q=", + "integrity": "sha512-MX60Bv2G83Zks9pi3oLOmRgnPAnwrlMn+lftMrWBm199VQjk46/xgzBi9lPfpZldw2+EI2S+OevuLIaDuxCWRw==", "dev": true, "requires": { "fs-extra": "0.30.0", diff --git a/tests/acceptance/NewsletterCreationCest.php b/tests/acceptance/NewsletterCreationCest.php index ad774c118c..00658a10c7 100644 --- a/tests/acceptance/NewsletterCreationCest.php +++ b/tests/acceptance/NewsletterCreationCest.php @@ -23,8 +23,9 @@ class NewsletterCreationCest { $I->click('Next'); // step 3 - select template - $post_notification_template = '[data-automation-id=\'select_template_14\']'; + $post_notification_template = '[data-automation-id=\'select_template_0\']'; $I->waitForElement($post_notification_template); + $I->see('Post Notifications', ['css' => 'a.current']); $I->seeInCurrentUrl('#/template'); $I->click($post_notification_template); diff --git a/tests/javascript/newsletter_editor/components/save.spec.js b/tests/javascript/newsletter_editor/components/save.spec.js index aa42039ea5..baa23026b8 100644 --- a/tests/javascript/newsletter_editor/components/save.spec.js +++ b/tests/javascript/newsletter_editor/components/save.spec.js @@ -143,6 +143,13 @@ define([ }); EditorApplication.getBody = sinon.stub(); + EditorApplication.getNewsletter = function () { + return { + get: function () { + return 'standard'; + } + }; + }; module = SaveInjector({ mailpoet: { Ajax: { diff --git a/tests/unit/API/JSON/v1/NewsletterTemplatesTest.php b/tests/unit/API/JSON/v1/NewsletterTemplatesTest.php index 0fb14aa72a..f2c3ebfd12 100644 --- a/tests/unit/API/JSON/v1/NewsletterTemplatesTest.php +++ b/tests/unit/API/JSON/v1/NewsletterTemplatesTest.php @@ -15,6 +15,7 @@ class NewsletterTemplatesTest extends \MailPoetTest { NewsletterTemplate::createOrUpdate(array( 'name' => 'Template #2', + 'newsletter_id' => 1, 'description' => 'My Second Template', 'body' => '{"key2": "value2"}' )); @@ -53,7 +54,7 @@ class NewsletterTemplatesTest extends \MailPoetTest { expect($response->data)->equals($templates); } - function testItCanSaveANewsletterTemplate() { + function testItCanSaveANewTemplate() { $template_data = array( 'name' => 'Template #3', 'description' => 'My Third Template', @@ -68,6 +69,53 @@ class NewsletterTemplatesTest extends \MailPoetTest { ); } + function testItCanSaveANewTemplateAssociatedWithANewsletter() { + $template_data = array( + 'newsletter_id' => 2, + 'name' => 'Template #3', + 'description' => 'My Third Template', + 'body' => '{"key3": "value3"}' + ); + + $router = new NewsletterTemplates(); + $response = $router->save($template_data); + expect($response->status)->equals(APIResponse::STATUS_OK); + expect($response->data)->equals( + NewsletterTemplate::findOne($response->data['id'])->asArray() + ); + } + + function testItCanUpdateTemplateAssociatedWithANewsletter() { + $template_data = array( + 'newsletter_id' => '1', + 'name' => 'Template #2', + 'description' => 'My Updated Second Template', + 'body' => '{"key3": "value3"}' + ); + + $template_id = NewsletterTemplate::whereEqual('newsletter_id', 1)->findOne()->id; + + $router = new NewsletterTemplates(); + $response = $router->save($template_data); + expect($response->status)->equals(APIResponse::STATUS_OK); + + $template_data['body'] = json_decode($template_data['body'], true); + + $normalize = function($array) { + $result = array(); + foreach($array as $key => $value) { + if(in_array($key, ['newsletter_id', 'name', 'description', 'body'])) { + $result[$key] = $value; + } + } + return $result; + }; + + expect($normalize($response->data))->equals($template_data); + $template = NewsletterTemplate::findOne($template_id)->asArray(); + expect($normalize($template))->equals($template_data); + } + function testItCanDeleteANewsletterTemplate() { $template = NewsletterTemplate::where('name', 'Template #2')->findOne(); expect($template->deleted_at)->null(); diff --git a/views/newsletters.html b/views/newsletters.html index f92d8512cc..c02d7aac83 100644 --- a/views/newsletters.html +++ b/views/newsletters.html @@ -264,7 +264,13 @@ 'confirmEdit': __('Sending is in progress. Do you want to pause sending and edit the newsletter?'), 'confirmTitle': __('Confirm to proceed'), 'confirmLabel': __('Confirm'), - 'cancelLabel': __('Cancel') + 'cancelLabel': __('Cancel'), + + 'recentlySent': __('Recently sent'), + 'savedTemplates': __('Your saved templates'), + 'blank': _x('Blank', 'Blank newsletters templates category'), + 'sample': _x('Sample', 'Sample newsletters templates category'), + 'noTemplates': __('This category does not contain any template yet!') }) %> <% endblock %>