Vulcan/packages/vulcan-subscribe/lib/components/SubscribeTo.jsx

107 lines
3.4 KiB
React
Raw Normal View History

2017-05-19 14:42:43 -06:00
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
2017-02-07 12:51:11 +01:00
import { intlShape, FormattedMessage } from 'react-intl';
import { compose, graphql } from 'react-apollo';
import gql from 'graphql-tag';
2017-03-23 16:27:59 +09:00
import Users from 'meteor/vulcan:users';
import { withCurrentUser, withMessages, registerComponent, Utils } from 'meteor/vulcan:core';
2017-02-07 12:51:11 +01:00
// boolean -> unsubscribe || subscribe
const getSubscribeAction = subscribed => subscribed ? 'unsubscribe' : 'subscribe'
2017-05-19 14:42:43 -06:00
class SubscribeToActionHandler extends PureComponent {
constructor(props, context) {
super(props, context);
this.onSubscribe = this.onSubscribe.bind(this);
2017-02-07 12:51:11 +01:00
this.state = {
subscribed: !!Users.isSubscribedTo(props.currentUser, props.document, props.documentType),
};
}
2017-02-07 12:51:11 +01:00
async onSubscribe(e) {
try {
e.preventDefault();
const { document, documentType } = this.props;
const action = getSubscribeAction(this.state.subscribed);
// todo: change the mutation to auto-update the user in the store
await this.setState(prevState => ({subscribed: !prevState.subscribed}));
// mutation name will be for example postsSubscribe
await this.props[`${documentType + Utils.capitalize(action)}`]({documentId: document._id});
// success message will be for example posts.subscribed
this.props.flash(this.context.intl.formatMessage(
{id: `${documentType}.${action}d`},
// handle usual name properties
{name: document.name || document.title || document.displayName}
), "success");
} catch(error) {
this.props.flash(error.message, "error");
}
}
render() {
2017-02-07 12:51:11 +01:00
const { currentUser, document, documentType } = this.props;
const { subscribed } = this.state;
const action = `${documentType}.${getSubscribeAction(subscribed)}`;
// can't subscribe to yourself or to own post (also validated on server side)
2017-02-07 12:51:11 +01:00
if (!currentUser || !document || (documentType === 'posts' && document.userId === currentUser._id) || (documentType === 'users' && document._id === currentUser._id)) {
return null;
}
const className = this.props.className ? this.props.className : "";
2017-02-07 12:51:11 +01:00
return Users.canDo(currentUser, action) ? <a className={className} onClick={this.onSubscribe}><FormattedMessage id={action} /></a> : null;
}
}
2017-02-07 12:51:11 +01:00
SubscribeToActionHandler.propTypes = {
2017-05-19 14:42:43 -06:00
document: PropTypes.object.isRequired,
className: PropTypes.string,
currentUser: PropTypes.object,
};
2017-02-07 12:51:11 +01:00
SubscribeToActionHandler.contextTypes = {
intl: intlShape
};
2017-02-07 12:51:11 +01:00
const subscribeMutationContainer = ({documentType, actionName}) => graphql(gql`
mutation ${documentType + actionName}($documentId: String) {
${documentType + actionName}(documentId: $documentId) {
_id
subscribedItems
}
}
`, {
props: ({ownProps, mutate}) => ({
[documentType + actionName]: vars => {
return mutate({
variables: vars,
});
},
}),
});
const SubscribeTo = props => {
const documentType = Utils.getCollectionNameFromTypename(props.document.__typename);
2017-02-07 12:51:11 +01:00
const withSubscribeMutations = ['Subscribe', 'Unsubscribe'].map(actionName => subscribeMutationContainer({documentType, actionName}));
const EnhancedHandler = compose(...withSubscribeMutations)(SubscribeToActionHandler);
return <EnhancedHandler {...props} documentType={documentType} />;
2017-05-19 14:42:43 -06:00
};
2017-02-07 12:51:11 +01:00
registerComponent('SubscribeTo', SubscribeTo, withCurrentUser, withMessages);