Create settings for slack/email
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import Nodemailer from 'nodemailer';
|
||||
import { email, starters, mains, getRsvpEnd } from '../config';
|
||||
import { handleError } from '../core/rollbar';
|
||||
import Settings from '../data/models/Settings';
|
||||
|
||||
const transporter = Nodemailer.createTransport({
|
||||
service: 'gmail',
|
||||
@@ -36,7 +37,8 @@ ${person.attending && person.dietary.length > 0 ? `<p>Your dietary requirements
|
||||
}
|
||||
|
||||
export const sendRSVPEmail = function sendRSVPEmail(person) {
|
||||
if (email.enabled) {
|
||||
Settings.findAll().then(data => {
|
||||
if (data[0].email) {
|
||||
const mailOptions = {
|
||||
from: `"${email.senderName}" <${email.senderAddress}>`,
|
||||
to: person.email,
|
||||
@@ -51,6 +53,9 @@ export const sendRSVPEmail = function sendRSVPEmail(person) {
|
||||
}
|
||||
});
|
||||
}
|
||||
}).catch(err => {
|
||||
handleError(err);
|
||||
});
|
||||
};
|
||||
|
||||
export const sendRSVPEmailWithDebounce = function sendRSVPEmailWithDebounce(person) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import Slack from 'slack-node';
|
||||
import { slackWebhook } from '../config';
|
||||
import { handleError } from '../core/rollbar';
|
||||
import Settings from '../data/models/Settings';
|
||||
|
||||
const slack = new Slack();
|
||||
slack.setWebhook(slackWebhook);
|
||||
@@ -9,6 +10,8 @@ slack.setWebhook(slackWebhook);
|
||||
const slackTimers = {};
|
||||
|
||||
export const sendSlackMsg = function sendSlackMsg(text, channel) {
|
||||
Settings.findAll().then(data => {
|
||||
if (data[0].slack) {
|
||||
slack.webhook({
|
||||
channel,
|
||||
username: 'weddingbot',
|
||||
@@ -18,6 +21,10 @@ export const sendSlackMsg = function sendSlackMsg(text, channel) {
|
||||
handleError(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
}).catch(err => {
|
||||
handleError(err);
|
||||
});
|
||||
};
|
||||
|
||||
export const sendSlackMsgWithDebounce = function sendSlackMsgWithDebounce(text, channel, key) {
|
||||
|
||||
23
src/data/models/Settings.js
Normal file
23
src/data/models/Settings.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import DataType from 'sequelize';
|
||||
import Model from '../sequelize';
|
||||
|
||||
const Settings = Model.define('Settings', {
|
||||
key: {
|
||||
type: DataType.UUID,
|
||||
defaultValue: DataType.UUIDV1,
|
||||
primaryKey: true,
|
||||
},
|
||||
|
||||
slack: {
|
||||
type: DataType.BOOLEAN,
|
||||
defaultValue: false,
|
||||
},
|
||||
|
||||
email: {
|
||||
type: DataType.BOOLEAN,
|
||||
defaultValue: false,
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
export default Settings;
|
||||
12
src/data/queries/settings.js
Normal file
12
src/data/queries/settings.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import { GraphQLList as List } from 'graphql';
|
||||
import SettingsItemType from '../types/SettingsItemType';
|
||||
import Settings from '../models/Settings';
|
||||
|
||||
const settings = {
|
||||
type: new List(SettingsItemType),
|
||||
resolve() {
|
||||
return Settings.findAll();
|
||||
},
|
||||
};
|
||||
|
||||
export default settings;
|
||||
@@ -7,6 +7,7 @@ import me from './queries/me';
|
||||
import getAllPersons from './queries/getAllPersons';
|
||||
import getPersonByKey from './queries/getPersonByKey';
|
||||
import getPersonsByPassword from './queries/getPersonsByPassword';
|
||||
import settings from './queries/settings';
|
||||
|
||||
const schema = new Schema({
|
||||
query: new ObjectType({
|
||||
@@ -16,6 +17,7 @@ const schema = new Schema({
|
||||
getAllPersons,
|
||||
getPersonByKey,
|
||||
getPersonsByPassword,
|
||||
settings,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
17
src/data/types/SettingsItemType.js
Normal file
17
src/data/types/SettingsItemType.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import {
|
||||
GraphQLObjectType as ObjectType,
|
||||
GraphQLID as ID,
|
||||
GraphQLBoolean as BooleanType,
|
||||
GraphQLNonNull as NonNull,
|
||||
} from 'graphql';
|
||||
|
||||
const SettingsItemType = new ObjectType({
|
||||
name: 'SettingsItem',
|
||||
fields: {
|
||||
key: { type: new NonNull(ID) },
|
||||
slack: { type: BooleanType },
|
||||
email: { type: BooleanType },
|
||||
},
|
||||
});
|
||||
|
||||
export default SettingsItemType;
|
||||
@@ -11,3 +11,18 @@
|
||||
max-width: var(--max-content-width);
|
||||
}
|
||||
|
||||
.formGroup {
|
||||
position: relative;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.label {
|
||||
display: inline-block;
|
||||
margin-bottom: 5px;
|
||||
max-width: 100%;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.input {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import React, { PropTypes } from 'react';
|
||||
import withStyles from 'isomorphic-style-loader/lib/withStyles';
|
||||
import s from './Admin.css';
|
||||
import Link from '../../components/Link';
|
||||
import Button from '../../components/Button';
|
||||
|
||||
class Admin extends React.Component {
|
||||
static propTypes = {
|
||||
@@ -26,6 +27,10 @@ class Admin extends React.Component {
|
||||
hash: PropTypes.string,
|
||||
time: PropTypes.string,
|
||||
}),
|
||||
settings: PropTypes.shape({
|
||||
slack: PropTypes.boolean,
|
||||
email: PropTypes.boolean,
|
||||
}),
|
||||
};
|
||||
|
||||
render() {
|
||||
@@ -54,6 +59,38 @@ class Admin extends React.Component {
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<h3>Settings</h3>
|
||||
<form method="post" action="/admin/settings">
|
||||
<div className={s.formGroup}>
|
||||
<label className={s.label} htmlFor="slack">
|
||||
Send slack messages on RSVP:
|
||||
</label>
|
||||
<input
|
||||
className={s.input}
|
||||
type="checkbox"
|
||||
name="slack"
|
||||
defaultChecked={this.props.settings.slack}
|
||||
/>
|
||||
</div>
|
||||
<div className={s.formGroup}>
|
||||
<label className={s.label} htmlFor="email">
|
||||
Send confirmation emails on RSVP:
|
||||
</label>
|
||||
<input
|
||||
className={s.input}
|
||||
type="checkbox"
|
||||
name="email"
|
||||
defaultChecked={this.props.settings.email}
|
||||
/>
|
||||
</div>
|
||||
<div className={s.formGroup}>
|
||||
<Button type="submit">
|
||||
Save
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div>
|
||||
Build hash: <a href={`https://bitbucket.org/dan_head/wedding/commits/${this.props.build.hash}`}>{this.props.build.hash}</a>
|
||||
</div>
|
||||
|
||||
@@ -19,8 +19,11 @@ export default {
|
||||
},
|
||||
credentials: 'include',
|
||||
});
|
||||
|
||||
const settingsResp = await fetchQL('{settings{slack,email}}');
|
||||
const { data } = await resp.json();
|
||||
const config = await configResp.json();
|
||||
const settings = await settingsResp.json();
|
||||
const people = data.getAllPersons || [];
|
||||
|
||||
const food = {
|
||||
@@ -47,6 +50,7 @@ export default {
|
||||
starters={food.starters}
|
||||
mains={food.mains}
|
||||
build={config.build}
|
||||
settings={settings.data.settings[0]}
|
||||
/></Layout>,
|
||||
};
|
||||
},
|
||||
|
||||
@@ -112,7 +112,6 @@ class AdminPerson extends React.Component {
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -23,6 +23,7 @@ import routes from './routes';
|
||||
import assets from './assets'; // eslint-disable-line import/no-unresolved
|
||||
import { port, auth, starters, mains, rsvpEndDate } from './config';
|
||||
import Person from './data/models/Person';
|
||||
import Settings from './data/models/Settings';
|
||||
import Rollbar from './core/rollbar';
|
||||
import { sendSlackMsg, sendSlackMsgWithDebounce } from './core/slack';
|
||||
import sequelize from './data/sequelize';
|
||||
@@ -318,6 +319,29 @@ app.post('/admin/people/import', (req, res, next) => {
|
||||
}
|
||||
});
|
||||
|
||||
app.post('/admin/settings', (req, res, next) => {
|
||||
try {
|
||||
Settings.destroy({ where: {} }).then(() => {
|
||||
const settings = {
|
||||
slack: !!req.body.slack,
|
||||
email: !!req.body.email,
|
||||
};
|
||||
Settings.create(settings).then(() => {
|
||||
res.redirect(201, '/admin');
|
||||
}).catch(err => {
|
||||
Rollbar.handleError(err);
|
||||
next(err);
|
||||
});
|
||||
}).catch(err => {
|
||||
Rollbar.handleError(err);
|
||||
next(err);
|
||||
});
|
||||
} catch (err) {
|
||||
Rollbar.handleError(err);
|
||||
next(err);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
//
|
||||
// Register server-side rendering middleware
|
||||
|
||||
Reference in New Issue
Block a user