Dashboard page (#150)

This commit is contained in:
Cássio Souza 2016-11-02 12:25:43 -02:00 committed by GitHub
parent 44bbb84d44
commit a6fc8506f5
8 changed files with 118 additions and 99 deletions

View File

@ -108,7 +108,7 @@ class UnpublishedListing extends React.Component {
const columns = this.renderColumns(this.props.entries);
return (
<div className={styles.clear}>
<h1>Editorial Workflow</h1>
<h5>Editorial Workflow</h5>
<div className={styles.container}>
{columns}
</div>

View File

@ -5,10 +5,9 @@ import { loadEntries } from '../actions/entries';
import { selectEntries } from '../reducers';
import { Loader } from '../components/UI';
import EntryListing from '../components/EntryListing';
import styles from './CollectionPage.css';
import CollectionPageHOC from './editorialWorkflow/CollectionPageHOC';
import styles from './breakpoints.css';
class DashboardPage extends React.Component {
class CollectionPage extends React.Component {
static propTypes = {
collection: ImmutablePropTypes.map.isRequired,
@ -59,12 +58,6 @@ class DashboardPage extends React.Component {
}
}
/*
* Instead of checking the publish mode everywhere to dispatch & render the additional editorial workflow stuff,
* We delegate it to a Higher Order Component
*/
DashboardPage = CollectionPageHOC(DashboardPage); // eslint-disable-line
function mapStateToProps(state, ownProps) {
const { collections } = state;
@ -77,4 +70,4 @@ function mapStateToProps(state, ownProps) {
return { slug, collection, collections, page, entries };
}
export default connect(mapStateToProps)(DashboardPage);
export default connect(mapStateToProps)(CollectionPage);

View File

@ -0,0 +1,13 @@
import React from 'react';
import UnpublishedEntriesPanel from './editorialWorkflow/UnpublishedEntriesPanel';
import styles from './breakpoints.css';
export default function DashboardPage() {
return (
<div className={styles.root}>
<h1>Dashboard</h1>
<UnpublishedEntriesPanel />
</div>
);
}

View File

@ -5,7 +5,7 @@ import { selectSearchedEntries } from '../reducers';
import { searchEntries } from '../actions/entries';
import { Loader } from '../components/UI';
import EntryListing from '../components/EntryListing';
import styles from './CollectionPage.css';
import styles from './breakpoints.css';
class SearchPage extends React.Component {
@ -13,7 +13,7 @@ class SearchPage extends React.Component {
isFetching: PropTypes.bool,
searchEntries: PropTypes.func.isRequired,
searchTerm: PropTypes.string.isRequired,
entries: ImmutablePropTypes.list
entries: ImmutablePropTypes.list,
};
componentDidMount() {
@ -34,15 +34,15 @@ class SearchPage extends React.Component {
render() {
const { collections, searchTerm, entries, isFetching, page } = this.props;
return <div className={styles.root}>
return (<div className={styles.root}>
{(isFetching === true || !entries) ?
<Loader active>{['Loading Entries', 'Caching Entries', 'This might take several minutes']}</Loader>
:
<EntryListing collections={collections} entries={entries} page={page} onPaginate={this.handleLoadMore}>
Results for {searchTerm}
</EntryListing>
<EntryListing collections={collections} entries={entries} page={page} onPaginate={this.handleLoadMore}>
Results for {searchTerm}
</EntryListing>
}
</div>;
</div>);
}
}

View File

@ -4,36 +4,35 @@
@media (max-width: 749px) and (min-width: 495px) {
.root {
width: 495px;
margin: auto;
width: 495px;
}
}
@media (max-width: 1004px) and (min-width: 750px) {
.root {
width: 750px;
margin: auto;
width: 750px;
}
}
@media (max-width: 1514px) and (min-width: 1005px) {
.root {
width: 1005px;
margin: auto;
width: 1005px;
}
}
@media (max-width: 1769px) and (min-width: 1515px) {
.root {
width: 1515px;
margin: auto;
width: 1515px;
}
}
@media (min-width: 1770px) {
.root {
width: 1770px;
margin: auto;
width: 1770px;
}
}

View File

@ -1,68 +0,0 @@
import React, { PropTypes } from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { OrderedMap } from 'immutable';
import { loadUnpublishedEntries, updateUnpublishedEntryStatus, publishUnpublishedEntry } from '../../actions/editorialWorkflow';
import { selectUnpublishedEntries } from '../../reducers';
import { EDITORIAL_WORKFLOW, status } from '../../constants/publishModes';
import UnpublishedListing from '../../components/UnpublishedListing';
import { connect } from 'react-redux';
import styles from '../CollectionPage.css';
export default function CollectionPageHOC(CollectionPage) {
class CollectionPageHOC extends CollectionPage {
static propTypes = {
dispatch: PropTypes.func.isRequired,
isEditorialWorkflow: PropTypes.bool.isRequired,
unpublishedEntries: ImmutablePropTypes.map,
};
componentDidMount() {
const { dispatch, isEditorialWorkflow } = this.props;
if (isEditorialWorkflow) {
dispatch(loadUnpublishedEntries());
}
super.componentDidMount();
}
render() {
const { isEditorialWorkflow, unpublishedEntries, updateUnpublishedEntryStatus, publishUnpublishedEntry } = this.props;
if (!isEditorialWorkflow) return super.render();
return (
<div>
<div className={styles.root}>
<UnpublishedListing
entries={unpublishedEntries}
handleChangeStatus={updateUnpublishedEntryStatus}
handlePublish={publishUnpublishedEntry}
/>
</div>
{super.render()}
</div>
);
}
}
function mapStateToProps(state) {
const publish_mode = state.config.get('publish_mode');
const isEditorialWorkflow = (publish_mode === EDITORIAL_WORKFLOW);
const returnObj = { isEditorialWorkflow };
if (isEditorialWorkflow) {
/*
* Generates an ordered Map of the available status as keys.
* Each key containing a List of available unpubhlished entries
* Eg.: OrderedMap{'draft':List(), 'pending_review':List(), 'pending_publish':List()}
*/
returnObj.unpublishedEntries = status.reduce((acc, currStatus) => {
return acc.set(currStatus, selectUnpublishedEntries(state, currStatus));
}, OrderedMap());
}
return returnObj;
}
return connect(mapStateToProps, {
updateUnpublishedEntryStatus,
publishUnpublishedEntry,
})(CollectionPageHOC);
}

View File

@ -0,0 +1,61 @@
import React, { Component, PropTypes } from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { OrderedMap } from 'immutable';
import { connect } from 'react-redux';
import { loadUnpublishedEntries, updateUnpublishedEntryStatus, publishUnpublishedEntry } from '../../actions/editorialWorkflow';
import { selectUnpublishedEntries } from '../../reducers';
import { EDITORIAL_WORKFLOW, status } from '../../constants/publishModes';
import UnpublishedListing from '../../components/UnpublishedListing';
class unpublishedEntriesPanel extends Component {
static propTypes = {
isEditorialWorkflow: PropTypes.bool.isRequired,
unpublishedEntries: ImmutablePropTypes.map,
loadUnpublishedEntries: PropTypes.func.isRequired,
updateUnpublishedEntryStatus: PropTypes.func.isRequired,
publishUnpublishedEntry: PropTypes.func.isRequired,
};
componentDidMount() {
const { loadUnpublishedEntries, isEditorialWorkflow } = this.props;
if (isEditorialWorkflow) {
loadUnpublishedEntries();
}
}
render() {
const { isEditorialWorkflow, unpublishedEntries, updateUnpublishedEntryStatus, publishUnpublishedEntry } = this.props;
if (!isEditorialWorkflow) return null;
return (
<UnpublishedListing
entries={unpublishedEntries}
handleChangeStatus={updateUnpublishedEntryStatus}
handlePublish={publishUnpublishedEntry}
/>
);
}
}
function mapStateToProps(state) {
const isEditorialWorkflow = (state.config.get('publish_mode') === EDITORIAL_WORKFLOW);
const returnObj = { isEditorialWorkflow };
if (isEditorialWorkflow) {
/*
* Generates an ordered Map of the available status as keys.
* Each key containing a List of available unpubhlished entries
* Eg.: OrderedMap{'draft':List(), 'pending_review':List(), 'pending_publish':List()}
*/
returnObj.unpublishedEntries = status.reduce((acc, currStatus) => (
acc.set(currStatus, selectUnpublishedEntries(state, currStatus))
), OrderedMap());
}
return returnObj;
}
export default connect(mapStateToProps, {
loadUnpublishedEntries,
updateUnpublishedEntryStatus,
publishUnpublishedEntry,
})(unpublishedEntriesPanel);

View File

@ -1,6 +1,7 @@
import React from 'react';
import { Route, IndexRoute } from 'react-router';
import App from '../containers/App';
import DashboardPage from '../containers/DashboardPage';
import CollectionPage from '../containers/CollectionPage';
import EntryPage from '../containers/EntryPage';
import SearchPage from '../containers/SearchPage';
@ -8,12 +9,32 @@ import NotFoundPage from '../containers/NotFoundPage';
export default (
<Route path="/" component={App}>
<IndexRoute component={CollectionPage}/>
<Route path="/collections/:name" component={CollectionPage}/>
<Route path="/collections/:name/entries/new" component={EntryPage} newRecord />
<Route path="/collections/:name/entries/:slug" component={EntryPage} />
<Route path="/editorialworkflow/:name/:status/:slug" component={EntryPage} unpublishedEntry />
<Route path="/search/:searchTerm" component={SearchPage}/>
<Route path="*" component={NotFoundPage}/>
<IndexRoute component={DashboardPage} />
<Route
path="/collections/:name"
component={CollectionPage}
/>
<Route
path="/collections/:name/entries/new"
component={EntryPage}
newRecord
/>
<Route
path="/collections/:name/entries/:slug"
component={EntryPage}
/>
<Route
path="/editorialworkflow/:name/:status/:slug"
component={EntryPage}
unpublishedEntry
/>
<Route
path="/search/:searchTerm"
component={SearchPage}
/>
<Route
path="*"
component={NotFoundPage}
/>
</Route>
);