|
@@ -25,7 +25,7 @@ class Editor extends React.PureComponent {
|
|
|
rawInput: null,
|
|
|
selContentType: "richtext",
|
|
|
contentType: "richtext",
|
|
|
- body: "",
|
|
|
+ body: ""
|
|
|
}
|
|
|
|
|
|
quillModules = {
|
|
@@ -129,7 +129,9 @@ class Editor extends React.PureComponent {
|
|
|
modules={ this.quillModules }
|
|
|
defaultValue={ this.props.record.body }
|
|
|
ref={ (o) => {
|
|
|
- this.setState({ quill: o })
|
|
|
+ if(o) {
|
|
|
+ this.setState({ quill: o })
|
|
|
+ }
|
|
|
}}
|
|
|
onChange={ () => {
|
|
|
if(!this.state.quill) {
|
|
@@ -167,7 +169,8 @@ class Editor extends React.PureComponent {
|
|
|
class TheFormDef extends React.PureComponent {
|
|
|
state = {
|
|
|
editorVisible: false,
|
|
|
- sendLater: false
|
|
|
+ sendLater: false,
|
|
|
+ loading: false
|
|
|
}
|
|
|
|
|
|
componentWillReceiveProps(nextProps) {
|
|
@@ -200,15 +203,16 @@ class TheFormDef extends React.PureComponent {
|
|
|
if (err) {
|
|
|
return
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
if(!values.tags) {
|
|
|
values.tags = []
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
values.body = this.props.body
|
|
|
values.content_type = this.props.contentType
|
|
|
-
|
|
|
+
|
|
|
// Create a new campaign.
|
|
|
+ this.setState({ loading: true })
|
|
|
if(!this.props.isSingle) {
|
|
|
this.props.modelRequest(cs.ModelCampaigns, cs.Routes.CreateCampaign, cs.MethodPost, values).then((resp) => {
|
|
|
notification["success"]({ placement: "topRight",
|
|
@@ -218,21 +222,52 @@ class TheFormDef extends React.PureComponent {
|
|
|
this.props.route.history.push(cs.Routes.ViewCampaign.replace(":id", resp.data.data.id))
|
|
|
this.props.fetchRecord(resp.data.data.id)
|
|
|
this.props.setCurrentTab("content")
|
|
|
+ this.setState({ loading: false })
|
|
|
}).catch(e => {
|
|
|
notification["error"]({ message: "Error", description: e.message })
|
|
|
})
|
|
|
} else {
|
|
|
this.props.modelRequest(cs.ModelCampaigns, cs.Routes.UpdateCampaign, cs.MethodPut, { ...values, id: this.props.record.id }).then((resp) => {
|
|
|
notification["success"]({ placement: "topRight",
|
|
|
- message: "Campaign updated",
|
|
|
- description: `"${values["name"]}" updated` })
|
|
|
+ message: "Campaign updated",
|
|
|
+ description: `"${values["name"]}" updated` })
|
|
|
}).catch(e => {
|
|
|
notification["error"]({ message: "Error", description: e.message })
|
|
|
+ this.setState({ loading: false })
|
|
|
})
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ handleTestCampaign = (e) => {
|
|
|
+ e.preventDefault()
|
|
|
+ this.props.form.validateFields((err, values) => {
|
|
|
+ if (err) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if(!values.tags) {
|
|
|
+ values.tags = []
|
|
|
+ }
|
|
|
+
|
|
|
+ values.id = this.props.record.id
|
|
|
+ values.body = this.props.body
|
|
|
+ values.content_type = this.props.contentType
|
|
|
+
|
|
|
+ this.setState({ loading: true })
|
|
|
+ this.props.request(cs.Routes.TestCampaign, cs.MethodPost, values).then((resp) => {
|
|
|
+ this.setState({ loading: false })
|
|
|
+ notification["success"]({ placement: "topRight",
|
|
|
+ message: "Test sent",
|
|
|
+ description: `Test messages sent` })
|
|
|
+ }).catch(e => {
|
|
|
+ this.setState({ loading: false })
|
|
|
+ notification["error"]({ message: "Error", description: e.message })
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
render() {
|
|
|
const { record } = this.props;
|
|
|
const { getFieldDecorator } = this.props.form
|
|
@@ -244,101 +279,107 @@ class TheFormDef extends React.PureComponent {
|
|
|
|
|
|
return (
|
|
|
<div>
|
|
|
- <Form onSubmit={ this.handleSubmit }>
|
|
|
- <Form.Item {...formItemLayout} label="Campaign name">
|
|
|
- {getFieldDecorator("name", {
|
|
|
- extra: "This is internal and will not be visible to subscribers",
|
|
|
- initialValue: record.name,
|
|
|
- rules: [{ required: true }]
|
|
|
- })(<Input disabled={ this.props.formDisabled }autoFocus maxLength="200" />)}
|
|
|
- </Form.Item>
|
|
|
- <Form.Item {...formItemLayout} label="Subject">
|
|
|
- {getFieldDecorator("subject", {
|
|
|
- initialValue: record.subject,
|
|
|
- rules: [{ required: true }]
|
|
|
- })(<Input disabled={ this.props.formDisabled } maxLength="500" />)}
|
|
|
- </Form.Item>
|
|
|
- <Form.Item {...formItemLayout} label="From address">
|
|
|
- {getFieldDecorator("from_email", {
|
|
|
- initialValue: record.from_email,
|
|
|
- rules: [{ required: true }, { validator: this.validateEmail }]
|
|
|
- })(<Input disabled={ this.props.formDisabled } placeholder="Company Name <email@company.com>" maxLength="200" />)}
|
|
|
- </Form.Item>
|
|
|
- <Form.Item {...formItemLayout} label="Lists" extra="Lists to subscribe to">
|
|
|
- {getFieldDecorator("lists", { initialValue: subLists, rules: [{ required: true }] })(
|
|
|
- <Select disabled={ this.props.formDisabled } mode="multiple">
|
|
|
- {[...this.props.data[cs.ModelLists]].map((v, i) =>
|
|
|
- <Select.Option value={ v["id"] } key={ v["id"] }>{ v["name"] }</Select.Option>
|
|
|
- )}
|
|
|
- </Select>
|
|
|
- )}
|
|
|
- </Form.Item>
|
|
|
- <Form.Item {...formItemLayout} label="Template" extra="Template">
|
|
|
- {getFieldDecorator("template_id", { initialValue: record.template_id, rules: [{ required: true }] })(
|
|
|
- <Select disabled={ this.props.formDisabled }>
|
|
|
- {[...this.props.data[cs.ModelTemplates]].map((v, i) =>
|
|
|
- <Select.Option value={ v["id"] } key={ v["id"] }>{ v["name"] }</Select.Option>
|
|
|
- )}
|
|
|
- </Select>
|
|
|
- )}
|
|
|
- </Form.Item>
|
|
|
- <Form.Item {...formItemLayout} label="Tags" extra="Hit Enter after typing a word to add multiple tags">
|
|
|
- {getFieldDecorator("tags", { initialValue: record.tags })(
|
|
|
- <Select disabled={ this.props.formDisabled } mode="tags"></Select>
|
|
|
+ <Spin spinning={ this.state.loading }>
|
|
|
+ <Form onSubmit={ this.handleSubmit }>
|
|
|
+ <Form.Item {...formItemLayout} label="Campaign name">
|
|
|
+ {getFieldDecorator("name", {
|
|
|
+ extra: "This is internal and will not be visible to subscribers",
|
|
|
+ initialValue: record.name,
|
|
|
+ rules: [{ required: true }]
|
|
|
+ })(<Input disabled={ this.props.formDisabled }autoFocus maxLength="200" />)}
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item {...formItemLayout} label="Subject">
|
|
|
+ {getFieldDecorator("subject", {
|
|
|
+ initialValue: record.subject,
|
|
|
+ rules: [{ required: true }]
|
|
|
+ })(<Input disabled={ this.props.formDisabled } maxLength="500" />)}
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item {...formItemLayout} label="From address">
|
|
|
+ {getFieldDecorator("from_email", {
|
|
|
+ initialValue: record.from_email,
|
|
|
+ rules: [{ required: true }, { validator: this.validateEmail }]
|
|
|
+ })(<Input disabled={ this.props.formDisabled } placeholder="Company Name <email@company.com>" maxLength="200" />)}
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item {...formItemLayout} label="Lists" extra="Lists to subscribe to">
|
|
|
+ {getFieldDecorator("lists", { initialValue: subLists, rules: [{ required: true }] })(
|
|
|
+ <Select disabled={ this.props.formDisabled } mode="multiple">
|
|
|
+ {[...this.props.data[cs.ModelLists]].map((v, i) =>
|
|
|
+ <Select.Option value={ v["id"] } key={ v["id"] }>{ v["name"] }</Select.Option>
|
|
|
+ )}
|
|
|
+ </Select>
|
|
|
)}
|
|
|
- </Form.Item>
|
|
|
- <Form.Item {...formItemLayout} label="Messenger">
|
|
|
- {getFieldDecorator("messenger", { initialValue: record.messenger ? record.messenger : "email" })(
|
|
|
- <Radio.Group className="messengers">
|
|
|
- {[...this.props.messengers].map((v, i) =>
|
|
|
- <Radio disabled={ this.props.formDisabled } value={v} key={v}>{ v }</Radio>
|
|
|
- )}
|
|
|
- </Radio.Group>
|
|
|
- )}
|
|
|
- </Form.Item>
|
|
|
-
|
|
|
- <hr />
|
|
|
- <Form.Item {...formItemLayout} label="Send later?">
|
|
|
- <Row>
|
|
|
- <Col span={ 2 }>
|
|
|
- {getFieldDecorator("send_later", { defaultChecked: this.props.isSingle })(
|
|
|
- <Switch disabled={ this.props.formDisabled }
|
|
|
- checked={ this.state.sendLater }
|
|
|
- onChange={ this.handleSendLater } />
|
|
|
- )}
|
|
|
- </Col>
|
|
|
- <Col span={ 12 }>
|
|
|
- {this.state.sendLater && getFieldDecorator("send_at",
|
|
|
- { initialValue: (record && typeof(record.send_at) === "string") ? moment(record.send_at) : moment(new Date()).add(1, "days").startOf("day") })(
|
|
|
- <DatePicker
|
|
|
- disabled={ this.props.formDisabled }
|
|
|
- showTime
|
|
|
- format="YYYY-MM-DD HH:mm:ss"
|
|
|
- placeholder="Select a date and time"
|
|
|
- />
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item {...formItemLayout} label="Template" extra="Template">
|
|
|
+ {getFieldDecorator("template_id", { initialValue: record.template_id, rules: [{ required: true }] })(
|
|
|
+ <Select disabled={ this.props.formDisabled }>
|
|
|
+ {[...this.props.data[cs.ModelTemplates]].map((v, i) =>
|
|
|
+ <Select.Option value={ v["id"] } key={ v["id"] }>{ v["name"] }</Select.Option>
|
|
|
+ )}
|
|
|
+ </Select>
|
|
|
+ )}
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item {...formItemLayout} label="Tags" extra="Hit Enter after typing a word to add multiple tags">
|
|
|
+ {getFieldDecorator("tags", { initialValue: record.tags })(
|
|
|
+ <Select disabled={ this.props.formDisabled } mode="tags"></Select>
|
|
|
)}
|
|
|
- </Col>
|
|
|
- </Row>
|
|
|
- </Form.Item>
|
|
|
-
|
|
|
- { !this.props.formDisabled &&
|
|
|
- <Form.Item {...formItemTailLayout}>
|
|
|
- <Button htmlType="submit" type="primary">
|
|
|
- <Icon type="save" /> { !this.props.isSingle ? "Continue" : "Save changes" }
|
|
|
- </Button>
|
|
|
</Form.Item>
|
|
|
- }
|
|
|
- </Form>
|
|
|
+ <Form.Item {...formItemLayout} label="Messenger">
|
|
|
+ {getFieldDecorator("messenger", { initialValue: record.messenger ? record.messenger : "email" })(
|
|
|
+ <Radio.Group className="messengers">
|
|
|
+ {[...this.props.messengers].map((v, i) =>
|
|
|
+ <Radio disabled={ this.props.formDisabled } value={v} key={v}>{ v }</Radio>
|
|
|
+ )}
|
|
|
+ </Radio.Group>
|
|
|
+ )}
|
|
|
+ </Form.Item>
|
|
|
|
|
|
- { this.props.isSingle &&
|
|
|
- <div>
|
|
|
<hr />
|
|
|
- <Form.Item {...formItemLayout} label="Send test e-mails" extra="Hit Enter after typing an e-mail to add multiple emails">
|
|
|
- <Select mode="tags" style={{ minWidth: 320 }}></Select>
|
|
|
- <div><Button htmlType="submit"><Icon type="mail" /> Send test</Button></div>
|
|
|
+ <Form.Item {...formItemLayout} label="Send later?">
|
|
|
+ <Row>
|
|
|
+ <Col span={ 2 }>
|
|
|
+ {getFieldDecorator("send_later", { defaultChecked: this.props.isSingle })(
|
|
|
+ <Switch disabled={ this.props.formDisabled }
|
|
|
+ checked={ this.state.sendLater }
|
|
|
+ onChange={ this.handleSendLater } />
|
|
|
+ )}
|
|
|
+ </Col>
|
|
|
+ <Col span={ 12 }>
|
|
|
+ {this.state.sendLater && getFieldDecorator("send_at",
|
|
|
+ { initialValue: (record && typeof(record.send_at) === "string") ? moment(record.send_at) : moment(new Date()).add(1, "days").startOf("day") })(
|
|
|
+ <DatePicker
|
|
|
+ disabled={ this.props.formDisabled }
|
|
|
+ showTime
|
|
|
+ format="YYYY-MM-DD HH:mm:ss"
|
|
|
+ placeholder="Select a date and time"
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ </Col>
|
|
|
+ </Row>
|
|
|
</Form.Item>
|
|
|
- </div>
|
|
|
- }
|
|
|
+
|
|
|
+ { !this.props.formDisabled &&
|
|
|
+ <Form.Item {...formItemTailLayout}>
|
|
|
+ <Button htmlType="submit" type="primary">
|
|
|
+ <Icon type="save" /> { !this.props.isSingle ? "Continue" : "Save changes" }
|
|
|
+ </Button>
|
|
|
+ </Form.Item>
|
|
|
+ }
|
|
|
+
|
|
|
+ { this.props.isSingle &&
|
|
|
+ <div>
|
|
|
+ <hr />
|
|
|
+ <Form.Item {...formItemLayout} label="Send test messages" extra="Hit Enter after typing an address to add multiple recipients. The addresses must belong to existing subscribers.">
|
|
|
+ {getFieldDecorator("subscribers")(
|
|
|
+ <Select mode="tags" style={{ width: "100%" }}></Select>
|
|
|
+ )}
|
|
|
+ </Form.Item>
|
|
|
+ <Form.Item {...formItemLayout} label=" " colon={ false }>
|
|
|
+ <Button onClick={ this.handleTestCampaign }><Icon type="mail" /> Send test</Button>
|
|
|
+ </Form.Item>
|
|
|
+ </div>
|
|
|
+ }
|
|
|
+ </Form>
|
|
|
+ </Spin>
|
|
|
</div>
|
|
|
|
|
|
)
|
|
@@ -381,7 +422,7 @@ class Campaign extends React.PureComponent {
|
|
|
}
|
|
|
|
|
|
fetchRecord = (id) => {
|
|
|
- this.props.request(cs.Routes.GetCampaigns, cs.MethodGet, { id: id }).then((r) => {
|
|
|
+ this.props.request(cs.Routes.GetCampaign, cs.MethodGet, { id: id }).then((r) => {
|
|
|
const record = r.data.data
|
|
|
this.setState({ record: record, loading: false })
|
|
|
|
|
@@ -440,7 +481,7 @@ class Campaign extends React.PureComponent {
|
|
|
record={ this.state.record }
|
|
|
isSingle={ this.state.record.id ? true : false }
|
|
|
messengers={ this.state.messengers }
|
|
|
- body={ this.state.body }
|
|
|
+ body={ this.state.body ? this.state.body : this.state.record.body }
|
|
|
contentType={ this.state.contentType }
|
|
|
formDisabled={ this.state.formDisabled }
|
|
|
fetchRecord={ this.fetchRecord }
|
|
@@ -476,8 +517,7 @@ class Campaign extends React.PureComponent {
|
|
|
<Media { ...{ ...this.props,
|
|
|
insertMedia: this.state.editor ? this.state.editor.insertMedia : null,
|
|
|
onCancel: this.toggleMedia,
|
|
|
- onOk: this.toggleMedia
|
|
|
- }} />
|
|
|
+ onOk: this.toggleMedia }} />
|
|
|
</Modal>
|
|
|
|
|
|
{ this.state.previewRecord &&
|