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';
|
2016-09-12 15:35:56 +02:00
|
|
|
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-08 19:04:54 -03:00
|
|
|
import { 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;
|
|
|
|
const oldStatus = monitor.getItem().currentStatus;
|
|
|
|
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
|
|
|
|
*/
|
|
|
|
function EntryCard({ connectDragSource, children }) {
|
|
|
|
return connectDragSource(
|
|
|
|
<div>
|
|
|
|
<Card className={styles.card}>
|
|
|
|
{children}
|
|
|
|
</Card>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
const cardDragSpec = {
|
|
|
|
beginDrag(props) {
|
|
|
|
return {
|
|
|
|
slug: props.slug,
|
|
|
|
collection: props.collection,
|
|
|
|
currentStatus: props.status
|
|
|
|
};
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
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-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');
|
2016-09-13 03:59:48 -03:00
|
|
|
const link = `/editorialworkflow/${entry.getIn(['metaData', 'collection'])}/${entry.getIn(['metaData', 'status'])}/${entry.get('slug')}`;
|
2016-09-09 17:15:58 -03:00
|
|
|
return (
|
2016-09-13 16:00:24 -03:00
|
|
|
<EntryCard
|
|
|
|
key={entry.get('slug')}
|
|
|
|
slug={entry.get('slug')}
|
|
|
|
status={entry.getIn(['metaData', 'status'])}
|
|
|
|
collection={entry.getIn(['metaData', 'collection'])}
|
|
|
|
>
|
2016-09-13 03:59:48 -03:00
|
|
|
<h1><Link to={link}>{entry.getIn(['data', 'title'])}</Link> <small>by {author}</small></h1>
|
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-08 19:04:54 -03:00
|
|
|
};
|
2016-09-13 16:00:24 -03:00
|
|
|
|
|
|
|
export default DragDropContext(HTML5Backend)(UnpublishedListing);
|