Merge branch 'master' into optional-google-fonts

This commit is contained in:
Riley Davis
2017-04-07 10:42:20 -06:00
61 changed files with 974 additions and 151 deletions
+2 -2
View File
@@ -1,8 +1,8 @@
import React from 'react';
import ReactDOM from 'react-dom';
import {render} from 'react-dom';
import {GraphQLDocs} from 'graphql-docs';
import fetcher from './services/fetcher';
// Render the application into the DOM
ReactDOM.render(<GraphQLDocs fetcher={fetcher} />, document.querySelector('#root'));
render(<GraphQLDocs fetcher={fetcher} />, document.querySelector('#root'));
+5 -1
View File
@@ -19,6 +19,7 @@ import FlagComment from 'coral-plugin-flags/FlagComment';
import LikeButton from 'coral-plugin-likes/LikeButton';
import {BestButton, IfUserCanModifyBest, BEST_TAG, commentIsBest, BestIndicator} from 'coral-plugin-best/BestButton';
import LoadMore from 'coral-embed-stream/src/LoadMore';
import {Slot} from 'coral-framework';
import styles from './Comment.css';
@@ -157,6 +158,7 @@ class Comment extends React.Component {
? <TagLabel><BestIndicator /></TagLabel>
: null }
<PubDate created_at={comment.created_at} />
<Slot fill="commentInfoBar" commentId={comment.id} />
<Content body={comment.body} />
<div className="commentActionsLeft comment__action-container">
@@ -187,6 +189,7 @@ class Comment extends React.Component {
removeBest={removeBestTag} />
</IfUserCanModifyBest>
</ActionButton>
<Slot fill="commentDetail" commentId={comment.id} />
</div>
<div className="commentActionsRight comment__action-container">
<ActionButton>
@@ -241,7 +244,8 @@ class Comment extends React.Component {
showSignInDialog={showSignInDialog}
reactKey={reply.id}
key={reply.id}
comment={reply} />;
comment={reply}
/>;
})
}
{
+1 -1
View File
@@ -313,5 +313,5 @@ export default compose(
addCommentTag,
removeCommentTag,
deleteAction,
queryStream
queryStream,
)(Embed);
+5 -2
View File
@@ -41,7 +41,8 @@ class Stream extends React.Component {
deleteAction,
showSignInDialog,
addCommentTag,
removeCommentTag
removeCommentTag,
pluginProps
} = this.props;
return (
@@ -67,7 +68,9 @@ class Stream extends React.Component {
showSignInDialog={showSignInDialog}
key={comment.id}
reactKey={comment.id}
comment={comment} />
comment={comment}
pluginProps={pluginProps}
/>
)
}
</div>
+2 -2
View File
@@ -255,13 +255,13 @@ hr {
.commentActionsRight, .replyActionsRight {
display: flex;
justify-content: flex-end;
width: 50%;
width: 30%;
}
.commentActionsLeft, .replyActionsLeft {
display: flex;
justify-content: flex-start;
float: left;
width: 50%;
width: 70%;
}
.comment__action-container .material-icons {
+1 -1
View File
@@ -3,7 +3,7 @@ import coralApi from '../helpers/response';
import {addNotification} from '../actions/notification';
import {pym} from 'coral-framework';
import I18n from '../../coral-framework/modules/i18n/i18n';
import I18n from 'coral-framework/modules/i18n/i18n';
import translations from './../translations';
const lang = new I18n(translations);
+22 -1
View File
@@ -1,3 +1,5 @@
import {gql} from 'react-apollo';
import client from 'coral-framework/services/client';
import I18n from '../../coral-framework/modules/i18n/i18n';
import translations from './../translations';
const lang = new I18n(translations);
@@ -5,6 +7,20 @@ import * as actions from '../constants/auth';
import coralApi, {base} from '../helpers/response';
import {pym} from 'coral-framework';
const ME_QUERY = gql`
query Me {
me {
status
}
}
`;
function fetchMe() {
return client.query({
fetchPolicy: 'network-only',
query: ME_QUERY});
}
// Dialog Actions
export const showSignInDialog = (offset = 0) => ({type: actions.SHOW_SIGNIN_DIALOG, offset});
export const hideSignInDialog = () => ({type: actions.HIDE_SIGNIN_DIALOG});
@@ -52,6 +68,7 @@ export const fetchSignIn = (formData) => (dispatch) => {
const isAdmin = !!user && !!user.roles.filter(i => i === 'ADMIN').length;
dispatch(signInSuccess(user, isAdmin));
dispatch(hideSignInDialog());
fetchMe();
})
.catch(error => {
if (error.metadata) {
@@ -104,6 +121,7 @@ export const facebookCallback = (err, data) => dispatch => {
dispatch(signInFacebookSuccess(user));
dispatch(hideSignInDialog());
dispatch(showCreateUsernameDialog());
fetchMe();
} catch (err) {
dispatch(signInFacebookFailure(err));
return;
@@ -151,7 +169,10 @@ const logOutFailure = () => ({type: actions.LOGOUT_FAILURE});
export const logout = () => dispatch => {
dispatch(logOutRequest());
return coralApi('/auth', {method: 'DELETE'})
.then(() => dispatch(logOutSuccess()))
.then(() => {
dispatch(logOutSuccess());
fetchMe();
})
.catch(error => dispatch(logOutFailure(error)));
};
+9
View File
@@ -0,0 +1,9 @@
import * as authActions from './auth';
import * as assetActions from './asset';
import * as notificationActions from './notification';
export default {
authActions,
assetActions,
notificationActions,
};
+19
View File
@@ -0,0 +1,19 @@
import React, {Component} from 'react';
import {getSlotElements} from 'coral-framework/helpers/plugins';
class Slot extends Component {
render() {
const {fill, ...rest} = this.props;
return (
<div>
{getSlotElements(fill, rest)}
</div>
);
}
}
Slot.propTypes = {
fill: React.PropTypes.string
};
export default Slot;
+21
View File
@@ -0,0 +1,21 @@
import React from 'react';
import merge from 'lodash/merge';
import flatten from 'lodash/flatten';
import plugins from 'pluginsConfig';
export const pluginReducers = merge(
...plugins
.filter(o => o.module.reducer)
.map(o => ({...o.module.reducer}))
);
/**
* Returns React Elements for given slot.
*/
export function getSlotElements(slot, props = {}) {
const components = flatten(plugins
.filter(o => o.module.slots[slot])
.map(o => o.module.slots[slot]));
return components
.map((component, i) => React.createElement(component, {...props, key: i}));
}
+8 -7
View File
@@ -1,15 +1,16 @@
import store from './services/store';
import pym from './services/PymConnection';
import I18n from './modules/i18n/i18n';
import * as authActions from './actions/auth';
import * as assetActions from './actions/asset';
import * as notificationActions from './actions/notification';
import actions from './actions';
import Slot from './components/Slot';
export {
// TODO (bc): Deprecate old actions. Spreading actions is now needed.
export default {
pym,
Slot,
I18n,
store,
authActions,
assetActions,
notificationActions
actions,
...actions
};
@@ -0,0 +1,33 @@
/**
* Executes `source` to retrieve plugins configuration
* and loads the `index.js` of specified plugins.
*
* Outputs a module that looks like the following:
*
* module.exports = [{plugin: string, module: object}, ...]
*
*/
const {stripIndent} = require('common-tags');
function getPluginList(config) {
if (config && config.client) {
return config.client.map(x => typeof x === 'string' ? x : Object.keys(x)[0]);
}
return [];
}
module.exports = function(source) {
this.cacheable();
const config = this.exec(source, this.resourcePath);
const plugins = getPluginList(config).map((plugin) => `{
module: require('${plugin}/client'),
plugin: '${plugin}'
}`);
return stripIndent`
module.exports = [
${plugins.join(',')}
];
`;
};
+2
View File
@@ -1,9 +1,11 @@
import auth from './auth';
import user from './user';
import asset from './asset';
import {pluginReducers} from '../helpers/plugins';
export default {
auth,
user,
asset,
...pluginReducers
};
+3 -1
View File
@@ -6,9 +6,11 @@ export const client = new ApolloClient({
queryTransformer: addTypename,
dataIdFromObject: (result) => {
if (result.id && result.__typename) { // eslint-disable-line no-underscore-dangle
return result.__typename + result.id; // eslint-disable-line no-underscore-dangle
return `${result.__typename}_${result.id}`; // eslint-disable-line no-underscore-dangle
}
return null;
},
networkInterface: getNetworkInterface()
});
export default client;
+7
View File
@@ -0,0 +1,7 @@
/**
* getActionSummary
* retrieves the action summary based on the type and the comment
*/
export const getActionSummary = (type, comment) =>
comment.action_summaries.filter(a => a.__typename === type)[0];