Merge branch 'master' into i18n-refactor

This commit is contained in:
gaba
2017-05-15 14:02:34 -07:00
251 changed files with 4984 additions and 1874 deletions
@@ -15,6 +15,6 @@ module.exports = (router) => {
router.get('/api/v1/auth/facebook/callback', (req, res, next) => {
// Perform the facebook login flow and pass the data back through the opener.
passport.authenticate('facebook', HandleAuthPopupCallback(req, res, next))(req, res, next);
passport.authenticate('facebook', {session: false}, HandleAuthPopupCallback(req, res, next))(req, res, next);
});
};
+14
View File
@@ -0,0 +1,14 @@
{
"presets": [
"es2015"
],
"plugins": [
"add-module-exports",
"transform-class-properties",
"transform-decorators-legacy",
"transform-object-assign",
"transform-object-rest-spread",
"transform-async-to-generator",
"transform-react-jsx"
]
}
@@ -0,0 +1,23 @@
{
"env": {
"browser": true,
"es6": true,
"mocha": true
},
"parserOptions": {
"sourceType": "module",
"ecmaFeatures": {
"experimentalObjectRestSpread": true,
"jsx": true
}
},
"parser": "babel-eslint",
"plugins": [
"react"
],
"rules": {
"react/jsx-uses-react": "error",
"react/jsx-uses-vars": "error",
"no-console": ["warn", { "allow": ["warn", "error"] }]
}
}
@@ -0,0 +1,52 @@
import React from 'react';
import {Icon} from 'coral-ui';
import styles from './styles.css';
import {I18n} from 'coral-framework';
import translations from './translations.json';
import {withReaction} from 'coral-plugin-api';
const lang = new I18n(translations);
class LoveButton extends React.Component {
handleClick = () => {
const {
postReaction,
deleteReaction,
showSignInDialog,
alreadyReacted
} = this.props;
const {root: {me}, comment} = this.props;
// If the current user does not exist, trigger sign in dialog.
if (!me) {
showSignInDialog();
return;
}
// If the current user is banned, do nothing.
if (me.status === 'BANNED') {
return;
}
if (alreadyReacted()) {
deleteReaction();
} else {
postReaction();
}
};
render() {
const {count, alreadyReacted} = this.props;
return (
<button
className={`${styles.button} ${alreadyReacted() ? styles.loved : ''}`}
onClick={this.handleClick}
>
<span>{lang.t(alreadyReacted() ? 'loved' : 'love')}</span>
<Icon name="favorite" />
<span>{count > 0 && count}</span>
</button>
);
}
}
export default withReaction('love')(LoveButton);
@@ -0,0 +1,20 @@
import React from 'react';
import styles from './style.css';
import cn from 'classnames';
export default class LoveIcon extends React.Component {
render() {
const {me} = this.props.data;
let love = me && me.roles && me.roles[0] === 'ADMIN';
return (
<div className={styles.love}>
<button
className={cn(styles.button, {[styles.love]: love})} >
<i className={cn('love')} aria-hidden="true"/>
</button>
</div>
);
}
}
@@ -0,0 +1,30 @@
.love {
display: inline-block;
}
.button {
color: #2a2a2a;
margin: 5px 10px 5px 0px;
background: none;
padding: 0px;
border: none;
font-size: inherit;
&:hover {
color: #767676;
cursor: pointer;
}
&.love {
color: #c98211;
&:hover {
color: #e59614;
cursor: pointer;
}
}
}
.icon {
padding: 0 5px;
}
@@ -0,0 +1,19 @@
import {compose, gql, graphql} from 'react-apollo';
import LoveIcon from '../components/LoveIcon';
export const LOVE_QUERY = gql`
query LoveQuery {
me {
status
roles
}
}
`;
const withQuery = graphql(LOVE_QUERY);
const enhance = compose(
withQuery,
);
export default enhance(LoveIcon);
@@ -0,0 +1,7 @@
import LoveButton from './LoveButton';
export default {
slots: {
commentReactions: [LoveButton]
}
};
@@ -0,0 +1,26 @@
.respect {
display: inline-block;
}
.button {
color: #2a2a2a;
margin: 5px 10px 5px 0px;
background: none;
padding: 0px;
border: none;
font-size: inherit;
&:hover {
color: #767676;
cursor: pointer;
}
&.loved {
color: #e52338;
&:hover {
color: #e52839;
cursor: pointer;
}
}
}
@@ -0,0 +1,10 @@
{
"en": {
"love": "Love",
"loved": "Loved"
},
"es": {
"love": "Amo",
"loved": "Amé"
}
}
+37
View File
@@ -0,0 +1,37 @@
const {readFileSync} = require('fs');
const path = require('path');
const wrapResponse = require('../../graph/helpers/response');
module.exports = {
typeDefs: readFileSync(path.join(__dirname, 'server/typeDefs.graphql'), 'utf8'),
resolvers: {
RootMutation: {
createLove(_, {love: {item_id, item_type}}, {mutators: {Action}}) {
return wrapResponse('love')(Action.create({item_id, item_type, action_type: 'LOVE'}));
}
}
},
hooks: {
Action: {
__resolveType: {
post({action_type}) {
switch (action_type) {
case 'LOVE':
return 'LoveAction';
}
}
}
},
ActionSummary: {
__resolveType: {
post({action_type}) {
switch (action_type) {
case 'LOVE':
return 'LoveActionSummary';
}
}
}
}
}
};
@@ -0,0 +1,70 @@
enum ACTION_TYPE {
# Represents a Love.
LOVE
}
enum ASSET_METRICS_SORT {
# Represents a LoveAction.
LOVE
}
input CreateLoveInput {
# The item's id for which we are to create a love.
item_id: ID!
# The type of the item for which we are to create the love.
item_type: ACTION_ITEM_TYPE!
}
# LoveAction is used by users who "love" a specific entity.
type LoveAction implements Action {
# The ID of the action.
id: ID!
# The author of the action.
user: User
# The time when the Action was updated.
updated_at: Date
# The time when the Action was created.
created_at: Date
}
type LoveActionSummary implements ActionSummary {
# The count of actions with this group.
count: Int
# The current user's action.
current_user: LoveAction
}
# A summary of counts related to all the Loves on an Asset.
type LoveAssetActionSummary implements AssetActionSummary {
# Number of loves associated with actionable types on this this Asset.
actionCount: Int
# Number of unique actionable types that are referenced by the loves.
actionableItemCount: Int
}
type CreateLoveResponse implements Response {
# The love that was created.
love: LoveAction
# An array of errors relating to the mutation that occurred.
errors: [UserError]
}
type RootMutation {
# Creates a love on an entity.
createLove(love: CreateLoveInput!): CreateLoveResponse
}
+14
View File
@@ -0,0 +1,14 @@
{
"presets": [
"es2015"
],
"plugins": [
"add-module-exports",
"transform-class-properties",
"transform-decorators-legacy",
"transform-object-assign",
"transform-object-rest-spread",
"transform-async-to-generator",
"transform-react-jsx"
]
}
@@ -0,0 +1,23 @@
{
"env": {
"browser": true,
"es6": true,
"mocha": true
},
"parserOptions": {
"sourceType": "module",
"ecmaFeatures": {
"experimentalObjectRestSpread": true,
"jsx": true
}
},
"parser": "babel-eslint",
"plugins": [
"react"
],
"rules": {
"react/jsx-uses-react": "error",
"react/jsx-uses-vars": "error",
"no-console": ["warn", { "allow": ["warn", "error"] }]
}
}
@@ -0,0 +1,8 @@
import React from 'react';
import styles from './styles.css'
export default (props) => (
<div className={styles.box}>
Comment Status: {props.comment.status}
</div>
)
@@ -0,0 +1,32 @@
import React from 'react';
import Box from './Box';
import {Button} from 'coral-ui'
import styles from './styles.css';
export default class Footer extends React.Component {
constructor() {
super();
this.state = {
show: false
};
}
handleClick = () => {
this.setState(state => ({
show: !state.show
}))
}
render() {
const {show} = this.state;
return (
<div className={styles.container}>
<Button cStyle="darkGrey" onClick={this.handleClick}>
Show Comment Status
</Button>
{show ? <Box comment={this.props.comment} /> : null}
</div>
);
}
}
@@ -0,0 +1,8 @@
.container {
padding: 0 14px 10px;
}
.box {
font-size: 12px;
padding: 10px 14px;
}
+7
View File
@@ -0,0 +1,7 @@
import Container from './components/Container';
export default {
slots: {
adminCommentDetailArea: [Container],
}
};
+4
View File
@@ -0,0 +1,4 @@
const {readFileSync} = require('fs');
const path = require('path');
module.exports = {};
@@ -1,15 +1,15 @@
import {compose, gql, graphql} from 'react-apollo';
import {compose, gql} from 'react-apollo';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import get from 'lodash/get';
import withFragments from 'coral-framework/hocs/withFragments';
import {withFragments, withMutation} from 'coral-framework/hocs';
import {showSignInDialog} from 'coral-framework/actions/auth';
import RespectButton from '../components/RespectButton';
const isRespectAction = (a) => a.__typename === 'RespectActionSummary';
const COMMENT_FRAGMENT = gql`
fragment RespectButton_updateFragment on Comment {
fragment CoralRespect_UpdateFragment on Comment {
action_summaries {
... on RespectActionSummary {
count
@@ -21,8 +21,8 @@ const COMMENT_FRAGMENT = gql`
}
`;
const withDeleteAction = graphql(gql`
mutation deleteAction($id: ID!) {
const withDeleteAction = withMutation(gql`
mutation CoralRespect_DeleteAction($id: ID!) {
deleteAction(id:$id) {
errors {
translation_key
@@ -66,8 +66,8 @@ const withDeleteAction = graphql(gql`
}),
});
const withPostRespect = graphql(gql`
mutation createRespect($respect: CreateRespectInput!) {
const withPostRespect = withMutation(gql`
mutation CoralRespect_CreateRespect($respect: CreateRespectInput!) {
createRespect(respect: $respect) {
respect {
id
@@ -131,20 +131,20 @@ const withPostRespect = graphql(gql`
}),
});
const mapDispatchToProps = dispatch =>
const mapDispatchToProps = (dispatch) =>
bindActionCreators({showSignInDialog}, dispatch);
const enhance = compose(
withFragments({
root: gql`
fragment RespectButton_root on RootQuery {
fragment CoralRespect_RespectButton_root on RootQuery {
me {
status
}
}
`,
comment: gql`
fragment RespectButton_comment on Comment {
fragment CoralRespect_RespectButton_comment on Comment {
action_summaries {
... on RespectActionSummary {
count