diff --git a/assets/css/src/common.styl b/assets/css/src/common.styl
index fa1130a165..2b929b74ae 100644
--- a/assets/css/src/common.styl
+++ b/assets/css/src/common.styl
@@ -15,4 +15,12 @@ a:focus
// hide elements
.mailpoet_hidden
- display: none
\ No newline at end of file
+ display: none
+
+// select 2
+.select2-container
+ width: 25em
+
+@media screen and (max-width: 782px)
+ .select2-container
+ width: 100% !important
\ No newline at end of file
diff --git a/assets/js/src/form/fields/field.jsx b/assets/js/src/form/fields/field.jsx
index c61d1d022b..535077b9dc 100644
--- a/assets/js/src/form/fields/field.jsx
+++ b/assets/js/src/form/fields/field.jsx
@@ -4,7 +4,8 @@ define([
'form/fields/textarea.jsx',
'form/fields/select.jsx',
'form/fields/radio.jsx',
- 'form/fields/checkbox.jsx'
+ 'form/fields/checkbox.jsx',
+ 'form/fields/selection.jsx'
],
function(
React,
@@ -12,7 +13,8 @@ function(
FormFieldTextarea,
FormFieldSelect,
FormFieldRadio,
- FormFieldCheckbox
+ FormFieldCheckbox,
+ FormFieldSelection
) {
var FormField = React.createClass({
renderField: function(data, inline = false) {
@@ -26,29 +28,33 @@ function(
var field = false;
if(data.field['field'] !== undefined) {
- field = data.field.field;
- } else{
- switch(data.field.type) {
- case 'text':
- field = ();
- break;
+ data.field = jQuery.merge(data.field, data.field.field);
+ }
- case 'textarea':
- field = ();
- break;
+ switch(data.field.type) {
+ case 'text':
+ field = ();
+ break;
- case 'select':
- field = ();
- break;
+ case 'textarea':
+ field = ();
+ break;
- case 'radio':
- field = ();
- break;
+ case 'select':
+ field = ();
+ break;
- case 'checkbox':
- field = ();
- break;
- }
+ case 'radio':
+ field = ();
+ break;
+
+ case 'checkbox':
+ field = ();
+ break;
+
+ case 'selection':
+ field = ();
+ break;
}
if(inline === true) {
@@ -75,7 +81,8 @@ function(
return this.renderField({
index: index,
field: subfield,
- item: this.props.item
+ item: this.props.item,
+ onValueChange: this.props.onValueChange || false
});
}.bind(this));
} else {
diff --git a/assets/js/src/form/fields/selection.jsx b/assets/js/src/form/fields/selection.jsx
index d91fa7c776..f39cbca579 100644
--- a/assets/js/src/form/fields/selection.jsx
+++ b/assets/js/src/form/fields/selection.jsx
@@ -1,6 +1,7 @@
define([
'react',
- 'jquery'
+ 'jquery',
+ 'select2'
],
function(
React,
@@ -9,43 +10,45 @@ function(
var Selection = React.createClass({
getInitialState: function() {
return {
- loading: false,
- items: [],
- selected: []
+ items: []
}
},
componentWillMount: function() {
this.loadCachedItems();
},
componentDidMount: function() {
- if(this.props.select2) {
- jQuery('#'+this.props.id).select2({
- width: '25em'
- });
- }
+ jQuery('#'+this.props.field.id).select2()
+ .on('change', this.handleChange);
+ },
+ componentDidUpdate: function() {
+ jQuery('#'+this.props.field.id).select2(
+ 'val',
+ (this.props.item[this.props.field.name])
+ );
},
loadCachedItems: function() {
- if(typeof(window['mailpoet_'+this.props.endpoint]) !== 'undefined') {
- var items = window['mailpoet_'+this.props.endpoint];
+ if(typeof(window['mailpoet_'+this.props.field.endpoint]) !== 'undefined') {
+ var items = window['mailpoet_'+this.props.field.endpoint];
this.setState({
items: items
});
}
},
handleChange: function() {
- this.setState({
- selected: jQuery('#'+this.props.id).val()
+ return this.props.onValueChange({
+ target: {
+ value: jQuery('#'+this.props.field.id).select2('val'),
+ name: this.props.field.name
+ }
});
},
- getSelected: function() {
- return this.state.selected;
- },
render: function() {
var options = this.state.items.map(function(item, index) {
return (
);
@@ -54,12 +57,12 @@ function(
return (
+ id={ this.props.field.id || 'mailpoet_field_selection'}
+ placeholder={ this.props.field.placeholder }
+ multiple={ this.props.field.multiple }
+ onChange={ this.handleChange }
+ defaultValue={ this.props.item[this.props.field.name] }
+ >{ options }
);
}
});
diff --git a/assets/js/src/newsletters/send.jsx b/assets/js/src/newsletters/send.jsx
index fb8cb82022..b55d60e886 100644
--- a/assets/js/src/newsletters/send.jsx
+++ b/assets/js/src/newsletters/send.jsx
@@ -27,17 +27,14 @@ define(
type: 'text'
},
{
- name: 'list',
+ name: 'segments',
label: 'Lists',
tip: "The subscriber list that will be used for this campaign.",
- field: (
-
- )
+ type: 'selection',
+ placeholder: "Select a list",
+ id: "mailpoet_segments",
+ endpoint: "segments",
+ multiple: true
},
{
name: 'sender',
diff --git a/lib/Config/Migrator.php b/lib/Config/Migrator.php
index c35e8a374d..3b4df34047 100644
--- a/lib/Config/Migrator.php
+++ b/lib/Config/Migrator.php
@@ -116,7 +116,8 @@ class Migrator {
'segment_id mediumint(9) NOT NULL,',
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
- 'PRIMARY KEY (id)'
+ 'PRIMARY KEY (id)',
+ 'UNIQUE KEY subscriber_segment (subscriber_id, segment_id)'
);
return $this->sqlify(__FUNCTION__, $attributes);
}
@@ -128,7 +129,8 @@ class Migrator {
'segment_id mediumint(9) NOT NULL,',
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
- 'PRIMARY KEY (id)'
+ 'PRIMARY KEY (id)',
+ 'UNIQUE KEY newsletter_segment (newsletter_id, segment_id)'
);
return $this->sqlify(__FUNCTION__, $attributes);
}
diff --git a/lib/Models/Newsletter.php b/lib/Models/Newsletter.php
index 601d26c9e4..13f004078f 100644
--- a/lib/Models/Newsletter.php
+++ b/lib/Models/Newsletter.php
@@ -107,7 +107,7 @@ class Newsletter extends Model {
$saved = $newsletter->save();
if($saved === true) {
- return true;
+ return $newsletter->id();
} else {
$errors = $newsletter->getValidationErrors();
if(!empty($errors)) {
diff --git a/lib/Router/Newsletters.php b/lib/Router/Newsletters.php
index 505fcd3578..d8ae5b4fc3 100644
--- a/lib/Router/Newsletters.php
+++ b/lib/Router/Newsletters.php
@@ -7,6 +7,7 @@ use MailPoet\Models\Newsletter;
use MailPoet\Models\Segment;
use MailPoet\Models\Subscriber;
use MailPoet\Models\NewsletterTemplate;
+use MailPoet\Models\NewsletterSegment;
use MailPoet\Newsletter\Renderer\Renderer;
if(!defined('ABSPATH')) exit;
@@ -21,7 +22,12 @@ class Newsletters {
if($newsletter === false) {
wp_send_json(false);
} else {
- wp_send_json($newsletter->asArray());
+ $segments = $newsletter->segments()->findArray();
+ $newsletter = $newsletter->asArray();
+ $newsletter['segments'] = array_map(function($segment) {
+ return $segment['id'];
+ }, $segments);
+ wp_send_json($newsletter);
}
}
@@ -31,12 +37,26 @@ class Newsletters {
}
function save($data = array()) {
- $result = Newsletter::createOrUpdate($data);
- if($result !== true) {
- wp_send_json($result);
- } else {
- wp_send_json(true);
+ if(isset($data['segments'])) {
+ $segment_ids = $data['segments'];
+ unset($data['segments']);
}
+
+ $newsletter_id = Newsletter::createOrUpdate($data);
+
+ if($newsletter_id !== false && !empty($segment_ids)) {
+ // remove previous relationships with segments
+ NewsletterSegment::where('newsletter_id', $newsletter_id)->deleteMany();
+ // create relationship with segments
+ foreach($segment_ids as $segment_id) {
+ $relation = NewsletterSegment::create();
+ $relation->segment_id = $segment_id;
+ $relation->newsletter_id = $newsletter_id;
+ $relation->save();
+ }
+ }
+
+ wp_send_json(($newsletter_id !== false));
}
function delete($id) {