merge master

This commit is contained in:
riley
2017-05-19 11:05:46 -06:00
61 changed files with 1222 additions and 245 deletions
@@ -0,0 +1,53 @@
.button {
-webkit-transform: scale(.8);
transform: scale(.8);
margin: 0;
}
.root {
color: black;
> :global(.mdl-menu__container) {
margin-left: 10px;
> :global(.mdl-menu__outline) {
box-shadow: none;
}
}
}
.buttonOpen {
box-shadow: none;
color: white;
background-color: #616161;
}
.arrowIcon {
margin-left: 6px;
margin-right: 0;
vertical-align: middle;
margin-right: 0;
font-size: 14px;
}
.menu {
padding: 0;
}
.menuItem {
background-color: #2a2a2a;
color: white;
&:first-child {
margin-bottom: 1px;
border-radius: 2px 2px 0px 0px;
}
&:last-child {
border-radius: 0px 0px 2px 2px;
}
&:hover, &:active, &:focus {
background-color: #767676;
}
&[disabled], &[disabled]:hover, &[disabled]:focus, &[disabled]:active {
background-color: #262626;
color: rgba(255, 255, 255, 0.5);
}
}
@@ -0,0 +1,64 @@
import React, {PropTypes} from 'react';
import {Button, Icon} from 'coral-ui';
import {Menu} from 'react-mdl';
import cn from 'classnames';
import {findDOMNode} from 'react-dom';
import styles from './ActionsMenu.css';
import I18n from 'coral-framework/modules/i18n/i18n';
import translations from 'coral-admin/src/translations.json';
const lang = new I18n(translations);
let count = 0;
class ActionsMenu extends React.Component {
id = `actions-dropdown-${count++}`;
menu = null;
state = {open: false};
timeout = null;
componentWillUnmount() {
clearTimeout(this.timeout);
}
handleRef = (ref) => {
this.menu = ref ? findDOMNode(ref).parentNode : null;
}
syncOpenState = () => {
clearTimeout(this.timeout);
this.timeout = setTimeout(() => {
this.setState({open: this.menu.className.indexOf('is-visible') >= 0});
}, 150);
};
render() {
return (
<div className={styles.root} onBlur={this.syncOpenState} >
<Button
cStyle='actions'
className={cn(styles.button, {[styles.buttonOpen]: this.state.open})}
disabled={false}
id={this.id}
onClick={this.syncOpenState}
icon={this.props.icon}
raised>
{lang.t('modqueue.actions')}
<Icon
name={this.state.open ? 'keyboard_arrow_up' : 'keyboard_arrow_down'}
className={styles.arrowIcon}
/>
</Button>
<Menu target={this.id} className={styles.menu} ref={this.handleRef}>
{this.props.children}
</Menu>
</div>
);
}
}
ActionsMenu.propTypes = {
icon: PropTypes.string,
};
export default ActionsMenu;
@@ -0,0 +1,9 @@
import React from 'react';
import cn from 'classnames';
import {MenuItem} from 'react-mdl';
import styles from './ActionsMenu.css';
const ActionsMenuItem = (props) =>
<MenuItem className={cn(styles.menuItem, props.className)} {...props} />;
export default ActionsMenuItem;
+5 -5
View File
@@ -1,16 +1,16 @@
import React from 'react';
import {Provider} from 'react-redux';
import ToastContainer from './ToastContainer';
import 'material-design-lite';
import store from 'services/store';
import AppRouter from '../AppRouter';
export default class App extends React.Component {
render () {
return (
<Provider store={store}>
<AppRouter store={store} />
</Provider>
<div>
<ToastContainer />
<AppRouter />
</div>
);
}
}
@@ -1,11 +0,0 @@
.banButton {
-webkit-transform: scale(.8);
transform: scale(.8);
margin: 0;
i {
vertical-align: middle;
margin-right: 5px;
font-size: 14px;
}
}
@@ -1,26 +0,0 @@
import React, {PropTypes} from 'react';
import {Button, Icon} from 'coral-ui';
import styles from './BanUserButton.css';
import I18n from 'coral-framework/modules/i18n/i18n';
import translations from 'coral-admin/src/translations.json';
const lang = new I18n(translations);
const BanUserButton = ({user, ...props}) => (
<div className={styles.ban}>
<Button cStyle='ban'
className={`ban ${styles.banButton}`}
disabled={user.status === 'BANNED' ? 'disabled' : ''}
onClick={props.onClick}
raised>
<Icon name='not_interested' />
{lang.t('comment.ban_user')}
</Button>
</div>
);
BanUserButton.propTypes = {
onClick: PropTypes.func.isRequired
};
export default BanUserButton;
@@ -1,164 +0,0 @@
.dialog {
border: none;
box-shadow: 0 9px 46px 8px rgba(0, 0, 0, 0.14), 0 11px 15px -7px rgba(0, 0, 0, 0.12), 0 24px 38px 3px rgba(0, 0, 0, 0.2);
width: 500px;
top: 50%;
transform: translateY(-50%);
height: 184px;
padding: 20px;
h2 {
color: black;
font-size: 1.76em;
font-weight: 500;
margin: 0;
}
h3 {
color: black;
font-size: 1.4em;
font-weight: 500;
margin: 0;
}
}
.textField {
margin-top: 15px;
}
.textField label {
font-size: 1.08em;
font-weight: bold;
margin-bottom: 5px;
}
.textField input {
width: 100%;
display: block;
border: none;
outline: none;
border: 1px solid rgba(0,0,0,.12);
padding: 10px 6px;
box-sizing: border-box;
border-radius: 2px;
margin: 5px auto;
}
.footer {
margin: 20px auto 10px;
text-align: center;
}
.footer span {
display: block;
margin-bottom: 5px;
}
.footer a {
color: #2c69b6;
cursor: pointer;
margin: 0 5px;
}
.socialConnections {
margin-bottom: 20px;
}
.signInButton {
margin-top: 10px;
}
.close {
font-size: 20px;
line-height: 14px;
top: 10px;
right: 10px;
position: absolute;
display: block;
font-weight: bold;
color: #363636;
cursor: pointer;
}
.close:hover {
color: #6b6b6b;
}
input.error{
border: solid 2px #f44336;
}
.errorMsg, .hint {
color: grey;
font-weight: 600;
padding: 3px 0 16px;
}
.alert {
padding: 10px;
margin-bottom: 20px;
border-radius: 2px;
}
.alert--success {
border: solid 1px #1ec00e;
background: #cbf1b8;
color: #006900;
}
.alert--error {
background: #FFEBEE;
color: #B71C1C;
}
.userBox a {
color: #2c69b6;
cursor: pointer;
margin: 0px;
}
.attention {
display: inline-block;
width: 15px;
height: 15px;
background: #B71C1C;
color: #FFEBEE;
font-weight: bolder;
padding: 4px;
vertical-align: middle;
border-radius: 20px;
box-sizing: border-box;
font-size: 9px;
line-height: 7px;
text-align: center;
margin-right: 5px;
}
.action {
margin-top: 15px;
}
.passwordRequestSuccess {
border: 1px solid green;
background-color: lightgreen;
padding: 10px;
}
.passwordRequestFailure {
border: 1px solid orange;
background-color: 1px solid coral;
padding: 10px;
}
.cancel {
margin-right: 10px;
width: 47%;
}
.ban {
width: 47%;
}
.buttons {
margin: 20px 0;
}
@@ -1,55 +0,0 @@
import React, {PropTypes} from 'react';
import {Dialog} from 'coral-ui';
import styles from './BanUserDialog.css';
import Button from 'coral-ui/components/Button';
import I18n from 'coral-framework/modules/i18n/i18n';
import translations from '../translations';
const lang = new I18n(translations);
const onBanClick = (userId, commentId, commentStatus, handleBanUser, rejectComment, handleClose) => (e) => {
e.preventDefault();
handleBanUser({userId})
.then(handleClose)
.then(() => commentStatus === 'REJECTED' ? null : rejectComment({commentId}));
};
const BanUserDialog = ({open, handleClose, handleBanUser, rejectComment, user, commentId, commentStatus, showRejectedNote}) => (
<Dialog
className={styles.dialog}
id="banuserDialog"
open={open}
onClose={handleClose}
onCancel={handleClose}
title={lang.t('bandialog.ban_user')}>
<span className={styles.close} onClick={handleClose}>×</span>
<div>
<div className={styles.header}>
<h2>{lang.t('bandialog.ban_user')}</h2>
</div>
<div className={styles.separator}>
<h3>{lang.t('bandialog.are_you_sure', user.name)}</h3>
<i>{showRejectedNote && lang.t('bandialog.note')}</i>
</div>
<div className={styles.buttons}>
<Button cStyle="cancel" className={styles.cancel} onClick={handleClose} raised>
{lang.t('bandialog.cancel')}
</Button>
<Button cStyle="black" className={styles.ban} onClick={onBanClick(user.id, commentId, commentStatus, handleBanUser, rejectComment, handleClose)} raised>
{lang.t('bandialog.yes_ban_user')}
</Button>
</div>
</div>
</Dialog>
);
BanUserDialog.propTypes = {
handleBanUser: PropTypes.func.isRequired,
handleClose: PropTypes.func.isRequired,
rejectComment: PropTypes.func.isRequired,
commentId: PropTypes.string,
user: PropTypes.object.isRequired,
};
export default BanUserDialog;
@@ -0,0 +1,226 @@
@keyframes :global(bounceInRight) {
from, 60%, 75%, 90%, to {
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); }
from {
opacity: 0;
transform: translate3d(3000px, 0, 0); }
60% {
opacity: 1;
transform: translate3d(-25px, 0, 0); }
75% {
transform: translate3d(10px, 0, 0); }
90% {
transform: translate3d(-5px, 0, 0); }
to {
transform: none; } }
@keyframes :global(bounceOutRight) {
20% {
opacity: 1;
transform: translate3d(-20px, 0, 0); }
to {
opacity: 0;
transform: translate3d(2000px, 0, 0); } }
@keyframes :global(bounceInLeft) {
from, 60%, 75%, 90%, to {
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); }
0% {
opacity: 0;
transform: translate3d(-3000px, 0, 0); }
60% {
opacity: 1;
transform: translate3d(25px, 0, 0); }
75% {
transform: translate3d(-10px, 0, 0); }
90% {
transform: translate3d(5px, 0, 0); }
to {
transform: none; } }
@keyframes :global(bounceOutLeft) {
20% {
opacity: 1;
transform: translate3d(20px, 0, 0); }
to {
opacity: 0;
transform: translate3d(-2000px, 0, 0); } }
@keyframes :global(bounceInUp) {
from, 60%, 75%, 90%, to {
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); }
from {
opacity: 0;
transform: translate3d(0, 3000px, 0); }
60% {
opacity: 1;
transform: translate3d(0, -20px, 0); }
75% {
transform: translate3d(0, 10px, 0); }
90% {
transform: translate3d(0, -5px, 0); }
to {
transform: translate3d(0, 0, 0); } }
@keyframes :global(bounceOutUp) {
20% {
transform: translate3d(0, -10px, 0); }
40%, 45% {
opacity: 1;
transform: translate3d(0, 20px, 0); }
to {
opacity: 0;
transform: translate3d(0, -2000px, 0); } }
@keyframes :global(bounceInDown) {
from, 60%, 75%, 90%, to {
animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); }
0% {
opacity: 0;
transform: translate3d(0, -3000px, 0); }
60% {
opacity: 1;
transform: translate3d(0, 25px, 0); }
75% {
transform: translate3d(0, -10px, 0); }
90% {
transform: translate3d(0, 5px, 0); }
to {
transform: none; } }
@keyframes :global(bounceOutDown) {
20% {
transform: translate3d(0, 10px, 0); }
40%, 45% {
opacity: 1;
transform: translate3d(0, -20px, 0); }
to {
opacity: 0;
transform: translate3d(0, 2000px, 0); } }
@keyframes :global(track-progress) {
0% {
width: 100%; }
100% {
width: 0; } }
:global {
.bounceOutRight, .toast-exit--top-right, .toast-exit--bottom-right {
animation-name: bounceOutRight; }
.bounceInRight, .toast-enter--top-right, .toast-enter--bottom-right {
animation-name: bounceInRight; }
.bounceInLeft, .toast-enter--top-left, .toast-enter--bottom-left {
animation-name: bounceInLeft; }
.bounceOutLeft, .toast-exit--top-left, .toast-exit--bottom-left {
animation-name: bounceOutLeft; }
.bounceInUp, .toast-enter--bottom-center {
animation-name: bounceInUp; }
.bounceOutUp, .toast-exit--top-center {
animation-name: bounceOutUp; }
.bounceInDown, .toast-enter--top-center {
animation-name: bounceInDown; }
.bounceOutDown, .toast-exit--bottom-center {
animation-name: bounceOutDown; }
.animated {
animation-duration: 0.75s;
animation-fill-mode: both; }
.toastify {
z-index: 999;
position: fixed;
padding: 4px;
width: 350px;
max-width: 98%;
color: #999;
box-sizing: border-box; }
.toastify--top-left {
top: 1em;
left: 1em; }
.toastify--top-center {
top: 1em;
left: 50%;
margin-left: -175px; }
.toastify--top-right {
top: 1em;
right: 2em; }
.toastify--bottom-left {
bottom: 1em;
left: 1em; }
.toastify--bottom-center {
bottom: 1em;
left: 50%;
margin-left: -175px; }
.toastify--bottom-right {
bottom: 1em;
right: 2em; }
.toastify__img {
float: left;
margin-right: 8px;
vertical-align: middle; }
.toastify__close {
position: absolute;
top: 18px;
left: 12px;
width: 20px;
height: 16px;
padding: 0;
text-align: center;
text-decoration: none;
color: white;
font-weight: bold;
font-size: 14px;
background: transparent;
outline: none;
border: none;
cursor: pointer;
opacity: 0.8;
transition: .3s ease; }
.toastify__close:hover, .toastify__close:focus {
opacity: 1;
}
.toastify-content {
position: relative;
width: 100%;
margin-bottom: 12px;
padding: 18px 24px 20px 48px;
box-sizing: border-box;
background: #404040;
border-radius: 2px;
box-shadow: 0 2px 15px 0 rgba(0, 0, 0, 0.1), 0 3px 20px 0 rgba(0, 0, 0, 0.05); }
.toastify-content--info {
background: #2488cb; }
.toastify-content--success {
background: #008577; }
.toastify-content--warning {
background: #ef6c2b; }
.toastify-content--error {
background: #ef342b; }
.toastify__body {
color: white;
font-size: 15px;
font-weight: 400;
}
.toastify__progress {
position: absolute;
bottom: 0;
left: 0;
width: 0;
height: 4px;
z-index: 999;
opacity: 0.8;
border-radius: 2px;
animation: track-progress linear 1;
background-color: white;
}
}
@@ -0,0 +1,7 @@
import './ToastContainer.css';
import {defaultProps} from 'recompose';
import {ToastContainer} from 'react-toastify';
export default defaultProps({
autoClose: 5000,
})(ToastContainer);