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:
@ -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';
|
||||
|
115
src/components/UI/loader/Loader.css
Normal file
115
src/components/UI/loader/Loader.css
Normal 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;
|
||||
}
|
68
src/components/UI/loader/Loader.js
Normal file
68
src/components/UI/loader/Loader.js
Normal 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>;
|
||||
|
||||
}
|
||||
}
|
29
src/components/UnpublishedListing.css
Normal file
29
src/components/UnpublishedListing.css
Normal 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;
|
||||
}
|
||||
}
|
50
src/components/UnpublishedListing.js
Normal file
50
src/components/UnpublishedListing.js
Normal 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,
|
||||
};
|
Reference in New Issue
Block a user