Merge remote-tracking branch 'origin/react-pr' into react-ui-updates

Replaced dateFormat with moment

Conflicts:
	package.json
	src/backends/netlify-git/API.js
	src/containers/CollectionPage.js
	src/formats/formats.js
This commit is contained in:
Mathias Biilmann Christensen
2016-09-12 15:35:56 +02:00
24 changed files with 617 additions and 58 deletions

View File

@ -1,2 +1,3 @@
export { default as Card } from './card/Card';
export { default as Loader } from './loader/Loader';
export { default as Icon } from './icon/Icon';

View File

@ -0,0 +1,115 @@
.loader {
display: none;
position: absolute;
top: 50%;
left: 50%;
margin: 0px;
text-align: center;
z-index: 1000;
-webkit-transform: translateX(-50%) translateY(-50%);
-ms-transform: translateX(-50%) translateY(-50%);
transform: translateX(-50%) translateY(-50%);
}
/* Static Shape */
.loader:before {
position: absolute;
content: '';
top: 0%;
left: 50%;
width: 100%;
height: 100%;
border-radius: 500rem;
border: 0.2em solid rgba(0, 0, 0, 0.1);
}
/* Active Shape */
.loader:after {
position: absolute;
content: '';
top: 0%;
left: 50%;
width: 100%;
height: 100%;
animation: loader 0.6s linear;
animation-iteration-count: infinite;
border-radius: 500rem;
border-color: #767676 transparent transparent;
border-style: solid;
border-width: 0.2em;
box-shadow: 0px 0px 0px 1px transparent;
}
/* Active Animation */
@-webkit-keyframes loader {
from {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes loader {
from {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.loader:before,
.loader:after {
width: 2.28571429rem;
height: 2.28571429rem;
margin: 0em 0em 0em -1.14285714rem;
}
.text {
width: auto !important;
height: auto !important;
text-align: center;
color: #767676;
margin-top: 35px;
}
.active {
display: block;
}
.disabled {
display: none;
}
/*Animations*/
.animateItem{
position: absolute;
white-space: nowrap;
transform: translateX(-50%);
}
.enter {
opacity: 0.01;
}
.enter.enterActive {
opacity: 1;
transition: opacity 500ms ease-in;
}
.leave {
opacity: 1;
}
.leave.leaveActive {
opacity: 0.01;
transition: opacity 300ms ease-in;
}

View File

@ -0,0 +1,68 @@
import React from 'react';
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
import styles from './Loader.css';
export default class Loader extends React.Component {
constructor(props) {
super(props);
this.state = {
currentItem: 0,
};
this.setAnimation = this.setAnimation.bind(this);
this.renderChild = this.renderChild.bind(this);
}
componentWillUnmount() {
if (this.interval) {
clearInterval(this.interval);
}
}
setAnimation() {
if (this.interval) return;
const { children } = this.props;
this.interval = setInterval(() => {
const nextItem = (this.state.currentItem === children.length - 1) ? 0 : this.state.currentItem + 1;
this.setState({ currentItem: nextItem });
}, 5000);
}
renderChild() {
const { children } = this.props;
const { currentItem } = this.state;
if (!children) {
return null;
} else if (typeof children == 'string') {
return <div className={styles.text}>{children}</div>;
} else if (Array.isArray(children)) {
this.setAnimation();
return <div className={styles.text}>
<ReactCSSTransitionGroup
transitionName={styles}
transitionEnterTimeout={500}
transitionLeaveTimeout={500}
>
<div key={currentItem} className={styles.animateItem}>{children[currentItem]}</div>
</ReactCSSTransitionGroup>
</div>;
}
}
render() {
const { active, style, className = '' } = this.props;
// Class names
let classNames = styles.loader;
if (active) {
classNames += ` ${styles.active}`;
}
if (className.length > 0) {
classNames += ` ${className}`;
}
return <div className={classNames} style={style}>{this.renderChild()}</div>;
}
}

View File

@ -0,0 +1,29 @@
.column {
position: relative;
display: inline-block;
vertical-align: top;
text-align: center;
width: 28%;
}
.column:not(:last-child) {
margin-right: 8%;
}
.card {
width: 100% !important;
margin: 7px 0;
& h1 {
font-size: 17px;
& small {
font-weight: normal;
}
}
& p {
color: #555;
font-size: 12px;
margin-top: 5px;
}
}

View File

@ -0,0 +1,50 @@
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';
import moment from 'moment';
import { Card } from './UI';
import { statusDescriptions } from '../constants/publishModes';
import styles from './UnpublishedListing.css';
export default class UnpublishedListing extends React.Component {
renderColumns(entries, column) {
if (!entries) return;
if (!column) {
return entries.entrySeq().map(([currColumn, currEntries]) => (
<div key={currColumn} className={styles.column}>
<h3>{statusDescriptions.get(currColumn)}</h3>
{this.renderColumns(currEntries, currColumn)}
</div>
));
} else {
return <div>
{entries.map(entry => {
// Look for an "author" field. Fallback to username on backend implementation;
const author = entry.getIn(['data', 'author'], entry.getIn(['metaData', 'user']));
const timeStamp = moment(entry.getIn(['metaData', 'timeStamp'])).formate('llll');
return (
<Card key={entry.get('slug')} className={styles.card}>
<h1>{entry.getIn(['data', 'title'])} <small>by {author}</small></h1>
<p>Last updated: {timeStamp} by {entry.getIn(['metaData', 'user'])}</p>
</Card>
);
}
)}
</div>;
}
}
render() {
const columns = this.renderColumns(this.props.entries);
return (
<div>
{columns}
</div>
);
}
}
UnpublishedListing.propTypes = {
entries: ImmutablePropTypes.orderedMap,
};