stitch-ui
Version:
262 lines (257 loc) • 8.3 kB
JavaScript
import React from "react"; // eslint-disable-line no-unused-vars
import PropTypes from "prop-types";
import Modal from "react-modal";
import { Map } from "immutable";
import {
Banner,
Tooltip,
Button,
FormRow,
FormRowInputGroup,
FormRowLabelGroup
} from "../../core";
import {
PUSH_SAVE_ALERTKEY,
SAVE_TYPE_DRAFT,
SAVE_TYPE_SENT,
FIELD_TEXT,
FIELD_LABEL,
FIELD_TOPIC,
ALERT_TTL_MS
} from "../constants";
class MessageEditor extends React.Component {
static makeTopicPipeline(topicName, body) {
return [
{
service: "gcm",
action: "send",
args: {
to: `/topics/${topicName}`,
notification: { body }
}
}
];
}
constructor(props) {
super(props);
this.saveDraft = this.saveDraft.bind(this);
this.sendMessage = this.sendMessage.bind(this);
}
saveDraft(msg) {
let p;
if (this.props.editingMessageId) {
// We're editing an existing message; just update the existing message data using its _id
p = this.props.saveMessage(this.props.editingMessageId, {
message: msg.get(FIELD_TEXT),
label: msg.get(FIELD_LABEL),
topic: msg.get(FIELD_TOPIC),
type: SAVE_TYPE_DRAFT
});
} else {
// This is a new message that has not been saved yet, create it in the "Draft" state
p = this.props.createMessage({
message: msg.get(FIELD_TEXT),
label: msg.get(FIELD_LABEL),
topic: msg.get(FIELD_TOPIC),
type: SAVE_TYPE_DRAFT
});
}
return p
.then(this.props.onClose)
.then(() =>
this.props.addAlert(
PUSH_SAVE_ALERTKEY,
"Message has been saved as draft."
)
)
.then(this.props.reloadList);
}
sendMessage(msg) {
let p;
let messageId = this.props.editingMessageId;
if (this.props.editingMessageId) {
p = this.props.saveMessage(this.props.editingMessageId, {
message: msg.get(FIELD_TEXT),
label: msg.get(FIELD_LABEL),
topic: msg.get(FIELD_TOPIC),
type: SAVE_TYPE_DRAFT
});
} else {
p = this.props
.createMessage({
message: msg.get(FIELD_TEXT),
label: msg.get(FIELD_LABEL),
topic: msg.get(FIELD_TOPIC),
type: SAVE_TYPE_DRAFT
})
.then(m => {
messageId = m._id;
});
}
return p
.then(() =>
this.props.executePushPipeline(
MessageEditor.makeTopicPipeline(
msg.get(FIELD_TOPIC),
msg.get(FIELD_TEXT)
),
null,
{ systemUser: "1" }
)
)
.then(this.props.onClose)
.then(() =>
this.props.addAlert(PUSH_SAVE_ALERTKEY, "Message has been sent.", {
timeout: ALERT_TTL_MS
})
)
.then(() => this.props.setMessageStatus(messageId, SAVE_TYPE_SENT))
.then(() => this.props.reloadList());
}
render() {
const {
error,
newMessage,
open,
onClose,
setNewMessageText,
setNewMessageTopic,
setNewMessageLabel
} = this.props;
return (
<Modal
ref={ref => (this.modal = ref)}
isOpen={open}
onRequestClose={onClose}
contentLabel="Send Message"
className="view-modal-dialog"
overlayClassName="view-modal-overlay"
>
<div className="view-modal-content">
<div className="view-modal-header">
<button className="button view-modal-close" onClick={onClose}>
×
</button>
<h2 className="view-modal-title">New Push Notification</h2>
</div>
<div className="view-modal-body">
<Banner message={error} error />
<FormRow>
<FormRowLabelGroup>
<label htmlFor="message" className="form-row-label">
Message
<Tooltip
dataFor="tooltip-message"
place="top"
classNames="tooltip-indicator tooltip-indicator-small tooltip-indicator-secondary"
effect="float"
>
This is the content of your push notification.
</Tooltip>
</label>
</FormRowLabelGroup>
<FormRowInputGroup>
<input
type="text"
name="message"
className="text-input form-row-text-input"
placeholder="Message"
value={newMessage.get(FIELD_TEXT) || ""}
onChange={e => setNewMessageText(e.target.value)}
/>
</FormRowInputGroup>
</FormRow>
<FormRow>
<FormRowLabelGroup>
<label htmlFor="label" className="form-row-label">
Message Label
<Tooltip
dataFor="tooltip-message-label"
place="top"
classNames="tooltip-indicator tooltip-indicator-small tooltip-indicator-secondary"
effect="float"
>
This is used to identify notifications in Stitch. This is
not shown to your users.
</Tooltip>
</label>
</FormRowLabelGroup>
<FormRowInputGroup>
<input
type="text"
name="label"
className="text-input form-row-text-input"
placeholder="Label"
value={newMessage.get(FIELD_LABEL) || ""}
onChange={e => setNewMessageLabel(e.target.value)}
/>
</FormRowInputGroup>
</FormRow>
<FormRow last>
<FormRowLabelGroup>
<label htmlFor="topic" className="form-row-label">
Topic
<Tooltip
dataFor="tooltip-topic"
place="top"
classNames="tooltip-indicator tooltip-indicator-small tooltip-indicator-secondary"
effect="float"
>
This is a pub/sub pattern to send notifications to
subscribers of this topic.
</Tooltip>
</label>
</FormRowLabelGroup>
<FormRowInputGroup>
<input
type="text"
name="topic"
className="text-input form-row-text-input"
placeholder="Topic"
value={newMessage.get("topic") || ""}
onChange={e => setNewMessageTopic(e.target.value)}
/>
</FormRowInputGroup>
</FormRow>
<footer className="view-modal-footer">
<div className="view-modal-actions tabs-content-actions">
<div className="tabs-content-actions-left">
<Button onClick={onClose}>Cancel</Button>
</div>
<div className="tabs-content-actions-right">
<Button onClick={() => this.saveDraft(newMessage)}>
Save Draft
</Button>
<Button primary onClick={() => this.sendMessage(newMessage)}>
Send Message
</Button>
</div>
</div>
</footer>
</div>
</div>
</Modal>
);
}
}
MessageEditor.propTypes = {
addAlert: PropTypes.func.isRequired,
createMessage: PropTypes.func.isRequired,
editingMessageId: PropTypes.string,
error: PropTypes.string,
executePushPipeline: PropTypes.func.isRequired,
newMessage: PropTypes.instanceOf(Map).isRequired,
onClose: PropTypes.func.isRequired,
open: PropTypes.bool.isRequired,
reloadList: PropTypes.func.isRequired,
saveMessage: PropTypes.func.isRequired,
setMessageStatus: PropTypes.func.isRequired,
setNewMessageLabel: PropTypes.func.isRequired,
setNewMessageText: PropTypes.func.isRequired,
setNewMessageTopic: PropTypes.func.isRequired
};
MessageEditor.defaultProps = {
editingMessageId: null,
error: null
};
export default MessageEditor;