From ed9407a890e10c30b74d1e4f3b78cf9e22caf95e Mon Sep 17 00:00:00 2001 From: Jonathan Labreuille Date: Fri, 9 Oct 2015 14:48:54 +0200 Subject: [PATCH] fixed multiple select component --- assets/css/src/common.styl | 10 ++++- assets/js/src/form/fields/field.jsx | 51 ++++++++++++++----------- assets/js/src/form/fields/selection.jsx | 51 +++++++++++++------------ assets/js/src/newsletters/send.jsx | 15 +++----- lib/Config/Migrator.php | 6 ++- lib/Models/Newsletter.php | 2 +- lib/Router/Newsletters.php | 32 +++++++++++++--- 7 files changed, 102 insertions(+), 65 deletions(-) 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) {