diff --git a/assets/css/src/form.styl b/assets/css/src/form.styl index 90dda5fd63..999681a9ad 100644 --- a/assets/css/src/form.styl +++ b/assets/css/src/form.styl @@ -1,2 +1,5 @@ +.mailpoet_form + margin: 0 0 20px 0 + .mailpoet_form td - vertical-align: top !important \ No newline at end of file + vertical-align: top !important diff --git a/assets/js/src/form/fields/date.jsx b/assets/js/src/form/fields/date.jsx index 0b6de1644d..2d7b49deae 100644 --- a/assets/js/src/form/fields/date.jsx +++ b/assets/js/src/form/fields/date.jsx @@ -9,6 +9,13 @@ define([ render() { const yearsRange = 100; const years = []; + + if (this.props.empty_value_label !== undefined) { + years.push(( + { this.props.empty_value_label } + )); + } + const currentYear = Moment().year(); for (let i = currentYear; i >= currentYear - yearsRange; i--) { years.push(( @@ -33,6 +40,13 @@ define([ class FormFieldDateMonth extends React.Component { render() { const months = []; + + if (this.props.empty_value_label !== undefined) { + months.push(( + { this.props.empty_value_label } + )); + } + for (let i = 1; i <= 12; i++) { months.push(( { this.props.empty_value_label } + )); + } + for (let i = 1; i <= 31; i++) { days.push(( 0) { + if (~~(newTimeStamp) > 0) { // convert milliseconds to seconds newTimeStamp /= 1000; return this.props.onValueChange({ @@ -158,6 +179,7 @@ define([ key={ 'year' } name={ this.props.field.name } year={ this.state.year } + empty_value_label={ this.props.field.empty_year_label } />); break; @@ -169,6 +191,7 @@ define([ name={ this.props.field.name } month={ this.state.month } monthNames={ monthNames } + empty_value_label={ this.props.field.empty_month_label } />); break; @@ -179,6 +202,7 @@ define([ key={ 'day' } name={ this.props.field.name } day={ this.state.day } + empty_value_label={ this.props.field.empty_day_label } />); break; } diff --git a/assets/js/src/form/fields/select.jsx b/assets/js/src/form/fields/select.jsx index ea2527cccb..eaaaa12019 100644 --- a/assets/js/src/form/fields/select.jsx +++ b/assets/js/src/form/fields/select.jsx @@ -10,12 +10,27 @@ function( return false; } - var values = (this.props.field.filterValues !== undefined) - ? this.props.field.filterValues(this.props.item) - : this.props.field.values; + let values = this.props.field.values; + let filter = false; + let empty_option = false; + + if (this.props.field.empty_value_label !== undefined) { + empty_option = ( + { this.props.field.empty_value_label } + ); + } + + if (this.props.field['filter'] !== undefined) { + filter = this.props.field.filter; + } const options = Object.keys(values).map( (value, index) => { + + if (filter !== false && filter(this.props.item, value) === false) { + return; + } + return ( + {empty_option} {options} ); diff --git a/assets/js/src/form/fields/text.jsx b/assets/js/src/form/fields/text.jsx index 47da6cc518..3cfa5e9f54 100644 --- a/assets/js/src/form/fields/text.jsx +++ b/assets/js/src/form/fields/text.jsx @@ -4,9 +4,9 @@ define([ function( React ) { - var FormFieldText = React.createClass({ + const FormFieldText = React.createClass({ render: function() { - var value = this.props.item[this.props.field.name]; + let value = this.props.item[this.props.field.name]; if(value === undefined) { value = this.props.field.defaultValue || ''; } @@ -15,9 +15,9 @@ function( - { beforeFormContent } + { beforeFormContent } 0); } }, { @@ -25,7 +27,7 @@ define( label: MailPoet.I18n.t('firstname'), type: 'text', disabled: function(subscriber) { - if (subscriber.wp_user_id !== null) return 'disabled'; + return ~~(subscriber.wp_user_id > 0); } }, { @@ -33,7 +35,7 @@ define( label: MailPoet.I18n.t('lastname'), type: 'text', disabled: function(subscriber) { - if (subscriber.wp_user_id !== null) return 'disabled'; + return ~~(subscriber.wp_user_id > 0); } }, { @@ -41,15 +43,15 @@ define( label: MailPoet.I18n.t('status'), type: 'select', values: { - 'unconfirmed': MailPoet.I18n.t('unconfirmed'), 'subscribed': MailPoet.I18n.t('subscribed'), + 'unconfirmed': MailPoet.I18n.t('unconfirmed'), 'unsubscribed': MailPoet.I18n.t('unsubscribed') }, - filterValues: function(subscriber) { - if (subscriber.wp_user_id !== null) { - delete this.values.unconfirmed; + filter: function(subscriber, value) { + if (~~(subscriber.wp_user_id) > 0 && value === 'unconfirmed') { + return false; } - return this.values; + return true; } }, { @@ -115,6 +117,19 @@ define( field.values = custom_field.params.values; } + // add empty values' label for selects (date, select) + switch(custom_field.type) { + case 'date': + field.empty_year_label = MailPoet.I18n.t('year'); + field.empty_month_label = MailPoet.I18n.t('month'); + field.empty_day_label = MailPoet.I18n.t('day'); + break; + + case 'select': + field.empty_value_label = '-'; + break; + } + fields.push(field); }); @@ -128,17 +143,35 @@ define( }; var beforeFormContent = function(subscriber) { - if (subscriber.wp_user_id !== null) { - var content = - '' + - MailPoet.I18n.t('wordPressUserNotice') - .replace('[link]', '') - .replace('[/link]', '') + - ''; - return + if (~~(subscriber.wp_user_id) > 0) { + return ( + + { ReactStringReplace( + MailPoet.I18n.t('WPUserEditNotice'), + /\[link\](.*?)\[\/link\]/g, + (match, i) => ( + { match } + ) + ) + } + + ); } }; + var afterFormContent = function(subscriber) { + return ( + + + { MailPoet.I18n.t('tip') } + { MailPoet.I18n.t('customFieldsTip') } + + ); + } + var Link = Router.Link; var SubscriberForm = React.createClass({ @@ -156,6 +189,7 @@ define( params={ this.props.params } messages={ messages } beforeFormContent={ beforeFormContent } + afterFormContent={ afterFormContent } /> ); diff --git a/assets/js/src/subscribers/list.jsx b/assets/js/src/subscribers/list.jsx index f8017303a9..d05d68688c 100644 --- a/assets/js/src/subscribers/list.jsx +++ b/assets/js/src/subscribers/list.jsx @@ -213,16 +213,6 @@ const bulk_actions = [ ); } }, -/* { - name: 'confirmUnconfirmed', - label: MailPoet.I18n.t('confirmUnconfirmed'), - onSuccess: function(response) { - MailPoet.Notice.success( - MailPoet.I18n.t('multipleSubscribersConfirmed') - .replace('%$1d', ~~response) - ); - } - },*/ { name: 'sendConfirmationEmail', label: MailPoet.I18n.t('resendConfirmationEmail'), @@ -290,10 +280,15 @@ const SubscriberList = React.createClass({ } let segments = false; + let subscribed_segments = []; + // WordPress Users + if (~~(subscriber.wp_user_id) > 0) { + subscribed_segments.push(MailPoet.I18n.t('WPUsersSegment')); + } + + // Subscriptions if (subscriber.subscriptions.length > 0) { - let subscribed_segments = []; - subscriber.subscriptions.map((subscription) => { const segment = this.getSegmentFromId(subscription.segment_id); if(segment === false) return; @@ -301,15 +296,14 @@ const SubscriberList = React.createClass({ subscribed_segments.push(segment.name); } }); - segments = ( - - - { subscribed_segments.join(', ') } - - - ); } + segments = ( + + { subscribed_segments.join(', ') } + + ); + let avatar = false; if(subscriber.avatar_url) { avatar = ( diff --git a/lib/Form/Block/Date.php b/lib/Form/Block/Date.php index 15fc9b9145..0ffbfbdbd0 100644 --- a/lib/Form/Block/Date.php +++ b/lib/Form/Block/Date.php @@ -109,6 +109,10 @@ class Date extends Base { $month_names = static::getMonthNames(); $html = ''; + + // empty value label + $html .= ''.__('Month').''; + for($i = 1; $i < 13; $i++) { $is_selected = ($i === $block['selected']) ? 'selected="selected"' : ''; $html .= ''; @@ -125,6 +129,7 @@ class Date extends Base { 'from' => (int)strftime('%Y') - 100, 'to' => (int)strftime('%Y') ); + // is default today if(!empty($block['params']['is_default_today'])) { $defaults['selected'] = (int)strftime('%Y'); @@ -135,6 +140,9 @@ class Date extends Base { $html = ''; + // empty value label + $html .= ''.__('Year').''; + // return years as an array for($i = (int)$block['to']; $i > (int)($block['from'] - 1); $i--) { $is_selected = ($i === $block['selected']) ? 'selected="selected"' : ''; @@ -158,6 +166,9 @@ class Date extends Base { $html = ''; + // empty value label + $html .= ''.__('Day').''; + // return days as an array for($i = 1; $i < 32; $i++) { $is_selected = ($i === $block['selected']) ? 'selected="selected"' : ''; diff --git a/lib/Form/Block/Select.php b/lib/Form/Block/Select.php index 89e62025c2..10f68b7903 100644 --- a/lib/Form/Block/Select.php +++ b/lib/Form/Block/Select.php @@ -13,9 +13,12 @@ class Select extends Base { $html .= static::renderLabel($block); $html .= ''; - if(isset($block['params']['label_within']) - && $block['params']['label_within']) { + if(isset($block['params']['label_within']) && $block['params']['label_within']) { $html .= ''.static::getFieldLabel($block).''; + } else { + if(empty($block['params']['required']) || !$block['params']['required']) { + $html .= '-'; + } } $options = (!empty($block['params']['values']) diff --git a/lib/Models/Subscriber.php b/lib/Models/Subscriber.php index 27fa1bab6a..9aad226a5a 100644 --- a/lib/Models/Subscriber.php +++ b/lib/Models/Subscriber.php @@ -539,12 +539,6 @@ class Subscriber extends Model { return false; } -/* static function bulkConfirmUnconfirmed($orm) { - $subscribers = $orm->findResultSet(); - $subscribers->set('status', self::STATUS_SUBSCRIBED)->save(); - return $subscribers->count(); - }*/ - static function bulkSendConfirmationEmail($orm) { $subscribers = $orm ->where('status', self::STATUS_UNCONFIRMED) diff --git a/lib/Subscription/Pages.php b/lib/Subscription/Pages.php index ea36bf6cbb..5a2ad76e78 100644 --- a/lib/Subscription/Pages.php +++ b/lib/Subscription/Pages.php @@ -32,6 +32,7 @@ class Pages { // manage subscription link shortcode // [mailpoet_manage text="Manage your subscription"] add_shortcode('mailpoet_manage', array($this, 'getManageLink')); + add_shortcode('mailpoet_manage_subscription', array($this, 'getManageContent')); } private function isPreview() { @@ -203,7 +204,7 @@ class Pages { } } - private function getManageContent() { + public function getManageContent() { if($this->isPreview()) { $subscriber = Subscriber::create(); $subscriber->hydrate(array( @@ -273,6 +274,7 @@ class Pages { 'id' => 'status', 'type' => 'select', 'params' => array( + 'required' => true, 'label' => __('Status'), 'values' => array( array( diff --git a/package.json b/package.json index 39d9bce4ed..7e54c6066b 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "react-infinity": "latest", "react-prefixr": "latest", "react-router": "latest", + "react-string-replace": "^0.3.2", "react-waypoint": "latest", "select2": "^4.0.0", "spectrum-colorpicker": "^1.6.2", diff --git a/views/form/templates/blocks/date_days.hbs b/views/form/templates/blocks/date_days.hbs index 38e13a0b8e..099cec2af8 100644 --- a/views/form/templates/blocks/date_days.hbs +++ b/views/form/templates/blocks/date_days.hbs @@ -1,5 +1,6 @@ <% set currentDay = 'now' | date('d') | number_format %> + <%= __('Day') %> <% for day in 1..31 %> diff --git a/views/form/templates/blocks/date_months.hbs b/views/form/templates/blocks/date_months.hbs index 4ce4d6d3f6..f145483324 100644 --- a/views/form/templates/blocks/date_months.hbs +++ b/views/form/templates/blocks/date_months.hbs @@ -1,5 +1,6 @@ <% set currentMonth = 'now'|date('n') %> + <%= __('Month') %> <% for month in 1..12 %> diff --git a/views/form/templates/blocks/date_years.hbs b/views/form/templates/blocks/date_years.hbs index ce13f49914..5e6f143e15 100644 --- a/views/form/templates/blocks/date_years.hbs +++ b/views/form/templates/blocks/date_years.hbs @@ -2,6 +2,7 @@ <% set minYear = currentYear - 100 %> + <%= __('Year') %> <% for year in currentYear..minYear %> diff --git a/views/form/templates/blocks/select.hbs b/views/form/templates/blocks/select.hbs index d9cf5bcc6c..248b4be8da 100644 --- a/views/form/templates/blocks/select.hbs +++ b/views/form/templates/blocks/select.hbs @@ -8,6 +8,8 @@ {{#if params.label_within}} {{ params.label }}{{#if params.required}} *{{/if}} + {{else}} + {{#unless params.required}}-{{/unless}} {{/if}} {{#each params.values}} {{ value }} diff --git a/views/subscribers/subscribers.html b/views/subscribers/subscribers.html index da519e752e..2dd68d625a 100644 --- a/views/subscribers/subscribers.html +++ b/views/subscribers/subscribers.html @@ -73,12 +73,16 @@ 'multipleSubscribersRemovedFromList': __('%$1d subscribers were removed from list %$2s.'), 'removeFromAllLists': __('Remove from all lists'), 'multipleSubscribersRemovedFromAllLists': __('%$1d subscribers were removed from all lists.'), - 'confirmUnconfirmed': __('Confirm unconfirmed'), - 'multipleSubscribersConfirmed': __('%$1d subscribers have been confirmed.'), 'resendConfirmationEmail': __('Resend confirmation email'), 'multipleConfirmationEmailsSent': __('%$1d confirmation emails have been sent.'), 'listsToWhichSubscriberWasSubscribed': __('Lists to which the subscriber was subscribed.'), - 'wordPressUserNotice': __('This subscriber is a registered WordPress user. [link]Edit his profile[/link] to change his email.'), + 'WPUsersSegment': __('WordPress Users'), + 'WPUserEditNotice': __('This subscriber is a registered WordPress user. [link]Edit his profile[/link] to change his email.'), + 'tip': __('Tip:'), + 'customFieldsTip': __('need to add new fields like telephone number or address? You can add custom fields by editing any form.'), + 'year': __('Year'), + 'month': __('Month'), + 'day': __('Day'), 'new': __('New'), 'import': __('Import'), 'export': __('Export'),
' + - MailPoet.I18n.t('wordPressUserNotice') - .replace('[link]', '') - .replace('[/link]', '') + - '
+ { ReactStringReplace( + MailPoet.I18n.t('WPUserEditNotice'), + /\[link\](.*?)\[\/link\]/g, + (match, i) => ( + { match } + ) + ) + } +
+ + { MailPoet.I18n.t('tip') } + { MailPoet.I18n.t('customFieldsTip') } +