Files
talk/client/coral-embed-stream/src/containers/Embed.js
T
2018-02-26 22:38:43 +01:00

331 lines
7.9 KiB
JavaScript

import React from 'react';
import { compose, gql } from 'react-apollo';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import get from 'lodash/get';
import branch from 'recompose/branch';
import renderComponent from 'recompose/renderComponent';
import { Spinner } from 'coral-ui';
import {
focusSignInDialog,
blurSignInDialog,
hideSignInDialog,
} from '../actions/login';
import { updateStatus } from 'coral-framework/actions/auth';
import {
getDefinitionName,
getSlotFragmentSpreads,
} from 'coral-framework/utils';
import { withQuery, withPopupAuthHandler } from 'coral-framework/hocs';
import Embed from '../components/Embed';
import Stream from '../tabs/stream/containers/Stream';
import AutomaticAssetClosure from './AutomaticAssetClosure';
import Configure from '../tabs/configure/containers/Configure';
import { notify } from 'coral-framework/actions/notification';
import t from 'coral-framework/services/i18n';
import PropTypes from 'prop-types';
import { setActiveTab } from '../actions/embed';
class EmbedContainer extends React.Component {
static contextTypes = {
pym: PropTypes.object,
};
subscriptions = [];
subscribeToUpdates(props = this.props) {
if (props.currentUser) {
const newSubscriptions = [
{
document: USER_BANNED_SUBSCRIPTION,
updateQuery: (
_,
{ subscriptionData: { data: { userBanned: { state } } } }
) => {
notify('info', t('your_account_has_been_banned'));
props.updateStatus(state.status);
},
},
{
document: USER_SUSPENDED_SUBSCRIPTION,
updateQuery: (
_,
{ subscriptionData: { data: { userSuspended: { state } } } }
) => {
notify('info', t('your_account_has_been_suspended'));
props.updateStatus(state.status);
},
},
{
document: USERNAME_REJECTED_SUBSCRIPTION,
updateQuery: (
_,
{ subscriptionData: { data: { usernameRejected: { state } } } }
) => {
notify('info', t('your_username_has_been_rejected'));
props.updateStatus(state.status);
},
},
];
this.subscriptions = newSubscriptions.map(s =>
props.data.subscribeToMore({
document: s.document,
variables: {
user_id: props.currentUser.id,
},
updateQuery: s.updateQuery,
})
);
}
}
unsubscribe() {
this.subscriptions.forEach(unsubscribe => unsubscribe());
this.subscriptions = [];
}
resubscribe(props) {
this.unsubscribe();
this.subscribeToUpdates(props);
}
componentDidMount() {
this.subscribeToUpdates();
}
componentWillUnmount() {
this.unsubscribe();
}
componentWillReceiveProps(nextProps) {
if (this.props.currentUser !== nextProps.currentUser) {
// Refetch after login/logout.
this.props.data.refetch();
this.resubscribe(nextProps);
}
}
componentDidUpdate(prevProps) {
if (
!get(prevProps, 'root.asset.comment') &&
get(this.props, 'root.asset.comment')
) {
// Scroll to a permalinked comment if one is in the URL once the page is done rendering.
setTimeout(
() =>
this.context.pym.scrollParentToChildEl('talk-embed-stream-container'),
0
);
}
}
render() {
if (!this.props.root.asset) {
return <Spinner />;
}
return (
<Embed
setActiveTab={this.props.setActiveTab}
currentUser={this.props.currentUser}
blurSignInDialog={this.props.blurSignInDialog}
focusSignInDialog={this.props.focusSignInDialog}
hideSignInDialog={this.props.hideSignInDialog}
router={this.props.router}
commentId={this.props.commentId}
root={this.props.root}
activeTab={this.props.activeTab}
data={this.props.data}
showSignInDialog={this.props.showSignInDialog}
signInDialogFocus={this.props.signInDialogFocus}
parentUrl={this.props.parentUrl}
/>
);
}
}
const USER_BANNED_SUBSCRIPTION = gql`
subscription UserBanned($user_id: ID!) {
userBanned(user_id: $user_id) {
id
state {
status {
username {
status
}
banned {
status
}
suspension {
until
}
}
}
}
}
`;
const USER_SUSPENDED_SUBSCRIPTION = gql`
subscription UserSuspended($user_id: ID!) {
userSuspended(user_id: $user_id) {
id
state {
status {
username {
status
}
banned {
status
}
suspension {
until
}
}
}
}
}
`;
const USERNAME_REJECTED_SUBSCRIPTION = gql`
subscription UsernameRejected($user_id: ID!) {
usernameRejected(user_id: $user_id) {
id
state {
status {
username {
status
}
banned {
status
}
suspension {
until
}
}
}
}
}
`;
const slots = [
'embed',
'embedStreamTabs',
'embedStreamTabsPrepend',
'embedStreamTabPanes',
];
const EMBED_QUERY = gql`
query CoralEmbedStream_Embed(
$assetId: ID,
$assetUrl: String,
$commentId: ID!,
$hasComment: Boolean!,
$excludeIgnored: Boolean,
$sortBy: SORT_COMMENTS_BY!,
$sortOrder: SORT_ORDER!,
) {
me {
id
state {
status {
username {
status
}
banned {
status
}
suspension {
until
}
}
}
}
asset(id: $assetId, url: $assetUrl) {
...${getDefinitionName(Configure.fragments.asset)}
...${getDefinitionName(Stream.fragments.asset)}
...${getDefinitionName(AutomaticAssetClosure.fragments.asset)}
}
${getSlotFragmentSpreads(slots, 'root')}
...${getDefinitionName(Stream.fragments.root)}
...${getDefinitionName(Configure.fragments.root)}
}
${Stream.fragments.root}
${Stream.fragments.asset}
${Configure.fragments.root}
${Configure.fragments.asset}
${AutomaticAssetClosure.fragments.asset}
`;
export const withEmbedQuery = withQuery(EMBED_QUERY, {
options: ({
currentUser,
commentId,
assetId,
assetUrl,
sortBy,
sortOrder,
}) => ({
variables: {
assetId,
assetUrl,
commentId,
hasComment: commentId !== '',
excludeIgnored: Boolean(currentUser && currentUser.id),
sortBy,
sortOrder,
},
}),
});
EmbedContainer.propTypes = {
setActiveTab: PropTypes.func,
currentUser: PropTypes.object,
blurSignInDialog: PropTypes.func,
focusSignInDialog: PropTypes.func,
hideSignInDialog: PropTypes.func,
router: PropTypes.object,
commentId: PropTypes.string,
root: PropTypes.object,
activeTab: PropTypes.string,
parentUrl: PropTypes.string,
data: PropTypes.object,
showSignInDialog: PropTypes.bool,
signInDialogFocus: PropTypes.bool,
};
const mapStateToProps = state => ({
currentUser: state.auth.user,
checkedInitialLogin: state.auth.checkedInitialLogin,
commentId: state.stream.commentId,
assetId: state.stream.assetId,
assetUrl: state.stream.assetUrl,
activeTab: state.embed.activeTab,
config: state.config,
sortOrder: state.stream.sortOrder,
sortBy: state.stream.sortBy,
showSignInDialog: state.login.showSignInDialog,
signInDialogFocus: state.login.signInDialogFocus,
parentUrl: state.login.parentUrl,
});
const mapDispatchToProps = dispatch =>
bindActionCreators(
{
setActiveTab,
notify,
focusSignInDialog,
blurSignInDialog,
hideSignInDialog,
updateStatus,
},
dispatch
);
export default compose(
withPopupAuthHandler,
connect(mapStateToProps, mapDispatchToProps),
branch(props => !props.checkedInitialLogin, renderComponent(Spinner)),
withEmbedQuery
)(EmbedContainer);