Skip to content

Commit

Permalink
MobX for pages: YourProfile, TeamProfile, TeamMembers
Browse files Browse the repository at this point in the history
  • Loading branch information
tima101 committed Jun 27, 2018
1 parent 638b0e8 commit 1e1d218
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 36 deletions.
4 changes: 3 additions & 1 deletion api/server/api/team-leader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,9 @@ router.post('/teams/invite-member', async (req, res) => {

await Invitation.add({ userId: req.user.id, teamId, email });

res.json({ done: 1 });
const newInvitation = await Invitation.add({ userId: req.user.id, teamId, email });

res.json({ newInvitation });
} catch (err) {
console.error(err);
res.json({ error: err.post || err.toString() });
Expand Down
4 changes: 3 additions & 1 deletion api/server/models/Invitation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,14 +124,16 @@ class InvitationClass extends mongoose.Model {
invitationURL: `${ROOT_URL}/invitation?token=${token}`,
});

sendEmail({
await sendEmail({
from: `Kelly from async-await.com <${process.env.EMAIL_SUPPORT_FROM_ADDRESS}>`,
to: [email],
subject: template.subject,
body: template.message,
}).catch(err => {
logger.error('Email sending error:', err);
});

return await this.findOne({ teamId, email }).lean();
}

static async getTeamInvitedUsers({ userId, teamId }) {
Expand Down
10 changes: 5 additions & 5 deletions app/components/teams/InviteMember.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,17 @@ class InviteMember extends React.Component<Props, State> {
NProgress.start();
try {
this.setState({ disabled: true });
await store.currentTeam.inviteMember(email);
await store.currentTeam.inviteMember({ email });

this.setState({ email: '' });
notify('You successfully sent invitation.');
this.props.onClose();
NProgress.done();
notify('You successfully sent invitation.');
} catch (error) {
console.log(error);
notify(error);
} finally {
NProgress.done();
this.props.onClose();
this.setState({ disabled: false });
NProgress.done();
}
};

Expand All @@ -76,6 +75,7 @@ class InviteMember extends React.Component<Props, State> {
<DialogTitle id="invite-memter-dialog-title">Invite member</DialogTitle>
<form onSubmit={this.onSubmit} style={{ padding: '20px' }}>
<TextField
autoFocus
value={this.state.email}
placeholder="Email"
onChange={event => {
Expand Down
18 changes: 16 additions & 2 deletions app/lib/store/team.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,22 @@ export class Team {
}

@action
async inviteMember(email: string) {
return await inviteMember({ teamId: this._id, email });
async inviteMember({ email }: { email: string }) {
this.isLoadingMembers = true;
try {
const { newInvitation } = await inviteMember({ teamId: this._id, email });

runInAction(() => {
this.invitedUsers.set(newInvitation._id, new Invitation(newInvitation));
this.isLoadingMembers = false;
});
} catch (error) {
runInAction(() => {
this.isLoadingMembers = false;
});

throw error;
}
}

@action
Expand Down
17 changes: 16 additions & 1 deletion app/lib/store/user.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { observable } from 'mobx';
import { observable, runInAction, action } from 'mobx';

import { updateProfile } from '../api/team-member';

export class User {
_id: string;
Expand All @@ -11,4 +13,17 @@ export class User {
constructor(params) {
Object.assign(this, params);
}

@action
async updateProfile({ name, avatarUrl }: { name: string; avatarUrl: string }) {
await updateProfile({
name: name,
avatarUrl: avatarUrl,
});

runInAction(() => {
this.displayName = name;
this.avatarUrl = avatarUrl;
});
}
}
8 changes: 2 additions & 6 deletions app/lib/withLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const LOG_OUT_URL = dev ? 'http://localhost:8000' : PRODUCTION_URL_API;

const styleLoadingDiv = {
padding: '20px',
}
};

Router.onRouteChangeStart = () => {
NProgress.start();
Expand Down Expand Up @@ -195,11 +195,7 @@ function withLayout(BaseComponent, { teamRequired = true } = {}) {
return (
<ThemeWrapper pageContext={this.pageContext}>
<Grid item sm={11} xs={12}>
<Link prefetch href="/settings/create-team">
<Button style={{ margin: '20px' }} variant="outlined">
Create team
</Button>
</Link>
<div style={styleLoadingDiv}>Select existing Team or create new Team.</div>
</Grid>
</ThemeWrapper>
);
Expand Down
22 changes: 14 additions & 8 deletions app/pages/settings/team-profile.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as React from 'react';
import Head from 'next/head';
import Router from 'next/router';
import TextField from '@material-ui/core/TextField';
import Button from '@material-ui/core/Button';
import Grid from '@material-ui/core/Grid';
Expand All @@ -12,7 +11,6 @@ import withAuth from '../../lib/withAuth';
import withLayout from '../../lib/withLayout';
import SettingList from '../../components/common/SettingList';
import notify from '../../lib/notifier';
import { updateTeam } from '../../lib/api/team-leader';
import {
getSignedRequestForUpload,
uploadFileUsingSignedPutRequest,
Expand Down Expand Up @@ -45,22 +43,29 @@ class TeamProfile extends React.Component<MyProps, MyState> {
event.preventDefault();
const teamId = this.props.store.currentTeam._id;
const { newName, newAvatarUrl } = this.state;
const { currentTeam } = this.props.store;

if (!newName) {
notify('Team name is required');
return;
}

NProgress.start();

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

const updatedTeam = await updateTeam({ teamId, name: newName, avatarUrl: newAvatarUrl });
await currentTeam.edit({ name: newName, avatarUrl: newAvatarUrl });

// Slack: Note: If you change your workspace’s URL, Slack will automatically redirect from the old to the new address. However, you should still make sure everyone in your workspace knows about the change because the old name will be placed back into the pool and could be used by some other workspace in the future.

// TODO: MobX instead of Router.push
Router.push(`/team/${updatedTeam.slug}/settings/team-settings`);
notify('You successfully updated team profile.');
// TODO: updating team slug creates many problems
// better solution is to assign unique team slug and allow TL to change team name
// team slug can start with 1 and increment by 1
NProgress.done();
notify('You successfully updated team profile. Reloading page...');
} catch (error) {
console.log(error);
NProgress.done();
notify(error);
} finally {
this.setState({ disabled: false });
Expand Down Expand Up @@ -101,7 +106,7 @@ class TeamProfile extends React.Component<MyProps, MyState> {
newAvatarUrl: responseFromApiServerForUpload.url,
});

await updateTeam({ teamId, name: currentTeam.name, avatarUrl: this.state.newAvatarUrl });
await currentTeam.edit({ name: currentTeam.name, avatarUrl: this.state.newAvatarUrl });

NProgress.done();
notify('You successfully uploaded new team logo.');
Expand Down Expand Up @@ -146,6 +151,7 @@ class TeamProfile extends React.Component<MyProps, MyState> {
</Grid>
<Grid item sm={10} xs={12} style={styleGridItem}>
<h3>Team Profile</h3>
<p />
<p>Only the Team Leader can access this page.</p>
<p>Create your own team to become a Team Leader.</p>
</Grid>
Expand Down
27 changes: 15 additions & 12 deletions app/pages/settings/your-profile.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as React from 'react';
import Head from 'next/head';
import Router from 'next/router';
import TextField from '@material-ui/core/TextField';
import Button from '@material-ui/core/Button';
import Grid from '@material-ui/core/Grid';
Expand All @@ -13,7 +12,6 @@ import withLayout from '../../lib/withLayout';
import SettingList from '../../components/common/SettingList';
import notify from '../../lib/notifier';
import {
updateProfile,
getSignedRequestForUpload,
uploadFileUsingSignedPutRequest,
} from '../../lib/api/team-member';
Expand All @@ -27,7 +25,7 @@ const styleGridItem = {
borderRight: '0.5px #aaa solid',
};

type MyProps = { store: Store, isTL: boolean };
type MyProps = { store: Store; isTL: boolean };
type MyState = { newName: string; newAvatarUrl: string; disabled: boolean };

class YourProfile extends React.Component<MyProps, MyState> {
Expand All @@ -44,23 +42,25 @@ class YourProfile extends React.Component<MyProps, MyState> {
onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();

const { currentUser } = this.props.store;

const { newName, newAvatarUrl } = this.state;

if (!newName) {
notify('Name is required');
return;
}

NProgress.start();

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

await updateProfile({ name: newName, avatarUrl: newAvatarUrl });

// TODO: MobX instead of Router.push
Router.push(`/settings/your-profile`);
await currentUser.updateProfile({ name: newName, avatarUrl: newAvatarUrl });
NProgress.done();
notify('You successfully updated your profile.');
} catch (error) {
console.log(error);
NProgress.done();
notify(error);
} finally {
this.setState({ disabled: false });
Expand Down Expand Up @@ -100,12 +100,15 @@ class YourProfile extends React.Component<MyProps, MyState> {
newAvatarUrl: responseFromApiServerForUpload.url,
});

await updateProfile({ name: currentUser.displayName, avatarUrl: this.state.newAvatarUrl });
await currentUser.updateProfile({
name: this.state.newName,
avatarUrl: this.state.newAvatarUrl,
});

NProgress.done();
notify('You successfully uploaded new photo.');
} catch (error) {
console.log(error);
NProgress.done();
notify(error);
NProgress.done();
} finally {
Expand All @@ -120,8 +123,8 @@ class YourProfile extends React.Component<MyProps, MyState> {
return (
<div style={{ padding: '0px', fontSize: '14px', height: '100%' }}>
<Head>
<title>Your Profile</title>
<meta name="description" content="View or edit your Async profile" />
<title>Your profile at Async</title>
<meta name="description" content="description" />
</Head>

<Grid container style={styleGrid}>
Expand Down

0 comments on commit 1e1d218

Please sign in to comment.