Skip to content

Commit

Permalink
notificationType (default, email) async-labs#18
Browse files Browse the repository at this point in the history
  • Loading branch information
tima101 committed Apr 17, 2019
1 parent a68fee1 commit ac3b010
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 32 deletions.
6 changes: 4 additions & 2 deletions api/server/api/team-member.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,14 @@ router.get('/teams', async (req, res, next) => {

router.post('/discussions/add', async (req, res, next) => {
try {
const { name, teamId, memberIds = [] } = req.body;
const { name, teamId, memberIds = [], notificationType } = req.body;

const discussion = await Discussion.add({
userId: req.user.id,
name,
teamId,
memberIds,
notificationType,
});

res.json({ discussion });
Expand All @@ -122,13 +123,14 @@ router.post('/discussions/add', async (req, res, next) => {

router.post('/discussions/edit', async (req, res, next) => {
try {
const { name, id, memberIds = [] } = req.body;
const { name, id, memberIds = [], notificationType } = req.body;

await Discussion.edit({
userId: req.user.id,
name,
id,
memberIds,
notificationType,
});

res.json({ done: 1 });
Expand Down
18 changes: 15 additions & 3 deletions api/server/models/Discussion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ const mongoSchema = new mongoose.Schema({
required: true,
default: Date.now,
},
notificationType: {
type: String,
enum: ['default', 'email'],
required: true,
default: 'default',
},
});

interface IDiscussionDocument extends mongoose.Document {
Expand All @@ -55,23 +61,27 @@ interface IDiscussionModel extends mongoose.Model<IDiscussionDocument> {
userId,
teamId,
memberIds,
notificationType,
}: {
name: string;
userId: string;
teamId: string;
memberIds: string[];
notificationType: string;
}): Promise<IDiscussionDocument>;

edit({
userId,
id,
name,
memberIds,
notificationType,
}: {
userId: string;
id: string;
name: string;
memberIds: string[];
notificationType: string;
}): Promise<{ teamId: string }>;

delete({ userId, id }: { userId: string; id: string }): Promise<{ teamId: string }>;
Expand Down Expand Up @@ -111,7 +121,7 @@ class DiscussionClass extends mongoose.Model {
return { discussions };
}

public static async add({ name, userId, teamId, memberIds = [] }) {
public static async add({ name, userId, teamId, memberIds = [], notificationType }) {
if (!name) {
throw new Error('Bad data');
}
Expand All @@ -127,10 +137,11 @@ class DiscussionClass extends mongoose.Model {
slug,
memberIds: uniq([userId, ...memberIds]),
createdAt: new Date(),
notificationType,
});
}

public static async edit({ userId, id, name, memberIds = [] }) {
public static async edit({ userId, id, name, memberIds = [], notificationType }) {
if (!id) {
throw new Error('Bad data');
}
Expand All @@ -146,14 +157,15 @@ class DiscussionClass extends mongoose.Model {
});

if (discussion.createdUserId !== userId && team.teamLeaderId !== userId) {
throw new Error('Permission denied. Only create user or team leader can update.');
throw new Error('Permission denied. Only author or team leader can edit Discussion.');
}

await this.updateOne(
{ _id: id },
{
name,
memberIds: uniq([userId, ...memberIds]),
notificationType,
},
);

Expand Down
83 changes: 62 additions & 21 deletions app/components/discussions/CreateDiscussionForm.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import Button from '@material-ui/core/Button';
import Drawer from '@material-ui/core/Drawer';
import FormControl from '@material-ui/core/FormControl';
import FormHelperText from '@material-ui/core/FormHelperText';
import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import Select from '@material-ui/core/Select';
import { withStyles } from '@material-ui/core/styles';
import TextField from '@material-ui/core/TextField';
import { inject } from 'mobx-react';
Expand Down Expand Up @@ -33,6 +38,7 @@ type State = {
memberIds: string[];
disabled: boolean;
content: string;
notificationType: string;
};

class CreateDiscussionForm extends React.Component<Props, State> {
Expand All @@ -41,6 +47,7 @@ class CreateDiscussionForm extends React.Component<Props, State> {
content: '',
memberIds: [],
disabled: false,
notificationType: 'default',
};

public handleClose = () => {
Expand Down Expand Up @@ -73,26 +80,6 @@ class CreateDiscussionForm extends React.Component<Props, State> {
<div style={{ width: '100%', height: '100%', padding: '20px' }}>
<h3>Create new Discussion</h3>
<form style={{ width: '100%', height: '60%' }} onSubmit={this.onSubmit}>
<p />
<div style={{ margin: '20px 0px' }}>
<Button
variant="outlined"
onClick={this.handleClose}
disabled={this.state.disabled}
>
Cancel
</Button>{' '}
<p />
<Button
type="submit"
variant="contained"
color="primary"
disabled={this.state.disabled}
>
Create Discussion
</Button>
{isMobile ? <p /> : null}
</div>
<p />
<br />
<TextField
Expand All @@ -106,13 +93,55 @@ class CreateDiscussionForm extends React.Component<Props, State> {
/>
<p />
{this.renderMemberChooser()}
<p />
<br />

<FormControl>
<InputLabel>Notification type</InputLabel>
<Select
value={this.state.notificationType}
onChange={event => {
this.setState({ notificationType: event.target.value });
}}
required
>
<MenuItem value="default">Default: notification in browser tab.</MenuItem>
<MenuItem value="email">
Default + Email: notification in browser tab and via email.
</MenuItem>
</Select>
<FormHelperText>
Choose how to notify members about new Posts inside Discussion.
</FormHelperText>
</FormControl>
<p />
<br />
<PostEditor
content={this.state.content}
onChanged={content => this.setState({ content })}
members={Array.from(store.currentTeam.members.values())}
/>
<p />
<br />
<div style={{ margin: '20px 0px' }}>
<Button
variant="outlined"
onClick={this.handleClose}
disabled={this.state.disabled}
>
Cancel
</Button>{' '}
<p />
<Button
type="submit"
variant="contained"
color="primary"
disabled={this.state.disabled}
>
Create Discussion
</Button>
{isMobile ? <p /> : null}
</div>
</form>
</div>
</Drawer>
Expand All @@ -134,7 +163,8 @@ class CreateDiscussionForm extends React.Component<Props, State> {
return;
}

const { name, memberIds, content } = this.state;
const { name, memberIds, content, notificationType } = this.state;

if (!name) {
notify('Name is required');
return;
Expand All @@ -145,13 +175,24 @@ class CreateDiscussionForm extends React.Component<Props, State> {
return;
}

if (!notificationType) {
notify('Please select notification type.');
return;
}

if (!memberIds || memberIds.length < 1) {
notify('Please assign at least one person to this Discussion.');
return;
}

NProgress.start();
try {
this.setState({ disabled: true });

const discussion = await currentTeam.addDiscussion({
name,
memberIds,
notificationType,
});

await discussion.addPost(content);
Expand Down
60 changes: 54 additions & 6 deletions app/components/discussions/EditDiscussionForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
import DialogTitle from '@material-ui/core/DialogTitle';
import FormControl from '@material-ui/core/FormControl';
import FormHelperText from '@material-ui/core/FormHelperText';
import InputLabel from '@material-ui/core/InputLabel';
import MenuItem from '@material-ui/core/MenuItem';
import Select from '@material-ui/core/Select';
import TextField from '@material-ui/core/TextField';
import { inject } from 'mobx-react';
import NProgress from 'nprogress';
Expand All @@ -26,6 +31,7 @@ type State = {
memberIds: string[];
disabled: boolean;
discussionId: string;
notificationType: string;
};

class EditDiscussionForm extends React.Component<Props, State> {
Expand All @@ -40,6 +46,7 @@ class EditDiscussionForm extends React.Component<Props, State> {
name: (discussion && discussion.name) || '',
memberIds: (discussion && discussion.memberIds) || [],
discussionId: discussion._id,
notificationType: discussion.notificationType || 'default',
};
}

Expand All @@ -48,6 +55,7 @@ class EditDiscussionForm extends React.Component<Props, State> {
memberIds: [],
disabled: false,
discussionId: '',
notificationType: 'default',
};

public render() {
Expand All @@ -71,7 +79,29 @@ class EditDiscussionForm extends React.Component<Props, State> {
<br />
<p />
{this.renderMemberChooser()}
<p />
<br />
<FormControl>
<InputLabel>Notification type</InputLabel>
<Select
value={this.state.notificationType}
onChange={event => {
this.setState({ notificationType: event.target.value });
}}
required
>
<MenuItem value="default">Default: notification in browser tab.</MenuItem>
<MenuItem value="email">
Default + Email: notification in browser tab and via email.
</MenuItem>
</Select>
<FormHelperText>
Choose how to notify members about new Posts inside Discussion.
</FormHelperText>
</FormControl>
<p />
<br />

<DialogActions>
<Button
color="primary"
Expand Down Expand Up @@ -110,24 +140,42 @@ class EditDiscussionForm extends React.Component<Props, State> {

const { discussion, store } = this.props;
const { currentTeam } = store;

if (!currentTeam) {
notify('Team have not selected');
return;
}

const { name, memberIds } = this.state;
const { name, memberIds, notificationType } = this.state;

if (!name) {
notify('Name is required');
notify('Please name this Discussion.');
return;
}

if (memberIds && !memberIds.includes(discussion.store.currentUser._id)) {
memberIds.push(discussion.store.currentUser._id);
}

if (!memberIds || memberIds.length < 1) {
notify('Please assign at least one person to this Issue.');
return;
}

if (!notificationType) {
notify('Please select notification type.');
return;
}

NProgress.start();
try {
this.setState({ disabled: true });

await discussion.edit({ name, memberIds: [discussion.store.currentUser._id, ...memberIds] });
await discussion.edit({
name,
memberIds: [discussion.store.currentUser._id, ...memberIds],
notificationType,
});

this.setState({ name: '', memberIds: [] });
this.setState({ name: '', memberIds: [], disabled: false, notificationType: 'default' });
notify('You successfully edited Discussion.');
} catch (error) {
console.log(error);
Expand Down
3 changes: 3 additions & 0 deletions app/lib/store/discussion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class Discussion {
public posts: IObservableArray<Post> = observable([]);

public isLoadingPosts = false;
public notificationType: string;

constructor(params) {
this._id = params._id;
Expand Down Expand Up @@ -73,6 +74,7 @@ class Discussion {

this.name = data.name;
this.memberIds.replace(data.memberIds || []);
this.notificationType = data.notificationType;
}

public async edit(data) {
Expand Down Expand Up @@ -135,6 +137,7 @@ decorate(Discussion, {
memberIds: observable,
posts: observable,
isLoadingPosts: observable,
notificationType: observable,

setInitialPosts: action,
loadPosts: action,
Expand Down

0 comments on commit ac3b010

Please sign in to comment.