static-cms/src/components/UnpublishedListing.js

151 lines
4.5 KiB
JavaScript
Raw Normal View History

2016-09-13 16:00:24 -03:00
import React, { PropTypes } from 'react';
import { DragDropContext, DragSource, DropTarget } from 'react-dnd';
import HTML5Backend from 'react-dnd-html5-backend';
2016-09-08 19:04:54 -03:00
import ImmutablePropTypes from 'react-immutable-proptypes';
import moment from 'moment';
2016-09-08 19:04:54 -03:00
import { Card } from './UI';
2016-09-13 11:27:06 -03:00
import { Link } from 'react-router';
2016-09-14 18:25:45 -03:00
import { status, statusDescriptions } from '../constants/publishModes';
2016-09-09 17:15:58 -03:00
import styles from './UnpublishedListing.css';
2016-09-08 19:04:54 -03:00
2016-09-13 16:00:24 -03:00
const CARD = 'card';
/*
* Column DropTarget Component
*/
function Column({ connectDropTarget, status, isOver, children }) {
const className = isOver ? `${styles.column} ${styles.highlighted}` : styles.column;
return connectDropTarget(
<div className={className}>
<h2>{statusDescriptions.get(status)}</h2>
{children}
</div>
);
}
const columnTargetSpec = {
drop(props, monitor) {
const slug = monitor.getItem().slug;
const collection = monitor.getItem().collection;
2016-09-14 18:25:45 -03:00
const oldStatus = monitor.getItem().ownStatus;
2016-09-13 16:00:24 -03:00
props.onChangeStatus(collection, slug, oldStatus, props.status);
}
};
function columnCollect(connect, monitor) {
return {
connectDropTarget: connect.dropTarget(),
isOver: monitor.isOver()
};
}
Column = DropTarget(CARD, columnTargetSpec, columnCollect)(Column);
/*
* Card DropTarget Component
*/
2016-09-14 18:25:45 -03:00
function EntryCard({ slug, collection, ownStatus, onRequestPublish, connectDragSource, children }) {
2016-09-13 16:00:24 -03:00
return connectDragSource(
<div>
<Card className={styles.card}>
{children}
2016-09-14 18:25:45 -03:00
{(ownStatus === status.last()) &&
<button onClick={onRequestPublish}>Publish now</button>
}
2016-09-13 16:00:24 -03:00
</Card>
</div>
);
}
const cardDragSpec = {
beginDrag(props) {
return {
slug: props.slug,
collection: props.collection,
2016-09-14 18:25:45 -03:00
ownStatus: props.ownStatus
2016-09-13 16:00:24 -03:00
};
}
};
function cardCollect(connect, monitor) {
return {
connectDragSource: connect.dragSource()
};
}
EntryCard = DragSource(CARD, cardDragSpec, cardCollect)(EntryCard);
/*
* The actual exported component implementation
*/
class UnpublishedListing extends React.Component {
constructor(props) {
super(props);
this.renderColumns = this.renderColumns.bind(this);
2016-09-14 18:25:45 -03:00
this.requestPublish = this.requestPublish.bind(this);
}
requestPublish(collection, slug, ownStatus) {
if (ownStatus !== status.last()) return;
if (window.confirm('Are you sure you want to publish this entry?')) {
this.props.handlePublish(collection, slug, ownStatus);
}
2016-09-13 16:00:24 -03:00
}
2016-09-09 17:15:58 -03:00
renderColumns(entries, column) {
2016-09-08 19:04:54 -03:00
if (!entries) return;
2016-09-09 17:15:58 -03:00
if (!column) {
return entries.entrySeq().map(([currColumn, currEntries]) => (
2016-09-13 16:00:24 -03:00
<Column
key={currColumn}
status={currColumn}
onChangeStatus={this.props.handleChangeStatus}
>
2016-09-09 17:15:58 -03:00
{this.renderColumns(currEntries, currColumn)}
2016-09-13 16:00:24 -03:00
</Column>
2016-09-09 17:15:58 -03:00
));
} else {
return <div>
2016-09-08 19:04:54 -03:00
{entries.map(entry => {
2016-09-09 17:15:58 -03:00
// Look for an "author" field. Fallback to username on backend implementation;
const author = entry.getIn(['data', 'author'], entry.getIn(['metaData', 'user']));
2016-09-13 11:27:06 -03:00
const timeStamp = moment(entry.getIn(['metaData', 'timeStamp'])).format('llll');
const link = `/editorialworkflow/${entry.getIn(['metaData', 'collection'])}/${entry.getIn(['metaData', 'status'])}/${entry.get('slug')}`;
2016-09-14 18:25:45 -03:00
const slug = entry.get('slug');
const status = entry.getIn(['metaData', 'status']);
const collection = entry.getIn(['metaData', 'collection']);
2016-09-09 17:15:58 -03:00
return (
2016-09-13 16:00:24 -03:00
<EntryCard
2016-09-14 18:25:45 -03:00
key={slug}
slug={slug}
ownStatus={status}
collection={collection}
onRequestPublish={this.requestPublish.bind(this, collection, slug, status)} // eslint-disable-line
2016-09-13 16:00:24 -03:00
>
2016-09-14 18:25:45 -03:00
<h2><Link to={link}>{entry.getIn(['data', 'title'])}</Link> <small>by {author}</small></h2>
2016-09-09 17:15:58 -03:00
<p>Last updated: {timeStamp} by {entry.getIn(['metaData', 'user'])}</p>
2016-09-13 16:00:24 -03:00
</EntryCard>
2016-09-09 17:15:58 -03:00
);
2016-09-08 19:04:54 -03:00
}
)}
2016-09-09 17:15:58 -03:00
</div>;
}
2016-09-08 19:04:54 -03:00
}
render() {
2016-09-09 17:15:58 -03:00
const columns = this.renderColumns(this.props.entries);
2016-09-08 19:04:54 -03:00
return (
2016-09-13 16:00:24 -03:00
<div className={styles.clear}>
2016-09-13 12:32:26 -03:00
<h1>Editorial Workflow</h1>
2016-09-13 16:00:24 -03:00
<div className={styles.container}>
2016-09-08 19:04:54 -03:00
{columns}
2016-09-13 16:00:24 -03:00
</div>
2016-09-08 19:04:54 -03:00
</div>
);
}
}
UnpublishedListing.propTypes = {
2016-09-09 17:15:58 -03:00
entries: ImmutablePropTypes.orderedMap,
2016-09-13 16:00:24 -03:00
handleChangeStatus: PropTypes.func.isRequired,
2016-09-14 18:25:45 -03:00
handlePublish: PropTypes.func.isRequired,
2016-09-08 19:04:54 -03:00
};
2016-09-13 16:00:24 -03:00
export default DragDropContext(HTML5Backend)(UnpublishedListing);