UNPKG

stitch-ui

Version:

365 lines (349 loc) 11.8 kB
import React from "react"; // eslint-disable-line no-unused-vars import PropTypes from "prop-types"; import { Map } from "immutable"; import { Route, Switch, Redirect } from "react-router-dom"; import { connect } from "react-redux"; import { appPropType } from "../../core/proptypes"; import MessageEditor from "./MessageEditor"; import MessageList from "./MessageList"; import * as actions from "../actions"; import * as serviceActions from "../../services/actions"; import { NavItem, Confirm, Banner, Button } from "../../core"; import { addAlert, AlertContainer } from "../../alert"; import { EditConfig, EditRules } from "../../service"; import { PUSH_SAVE_ALERTKEY, SAVE_TYPE_SENT, SAVE_TYPE_DRAFT } from "../constants"; export class PushNotifications extends React.Component { constructor(props) { super(props); this.state = { newMessageModalOpen: false }; this.getMessageOptions = this.getMessageOptions.bind(this); this.editMessage = this.editMessage.bind(this); this.duplicateMessage = this.duplicateMessage.bind(this); this.deleteMessage = this.deleteMessage.bind(this); } componentDidMount() { const { app: { groupId, _id }, hasGcm } = this.props; if (hasGcm) { this.props.loadSvc(groupId, _id, "gcm"); } } getMessageOptions(message) { if (message.type === SAVE_TYPE_SENT) { return ( <span> <li> <a onClick={() => this.duplicateMessage(message)}>Duplicate</a> </li> <li> <a onClick={() => this.deleteMessage(message._id)}>Delete</a> </li> </span> ); } else if (message.type === SAVE_TYPE_DRAFT) { return ( <span> <li> <a onClick={() => this.duplicateMessage(message)}>Duplicate</a> </li> <li> <a onClick={() => this.editMessage(message)}>Edit</a> </li> <li> <a onClick={() => this.deleteMessage(message._id)}>Delete</a> </li> </span> ); } return null; } deleteMessage(messageId) { return Confirm.confirm("Are you sure you want to delete this message?") .then(() => this.props.deleteMessage(messageId)) .then(() => this.messageList.load()); } duplicateMessage(message) { this.props.setNewMessageError(null); this.props.setNewMessageTopic(message.topic); this.props.setNewMessageLabel(message.label); this.props.setNewMessageText(message.message); this.setState({ newMessageModalOpen: true }); } editMessage(message) { this.props.setNewMessageError(null); this.props.setNewMessageTopic(message.topic); this.props.setNewMessageLabel(message.label); this.props.setNewMessageText(message.message); this.setState({ newMessageModalOpen: true, editingMessageId: message._id }); } render() { const { app, client, loadSvc, match, executePushPipeline, modalError, messages, saveMessage, createMessage, setMessageStatus, newMessage, loadMessages, setNewMessageText, setNewMessageTopic, setNewMessageLabel, addAlertFunc, loadingMessages, loadingMessagesError, sendMessage, hasGcm, gcmConfigured } = this.props; const configProps = { app, client, svcname: "gcm", service: { ...app.services.gcm, name: "gcm" }, onUpdate: loadSvc }; const banner = gcmConfigured ? <span /> : <Banner message="You must configure a GCM service before sending push notifications." warning clearable={false} />; return ( <div> <MessageEditor error={modalError} editingMessageId={this.state.editingMessageId} executePushPipeline={executePushPipeline} addAlert={addAlertFunc} newMessage={newMessage} saveMessage={saveMessage} createMessage={createMessage} setNewMessageTopic={setNewMessageTopic} setNewMessageText={setNewMessageText} setNewMessageLabel={setNewMessageLabel} setMessageStatus={setMessageStatus} sendMessage={sendMessage} open={this.state.newMessageModalOpen} reloadList={() => this.messageList.load()} onClose={() => this.setState({ newMessageModalOpen: false })} /> {banner} <div className="section-header section-header-has-tabs"> <div className="section-header-title"> <div className="section-header-title-text"> {"Push Notifications"} </div> <AlertContainer alertKey={PUSH_SAVE_ALERTKEY} /> <div className="section-header-title-controls"> <Button primary onClick={() => { this.props.setNewMessageError(null); this.props.setNewMessageText(""); this.props.setNewMessageTopic(""); this.props.setNewMessageLabel(""); this.setState({ newMessageModalOpen: true, editingMessageId: null }); }} > Send New Notification </Button> </div> </div> <ul className="section-header-tabs"> <NavItem to={`/groups/${app.groupId}/apps/${app._id}/push/sent`} className="section-header-tab apptabs-services section-header-tab-is-left" activeClassName="section-header-tab-is-active" linkClassName="section-header-tab-link" > Sent </NavItem> <NavItem to={`/groups/${app.groupId}/apps/${app._id}/push/drafts`} className="section-header-tab apptabs-services section-header-tab-is-right" activeClassName="section-header-tab-is-active" linkClassName="section-header-tab-link" > Drafts </NavItem> <NavItem to={`/groups/${app.groupId}/apps/${app._id}/push/config`} className="section-header-tab apptabs-services section-header-tab-is-right" activeClassName="section-header-tab-is-active" linkClassName="section-header-tab-link" > Config </NavItem> <NavItem to={`/groups/${app.groupId}/apps/${app._id}/push/rules`} className="section-header-tab apptabs-services section-header-tab-is-right" activeClassName="section-header-tab-is-active" linkClassName="section-header-tab-link" > Rules </NavItem> </ul> </div> <div className="tabs-content" /> <Switch> <Redirect exact from={`${match.url}`} to={`${match.url}/sent`} /> <Route path={`${match.url}/drafts`} render={() => <MessageList ref={x => (this.messageList = x)} getMessageOptions={this.getMessageOptions} messages={messages} messageType={SAVE_TYPE_DRAFT} loadMessages={loadMessages} loadingMessages={loadingMessages} loadingMessagesError={loadingMessagesError} />} /> <Route path={`${match.url}/sent`} render={() => <MessageList ref={x => (this.messageList = x)} getMessageOptions={this.getMessageOptions} messageType={SAVE_TYPE_SENT} messages={messages} loadMessages={loadMessages} loadingMessages={loadingMessages} loadingMessagesError={loadingMessagesError} />} /> <Route path={`${match.url}/config`} render={() => hasGcm ? <EditConfig {...configProps} /> : <span> {"Please create GCM service to continue."} </span>} /> <Route path={`${match.url}/rules`} render={() => hasGcm ? <EditRules {...configProps} /> : <span> {"Please create GCM service to continue."} </span>} /> </Switch> </div> ); } } const mapStateToProps = state => { const { modalError, newMessage, messages, loadingMessages, loadingMessagesError } = state.push; const hasGcm = !!state.app.root.services.gcm; const service = state.service.base; const gcmConfigured = hasGcm && service.serviceName === "gcm" && service.configInput.get("apiKey") !== "API-KEY" && service.configInput.get("senderId") !== "SENDER-ID"; return { modalError, newMessage, messages, loadingMessages, loadingMessagesError, hasGcm, gcmConfigured }; }; const mapDispatchToProps = (dispatch, ownProps) => ({ addAlertFunc: (key, message, options) => dispatch(addAlert(key, message, options)), executePushPipeline: pipeline => dispatch( actions.executePushPipeline( ownProps.app.groupId, ownProps.app._id, pipeline ) ), loadMessages: query => dispatch( actions.loadMessages(ownProps.app.groupId, ownProps.app._id, query) ), saveMessage: (messageId, message) => dispatch( actions.saveMessage( ownProps.app.groupId, ownProps.app._id, messageId, message ) ), createMessage: message => dispatch( actions.createMessage(ownProps.app.groupId, ownProps.app._id, message) ), deleteMessage: messageId => dispatch( actions.deleteMessage(ownProps.app.groupId, ownProps.app._id, messageId) ), setMessageStatus: (messageId, type) => dispatch( actions.setMessageStatus( ownProps.app.groupId, ownProps.app._id, messageId, type ) ), setNewMessageError: error => dispatch(actions.setNewMessageError({ error })), setNewMessageTopic: input => dispatch(actions.setNewMessageTopic({ input })), setNewMessageText: input => dispatch(actions.setNewMessageText({ input })), setNewMessageLabel: input => dispatch(actions.setNewMessageLabel({ input })), sendMessage: message => dispatch(actions.sendMessage({ message })), loadSvc: (groupId, appId, svcName, switching) => dispatch(serviceActions.loadSvc(groupId, appId, svcName, { switching })) }); PushNotifications.propTypes = { ...appPropType, addAlertFunc: PropTypes.func.isRequired, executePushPipeline: PropTypes.func.isRequired, loadMessages: PropTypes.func.isRequired, saveMessage: PropTypes.func.isRequired, createMessage: PropTypes.func.isRequired, deleteMessage: PropTypes.func.isRequired, setMessageStatus: PropTypes.func.isRequired, setNewMessageError: PropTypes.func.isRequired, setNewMessageTopic: PropTypes.func.isRequired, setNewMessageText: PropTypes.func.isRequired, setNewMessageLabel: PropTypes.func.isRequired, sendMessage: PropTypes.func.isRequired, modalError: PropTypes.string, newMessage: PropTypes.instanceOf(Map).isRequired, messages: PropTypes.array.isRequired, // eslint-disable-line react/forbid-prop-types loadingMessages: PropTypes.bool.isRequired, loadingMessagesError: PropTypes.string }; PushNotifications.defaultProps = { modalError: null, loadingMessagesError: null }; export default connect(mapStateToProps, mapDispatchToProps)(PushNotifications);