Commit 878ca8a152800bbb889f6aa5a106a87f8867cf95
1 parent
a8c5a7fb6d
Exists in
master
added signup form on index route for main site
Showing
12 changed files
with
345 additions
and
34 deletions
Show diff stats
imports/client/app/routes.js
... | ... | @@ -37,6 +37,7 @@ import { teachersViewController } from '/imports/client/views/org/admi |
37 | 37 | */ |
38 | 38 | import Signup from '/imports/client/views/nonOrg/enter/SignupView'; |
39 | 39 | import { NonOrgApp } from '/imports/client/layouts/NonOrgApp'; |
40 | +import {NonOrgAppModule} from '/imports/client/views/nonOrg/app/module/Index'; | |
40 | 41 | |
41 | 42 | /** |
42 | 43 | * Invalid Org Components |
... | ... | @@ -73,7 +74,7 @@ const getInvalidOrgRoute = () => ( |
73 | 74 | const getNonOrgRoutes = () => ( |
74 | 75 | <Router history={ browserHistory }> |
75 | 76 | <Route path="/" component={ NonOrgApp }> |
76 | - <IndexRoute name="index" component={ Index } /> | |
77 | + <IndexRoute name="index" component={ NonOrgAppModule } /> | |
77 | 78 | <Route name="signup" path="/signup" component={ Signup } /> |
78 | 79 | <Route path="*" component={ NotFound } /> |
79 | 80 | </Route> | ... | ... |
imports/client/layouts/NonOrgApp.js
1 | 1 | import React, { Component } from 'react'; |
2 | 2 | import { Grid } from 'react-bootstrap'; |
3 | -import {AppNavigationController} from '/imports/client/views/nonOrg/app/module/navigation/index'; | |
4 | 3 | /** |
5 | 4 | * user based redirection will take place here |
6 | 5 | */ |
7 | - export class App extends Component { | |
6 | + export class NonOrgApp extends Component { | |
8 | 7 | constructor(props) { |
9 | 8 | super(props); |
10 | 9 | this.state = { |
... | ... | @@ -14,7 +13,6 @@ import {AppNavigationController} from '/imports/client/views/nonOrg/app/modul |
14 | 13 | render(){ |
15 | 14 | return ( |
16 | 15 | <div> |
17 | - <AppNavigationController /> | |
18 | 16 | <Grid> |
19 | 17 | { this.props.children } |
20 | 18 | </Grid> | ... | ... |
imports/client/views/nonOrg/app/module/AppLayout.js
... | ... | @@ -0,0 +1,53 @@ |
1 | +import _ from 'lodash'; | |
2 | +import { Meteor } from 'meteor/meteor'; | |
3 | +import React, { Component } from 'react'; | |
4 | +import { Link } from 'react-router'; | |
5 | +import { Avatar } from '/imports/client/components/Avatar'; | |
6 | +import { Icon } from '/imports/client/components/Icon'; | |
7 | +import classNames from 'classnames'; | |
8 | + | |
9 | +import { logout } from '/imports/client/app/utils/loginMethods'; | |
10 | + | |
11 | +import Signup from '/imports/client/views/nonOrg/enter/SignupView'; | |
12 | +import { VerifyModule } from '/imports/client/views/verify/module/index'; | |
13 | +import ReactSVG from 'react-svg' | |
14 | + | |
15 | +export class AppLayout extends Component { | |
16 | + render() { | |
17 | + const {user, org} = this.props.data; | |
18 | + console.log(user); | |
19 | + if(!user) { | |
20 | + return ( | |
21 | + <Signup | |
22 | + /> | |
23 | + ); | |
24 | + } | |
25 | + | |
26 | + if(!user.isEmailVerified()) { | |
27 | + return ( | |
28 | + <VerifyModule | |
29 | + pane = {this.props.location.query.verify} | |
30 | + location = {this.props.location} | |
31 | + /> | |
32 | + ); | |
33 | + } | |
34 | + | |
35 | + | |
36 | + return ( | |
37 | + <div className = "appLayout-box"> | |
38 | + <div className = "appLayout-wrapOuter"> | |
39 | + <div className = "appLayout-wrapInner"> | |
40 | + <div className = "appLayout-menuWrap"> | |
41 | + </div> | |
42 | + <div className = "appLayout-contentWrap"> | |
43 | + <div className = "appLayout-content"> | |
44 | + | |
45 | + </div> | |
46 | + </div> | |
47 | + </div> | |
48 | + </div> | |
49 | + </div> | |
50 | + ); | |
51 | + }; | |
52 | + | |
53 | +}; | ... | ... |
imports/client/views/nonOrg/app/module/Index.js
1 | -import React from 'react'; | |
2 | -import { Jumbotron } from 'react-bootstrap'; | |
3 | - | |
4 | -const Index = () => ( | |
5 | - <div className="Index"> | |
6 | - <Jumbotron className="text-center"> | |
7 | - <h2>Base</h2> | |
8 | - <p>A starting point for Meteor applications.</p> | |
9 | - <p><a className="btn btn-success" href="https://themeteorchef.com/base" role="button">Read the Documentation</a></p> | |
10 | - <p style={ { fontSize: '16px', color: '#aaa' } }>Currently at v4.11.1</p> | |
11 | - </Jumbotron> | |
12 | - </div> | |
13 | -); | |
14 | - | |
15 | -export default Index; | |
1 | +// import { AppModule } from '/imports/client/views/app/module/index' | |
2 | +import { | |
3 | + composeWithTracker, | |
4 | + compose, | |
5 | + composeAll | |
6 | + } from 'react-komposer'; | |
7 | +import { AppLayout } from './AppLayout'; | |
8 | +import { Loading } from '/imports/client/components/Loading'; | |
9 | + | |
10 | +import { Users } from '/imports/collections/users/index'; | |
11 | +import { Orgs } from '/imports/collections/orgs/index'; | |
12 | + | |
13 | + | |
14 | +const meteorTick = (props, onData) => { | |
15 | + | |
16 | + const handles = [ | |
17 | + Meteor.subscribe('users.current'), | |
18 | + Meteor.subscribe('orgs.current'), | |
19 | + ]; | |
20 | + | |
21 | + if(_.every(handles, (handle) => (handle.ready()) )) { | |
22 | + const user = Users.current(); | |
23 | + console.log(user); | |
24 | + onData(null, { | |
25 | + data: { | |
26 | + user: user, | |
27 | + org: Orgs.current(), | |
28 | + }, | |
29 | + }); | |
30 | + } | |
31 | + | |
32 | + return () => { | |
33 | + _.each(handles, (handle) => handle.stop() ); | |
34 | + }; | |
35 | +}; | |
36 | + | |
37 | + | |
38 | +const reduxTick = (props, onData) => { | |
39 | + onData(null, { | |
40 | + location: props.location, | |
41 | + data: {} | |
42 | + }); | |
43 | +}; | |
44 | + | |
45 | + | |
46 | +export const NonOrgAppModule = composeAll( | |
47 | + composeWithTracker(meteorTick, Loading), | |
48 | + compose(reduxTick, Loading), | |
49 | +)(AppLayout); | ... | ... |
imports/client/views/nonOrg/app/module/navigation/AppNavigation.js
imports/client/views/nonOrg/app/module/navigation/AuthenticatedNavigation.js
... | ... | @@ -19,11 +19,6 @@ const AuthenticatedNavigation = () => ( |
19 | 19 | <NavItem eventKey={ 2 } href="/documents">Documents</NavItem> |
20 | 20 | </LinkContainer> |
21 | 21 | </Nav> |
22 | - <Nav pullRight> | |
23 | - <NavDropdown eventKey={ 3 } title={ userName() } id="basic-nav-dropdown"> | |
24 | - <MenuItem eventKey={ 3.1 } onClick={ handleLogout }>Logout</MenuItem> | |
25 | - </NavDropdown> | |
26 | - </Nav> | |
27 | 22 | </div> |
28 | 23 | ); |
29 | 24 | ... | ... |
imports/client/views/nonOrg/app/module/navigation/index.js
imports/client/views/verify/EmailPane.js
... | ... | @@ -0,0 +1,110 @@ |
1 | +import React from 'react'; | |
2 | +import { Link } from 'react-router'; | |
3 | +import { If, Case } from '/imports/client/components/Logic'; | |
4 | +import { Bert } from 'meteor/themeteorchef:bert'; | |
5 | + | |
6 | +import { Row, Col, Alert,ControlLabel, | |
7 | + FormGroup, FormControl, Button } from 'react-bootstrap'; | |
8 | + | |
9 | + | |
10 | +export class EmailPane extends React.Component { | |
11 | + | |
12 | + constructor(props) { | |
13 | + super(props); | |
14 | + | |
15 | + this.state = { | |
16 | + email: props.user.emails[0].address, | |
17 | + form: false, | |
18 | + }; | |
19 | + }; | |
20 | + | |
21 | + onUpdate(key, val) { | |
22 | + this.setState({[key]: val}); | |
23 | + }; | |
24 | + | |
25 | + onSetEmail() { | |
26 | + startEmailVerification.call({email: this.state.email}, (err, res)=>{ | |
27 | + Bert.alert('New verification email sent!', 'success'); | |
28 | + | |
29 | + }); | |
30 | + this.setState({form: false}); | |
31 | + }; | |
32 | + | |
33 | + onShowForm() { | |
34 | + this.setState({form: true}); | |
35 | + }; | |
36 | + | |
37 | + renderForm() { | |
38 | + const {user} = this.props; | |
39 | + | |
40 | + return ( | |
41 | + <div className = "wizardPane-box"> | |
42 | + <div className = "wizardPane-section"> | |
43 | + <div className="icon-circle icon-lg"> | |
44 | + <i className="icon icon-simple icon-envelope"></i> | |
45 | + </div> | |
46 | + <div className = "wizardPane-title"> | |
47 | + Set your email address | |
48 | + </div> | |
49 | + <div className = "col-xs-8 horizontalform verifyEmail wizardPane-text"> | |
50 | + <div className="form-row"> | |
51 | + <Col sm={4}> | |
52 | + Enter email | |
53 | + </Col> | |
54 | + <Col sm={8}> | |
55 | + <input | |
56 | + type = "text" | |
57 | + value = {this.state.email} | |
58 | + onChange = {(evt) => this.onUpdate('email', evt.currentTarget.value)} | |
59 | + placeholder = "Email" | |
60 | + /> | |
61 | + </Col> | |
62 | + </div> | |
63 | + | |
64 | + </div> | |
65 | + </div> | |
66 | + <div className = "wizardPane-section wizardPane-footer"> | |
67 | + <div | |
68 | + className = "wizardPane-button btn btn-blue" | |
69 | + onClick = {() => this.onSetEmail()} | |
70 | + > | |
71 | + Send verification email | |
72 | + </div> | |
73 | + </div> | |
74 | + </div> | |
75 | + ); | |
76 | + }; | |
77 | + | |
78 | + renderMessage() { | |
79 | + const {user} = this.props; | |
80 | + | |
81 | + return ( | |
82 | + <div className = "wizardPane-box"> | |
83 | + <div className = "wizardPane-section"> | |
84 | + | |
85 | + <div className = "wizardPane-title"> | |
86 | + <i className="icon-envelope icon"></i> | |
87 | + <h3>Verify your email</h3> | |
88 | + </div> | |
89 | + <div className = "wizardPane-text"> | |
90 | + Check your email โย we sent a verification link to<br/> | |
91 | + {user.emails[0].address} | |
92 | + </div> | |
93 | + </div> | |
94 | + <div className = "wizardPane-section wizardPane-footer"> | |
95 | + <div className="btn" | |
96 | + className = "wizardPane-link" | |
97 | + onClick = {() => this.onShowForm()} | |
98 | + > | |
99 | + Email did not arrive or want to use a different email? | |
100 | + </div> | |
101 | + </div> | |
102 | + </div> | |
103 | + ); | |
104 | + }; | |
105 | + | |
106 | + render() { | |
107 | + return this.state.form ? this.renderForm() : this.renderMessage(); | |
108 | + }; | |
109 | + | |
110 | +}; | ... | ... |
imports/client/views/verify/module/VerifyLayout.js
... | ... | @@ -0,0 +1,65 @@ |
1 | +import _ from 'lodash'; | |
2 | +import { Meteor } from 'meteor/meteor'; | |
3 | + | |
4 | +import React, { Component } from 'react'; | |
5 | +import { Link } from 'react-router'; | |
6 | +import { If, Case } from '/imports/client/components/Logic'; | |
7 | +import { Avatar } from '/imports/client/components/Avatar'; | |
8 | + | |
9 | +import { logout } from '/imports/client/app/utils/loginMethods'; | |
10 | + | |
11 | +import { EmailPane } from '/imports/client/views/verify/EmailPane'; | |
12 | +import ReactSVG from 'react-svg' | |
13 | + | |
14 | + | |
15 | +export class VerifyLayout extends Component { | |
16 | + | |
17 | + render() { | |
18 | + const user = this.props.data.user; | |
19 | + | |
20 | + return ( | |
21 | + <div className = "wizardLayout-box"> | |
22 | + <div className = "wizardLayout-top"> | |
23 | + <div className="container"> | |
24 | + <div className = "wizardLayout-topSpace logo-space-0"> | |
25 | + <ReactSVG | |
26 | + path="/files/images/svg/logo--white.svg" | |
27 | + className="enterPane__logo" | |
28 | + /> | |
29 | + </div> | |
30 | + <div className = "wizardLayout-topGroup"> | |
31 | + <div className = "wizardLayout-topItem"> | |
32 | + <Avatar | |
33 | + user = {user} | |
34 | + size = {20} | |
35 | + small = {true} | |
36 | + /> | |
37 | + | |
38 | + {user.getFullName()} | |
39 | + </div> | |
40 | + <div | |
41 | + className = "wizardLayout-topItem" | |
42 | + onClick = {() => logout()} | |
43 | + > | |
44 | + <i className="icon icon-simple icon-power"></i> | |
45 | + </div> | |
46 | + </div> | |
47 | + </div> | |
48 | + </div> | |
49 | + | |
50 | + <div className = "wizardLayout-wrap"> | |
51 | + <div className = "wizardLayout-content"> | |
52 | + | |
53 | + <EmailPane | |
54 | + user = {user} | |
55 | + /> | |
56 | + | |
57 | + </div> | |
58 | + </div> | |
59 | + </div> | |
60 | + ); | |
61 | + }; | |
62 | + | |
63 | +}; | |
64 | + | |
65 | + | ... | ... |
imports/client/views/verify/module/index.js
... | ... | @@ -0,0 +1,50 @@ |
1 | +// import { VerifyModule } from '/imports/client/views/verify/module/index' | |
2 | +import { | |
3 | + composeWithTracker, | |
4 | + compose, | |
5 | + composeAll | |
6 | + } from 'react-komposer'; | |
7 | +import { VerifyLayout } from './VerifyLayout'; | |
8 | +import { Loading } from '/imports/client/components/Loading'; | |
9 | + | |
10 | +import { Users } from '/imports/collections/users/index'; | |
11 | + | |
12 | + | |
13 | +const meteorTick = (props, onData) => { | |
14 | + | |
15 | + const handles = [ | |
16 | + Meteor.subscribe('users.current'), | |
17 | + ]; | |
18 | + | |
19 | + if(_.every(handles, (handle) => (handle.ready()) )) { | |
20 | + const user = Users.current(); | |
21 | + onData(null, { | |
22 | + data: { | |
23 | + user: user, | |
24 | + }, | |
25 | + }); | |
26 | + } | |
27 | + | |
28 | + return () => { | |
29 | + _.each(handles, (handle) => handle.stop() ); | |
30 | + }; | |
31 | +}; | |
32 | + | |
33 | + | |
34 | +const reduxTick = (props, onData) => { | |
35 | + onData(null, { | |
36 | + data: {} | |
37 | + }); | |
38 | +}; | |
39 | + | |
40 | + | |
41 | +export const VerifyModule = composeAll( | |
42 | + composeWithTracker(meteorTick, Loading), | |
43 | + compose(reduxTick, Loading), | |
44 | +)(VerifyLayout); | |
45 | + | |
46 | + | |
47 | + | |
48 | + | |
49 | + | |
50 | + | ... | ... |
imports/server/accounts/creation.js
... | ... | @@ -12,6 +12,7 @@ Accounts.validateNewUser((user) => { |
12 | 12 | }); |
13 | 13 | |
14 | 14 | Accounts.onCreateUser((options, user) => { |
15 | + | |
15 | 16 | if(options.orgSlug){ |
16 | 17 | orgId = Orgs.insert({ |
17 | 18 | slug: options.orgSlug, |
... | ... | @@ -23,11 +24,16 @@ Accounts.onCreateUser((options, user) => { |
23 | 24 | }], |
24 | 25 | }); |
25 | 26 | } |
27 | + console.log("options"); | |
28 | + console.log(options); | |
29 | + console.log("user"); | |
30 | + console.log(user); | |
26 | 31 | _.assign(user, { |
27 | 32 | role: Users.roles.ADMIN, |
28 | 33 | orgId: orgId, |
29 | - firstName: options.profile.firstName, | |
30 | - lastName: options.profile.lastName, | |
34 | + firstName: options.profile.name.first, | |
35 | + lastName: options.profile.name.last, | |
31 | 36 | }); |
37 | + console.log(user); | |
32 | 38 | return user; |
33 | 39 | }); | ... | ... |
imports/server/emails/verifyEmail.js
1 | 1 | import _ from 'lodash'; |
2 | 2 | import { Accounts } from 'meteor/accounts-base'; |
3 | +import { Orgs } from '/imports/collections/orgs/index'; | |
3 | 4 | |
4 | 5 | Accounts.config({ |
5 | 6 | sendVerificationEmail: true |
... | ... | @@ -10,22 +11,18 @@ Accounts.emailTemplates.verifyEmail = { |
10 | 11 | return '[YoungDesk] Verify Your Email Address'; |
11 | 12 | }, |
12 | 13 | text(user, url) { |
13 | - console.log(user); | |
14 | - if(user.firstName){ | |
15 | - const name = user.firstName; | |
16 | - }else{ | |
17 | - const name = user.profile.firstName; | |
18 | - } | |
19 | 14 | const theUrl = Meteor.absoluteUrl(`back/verifyEmail/${_.last(url.split('/'))}`); |
15 | + org = Orgs.findOne({"_id":user.orgId}); | |
20 | 16 | |
17 | + OrgUrl = theUrl.replace("http://","http://"+org.slug+"."); | |
21 | 18 | return ( |
22 | 19 | ` |
23 | -Hello, ${name}! | |
20 | +Hello, ${user.firstName}! | |
24 | 21 | |
25 | 22 | |
26 | 23 | To verify your email address, visit the following link: |
27 | 24 | |
28 | -${theUrl} | |
25 | +${OrgUrl} | |
29 | 26 | |
30 | 27 | If you did not request this verification, please ignore this email. |
31 | 28 | ... | ... |