Listing & Form & Refactoring

- finished implementing forms
- fixed form reset when clicking on new
- fixed responsive for select all checkbox and toggle item details
- refactored listing items' actions
- added Trash action
- cleaned up validations on models
- fixed syntax
- fixed tests
This commit is contained in:
Jonathan Labreuille
2015-09-15 16:00:07 +02:00
parent 79f1896cf3
commit 2a4945c956
21 changed files with 196 additions and 183 deletions

View File

@ -34,7 +34,7 @@ define(
name={ this.props.field.name }
id={ 'field_'+this.props.field.name }
value={ this.props.item[this.props.field.name] }
onChange={ this.props.onValueChange } >
onChange={ this.props.onValueChange }>
{options}
</select>
);
@ -228,6 +228,7 @@ define(
loading: false,
item: {}
});
this.refs.form.getDOMNode().reset();
} else {
this.loadItem(props.params.id);
}
@ -315,6 +316,7 @@ define(
return (
<form
ref="form"
className={ formClasses }
onSubmit={ this.handleSubmit }>

View File

@ -22,7 +22,8 @@ define(['react', 'classnames'], function(React, classNames) {
if(this.props.is_selectable === true) {
checkbox = (
<td className="manage-column column-cb mailpoet_check_column">
<td
className="manage-column column-cb check-column">
<label className="screen-reader-text">
{ 'Select All' }
</label>

View File

@ -3,6 +3,7 @@ define(
'mailpoet',
'jquery',
'react',
'react-router',
'classnames',
'listing/bulk_actions.jsx',
'listing/header.jsx',
@ -15,6 +16,7 @@ define(
MailPoet,
jQuery,
React,
Router,
classNames,
ListingBulkActions,
ListingHeader,
@ -23,7 +25,14 @@ define(
ListingGroups,
ListingFilters
) {
var ListingItem = React.createClass({
var Link = Router.Link;
var ListingItem = React.createClass({
getInitialState: function() {
return {
toggled: true
};
},
handleSelectItem: function(e) {
var is_checked = jQuery(e.target).is(':checked');
@ -34,13 +43,18 @@ define(
return !e.target.checked;
},
handleDeleteItem: function(id) {
this.props.onDeleteItem(id);
},
handleToggleItem: function(id) {
this.setState({ toggled: !this.state.toggled });
},
render: function() {
var checkbox = false;
if(this.props.is_selectable === true) {
checkbox = (
<th className="mailpoet_check_column" scope="row">
<th className="check-column" scope="row">
<label className="screen-reader-text">
{ 'Select ' + this.props.item.email }</label>
<input
@ -55,10 +69,35 @@ define(
);
}
var item_actions = (
<div>
<div className="row-actions">
<span className="edit">
<Link to="edit" params={{ id: this.props.item.id }}>Edit</Link>
</span>
&nbsp;|&nbsp;
<span className="trash">
<a
href="javascript:;"
onClick={ this.handleDeleteItem.bind(null, this.props.item.id) }>
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 })
return (
<tr>
<tr className={ row_classes }>
{ checkbox }
{ this.props.onRenderItem(this.props.item) }
{ this.props.onRenderItem(this.props.item, item_actions) }
</tr>
);
}
@ -124,6 +163,7 @@ define(
columns={ this.props.columns }
onSelectItem={ this.props.onSelectItem }
onRenderItem={ this.props.onRenderItem }
onDeleteItem={ this.props.onDeleteItem }
selection={ this.props.selection }
is_selectable={ this.props.is_selectable }
key={ 'item-' + item.id }
@ -170,19 +210,29 @@ define(
search: this.state.search,
sort_by: this.state.sort_by,
sort_order: this.state.sort_order
},
onSuccess: function(response) {
if(this.isMounted()) {
this.setState({
items: response.items || [],
filters: response.filters || [],
groups: response.groups || [],
count: response.count || 0,
loading: false
});
}
}.bind(this)
});
}
}).done(function(response) {
if(this.isMounted()) {
this.setState({
items: response.items || [],
filters: response.filters || [],
groups: response.groups || [],
count: response.count || 0,
loading: false
});
}
}.bind(this));
},
handleDeleteItem: function(id) {
this.setState({ loading: true });
MailPoet.Ajax.post({
endpoint: this.props.endpoint,
action: 'delete',
data: id
}).done(function() {
this.getItems();
}.bind(this));
},
handleSearch: function(search) {
this.setState({
@ -269,8 +319,8 @@ define(
this.getItems();
}.bind(this));
},
handleRenderItem: function(item) {
return this.props.onRenderItem(item);
handleRenderItem: function(item, actions) {
return this.props.onRenderItem(item, actions);
},
render: function() {
var items = this.state.items,
@ -326,6 +376,7 @@ define(
<ListingItems
onRenderItem={ this.handleRenderItem }
onDeleteItem={ this.handleDeleteItem }
columns={ this.props.columns }
is_selectable={ bulk_actions.length > 0 }
onSelectItem={ this.handleSelectItem }

View File

@ -34,7 +34,6 @@ define(
var NewsletterForm = React.createClass({
render: function() {
return (
<Form
endpoint="newsletters"

View File

@ -1,18 +1,14 @@
define(
[
'react',
'react-router',
'listing/listing.jsx',
'classnames',
'classnames'
],
function(
React,
Router,
Listing,
classNames
) {
var Link = Router.Link;
var columns = [
{
name: 'subject',
@ -32,7 +28,7 @@ define(
];
var NewsletterList = React.createClass({
renderItem: function(newsletter) {
renderItem: function(newsletter, actions) {
var rowClasses = classNames(
'manage-column',
'column-primary',
@ -45,12 +41,7 @@ define(
<strong>
<a>{ newsletter.subject }</a>
</strong>
<div className="row-actions">
<span className="edit">
<Link to="edit" params={{ id: newsletter.id }}>Edit</Link>
</span>
</div>
{ actions }
</td>
<td className="column-date" data-colname="Subscribed on">
<abbr>{ newsletter.created_at }</abbr>

View File

@ -1,18 +1,14 @@
define(
[
'react',
'react-router',
'listing/listing.jsx',
'classnames',
'classnames'
],
function(
React,
Router,
Listing,
classNames
) {
var Link = Router.Link;
var columns = [
{
name: 'name',
@ -32,7 +28,7 @@ define(
];
var SegmentList = React.createClass({
renderItem: function(segment) {
renderItem: function(segment, actions) {
var rowClasses = classNames(
'manage-column',
'column-primary',
@ -45,12 +41,7 @@ define(
<strong>
<a>{ segment.name }</a>
</strong>
<div className="row-actions">
<span className="edit">
<Link to="edit" params={{ id: segment.id }}>Edit</Link>
</span>
</div>
{ actions }
</td>
<td className="column-date" data-colname="Subscribed on">
<abbr>{ segment.created_at }</abbr>

View File

@ -31,8 +31,8 @@ define(
label: 'Status',
type: 'select',
values: {
'subscribed': 'Subscribed',
'unconfirmed': 'Unconfirmed',
'subscribed': 'Subscribed',
'unsubscribed': 'Unsubscribed'
}
}

View File

@ -1,18 +1,14 @@
define(
[
'react',
'react-router',
'listing/listing.jsx',
'classnames',
'classnames'
],
function(
React,
Router,
Listing,
classNames
) {
var Link = Router.Link;
var columns = [
{
name: 'email',
@ -62,8 +58,8 @@ define(
];
var List = React.createClass({
renderItem: function(subscriber) {
var rowClasses = classNames(
renderItem: function(subscriber, actions) {
var row_classes = classNames(
'manage-column',
'column-primary',
'has-row-actions'
@ -87,20 +83,11 @@ define(
return (
<div>
<td className={ rowClasses }>
<td className={ row_classes }>
<strong>
<a>{ subscriber.email }</a>
</strong>
<div className="row-actions">
<span className="edit">
<Link to="edit" params={{ id: subscriber.id }}>Edit</Link>
</span>
</div>
<button className="toggle-row" type="button">
<span className="screen-reader-text">Show more details</span>
</button>
{ actions }
</td>
<td className="column" data-colname="First name">
{ subscriber.first_name }
@ -125,7 +112,6 @@ define(
<Listing
endpoint="subscribers"
onRenderItem={ this.renderItem }
items={ this.getItems }
columns={ columns }
bulk_actions={ bulk_actions } />
);