mirror of
https://github.com/wassname/talk.git
synced 2026-08-06 13:41:02 +08:00
Merge branch 'master' into optional-google-fonts
This commit is contained in:
@@ -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'));
|
||||
|
||||
@@ -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}
|
||||
/>;
|
||||
})
|
||||
}
|
||||
{
|
||||
|
||||
@@ -313,5 +313,5 @@ export default compose(
|
||||
addCommentTag,
|
||||
removeCommentTag,
|
||||
deleteAction,
|
||||
queryStream
|
||||
queryStream,
|
||||
)(Embed);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)));
|
||||
};
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
import * as authActions from './auth';
|
||||
import * as assetActions from './asset';
|
||||
import * as notificationActions from './notification';
|
||||
|
||||
export default {
|
||||
authActions,
|
||||
assetActions,
|
||||
notificationActions,
|
||||
};
|
||||
@@ -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;
|
||||
@@ -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}));
|
||||
}
|
||||
@@ -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(',')}
|
||||
];
|
||||
`;
|
||||
};
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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];
|
||||
Reference in New Issue
Block a user