listing improvements
- added Trash group - added soft delete for subscribers - added restore/delete permanently features (including bulk actions and row actions) - listing bugfixes
This commit is contained in:
@@ -5,8 +5,10 @@ define(['react', 'classnames'], function(React, classNames) {
|
|||||||
return this.props.onSelectGroup(group);
|
return this.props.onSelectGroup(group);
|
||||||
},
|
},
|
||||||
render: function() {
|
render: function() {
|
||||||
var count = this.props.groups.length;
|
|
||||||
var groups = this.props.groups.map(function(group, index) {
|
var groups = this.props.groups.map(function(group, index) {
|
||||||
|
if(group.name === 'trash' && group.count === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var classes = classNames(
|
var classes = classNames(
|
||||||
{ 'current' : (group.name === this.props.group) }
|
{ 'current' : (group.name === this.props.group) }
|
||||||
@@ -14,12 +16,13 @@ define(['react', 'classnames'], function(React, classNames) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<li key={index}>
|
<li key={index}>
|
||||||
|
{(index > 0) ? ' |' : ''}
|
||||||
<a
|
<a
|
||||||
href="javascript:;"
|
href="javascript:;"
|
||||||
className={classes}
|
className={classes}
|
||||||
onClick={this.handleSelect.bind(this, group.name)} >
|
onClick={this.handleSelect.bind(this, group.name)} >
|
||||||
{group.label} <span className="count">({ group.count })</span>
|
{group.label} <span className="count">({ group.count })</span>
|
||||||
</a>{(index < (count - 1)) ? ' | ' : ''}
|
</a>
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
@@ -43,8 +43,11 @@ define(
|
|||||||
|
|
||||||
return !e.target.checked;
|
return !e.target.checked;
|
||||||
},
|
},
|
||||||
handleDeleteItem: function(id) {
|
handleRestoreItem: function(id) {
|
||||||
this.props.onDeleteItem(id);
|
this.props.onRestoreItem(id);
|
||||||
|
},
|
||||||
|
handleDeleteItem: function(id, confirm = false) {
|
||||||
|
this.props.onDeleteItem(id, confirm);
|
||||||
},
|
},
|
||||||
handleToggleItem: function(id) {
|
handleToggleItem: function(id) {
|
||||||
this.setState({ toggled: !this.state.toggled });
|
this.setState({ toggled: !this.state.toggled });
|
||||||
@@ -89,26 +92,65 @@ define(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var actions = (
|
if(this.props.group === 'trash') {
|
||||||
<div>
|
var actions = (
|
||||||
<div className="row-actions">
|
<div>
|
||||||
{ item_actions }
|
<div className="row-actions">
|
||||||
{ ' | ' }
|
<span>
|
||||||
<span className="trash">
|
<a
|
||||||
<a
|
href="javascript:;"
|
||||||
href="javascript:;"
|
onClick={ this.handleRestoreItem.bind(
|
||||||
onClick={ this.handleDeleteItem.bind(null, this.props.item.id) }>
|
null,
|
||||||
Trash
|
this.props.item.id
|
||||||
</a>
|
)}
|
||||||
</span>
|
>Restore</a>
|
||||||
|
</span>
|
||||||
|
{ ' | ' }
|
||||||
|
<span className="delete">
|
||||||
|
<a
|
||||||
|
className="submitdelete"
|
||||||
|
href="javascript:;"
|
||||||
|
onClick={ this.handleDeleteItem.bind(
|
||||||
|
null,
|
||||||
|
this.props.item.id,
|
||||||
|
true
|
||||||
|
)}
|
||||||
|
>Delete permanently</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={ this.handleToggleItem.bind(null, this.props.item.id) }
|
||||||
|
className="toggle-row" type="button">
|
||||||
|
<span className="screen-reader-text">Show more details</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<button
|
);
|
||||||
onClick={ this.handleToggleItem.bind(null, this.props.item.id) }
|
} else {
|
||||||
className="toggle-row" type="button">
|
var actions = (
|
||||||
<span className="screen-reader-text">Show more details</span>
|
<div>
|
||||||
</button>
|
<div className="row-actions">
|
||||||
</div>
|
{ item_actions }
|
||||||
);
|
{ ' | ' }
|
||||||
|
<span className="trash">
|
||||||
|
<a
|
||||||
|
href="javascript:;"
|
||||||
|
onClick={ this.handleDeleteItem.bind(
|
||||||
|
null,
|
||||||
|
this.props.item.id,
|
||||||
|
false
|
||||||
|
) }>
|
||||||
|
Trash
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={ this.handleToggleItem.bind(null, this.props.item.id) }
|
||||||
|
className="toggle-row" type="button">
|
||||||
|
<span className="screen-reader-text">Show more details</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
var row_classes = classNames({ 'is-expanded': !this.state.toggled })
|
var row_classes = classNames({ 'is-expanded': !this.state.toggled })
|
||||||
|
|
||||||
@@ -190,9 +232,11 @@ define(
|
|||||||
onSelectItem={ this.props.onSelectItem }
|
onSelectItem={ this.props.onSelectItem }
|
||||||
onRenderItem={ this.props.onRenderItem }
|
onRenderItem={ this.props.onRenderItem }
|
||||||
onDeleteItem={ this.props.onDeleteItem }
|
onDeleteItem={ this.props.onDeleteItem }
|
||||||
|
onRestoreItem={ this.props.onRestoreItem }
|
||||||
selection={ this.props.selection }
|
selection={ this.props.selection }
|
||||||
is_selectable={ this.props.is_selectable }
|
is_selectable={ this.props.is_selectable }
|
||||||
item_actions={ this.props.item_actions }
|
item_actions={ this.props.item_actions }
|
||||||
|
group={ this.props.group }
|
||||||
key={ 'item-' + item.id }
|
key={ 'item-' + item.id }
|
||||||
item={ item } />
|
item={ item } />
|
||||||
);
|
);
|
||||||
@@ -254,7 +298,21 @@ define(
|
|||||||
}
|
}
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
},
|
},
|
||||||
handleDeleteItem: function(id) {
|
handleRestoreItem: function(id) {
|
||||||
|
this.setState({
|
||||||
|
loading: true,
|
||||||
|
page: 1
|
||||||
|
});
|
||||||
|
|
||||||
|
MailPoet.Ajax.post({
|
||||||
|
endpoint: this.props.endpoint,
|
||||||
|
action: 'restore',
|
||||||
|
data: id
|
||||||
|
}).done(function() {
|
||||||
|
this.getItems();
|
||||||
|
}.bind(this));
|
||||||
|
},
|
||||||
|
handleDeleteItem: function(id, confirm = false) {
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: true,
|
loading: true,
|
||||||
page: 1
|
page: 1
|
||||||
@@ -263,7 +321,10 @@ define(
|
|||||||
MailPoet.Ajax.post({
|
MailPoet.Ajax.post({
|
||||||
endpoint: this.props.endpoint,
|
endpoint: this.props.endpoint,
|
||||||
action: 'delete',
|
action: 'delete',
|
||||||
data: id
|
data: {
|
||||||
|
id: id,
|
||||||
|
confirm: confirm
|
||||||
|
}
|
||||||
}).done(function() {
|
}).done(function() {
|
||||||
this.getItems();
|
this.getItems();
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
@@ -414,6 +475,22 @@ define(
|
|||||||
// bulk actions
|
// bulk actions
|
||||||
var bulk_actions = this.props.bulk_actions || [];
|
var bulk_actions = this.props.bulk_actions || [];
|
||||||
|
|
||||||
|
if(this.state.group === 'trash') {
|
||||||
|
bulk_actions = [
|
||||||
|
{
|
||||||
|
name: 'restore',
|
||||||
|
label: 'Restore'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'trash',
|
||||||
|
label: 'Delete permanently',
|
||||||
|
getData: function() {
|
||||||
|
return { confirm: true };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
// item actions
|
// item actions
|
||||||
var item_actions = this.props.item_actions || [];
|
var item_actions = this.props.item_actions || [];
|
||||||
|
|
||||||
@@ -464,6 +541,7 @@ define(
|
|||||||
<ListingItems
|
<ListingItems
|
||||||
onRenderItem={ this.handleRenderItem }
|
onRenderItem={ this.handleRenderItem }
|
||||||
onDeleteItem={ this.handleDeleteItem }
|
onDeleteItem={ this.handleDeleteItem }
|
||||||
|
onRestoreItem={ this.handleRestoreItem }
|
||||||
columns={ this.props.columns }
|
columns={ this.props.columns }
|
||||||
is_selectable={ bulk_actions.length > 0 }
|
is_selectable={ bulk_actions.length > 0 }
|
||||||
onSelectItem={ this.handleSelectItem }
|
onSelectItem={ this.handleSelectItem }
|
||||||
@@ -471,6 +549,7 @@ define(
|
|||||||
selection={ this.state.selection }
|
selection={ this.state.selection }
|
||||||
selected_ids={ this.state.selected_ids }
|
selected_ids={ this.state.selected_ids }
|
||||||
loading={ this.state.loading }
|
loading={ this.state.loading }
|
||||||
|
group={ this.state.group }
|
||||||
count={ this.state.count }
|
count={ this.state.count }
|
||||||
limit={ this.state.limit }
|
limit={ this.state.limit }
|
||||||
item_actions={ item_actions }
|
item_actions={ item_actions }
|
||||||
|
@@ -117,6 +117,14 @@ define(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'removeFromAllLists',
|
||||||
|
label: 'Remove from all lists'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'confirmUnconfirmed',
|
||||||
|
label: 'Confirm unconfirmed'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'trash',
|
name: 'trash',
|
||||||
label: 'Trash'
|
label: 'Trash'
|
||||||
@@ -153,14 +161,16 @@ define(
|
|||||||
return segment.name;
|
return segment.name;
|
||||||
}).join(', ');
|
}).join(', ');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var row_actions = false;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<td className={ row_classes }>
|
<td className={ row_classes }>
|
||||||
<strong>
|
<strong><Link to={ `/edit/${ subscriber.id }` }>
|
||||||
<Link to={ `/edit/${ subscriber.id }` }>
|
{ subscriber.email }
|
||||||
{ subscriber.email }
|
</Link></strong>
|
||||||
</Link>
|
|
||||||
</strong>
|
|
||||||
{ actions }
|
{ actions }
|
||||||
</td>
|
</td>
|
||||||
<td className="column" data-colname="First name">
|
<td className="column" data-colname="First name">
|
||||||
|
@@ -54,6 +54,7 @@ class Migrator {
|
|||||||
'email varchar(150) NOT NULL,',
|
'email varchar(150) NOT NULL,',
|
||||||
'status varchar(12) NOT NULL DEFAULT "unconfirmed",',
|
'status varchar(12) NOT NULL DEFAULT "unconfirmed",',
|
||||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||||
|
'deleted_at TIMESTAMP NULL DEFAULT NULL,',
|
||||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||||
'PRIMARY KEY (id),',
|
'PRIMARY KEY (id),',
|
||||||
'UNIQUE KEY email (email)'
|
'UNIQUE KEY email (email)'
|
||||||
@@ -82,6 +83,7 @@ class Migrator {
|
|||||||
'preheader varchar(250) NOT NULL,',
|
'preheader varchar(250) NOT NULL,',
|
||||||
'body longtext,',
|
'body longtext,',
|
||||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||||
|
'deleted_at TIMESTAMP NULL DEFAULT NULL,',
|
||||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||||
'PRIMARY KEY (id)'
|
'PRIMARY KEY (id)'
|
||||||
);
|
);
|
||||||
@@ -106,6 +108,7 @@ class Migrator {
|
|||||||
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||||
'name varchar(90) NOT NULL,',
|
'name varchar(90) NOT NULL,',
|
||||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||||
|
'deleted_at TIMESTAMP NULL DEFAULT NULL,',
|
||||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||||
'PRIMARY KEY (id),',
|
'PRIMARY KEY (id),',
|
||||||
'UNIQUE KEY name (name)'
|
'UNIQUE KEY name (name)'
|
||||||
@@ -170,8 +173,7 @@ class Migrator {
|
|||||||
'newsletter_type varchar(90) NOT NULL,',
|
'newsletter_type varchar(90) NOT NULL,',
|
||||||
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||||
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||||
'PRIMARY KEY (id),',
|
'PRIMARY KEY (id)'
|
||||||
'UNIQUE KEY name_newsletter_type (newsletter_type, name)'
|
|
||||||
);
|
);
|
||||||
return $this->sqlify(__FUNCTION__, $attributes);
|
return $this->sqlify(__FUNCTION__, $attributes);
|
||||||
}
|
}
|
||||||
|
@@ -69,18 +69,8 @@ class Subscriber extends Model {
|
|||||||
|
|
||||||
foreach($filters as $filter) {
|
foreach($filters as $filter) {
|
||||||
if($filter['name'] === 'segment') {
|
if($filter['name'] === 'segment') {
|
||||||
|
|
||||||
$segment = Segment::findOne($filter['value']);
|
$segment = Segment::findOne($filter['value']);
|
||||||
if($segment !== false) {
|
if($segment !== false) {
|
||||||
/*$orm = $orm
|
|
||||||
->select(MP_SUBSCRIBERS_TABLE.'.*')
|
|
||||||
->select('subscriber_segment.id', 'subscriber_segment_id')
|
|
||||||
->join(
|
|
||||||
MP_SUBSCRIBER_SEGMENT_TABLE,
|
|
||||||
MP_SUBSCRIBERS_TABLE.'.id = subscriber_segment.subscriber_id',
|
|
||||||
'subscriber_segment'
|
|
||||||
)
|
|
||||||
->where('subscriber_segment.segment_id', (int)$filter['value']);*/
|
|
||||||
$orm = $segment->subscribers();
|
$orm = $segment->subscribers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,35 +83,47 @@ class Subscriber extends Model {
|
|||||||
array(
|
array(
|
||||||
'name' => 'all',
|
'name' => 'all',
|
||||||
'label' => __('All'),
|
'label' => __('All'),
|
||||||
'count' => Subscriber::count()
|
'count' => Subscriber::whereNull('deleted_at')->count()
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'name' => 'subscribed',
|
'name' => 'subscribed',
|
||||||
'label' => __('Subscribed'),
|
'label' => __('Subscribed'),
|
||||||
'count' => Subscriber::where('status', 'subscribed')->count()
|
'count' => Subscriber::whereNull('deleted_at')
|
||||||
|
->where('status', 'subscribed')
|
||||||
|
->count()
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'name' => 'unconfirmed',
|
'name' => 'unconfirmed',
|
||||||
'label' => __('Unconfirmed'),
|
'label' => __('Unconfirmed'),
|
||||||
'count' => Subscriber::where('status', 'unconfirmed')->count()
|
'count' => Subscriber::whereNull('deleted_at')
|
||||||
|
->where('status', 'unconfirmed')
|
||||||
|
->count()
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'name' => 'unsubscribed',
|
'name' => 'unsubscribed',
|
||||||
'label' => __('Unsubscribed'),
|
'label' => __('Unsubscribed'),
|
||||||
'count' => Subscriber::where('status', 'unsubscribed')->count()
|
'count' => Subscriber::whereNull('deleted_at')
|
||||||
|
->where('status', 'unsubscribed')
|
||||||
|
->count()
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'name' => 'trash',
|
||||||
|
'label' => __('Trash'),
|
||||||
|
'count' => Subscriber::whereNotNull('deleted_at')->count()
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static function groupBy($orm, $group = null) {
|
static function groupBy($orm, $group = null) {
|
||||||
if($group === null or !in_array(
|
if($group === 'trash') {
|
||||||
$group,
|
return $orm->whereNotNull('deleted_at');
|
||||||
array('subscribed', 'unconfirmed', 'unsubscribed')
|
} else {
|
||||||
)) {
|
$orm = $orm->whereNull('deleted_at');
|
||||||
return $orm;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $orm->where('status', $group);
|
if(in_array($group, array('subscribed', 'unsubscribed', 'unconfirmed'))) {
|
||||||
|
return $orm->where('status', $group);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static function filterWithCustomFields($orm) {
|
static function filterWithCustomFields($orm) {
|
||||||
@@ -228,6 +230,54 @@ class Subscriber extends Model {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function removeFromAllLists($listing) {
|
||||||
|
$segments = Segment::findMany();
|
||||||
|
$segment_ids = array_map(function($segment) {
|
||||||
|
return $segment->id();
|
||||||
|
}, $segments);
|
||||||
|
|
||||||
|
if(!empty($segment_ids)) {
|
||||||
|
// delete relations with segment
|
||||||
|
$subscriber_ids = $listing->getSelectionIds();
|
||||||
|
SubscriberSegment::whereIn('subscriber_id', $subscriber_ids)
|
||||||
|
->whereIn('segment_id', $segment_ids)
|
||||||
|
->deleteMany();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function confirmUnconfirmed($listing) {
|
||||||
|
$subscriber_ids = $listing->getSelectionIds();
|
||||||
|
$subscribers = Subscriber::whereIn('id', $subscriber_ids)
|
||||||
|
->where('status', 'unconfirmed')
|
||||||
|
->findMany();
|
||||||
|
|
||||||
|
if(!empty($subscribers)) {
|
||||||
|
foreach($subscribers as $subscriber) {
|
||||||
|
$subscriber->set('status', 'subscribed');
|
||||||
|
$subscriber->save();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static function resendConfirmationEmail($listing) {
|
||||||
|
$subscriber_ids = $listing->getSelectionIds();
|
||||||
|
$subscribers = Subscriber::whereIn('id', $subscriber_ids)
|
||||||
|
->where('status', 'unconfirmed')
|
||||||
|
->findMany();
|
||||||
|
|
||||||
|
if(!empty($subscribers)) {
|
||||||
|
foreach($subscribers as $subscriber) {
|
||||||
|
// TODO: resend confirmation email
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static function addToList($listing, $data = array()) {
|
static function addToList($listing, $data = array()) {
|
||||||
$segment_id = (isset($data['segment_id']) ? (int)$data['segment_id'] : 0);
|
$segment_id = (isset($data['segment_id']) ? (int)$data['segment_id'] : 0);
|
||||||
$segment = Segment::findOne($segment_id);
|
$segment = Segment::findOne($segment_id);
|
||||||
@@ -246,11 +296,35 @@ class Subscriber extends Model {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static function trash($listing) {
|
static function trash($listing, $data = array()) {
|
||||||
// delete relations with all segments
|
if(isset($data['confirm']) && (bool)$data['confirm'] === true) {
|
||||||
$subscriber_ids = $listing->getSelectionIds();
|
// delete relations with all segments
|
||||||
\MailPoet\Models\SubscriberSegment::whereIn('subscriber_id', $subscriber_ids)->deleteMany();
|
$subscribers = $listing->getSelection()->findMany();
|
||||||
|
|
||||||
return $listing->getSelection()->deleteMany();
|
if(!empty($subscribers)) {
|
||||||
|
foreach($subscribers as $subscriber) {
|
||||||
|
$subscriber->delete();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
// soft delete
|
||||||
|
$subscribers = $listing->getSelection()->findResultSet();
|
||||||
|
if(!empty($subscribers)) {
|
||||||
|
$subscribers->set_expr('deleted_at', 'NOW()');
|
||||||
|
return $subscribers->save();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static function restore($listing, $data = array()) {
|
||||||
|
$subscribers = $listing->getSelection()->findResultSet();
|
||||||
|
if(!empty($subscribers)) {
|
||||||
|
$subscribers->set_expr('deleted_at', 'NULL');
|
||||||
|
return $subscribers->save();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -53,10 +53,26 @@ class Subscribers {
|
|||||||
wp_send_json($result);
|
wp_send_json($result);
|
||||||
}
|
}
|
||||||
|
|
||||||
function delete($id) {
|
function restore($id) {
|
||||||
$subscriber = Subscriber::findOne($id);
|
$subscriber = Subscriber::findOne($id);
|
||||||
if($subscriber !== false) {
|
if($subscriber !== false) {
|
||||||
$result = $subscriber->delete();
|
$subscriber->set_expr('deleted_at', 'NULL');
|
||||||
|
$result = $subscriber->save();
|
||||||
|
} else {
|
||||||
|
$result = false;
|
||||||
|
}
|
||||||
|
wp_send_json($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
function delete($data = array()) {
|
||||||
|
$subscriber = Subscriber::findOne($data['id']);
|
||||||
|
if($subscriber !== false) {
|
||||||
|
if(isset($data['confirm']) && (bool)$data['confirm'] === true) {
|
||||||
|
$result = $subscriber->delete();
|
||||||
|
} else {
|
||||||
|
$subscriber->set_expr('deleted_at', 'NOW()');
|
||||||
|
$result = $subscriber->save();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
$result = false;
|
$result = false;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user