Commit 39d8f536dc5551e3902d03d21d74903cfa54243b
1 parent
b48d5cb1c8
Exists in
master
some more cleamup
Showing
27 changed files
with
474 additions
and
185 deletions
Show diff stats
imports/client/components/validationMethods.js
1 | export default class Validation{ | 1 | export default class Validation{ |
2 | 2 | ||
3 | validateEmail (value) { | 3 | validateEmail (value) { |
4 | // regex from http://stackoverflow.com/questions/46155/validate-email-address-in-javascript | 4 | // regex from http://stackoverflow.com/questions/46155/validate-email-address-in-javascript |
5 | var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; | 5 | var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; |
6 | return re.test(value); | 6 | return re.test(value); |
7 | }; | 7 | }; |
8 | 8 | ||
9 | 9 | ||
10 | noSpecialChars(str){ | 10 | noSpecialChars(str){ |
11 | str = String(str); | 11 | str = String(str); |
12 | return !/[~`!#$%\^&*+=\-\[\]\\';,/{}|\\":<>\?]/g.test(str); | 12 | return !/[~`!#$%\^&*+=\-\[\]\\';,/{}|\\":<>\?]/g.test(str); |
13 | } | 13 | } |
14 | 14 | ||
15 | noQwertysAllowed (str){ | 15 | noQwertysAllowed (str){ |
16 | str = String(str); | 16 | str = String(str); |
17 | str = str.toLowerCase(); | 17 | str = str.toLowerCase(); |
18 | if(str.toLowerCase().IndexOf("qwerty") >-1){ | 18 | if(str.toLowerCase().IndexOf("qwerty") >-1){ |
19 | return false; | 19 | return false; |
20 | } else{ | 20 | } else{ |
21 | return true; | 21 | return true; |
22 | } | 22 | } |
23 | } | 23 | } |
24 | 24 | ||
25 | passwordValidation (str){ | 25 | passwordValidation (str){ |
26 | str = String(str); | 26 | str = String(str); |
27 | if(str.length <6){ | 27 | if(str.length <6){ |
28 | return false; | 28 | return false; |
29 | } else{ | 29 | } else{ |
30 | return true; | 30 | return true; |
31 | } | 31 | } |
32 | } | 32 | } |
33 | 33 | ||
34 | isNumberOnly(str){ | 34 | isNumberOnly(str){ |
35 | str = String(str); | 35 | str = String(str); |
36 | if(!/^\d+$/.test(str)){ | 36 | if(!/^\d+$/.test(str)){ |
37 | return false; | 37 | return false; |
38 | }else { | 38 | }else { |
39 | return true; | 39 | return true; |
40 | } | 40 | } |
41 | } | 41 | } |
42 | 42 | ||
43 | isValidACN(str){ | 43 | isValidACN(str){ |
44 | str = String(str); | 44 | str = String(str); |
45 | console.log(str); | ||
46 | if(/^\d+$/.test(str) && str.length ==9){ | 45 | if(/^\d+$/.test(str) && str.length ==9){ |
47 | return true; | 46 | return true; |
48 | } else{ | 47 | } else{ |
49 | return false; | 48 | return false; |
50 | } | 49 | } |
51 | } | 50 | } |
52 | containsNumbers(str){ | 51 | containsNumbers(str){ |
53 | str = String(str); | 52 | str = String(str); |
54 | if(/\d/g.test(str)){ | 53 | if(/\d/g.test(str)){ |
55 | return true; | 54 | return true; |
56 | }else{ | 55 | }else{ |
57 | return false; | 56 | return false; |
58 | } | 57 | } |
59 | } | 58 | } |
60 | 59 | ||
61 | isValidShortCode(str){ | 60 | isValidShortCode(str){ |
62 | str = String(str); | 61 | str = String(str); |
63 | if(containsNoSpecialCharacters(str) && !containsNumbers(str) && str.length <5){ | 62 | if(containsNoSpecialCharacters(str) && !containsNumbers(str) && str.length <5){ |
64 | return true; | 63 | return true; |
65 | } else{ | 64 | } else{ |
66 | return false; | 65 | return false; |
67 | } | 66 | } |
68 | } | 67 | } |
69 | }; | 68 | }; |
70 | 69 |
imports/client/layouts/OrgApp.js
1 | import React from 'react'; | 1 | import React from 'react'; |
2 | import { Grid } from 'react-bootstrap'; | 2 | import { Grid } from 'react-bootstrap'; |
3 | import AppNavigation from '/imports/client/views/org/module/navigation/AppNavigation'; | 3 | import AppNavigation from '/imports/client/views/org/app/module/navigation/AppNavigation'; |
4 | 4 | ||
5 | const App = ({ children }) => ( | 5 | const App = ({ children }) => ( |
6 | <div> | 6 | <div> |
7 | <AppNavigation /> | 7 | <AppNavigation /> |
8 | <Grid> | 8 | <Grid> |
9 | { children } | 9 | { children } |
10 | </Grid> | 10 | </Grid> |
11 | </div> | 11 | </div> |
12 | ); | 12 | ); |
13 | 13 | ||
14 | App.propTypes = { | 14 | App.propTypes = { |
15 | children: React.PropTypes.node, | 15 | children: React.PropTypes.node, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | export default App; | 18 | export default App; |
19 | 19 |
imports/client/views/nonOrg/enter/SignupView.js
1 | import React from 'react'; | 1 | import React from 'react'; |
2 | import { Link } from 'react-router'; | 2 | import { Link } from 'react-router'; |
3 | import { Row, Col, FormGroup, | 3 | import { Row, Col, FormGroup, |
4 | ControlLabel, FormControl, | 4 | ControlLabel, FormControl, |
5 | InputGroup, Button } from 'react-bootstrap'; | 5 | InputGroup, Button } from 'react-bootstrap'; |
6 | import handleSignup from './signup'; | 6 | import handleSignup from './signup'; |
7 | import { Orgs } from '/imports/collections/orgs/index'; | 7 | import { Orgs } from '/imports/collections/orgs/index'; |
8 | 8 | ||
9 | export default class Signup extends React.Component { | 9 | export default class Signup extends React.Component { |
10 | constructor(props) { | 10 | constructor(props) { |
11 | super(props); | 11 | super(props); |
12 | this.state = { | 12 | this.state = { |
13 | orgSlug: "" | 13 | orgSlug: "" |
14 | }; | 14 | }; |
15 | } | 15 | } |
16 | componentWillMount(){ | 16 | componentWillMount(){ |
17 | Meteor.subscribe('allOrgsSlug'); | 17 | Meteor.subscribe('allOrgsSlug'); |
18 | } | 18 | } |
19 | 19 | ||
20 | componentDidMount() { | 20 | componentDidMount() { |
21 | handleSignup({ component: this }); | 21 | handleSignup({ component: this }); |
22 | } | 22 | } |
23 | handleChange(e) { | 23 | handleChange(e) { |
24 | this.setState({ orgSlug: e.target.value }); | 24 | this.setState({ orgSlug: e.target.value }); |
25 | } | 25 | } |
26 | handleSubmit(event) { | 26 | handleSubmit(event) { |
27 | event.preventDefault(); | 27 | event.preventDefault(); |
28 | } | 28 | } |
29 | checkExistingOrgSlug() { | 29 | checkExistingOrgSlug() { |
30 | console.log(this.state.orgSlug); | ||
31 | if(this.state.orgSlug==""){return null} | 30 | if(this.state.orgSlug==""){return null} |
32 | searchOrg = Orgs.find({slug:this.state.orgSlug}).fetch(); | 31 | searchOrg = Orgs.find({slug:this.state.orgSlug}).fetch(); |
33 | if(searchOrg.length>0){ | 32 | if(searchOrg.length>0){ |
34 | return "error" | 33 | return "error" |
35 | }else{ | 34 | }else{ |
36 | return "success" | 35 | return "success" |
37 | } | 36 | } |
38 | } | 37 | } |
39 | render() { | 38 | render() { |
40 | return ( | 39 | return ( |
41 | <div className="Signup"> | 40 | <div className="Signup"> |
42 | <Row> | 41 | <Row> |
43 | <Col xs={ 12 } sm={ 6 } md={ 4 }> | 42 | <Col xs={ 12 } sm={ 6 } md={ 4 }> |
44 | <h4 className="page-header">Sign Up</h4> | 43 | <h4 className="page-header">Sign Up</h4> |
45 | <form | 44 | <form |
46 | ref={ form => (this.signupForm = form) } | 45 | ref={ form => (this.signupForm = form) } |
47 | onSubmit={ this.handleSubmit } | 46 | onSubmit={ this.handleSubmit } |
48 | > | 47 | > |
49 | <Row> | 48 | <Row> |
50 | <Col xs={ 12 } sm={ 12 }> | 49 | <Col xs={ 12 } sm={ 12 }> |
51 | <FormGroup controlId="orgSlugField" validationState={this.checkExistingOrgSlug()}> | 50 | <FormGroup controlId="orgSlugField" validationState={this.checkExistingOrgSlug()}> |
52 | <ControlLabel>Organisation name</ControlLabel> | 51 | <ControlLabel>Organisation name</ControlLabel> |
53 | <InputGroup> | 52 | <InputGroup> |
54 | <FormControl | 53 | <FormControl |
55 | type ="text" | 54 | type ="text" |
56 | ref ="orgSlug" | 55 | ref ="orgSlug" |
57 | name ="orgSlug" | 56 | name ="orgSlug" |
58 | placeholder ="School Name" | 57 | placeholder ="School URL" |
59 | onChange = {(e) => this.handleChange(e)} | 58 | onChange = {(e) => this.handleChange(e)} |
60 | /> | 59 | /> |
61 | <InputGroup.Addon>@yd.com</InputGroup.Addon> | 60 | <InputGroup.Addon>@yd.com</InputGroup.Addon> |
62 | </InputGroup> | 61 | </InputGroup> |
63 | </FormGroup> | 62 | </FormGroup> |
64 | </Col> | 63 | </Col> |
65 | </Row> | 64 | </Row> |
65 | <Row> | ||
66 | <Col xs={ 6 } sm={ 6 }> | ||
67 | <FormGroup> | ||
68 | <ControlLabel>First Name</ControlLabel> | ||
69 | <FormControl | ||
70 | type="text" | ||
71 | ref="orgName" | ||
72 | name="orgName" | ||
73 | placeholder="School Name" | ||
74 | /> | ||
75 | </FormGroup> | ||
76 | </Col> | ||
77 | </Row> | ||
66 | <Row> | 78 | <Row> |
67 | <Col xs={ 6 } sm={ 6 }> | 79 | <Col xs={ 6 } sm={ 6 }> |
68 | <FormGroup> | 80 | <FormGroup> |
69 | <ControlLabel>First Name</ControlLabel> | 81 | <ControlLabel>First Name</ControlLabel> |
70 | <FormControl | 82 | <FormControl |
71 | type="text" | 83 | type="text" |
72 | ref="firstName" | 84 | ref="firstName" |
73 | name="firstName" | 85 | name="firstName" |
74 | placeholder="First Name" | 86 | placeholder="First Name" |
75 | /> | 87 | /> |
76 | </FormGroup> | 88 | </FormGroup> |
77 | </Col> | 89 | </Col> |
78 | <Col xs={ 6 } sm={ 6 }> | 90 | <Col xs={ 6 } sm={ 6 }> |
79 | <FormGroup> | 91 | <FormGroup> |
80 | <ControlLabel>Last Name</ControlLabel> | 92 | <ControlLabel>Last Name</ControlLabel> |
81 | <FormControl | 93 | <FormControl |
82 | type="text" | 94 | type="text" |
83 | ref="lastName" | 95 | ref="lastName" |
84 | name="lastName" | 96 | name="lastName" |
85 | placeholder="Last Name" | 97 | placeholder="Last Name" |
86 | /> | 98 | /> |
87 | </FormGroup> | 99 | </FormGroup> |
88 | </Col> | 100 | </Col> |
89 | </Row> | 101 | </Row> |
90 | <FormGroup> | 102 | <FormGroup> |
91 | <ControlLabel>Email Address</ControlLabel> | 103 | <ControlLabel>Email Address</ControlLabel> |
92 | <FormControl | 104 | <FormControl |
93 | type="text" | 105 | type="text" |
94 | ref="emailAddress" | 106 | ref="emailAddress" |
95 | name="emailAddress" | 107 | name="emailAddress" |
96 | placeholder="Email Address" | 108 | placeholder="Email Address" |
97 | /> | 109 | /> |
98 | </FormGroup> | 110 | </FormGroup> |
99 | <FormGroup> | 111 | <FormGroup> |
100 | <ControlLabel>Password</ControlLabel> | 112 | <ControlLabel>Password</ControlLabel> |
101 | <FormControl | 113 | <FormControl |
102 | type="password" | 114 | type="password" |
103 | ref="password" | 115 | ref="password" |
104 | name="password" | 116 | name="password" |
105 | placeholder="Password" | 117 | placeholder="Password" |
106 | /> | 118 | /> |
107 | </FormGroup> | 119 | </FormGroup> |
108 | <Button type="submit" bsStyle="success">Sign Up</Button> | 120 | <Button type="submit" bsStyle="success">Sign Up</Button> |
109 | </form> | 121 | </form> |
110 | <p>Already have an account? <Link to="/login">Log In</Link>.</p> | 122 | <p>Already have an account? <Link to="/login">Log In</Link>.</p> |
111 | </Col> | 123 | </Col> |
112 | </Row> | 124 | </Row> |
113 | </div> | 125 | </div> |
114 | ); | 126 | ); |
115 | } | 127 | } |
116 | } | 128 | } |
imports/client/views/nonOrg/enter/signup.js
1 | /* eslint-disable no-undef */ | 1 | /* eslint-disable no-undef */ |
2 | 2 | ||
3 | import { browserHistory } from 'react-router'; | 3 | import { browserHistory } from 'react-router'; |
4 | import { Accounts } from 'meteor/accounts-base'; | 4 | import { Accounts } from 'meteor/accounts-base'; |
5 | import { Bert } from 'meteor/themeteorchef:bert'; | 5 | import { Bert } from 'meteor/themeteorchef:bert'; |
6 | import { Loading } from '/imports/client/components/Loading'; | 6 | import { Loading } from '/imports/client/components/Loading'; |
7 | import '/imports/client/components/validation'; | 7 | import '/imports/client/components/validation'; |
8 | import { Orgs } from '/imports/collections/orgs/index'; | 8 | import { Orgs } from '/imports/collections/orgs/index'; |
9 | 9 | ||
10 | let component; | 10 | let component; |
11 | 11 | ||
12 | const getUserData = () => ({ | 12 | const getUserData = () => ({ |
13 | email: document.querySelector('[name="emailAddress"]').value, | 13 | email: document.querySelector('[name="emailAddress"]').value, |
14 | password: document.querySelector('[name="password"]').value, | 14 | password: document.querySelector('[name="password"]').value, |
15 | orgSlug: document.querySelector('[name="orgSlug"]').value, | ||
16 | orgName: document.querySelector('[name="orgName"]').value, | ||
15 | profile: { | 17 | profile: { |
16 | name: { | 18 | name: { |
17 | first: document.querySelector('[name="firstName"]').value, | 19 | first: document.querySelector('[name="firstName"]').value, |
18 | last: document.querySelector('[name="lastName"]').value, | 20 | last: document.querySelector('[name="lastName"]').value, |
19 | }, | 21 | }, |
20 | }, | 22 | }, |
21 | }); | 23 | }); |
22 | 24 | ||
23 | const signup = () => { | 25 | const signup = () => { |
24 | const user = getUserData(); | 26 | const user = getUserData(); |
25 | 27 | ||
26 | Accounts.createUser(user, (error) => { | 28 | Accounts.createUser(user, (error) => { |
27 | if (error) { | 29 | if (error) { |
28 | Bert.alert(error.reason, 'danger'); | 30 | Bert.alert(error.reason, 'danger'); |
29 | } else { | 31 | } else { |
30 | browserHistory.push('/'); | 32 | browserHistory.push('/'); |
31 | Bert.alert('Welcome!', 'success'); | 33 | Bert.alert('Welcome!', 'success'); |
32 | } | 34 | } |
33 | }); | 35 | }); |
34 | }; | 36 | }; |
35 | $.validator.addMethod( | 37 | $.validator.addMethod( |
36 | "uniqueSlug", | 38 | "uniqueSlug", |
37 | function(value, element) { | 39 | function(value, element) { |
38 | slug = Orgs.find({slug:value}).fetch(); | 40 | slug = Orgs.find({slug:value}).fetch(); |
39 | console.log(slug); | ||
40 | if(slug.length>0){ | 41 | if(slug.length>0){ |
41 | return false; | 42 | return false; |
42 | }else{ | 43 | }else{ |
43 | return true | 44 | return true |
44 | } | 45 | } |
45 | }, | 46 | }, |
46 | "Name is Already Taken" | 47 | "Name is Already Taken" |
47 | ); | 48 | ); |
48 | const validate = () => { | 49 | const validate = () => { |
49 | $(component.signupForm).validate({ | 50 | $(component.signupForm).validate({ |
50 | rules: { | 51 | rules: { |
51 | orgSlug: { | 52 | orgSlug: { |
52 | required: true, | 53 | required: true, |
53 | uniqueSlug: true | 54 | uniqueSlug: true |
54 | }, | 55 | }, |
55 | firstName: { | 56 | firstName: { |
56 | required: true, | 57 | required: true, |
57 | }, | 58 | }, |
58 | lastName: { | 59 | lastName: { |
59 | required: true, | 60 | required: true, |
60 | }, | 61 | }, |
61 | emailAddress: { | 62 | emailAddress: { |
62 | required: true, | 63 | required: true, |
63 | email: true, | 64 | email: true, |
64 | }, | 65 | }, |
65 | password: { | 66 | password: { |
66 | required: true, | 67 | required: true, |
67 | minlength: 6, | 68 | minlength: 6, |
68 | }, | 69 | }, |
69 | }, | 70 | }, |
70 | messages: { | 71 | messages: { |
71 | orgSlug: { | 72 | orgSlug: { |
72 | required: 'Choose your school url', | 73 | required: 'Choose your school url', |
73 | uniqueSlug: 'This has already been taken!' | 74 | uniqueSlug: 'This has already been taken!' |
74 | }, | 75 | }, |
75 | firstName: { | 76 | firstName: { |
76 | required: 'First name?', | 77 | required: 'First name?', |
77 | }, | 78 | }, |
78 | lastName: { | 79 | lastName: { |
79 | required: 'Last name?', | 80 | required: 'Last name?', |
80 | }, | 81 | }, |
81 | emailAddress: { | 82 | emailAddress: { |
82 | required: 'Need an email address here.', | 83 | required: 'Need an email address here.', |
83 | email: 'Is this email address legit?', | 84 | email: 'Is this email address legit?', |
84 | }, | 85 | }, |
85 | password: { | 86 | password: { |
86 | required: 'Need a password here.', | 87 | required: 'Need a password here.', |
87 | minlength: 'Use at least six characters, please.', | 88 | minlength: 'Use at least six characters, please.', |
88 | }, | 89 | }, |
89 | }, | 90 | }, |
90 | submitHandler() { signup(); }, | 91 | submitHandler() { signup(); }, |
91 | }); | 92 | }); |
92 | }; | 93 | }; |
93 | 94 | ||
94 | export default function handleSignup(options) { | 95 | export default function handleSignup(options) { |
95 | component = options.component; | 96 | component = options.component; |
96 | validate(); | 97 | validate(); |
97 | } | 98 | } |
imports/client/views/org/app/module/AppLayout.js
File was created | 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 | |||
10 | export class AppLayout extends Component { | ||
11 | |||
12 | |||
13 | |||
14 | |||
15 | |||
16 | |||
17 | render() { | ||
18 | const {user} = this.props.data; | ||
19 | |||
20 | if(!user) { | ||
21 | return ( | ||
22 | <div className="NotLoggedIn"></div> | ||
23 | ); | ||
24 | } | ||
25 | return ( | ||
26 | <div className = "appLayout-box"> | ||
27 | |||
28 | <div className = "appLayout-wrapOuter"> | ||
29 | <div className = "appLayout-wrapInner"> | ||
30 | <div className = "appLayout-menuWrap"> | ||
31 | |||
32 | </div> | ||
33 | <div className = "appLayout-contentWrap"> | ||
34 | <div className = "appLayout-content"> | ||
35 | { this.props.children } | ||
36 | </div> | ||
37 | </div> | ||
38 | </div> | ||
39 | </div> | ||
40 | </div> | ||
41 | ); | ||
42 | }; | ||
43 | |||
44 | }; | ||
45 |
imports/client/views/org/app/module/Index.js
File was created | 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 | ]; | ||
19 | |||
20 | if(_.every(handles, (handle) => (handle.ready()) )) { | ||
21 | const user = Users.current(); | ||
22 | onData(null, { | ||
23 | data: { | ||
24 | user: user, | ||
25 | }, | ||
26 | }); | ||
27 | } | ||
28 | |||
29 | return () => { | ||
30 | _.each(handles, (handle) => handle.stop() ); | ||
31 | }; | ||
32 | }; | ||
33 | |||
34 | |||
35 | const reduxTick = (props, onData) => { | ||
36 | onData(null, { | ||
37 | location: props.location, | ||
38 | data: {} | ||
39 | }); | ||
40 | }; | ||
41 | |||
42 | |||
43 | export const AppModule = composeAll( | ||
44 | composeWithTracker(meteorTick, Loading), | ||
45 | compose(reduxTick, Loading), | ||
46 | )(AppLayout); | ||
47 |
imports/client/views/org/app/module/navigation/AppNavigation.js
File was created | 1 | import React from 'react'; | |
2 | import { Navbar } from 'react-bootstrap'; | ||
3 | import { Link } from 'react-router'; | ||
4 | import PublicNavigation from './PublicNavigation.js'; | ||
5 | import AuthenticatedNavigation from './AuthenticatedNavigation.js'; | ||
6 | import '/imports/client/assets/css/icons/icomoon/styles.css'; | ||
7 | import '/imports/client/assets/css/bootstrap.css'; | ||
8 | import '/imports/client/assets/css/core.css'; | ||
9 | import '/imports/client/assets/css/components.css'; | ||
10 | import '/imports/client/assets/css/colors.css'; | ||
11 | const renderNavigation = hasUser => (hasUser ? <AuthenticatedNavigation /> : <PublicNavigation />); | ||
12 | const AppNavigation = ({ hasUser }) => ( | ||
13 | <Navbar className="navbar-inverse bg-crimson"> | ||
14 | <Navbar.Header> | ||
15 | <Navbar.Brand> | ||
16 | <Link to="/">Home</Link> | ||
17 | </Navbar.Brand> | ||
18 | <Navbar.Toggle /> | ||
19 | </Navbar.Header> | ||
20 | <Navbar.Collapse> | ||
21 | { renderNavigation(hasUser) } | ||
22 | </Navbar.Collapse> | ||
23 | </Navbar> | ||
24 | ); | ||
25 | |||
26 | AppNavigation.propTypes = { | ||
27 | hasUser: React.PropTypes.object, | ||
28 | }; | ||
29 | |||
30 | export default AppNavigation; | ||
31 |
imports/client/views/org/app/module/navigation/AuthenticatedNavigation.js
File was created | 1 | import React from 'react'; | |
2 | import { browserHistory } from 'react-router'; | ||
3 | import { LinkContainer } from 'react-router-bootstrap'; | ||
4 | import { Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap'; | ||
5 | import { Meteor } from 'meteor/meteor'; | ||
6 | |||
7 | const handleLogout = () => Meteor.logout(() => browserHistory.push('/login')); | ||
8 | |||
9 | const userName = () => { | ||
10 | const user = Meteor.user(); | ||
11 | const name = user && user.profile ? user.profile.name : ''; | ||
12 | return user ? `${name.first} ${name.last}` : ''; | ||
13 | }; | ||
14 | |||
15 | const AuthenticatedNavigation = () => ( | ||
16 | <div> | ||
17 | <Nav> | ||
18 | <LinkContainer to="/documents"> | ||
19 | <NavItem eventKey={ 2 } href="/documents">Documents</NavItem> | ||
20 | </LinkContainer> | ||
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 | </div> | ||
28 | ); | ||
29 | |||
30 | export default AuthenticatedNavigation; | ||
31 |
imports/client/views/org/app/module/navigation/Loading.js
File was created | 1 | import React from 'react'; | |
2 | |||
3 | const Loading = () => ( | ||
4 | <svg | ||
5 | version="1.1" | ||
6 | className="Loading" | ||
7 | xmlns="http://www.w3.org/2000/svg" | ||
8 | x="0px" | ||
9 | y="0px" | ||
10 | width="40px" | ||
11 | height="40px" | ||
12 | viewBox="0 0 40 40" | ||
13 | enableBackground="new 0 0 40 40"> | ||
14 | <path | ||
15 | opacity="1.0" | ||
16 | fill="#eee" | ||
17 | d="M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946, | ||
18 | 14.946,14.946s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201, | ||
19 | 5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634c0-6.425, | ||
20 | 5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834, | ||
21 | 26.541,26.626,31.749,20.201,31.749z"/> | ||
22 | <path | ||
23 | fill="#da5347" | ||
24 | d="M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0 | ||
25 | C22.32,8.481,24.301,9.057,26.013,10.047z"> | ||
26 | </path> | ||
27 | </svg> | ||
28 | ); | ||
29 | |||
30 | export default Loading; | ||
31 |
imports/client/views/org/app/module/navigation/PublicNavigation.js
File was created | 1 | import React from 'react'; | |
2 | import { LinkContainer } from 'react-router-bootstrap'; | ||
3 | import { Nav, NavItem } from 'react-bootstrap'; | ||
4 | |||
5 | const PublicNavigation = () => ( | ||
6 | <Nav pullRight> | ||
7 | <LinkContainer to="signup"> | ||
8 | <NavItem eventKey={ 1 } href="/signup">Sign Up</NavItem> | ||
9 | </LinkContainer> | ||
10 | <LinkContainer to="login"> | ||
11 | <NavItem eventKey={ 2 } href="/login">Log In</NavItem> | ||
12 | </LinkContainer> | ||
13 | </Nav> | ||
14 | ); | ||
15 | |||
16 | export default PublicNavigation; | ||
17 |
imports/client/views/org/app/module/navigation/index.js
File was created | 1 | import { composeWithTracker } from 'react-komposer'; | |
2 | import { Meteor } from 'meteor/meteor'; | ||
3 | import AppNavigation from '../components/AppNavigation.js'; | ||
4 | |||
5 | const composer = (props, onData) => onData(null, { hasUser: Meteor.user() }); | ||
6 | |||
7 | export default composeWithTracker(composer, {}, {}, { pure: false })(AppNavigation); | ||
8 |
imports/client/views/org/enter/login/LoginView.js
1 | import React,{ Component } from 'react'; | 1 | import React,{ Component } from 'react'; |
2 | import { Link } from 'react-router'; | 2 | import { Link } from 'react-router'; |
3 | import { Row, Col, FormGroup, | 3 | import { Row, Col, FormGroup, |
4 | ControlLabel, FormControl, | 4 | ControlLabel, FormControl, |
5 | Button } from 'react-bootstrap'; | 5 | Button } from 'react-bootstrap'; |
6 | import handleLogin from './login'; | 6 | import handleLogin from './login'; |
7 | 7 | ||
8 | export class LoginView extends React.Component { | 8 | export class LoginView extends React.Component { |
9 | componentDidMount() { | 9 | componentDidMount() { |
10 | console.log(this); | ||
11 | handleLogin({ component: this }); | 10 | handleLogin({ component: this }); |
12 | } | 11 | } |
13 | 12 | ||
14 | handleSubmit(event) { | 13 | handleSubmit(event) { |
15 | event.preventDefault(); | 14 | event.preventDefault(); |
16 | } | 15 | } |
17 | 16 | ||
18 | render() { | 17 | render() { |
19 | return ( | 18 | return ( |
20 | <div className="Login"> | 19 | <div className="Login"> |
21 | <Row> | 20 | <Row> |
22 | <Col xs={ 12 } sm={ 6 } md={ 4 }> | 21 | <Col xs={ 12 } sm={ 6 } md={ 4 }> |
23 | <h4 className="page-header">Login</h4> | 22 | <h4 className="page-header">Login</h4> |
24 | <form | 23 | <form |
25 | ref={ form => (this.loginForm = form) } | 24 | ref={ form => (this.loginForm = form) } |
26 | className="login" | 25 | className="login" |
27 | onSubmit={ this.handleSubmit } | 26 | onSubmit={ this.handleSubmit } |
28 | > | 27 | > |
29 | <FormGroup> | 28 | <FormGroup> |
30 | <ControlLabel>Email Address</ControlLabel> | 29 | <ControlLabel>Email Address</ControlLabel> |
31 | <FormControl | 30 | <FormControl |
32 | type="email" | 31 | type="email" |
33 | ref="emailAddress" | 32 | ref="emailAddress" |
34 | name="emailAddress" | 33 | name="emailAddress" |
35 | placeholder="Email Address" | 34 | placeholder="Email Address" |
36 | /> | 35 | /> |
37 | </FormGroup> | 36 | </FormGroup> |
38 | <FormGroup> | 37 | <FormGroup> |
39 | <ControlLabel> | 38 | <ControlLabel> |
40 | <span className="pull-left">Password</span> | 39 | <span className="pull-left">Password</span> |
41 | <Link className="pull-right" to="/recover-password">Forgot Password?</Link> | 40 | <Link className="pull-right" to="/recover-password">Forgot Password?</Link> |
42 | </ControlLabel> | 41 | </ControlLabel> |
43 | <FormControl | 42 | <FormControl |
44 | type="password" | 43 | type="password" |
45 | ref="password" | 44 | ref="password" |
46 | name="password" | 45 | name="password" |
47 | placeholder="Password" | 46 | placeholder="Password" |
48 | /> | 47 | /> |
49 | </FormGroup> | 48 | </FormGroup> |
50 | <Button type="submit" bsStyle="success">Login</Button> | 49 | <Button type="submit" bsStyle="success">Login</Button> |
51 | </form> | 50 | </form> |
52 | </Col> | 51 | </Col> |
53 | </Row> | 52 | </Row> |
54 | </div> | 53 | </div> |
55 | ); | 54 | ); |
56 | } | 55 | } |
57 | } | 56 | } |
58 | 57 |
imports/client/views/org/module/Index.js
1 | import React from 'react'; | File was deleted | |
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; | ||
16 | 1 | import React from 'react'; |
imports/client/views/org/module/navigation/AppNavigation.js
1 | import React from 'react'; | File was deleted | |
2 | import { Navbar } from 'react-bootstrap'; | ||
3 | import { Link } from 'react-router'; | ||
4 | import PublicNavigation from './PublicNavigation.js'; | ||
5 | import AuthenticatedNavigation from './AuthenticatedNavigation.js'; | ||
6 | import '/imports/client/assets/css/icons/icomoon/styles.css'; | ||
7 | import '/imports/client/assets/css/bootstrap.css'; | ||
8 | import '/imports/client/assets/css/core.css'; | ||
9 | import '/imports/client/assets/css/components.css'; | ||
10 | import '/imports/client/assets/css/colors.css'; | ||
11 | const renderNavigation = hasUser => (hasUser ? <AuthenticatedNavigation /> : <PublicNavigation />); | ||
12 | console.log(React.PropTypes); | ||
13 | const AppNavigation = ({ hasUser }) => ( | ||
14 | <Navbar className="navbar-inverse bg-crimson"> | ||
15 | <Navbar.Header> | ||
16 | <Navbar.Brand> | ||
17 | <Link to="/">Home</Link> | ||
18 | </Navbar.Brand> | ||
19 | <Navbar.Toggle /> | ||
20 | </Navbar.Header> | ||
21 | <Navbar.Collapse> | ||
22 | { renderNavigation(hasUser) } | ||
23 | </Navbar.Collapse> | ||
24 | </Navbar> | ||
25 | ); | ||
26 | |||
27 | AppNavigation.propTypes = { | ||
28 | hasUser: React.PropTypes.object, | ||
29 | }; | ||
30 | |||
31 | export default AppNavigation; | ||
32 | 1 | import React from 'react'; |
imports/client/views/org/module/navigation/AuthenticatedNavigation.js
1 | import React from 'react'; | File was deleted | |
2 | import { browserHistory } from 'react-router'; | ||
3 | import { LinkContainer } from 'react-router-bootstrap'; | ||
4 | import { Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap'; | ||
5 | import { Meteor } from 'meteor/meteor'; | ||
6 | |||
7 | const handleLogout = () => Meteor.logout(() => browserHistory.push('/login')); | ||
8 | |||
9 | const userName = () => { | ||
10 | const user = Meteor.user(); | ||
11 | const name = user && user.profile ? user.profile.name : ''; | ||
12 | return user ? `${name.first} ${name.last}` : ''; | ||
13 | }; | ||
14 | |||
15 | const AuthenticatedNavigation = () => ( | ||
16 | <div> | ||
17 | <Nav> | ||
18 | <LinkContainer to="/documents"> | ||
19 | <NavItem eventKey={ 2 } href="/documents">Documents</NavItem> | ||
20 | </LinkContainer> | ||
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 | </div> | ||
28 | ); | ||
29 | |||
30 | export default AuthenticatedNavigation; | ||
31 | 1 | import React from 'react'; |
imports/client/views/org/module/navigation/Loading.js
1 | import React from 'react'; | File was deleted | |
2 | |||
3 | const Loading = () => ( | ||
4 | <svg | ||
5 | version="1.1" | ||
6 | className="Loading" | ||
7 | xmlns="http://www.w3.org/2000/svg" | ||
8 | x="0px" | ||
9 | y="0px" | ||
10 | width="40px" | ||
11 | height="40px" | ||
12 | viewBox="0 0 40 40" | ||
13 | enableBackground="new 0 0 40 40"> | ||
14 | <path | ||
15 | opacity="1.0" | ||
16 | fill="#eee" | ||
17 | d="M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946, | ||
18 | 14.946,14.946s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201, | ||
19 | 5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634c0-6.425, | ||
20 | 5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834, | ||
21 | 26.541,26.626,31.749,20.201,31.749z"/> | ||
22 | <path | ||
23 | fill="#da5347" | ||
24 | d="M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0 | ||
25 | C22.32,8.481,24.301,9.057,26.013,10.047z"> | ||
26 | </path> | ||
27 | </svg> | ||
28 | ); | ||
29 | |||
30 | export default Loading; | ||
31 | 1 | import React from 'react'; |
imports/client/views/org/module/navigation/PublicNavigation.js
1 | import React from 'react'; | File was deleted | |
2 | import { LinkContainer } from 'react-router-bootstrap'; | ||
3 | import { Nav, NavItem } from 'react-bootstrap'; | ||
4 | |||
5 | const PublicNavigation = () => ( | ||
6 | <Nav pullRight> | ||
7 | <LinkContainer to="signup"> | ||
8 | <NavItem eventKey={ 1 } href="/signup">Sign Up</NavItem> | ||
9 | </LinkContainer> | ||
10 | <LinkContainer to="login"> | ||
11 | <NavItem eventKey={ 2 } href="/login">Log In</NavItem> | ||
12 | </LinkContainer> | ||
13 | </Nav> | ||
14 | ); | ||
15 | |||
16 | export default PublicNavigation; | ||
17 | 1 | import React from 'react'; |
imports/client/views/org/module/navigation/index.js
1 | import { composeWithTracker } from 'react-komposer'; | File was deleted | |
2 | import { Meteor } from 'meteor/meteor'; | ||
3 | import AppNavigation from '../components/AppNavigation.js'; | ||
4 | |||
5 | const composer = (props, onData) => onData(null, { hasUser: Meteor.user() }); | ||
6 | |||
7 | export default composeWithTracker(composer, {}, {}, { pure: false })(AppNavigation); | ||
8 | 1 | import { composeWithTracker } from 'react-komposer'; |
imports/collections/orgs/index.js
1 | // import { Orgs } from '/imports/collections/orgs/index'; | 1 | // import { Orgs } from '/imports/collections/orgs/index'; |
2 | 2 | ||
3 | import _ from 'lodash'; | 3 | import _ from 'lodash'; |
4 | import { Mongo } from 'meteor/mongo'; | 4 | import { Mongo } from 'meteor/mongo'; |
5 | import { SimpleSchema } from 'meteor/aldeed:simple-schema'; | 5 | import { SimpleSchema } from 'meteor/aldeed:simple-schema'; |
6 | 6 | ||
7 | import { Users } from '/imports/collections/users/index'; | 7 | import { Users } from '/imports/collections/users/index'; |
8 | 8 | ||
9 | class Org { | 9 | class Org { |
10 | constructor(doc) { | 10 | constructor(doc) { |
11 | _.assign(this, doc); | 11 | _.assign(this, doc); |
12 | }; | 12 | }; |
13 | 13 | ||
14 | getUserIds() { | 14 | getUserIds() { |
15 | return _.filter(_.map(this.users, 'userId')); | 15 | return _.filter(_.map(this.users, 'userId')); |
16 | }; | 16 | }; |
17 | 17 | ||
18 | getInvitationIds() { | 18 | getInvitationIds() { |
19 | return _.filter(_.map(this.users, 'invitationId')); | 19 | return _.filter(_.map(this.users, 'invitationId')); |
20 | }; | 20 | }; |
21 | 21 | ||
22 | areDetailsDone() { | 22 | areDetailsDone() { |
23 | return ( | 23 | return ( |
24 | this.name && this.name.length && | 24 | this.name && this.name.length && |
25 | this.shortCode && this.shortCode.length && | 25 | this.shortCode && this.shortCode.length && |
26 | this.acn && this.acn.length | 26 | this.acn && this.acn.length |
27 | ); | 27 | ); |
28 | }; | 28 | }; |
29 | 29 | ||
30 | ifCurrentUserIsAdmin(){ | 30 | ifCurrentUserIsAdmin(){ |
31 | const user = Users.current(); | 31 | const user = Users.current(); |
32 | if(!user) return null; | 32 | if(!user) return null; |
33 | for(let i = 0; i < this.users.length; ++i) { | 33 | for(let i = 0; i < this.users.length; ++i) { |
34 | if( | 34 | if( |
35 | (this.users[i].role == "SECRETARY") | 35 | (this.users[i].role == "SECRETARY") |
36 | && this.users[i].userId == user._id | 36 | && this.users[i].userId == user._id |
37 | ) { | 37 | ) { |
38 | return true; | 38 | return true; |
39 | } | 39 | } |
40 | } | 40 | } |
41 | return false; | 41 | return false; |
42 | } | 42 | } |
43 | 43 | ||
44 | 44 | ||
45 | }; | 45 | }; |
46 | export { Org }; | 46 | export { Org }; |
47 | 47 | ||
48 | class OrgsCollection extends Mongo.Collection { | 48 | class OrgsCollection extends Mongo.Collection { |
49 | insert(item, callback) { | 49 | insert(item, callback) { |
50 | _.assign(item, { | 50 | _.assign(item, { |
51 | createdAt: new Date().getTime(), | 51 | createdAt: new Date().getTime(), |
52 | }); | 52 | }); |
53 | return super.insert(item, callback); | 53 | return super.insert(item, callback); |
54 | }; | 54 | }; |
55 | }; | 55 | }; |
56 | 56 | ||
57 | export const Orgs = new OrgsCollection('Orgs', { | 57 | export const Orgs = new OrgsCollection('Orgs', { |
58 | transform: (item) => { | 58 | transform: (item) => { |
59 | return new Org(item); | 59 | return new Org(item); |
60 | }, | 60 | }, |
61 | }); | 61 | }); |
62 | 62 | ||
63 | _.assign(Orgs, { | 63 | _.assign(Orgs, { |
64 | allOrgsCurrentUser: () => { | 64 | allOrgsCurrentUser: () => { |
65 | const user = Users.current(); | 65 | const user = Users.current(); |
66 | if(!user) return null; | 66 | if(!user) return null; |
67 | return Orgs.find({'users.userId': user._id}); | 67 | return Orgs.find({'users.userId': user._id}); |
68 | }, | 68 | }, |
69 | current: () => { | 69 | current: () => { |
70 | const user = Users.current(); | 70 | const user = Users.current(); |
71 | if(!user) return null; | 71 | if(!user) return null; |
72 | return Orgs.findOne({_id: user.orgId}); | 72 | return Orgs.findOne({_id: user.orgId}); |
73 | }, | 73 | }, |
74 | currentOrgUsers: () => { | 74 | currentOrgUsers: () => { |
75 | const OrgsArr = Orgs.current(); | 75 | const OrgsArr = Orgs.current(); |
76 | if(!OrgsArr) return null; | 76 | if(!OrgsArr) return null; |
77 | return OrgsArr.users; | 77 | return OrgsArr.users; |
78 | }, | 78 | }, |
79 | 79 | ||
80 | }); | 80 | }); |
81 | 81 | ||
82 | Orgs.deny({ | 82 | Orgs.deny({ |
83 | insert() { return true; }, | 83 | insert() { return true; }, |
84 | update() { return true; }, | 84 | update() { return true; }, |
85 | remove() { return true; }, | 85 | remove() { return true; }, |
86 | }); | 86 | }); |
87 | 87 | ||
88 | Orgs.schema = new SimpleSchema({ | 88 | Orgs.schema = new SimpleSchema({ |
89 | 89 | ||
90 | name: { type: String, }, | 90 | name: { type: String }, |
91 | slug: { type: String, optional: true}, | 91 | slug: { type: String }, |
92 | address: { type: String, optional: true}, | 92 | address: { type: String, optional: true}, |
93 | users: { | 93 | users: { |
94 | type: [new SimpleSchema({ | 94 | type: [new SimpleSchema({ |
95 | userId: { type: String, optional: true}, | 95 | userId: { type: String, optional: true}, |
96 | invitationId: { type: String, optional: true}, | 96 | invitationId: { type: String, optional: true}, |
97 | role: { type: String, }, | 97 | role: { type: String, }, |
98 | email: { type: String, optional: true}, | 98 | email: { type: String, optional: true}, |
99 | })], | 99 | })], |
100 | }, | 100 | }, |
101 | createdAt: { type: Date, autoValue: function(){return new Date();}}, | 101 | createdAt: { type: Date, autoValue: function(){return new Date();}}, |
102 | 102 | ||
103 | }); | 103 | }); |
104 | 104 | ||
105 | 105 | ||
106 | 106 | ||
107 | Orgs.attachSchema(Orgs.schema); | 107 | Orgs.attachSchema(Orgs.schema); |
108 | 108 | ||
109 | Orgs.publicFields = { | 109 | Orgs.publicFields = { |
110 | name: 1, | 110 | name: 1, |
111 | slug: 1, | 111 | slug: 1, |
112 | createdAt: 1, | 112 | createdAt: 1, |
113 | }; | 113 | }; |
114 | 114 |
imports/collections/students/index.js
File was created | 1 | // import { Users } from '/imports/collections/users/index'; | |
2 | // import { Users } from '/imports/collections/users/index'; | ||
3 | |||
4 | import _ from 'lodash'; | ||
5 | import { Meteor } from 'meteor/meteor'; | ||
6 | import { Mongo } from 'meteor/mongo'; | ||
7 | import { SimpleSchema } from 'meteor/aldeed:simple-schema'; | ||
8 | |||
9 | import { Orgs } from '/imports/collections/orgs/index'; | ||
10 | |||
11 | class User { | ||
12 | |||
13 | constructor(doc) { | ||
14 | _.assign(this, doc); | ||
15 | }; | ||
16 | |||
17 | isEmailVerified() { | ||
18 | return !! _.find(this.emails, x => x.verified); | ||
19 | }; | ||
20 | |||
21 | isPhoneVerified() { | ||
22 | return !! _.find(this.phones, x => x.verified); | ||
23 | }; | ||
24 | |||
25 | isIdentityVerified() { | ||
26 | return !! _.find(this.identities, x => x.verified); | ||
27 | }; | ||
28 | |||
29 | getRole() { | ||
30 | const org = Orgs.findOne({_id: this.orgId}); | ||
31 | if(!org) return null; | ||
32 | const connection = _.find(org.users, {userId: this._id}); | ||
33 | if(!connection) return null; | ||
34 | return connection.role; | ||
35 | }; | ||
36 | |||
37 | getFullName() { | ||
38 | return `${this.firstName} ${this.lastName}`; | ||
39 | }; | ||
40 | getFirstName() { | ||
41 | return `${this.firstName}`; | ||
42 | }; | ||
43 | getLastName() { | ||
44 | return `${this.lastName}`; | ||
45 | }; | ||
46 | getEmail() { | ||
47 | return `${this.emails[0].address}`; | ||
48 | }; | ||
49 | getOrganization(){ | ||
50 | return `${this.orgId}`; | ||
51 | }; | ||
52 | |||
53 | getNameByUserId(userId){ | ||
54 | var user = Users.findOne({"_id":userId}); | ||
55 | return user.firstName + " " + user.lastName; | ||
56 | } | ||
57 | getAvatarUrl() { | ||
58 | let random = parseInt(this._id.substr(0, 4), 36); | ||
59 | random = '' + (random % 32); | ||
60 | while(random.length < 3) random = '0' + random; | ||
61 | return `/files/random/random${ random }.png`; | ||
62 | }; | ||
63 | }; | ||
64 | |||
65 | export { User }; | ||
66 | |||
67 | |||
68 | const transform = function(doc) { | ||
69 | return new User(doc); | ||
70 | }; | ||
71 | |||
72 | export const Users = { | ||
73 | |||
74 | current: function() { | ||
75 | return Meteor.users.findOne({_id: Meteor.userId()}, _.extend({transform: transform})); | ||
76 | }, | ||
77 | |||
78 | find: function(selector, options) { | ||
79 | return Meteor.users.find(selector || {}, _.extend({transform: transform}, options)); | ||
80 | }, | ||
81 | |||
82 | findOne: function(selector, options) { | ||
83 | return Meteor.users.findOne(selector || {}, _.extend({transform: transform}, options)); | ||
84 | }, | ||
85 | |||
86 | insert: _.bind(Meteor.users.insert, Meteor.users), | ||
87 | update: _.bind(Meteor.users.update, Meteor.users), | ||
88 | remove: _.bind(Meteor.users.remove, Meteor.users), | ||
89 | allow: _.bind(Meteor.users.allow, Meteor.users), | ||
90 | deny: _.bind(Meteor.users.deny, Meteor.users), | ||
91 | attachSchema: _.bind(Meteor.users.attachSchema, Meteor.users), | ||
92 | |||
93 | }; | ||
94 | |||
95 | |||
96 | Users.deny({ | ||
97 | insert() { return true; }, | ||
98 | update() { return true; }, | ||
99 | remove() { return true; }, | ||
100 | }); | ||
101 | |||
102 | Users.roles = { | ||
103 | 'STUDENT': 'STUDENT', | ||
104 | 'TEACHER': 'TEACHER', | ||
105 | 'ADMIN': 'ADMIN', | ||
106 | 'PARENT': 'PARENT' | ||
107 | }; | ||
108 | |||
109 | |||
110 | Users.schema = new SimpleSchema({ | ||
111 | roles: { type: String }, | ||
112 | orgId: { type: String }, | ||
113 | admissionId: { type: String, optional: true }, | ||
114 | enrollmentDate: { type: String, optional: true }, | ||
115 | address: { type: String, optional: true }, | ||
116 | prefix: { type: String, optional: true }, | ||
117 | firstName: { type: String, optional: true }, | ||
118 | middlename: { type: String, optional: true }, | ||
119 | lastName: { type: String, optional: true }, | ||
120 | gender: { type: String, optional: true }, | ||
121 | dob: { type: String, optional: true }, | ||
122 | rollNo: { type: String, optional: true }, | ||
123 | class: { type: String, optional: true }, | ||
124 | section: { type: String, optional: true }, | ||
125 | bloodGroup: { type: String, optional: true }, | ||
126 | community: { type: String, optional: true }, | ||
127 | nationality: { type: String, optional: true }, | ||
128 | motherTongue: { type: String, optional: true }, | ||
129 | motherTongue: { type: String, optional: true }, | ||
130 | religion: { type: String, optional: true }, | ||
131 | permanentAddress: { | ||
132 | type: new SimpleSchema({ | ||
133 | home: { type: String, optional: true }, | ||
134 | street: { type: String, optional: true }, | ||
135 | town: { type: String, optional: true }, | ||
136 | city: { type: String, optional: true }, | ||
137 | state: { type: String, optional: true }, | ||
138 | zip: { type: String, optional: true }, | ||
139 | }), | ||
140 | }, | ||
141 | parent: { | ||
142 | type: [new SimpleSchema({ | ||
143 | id: { type: String, }, | ||
144 | relatinship: { type: Boolean, }, | ||
145 | })], | ||
146 | minCount: 1, | ||
147 | }, | ||
148 | emails: { | ||
149 | type: [new SimpleSchema({ | ||
150 | address: { type: String, }, | ||
151 | verified: { type: Boolean, }, | ||
152 | })], | ||
153 | }, | ||
154 | prevInstitute: { | ||
155 | type: [new SimpleSchema({ | ||
156 | name: { type: String, }, | ||
157 | fromYear: { type: Boolean, }, | ||
158 | toYear: { type: Boolean, }, | ||
159 | ydId: { type: Boolean, }, | ||
160 | })], | ||
161 | optional: true | ||
162 | }, | ||
163 | |||
164 | phones: { | ||
165 | type: [new SimpleSchema({ | ||
166 | country: { type: String, }, | ||
167 | prefix: { type: String, }, | ||
168 | number: { type: String, }, | ||
169 | verified: { type: Boolean, }, | ||
170 | })], | ||
171 | optional: true | ||
172 | }, | ||
173 | |||
174 | services: { | ||
175 | type: Object, | ||
176 | optional: true, | ||
177 | blackbox: true, | ||
178 | }, | ||
179 | |||
180 | isMetaUser: { type: Boolean, optional: true }, | ||
181 | |||
182 | createdAt: { type: Date, autoValue: function(){return new Date();}} | ||
183 | |||
184 | }); | ||
185 | |||
186 | Users.attachSchema(Users.schema); | ||
187 | |||
188 | Users.privateFields = { | ||
189 | orgId: 1, | ||
190 | address: 1, | ||
191 | |||
192 | firstName: 1, | ||
193 | lastName: 1, | ||
194 | emails: 1, | ||
195 | phones: 1, | ||
196 | |||
197 | isMetaUser: 1, | ||
198 | createdAt: 1, | ||
199 | }; | ||
200 | |||
201 | Users.publicFields = { | ||
202 | firstName: 1, | ||
203 | lastName: 1, | ||
204 | emails: 1, | ||
205 | |||
206 | createdAt: 1, | ||
207 | }; | ||
208 |
imports/collections/users/index.js
1 | // import { Users } from '/imports/collections/users/index'; | 1 | // import { Users } from '/imports/collections/users/index'; |
2 | // import { Users } from '/imports/collections/users/index'; | 2 | // import { Users } from '/imports/collections/users/index'; |
3 | 3 | ||
4 | import _ from 'lodash'; | 4 | import _ from 'lodash'; |
5 | import { Meteor } from 'meteor/meteor'; | 5 | import { Meteor } from 'meteor/meteor'; |
6 | import { Mongo } from 'meteor/mongo'; | 6 | import { Mongo } from 'meteor/mongo'; |
7 | import { SimpleSchema } from 'meteor/aldeed:simple-schema'; | 7 | import { SimpleSchema } from 'meteor/aldeed:simple-schema'; |
8 | 8 | ||
9 | import { Orgs } from '/imports/collections/orgs/index'; | 9 | import { Orgs } from '/imports/collections/orgs/index'; |
10 | 10 | ||
11 | class User { | 11 | class User { |
12 | 12 | ||
13 | constructor(doc) { | 13 | constructor(doc) { |
14 | _.assign(this, doc); | 14 | _.assign(this, doc); |
15 | }; | 15 | }; |
16 | 16 | ||
17 | isEmailVerified() { | 17 | isEmailVerified() { |
18 | return !! _.find(this.emails, x => x.verified); | 18 | return !! _.find(this.emails, x => x.verified); |
19 | }; | 19 | }; |
20 | 20 | ||
21 | isPhoneVerified() { | 21 | isPhoneVerified() { |
22 | return !! _.find(this.phones, x => x.verified); | 22 | return !! _.find(this.phones, x => x.verified); |
23 | }; | 23 | }; |
24 | 24 | ||
25 | isIdentityVerified() { | 25 | isIdentityVerified() { |
26 | return !! _.find(this.identities, x => x.verified); | 26 | return !! _.find(this.identities, x => x.verified); |
27 | }; | 27 | }; |
28 | 28 | ||
29 | getRole() { | 29 | getRole() { |
30 | const org = Orgs.findOne({_id: this.orgId}); | 30 | const org = Orgs.findOne({_id: this.orgId}); |
31 | if(!org) return null; | 31 | if(!org) return null; |
32 | const connection = _.find(org.users, {userId: this._id}); | 32 | const connection = _.find(org.users, {userId: this._id}); |
33 | if(!connection) return null; | 33 | if(!connection) return null; |
34 | return connection.role; | 34 | return connection.role; |
35 | }; | 35 | }; |
36 | 36 | ||
37 | getFullName() { | 37 | getFullName() { |
38 | return `${this.firstName} ${this.lastName}`; | 38 | return `${this.firstName} ${this.lastName}`; |
39 | }; | 39 | }; |
40 | getFirstName() { | 40 | getFirstName() { |
41 | return `${this.firstName}`; | 41 | return `${this.firstName}`; |
42 | }; | 42 | }; |
43 | getLastName() { | 43 | getLastName() { |
44 | return `${this.lastName}`; | 44 | return `${this.lastName}`; |
45 | }; | 45 | }; |
46 | getEmail() { | 46 | getEmail() { |
47 | return `${this.emails[0].address}`; | 47 | return `${this.emails[0].address}`; |
48 | }; | 48 | }; |
49 | getOrganization(){ | 49 | getOrganization(){ |
50 | return `${this.orgId}`; | 50 | return `${this.orgId}`; |
51 | }; | 51 | }; |
52 | 52 | ||
53 | getNameByUserId(userId){ | 53 | getNameByUserId(userId){ |
54 | var user = Users.findOne({"_id":userId}); | 54 | var user = Users.findOne({"_id":userId}); |
55 | return user.firstName + " " + user.lastName; | 55 | return user.firstName + " " + user.lastName; |
56 | } | 56 | } |
57 | getAvatarUrl() { | 57 | getAvatarUrl() { |
58 | let random = parseInt(this._id.substr(0, 4), 36); | 58 | let random = parseInt(this._id.substr(0, 4), 36); |
59 | random = '' + (random % 32); | 59 | random = '' + (random % 32); |
60 | while(random.length < 3) random = '0' + random; | 60 | while(random.length < 3) random = '0' + random; |
61 | return `/files/random/random${ random }.png`; | 61 | return `/files/random/random${ random }.png`; |
62 | }; | 62 | }; |
63 | }; | 63 | }; |
64 | 64 | ||
65 | export { User }; | 65 | export { User }; |
66 | 66 | ||
67 | 67 | ||
68 | const transform = function(doc) { | 68 | const transform = function(doc) { |
69 | return new User(doc); | 69 | return new User(doc); |
70 | }; | 70 | }; |
71 | 71 | ||
72 | export const Users = { | 72 | export const Users = { |
73 | 73 | ||
74 | current: function() { | 74 | current: function() { |
75 | return Meteor.users.findOne({_id: Meteor.userId()}, _.extend({transform: transform})); | 75 | return Meteor.users.findOne({_id: Meteor.userId()}, _.extend({transform: transform})); |
76 | }, | 76 | }, |
77 | 77 | ||
78 | find: function(selector, options) { | 78 | find: function(selector, options) { |
79 | return Meteor.users.find(selector || {}, _.extend({transform: transform}, options)); | 79 | return Meteor.users.find(selector || {}, _.extend({transform: transform}, options)); |
80 | }, | 80 | }, |
81 | 81 | ||
82 | findOne: function(selector, options) { | 82 | findOne: function(selector, options) { |
83 | return Meteor.users.findOne(selector || {}, _.extend({transform: transform}, options)); | 83 | return Meteor.users.findOne(selector || {}, _.extend({transform: transform}, options)); |
84 | }, | 84 | }, |
85 | 85 | ||
86 | insert: _.bind(Meteor.users.insert, Meteor.users), | 86 | insert: _.bind(Meteor.users.insert, Meteor.users), |
87 | update: _.bind(Meteor.users.update, Meteor.users), | 87 | update: _.bind(Meteor.users.update, Meteor.users), |
88 | remove: _.bind(Meteor.users.remove, Meteor.users), | 88 | remove: _.bind(Meteor.users.remove, Meteor.users), |
89 | allow: _.bind(Meteor.users.allow, Meteor.users), | 89 | allow: _.bind(Meteor.users.allow, Meteor.users), |
90 | deny: _.bind(Meteor.users.deny, Meteor.users), | 90 | deny: _.bind(Meteor.users.deny, Meteor.users), |
91 | attachSchema: _.bind(Meteor.users.attachSchema, Meteor.users), | 91 | attachSchema: _.bind(Meteor.users.attachSchema, Meteor.users), |
92 | 92 | ||
93 | }; | 93 | }; |
94 | 94 | ||
95 | 95 | ||
96 | Users.deny({ | 96 | Users.deny({ |
97 | insert() { return true; }, | 97 | insert() { return true; }, |
98 | update() { return true; }, | 98 | update() { return true; }, |
99 | remove() { return true; }, | 99 | remove() { return true; }, |
100 | }); | 100 | }); |
101 | 101 | ||
102 | Users.roles = { | 102 | Users.roles = { |
103 | 'STUDENT': 'STUDENT', | 103 | 'STUDENT': 'STUDENT', |
104 | 'TEACHER': 'TEACHER', | 104 | 'TEACHER': 'TEACHER', |
105 | 'ADMIN': 'ADMIN', | 105 | 'ADMIN': 'ADMIN', |
106 | 'PARENT': 'PARENT' | 106 | 'PARENT': 'PARENT' |
107 | }; | 107 | }; |
108 | 108 | ||
109 | 109 | ||
110 | Users.schema = new SimpleSchema({ | 110 | Users.schema = new SimpleSchema({ |
111 | roles: { type: String }, | 111 | role: { type: String }, |
112 | orgId: { type: String }, | 112 | orgId: { type: String }, |
113 | admissionId: { type: String }, | ||
114 | enrollmentDate: { type: String, optional: true }, | ||
115 | address: { type: String, optional: true }, | ||
116 | prefix: { type: String, optional: true }, | 113 | prefix: { type: String, optional: true }, |
117 | firstName: { type: String, optional: true }, | 114 | firstName: { type: String, optional: true }, |
118 | middlename: { type: String, optional: true }, | 115 | middlename: { type: String, optional: true }, |
119 | lastName: { type: String, optional: true }, | 116 | lastName: { type: String, optional: true }, |
120 | gender: { type: String, optional: true }, | 117 | gender: { type: String, optional: true }, |
121 | dob: { type: String, optional: true }, | 118 | dob: { type: String, optional: true }, |
122 | rollNo: { type: String, optional: true }, | ||
123 | class: { type: String, optional: true }, | ||
124 | section: { type: String, optional: true }, | ||
125 | bloodGroup: { type: String, optional: true }, | ||
126 | community: { type: String, optional: true }, | ||
127 | nationality: { type: String, optional: true }, | ||
128 | motherTongue: { type: String, optional: true }, | ||
129 | motherTongue: { type: String, optional: true }, | ||
130 | religion: { type: String, optional: true }, | ||
131 | permanentAddress: { | ||
132 | type: new SimpleSchema({ | ||
133 | home: { type: String, optional: true }, | ||
134 | street: { type: String, optional: true }, | ||
135 | town: { type: String, optional: true }, | ||
136 | city: { type: String, optional: true }, | ||
137 | state: { type: String, optional: true }, | ||
138 | zip: { type: String, optional: true }, | ||
139 | }), | ||
140 | }, | ||
141 | parent: { | ||
142 | type: [new SimpleSchema({ | ||
143 | id: { type: String, }, | ||
144 | relatinship: { type: Boolean, }, | ||
145 | })], | ||
146 | minCount: 1, | ||
147 | }, | ||
148 | emails: { | 119 | emails: { |
149 | type: [new SimpleSchema({ | 120 | type: [new SimpleSchema({ |
150 | address: { type: String, }, | 121 | address: { type: String, }, |
151 | verified: { type: Boolean, }, | 122 | verified: { type: Boolean, }, |
152 | })], | 123 | })], |
153 | }, | 124 | }, |
154 | prevInstitute: { | ||
155 | type: [new SimpleSchema({ | ||
156 | name: { type: String, }, | ||
157 | fromYear: { type: Boolean, }, | ||
158 | toYear: { type: Boolean, }, | ||
159 | ydId: { type: Boolean, }, | ||
160 | })], | ||
161 | optional: true | ||
162 | }, | ||
163 | |||
164 | phones: { | 125 | phones: { |
165 | type: [new SimpleSchema({ | 126 | type: [new SimpleSchema({ |
166 | country: { type: String, }, | 127 | country: { type: String, }, |
167 | prefix: { type: String, }, | 128 | prefix: { type: String, }, |
168 | number: { type: String, }, | 129 | number: { type: String, }, |
169 | verified: { type: Boolean, }, | 130 | verified: { type: Boolean, }, |
170 | })], | 131 | })], |
171 | optional: true | 132 | optional: true |
172 | }, | 133 | }, |
173 | 134 | ||
174 | services: { | 135 | services: { |
175 | type: Object, | 136 | type: Object, |
176 | optional: true, | 137 | optional: true, |
177 | blackbox: true, | 138 | blackbox: true, |
178 | }, | 139 | }, |
179 | 140 | ||
180 | isMetaUser: { type: Boolean, optional: true }, | 141 | isMetaUser: { type: Boolean, optional: true }, |
181 | 142 | ||
182 | createdAt: { type: Date, autoValue: function(){return new Date();}} | 143 | createdAt: { type: Date, autoValue: function(){return new Date();}} |
183 | 144 | ||
184 | }); | 145 | }); |
185 | 146 | ||
186 | Users.attachSchema(Users.schema); | 147 | Users.attachSchema(Users.schema); |
187 | 148 | ||
188 | Users.privateFields = { | 149 | Users.privateFields = { |
189 | orgId: 1, | 150 | orgId: 1, |
190 | address: 1, | 151 | address: 1, |
191 | 152 | ||
192 | firstName: 1, | 153 | firstName: 1, |
193 | lastName: 1, | 154 | lastName: 1, |
194 | emails: 1, | 155 | emails: 1, |
195 | phones: 1, | 156 | phones: 1, |
196 | 157 | ||
197 | isMetaUser: 1, | 158 | isMetaUser: 1, |
198 | createdAt: 1, | 159 | createdAt: 1, |
199 | }; | 160 | }; |
200 | 161 | ||
201 | Users.publicFields = { | 162 | Users.publicFields = { |
202 | firstName: 1, | 163 | firstName: 1, |
203 | lastName: 1, | 164 | lastName: 1, |
204 | emails: 1, | 165 | emails: 1, |
205 | 166 | ||
206 | createdAt: 1, | 167 | createdAt: 1, |
207 | }; | 168 | }; |
208 | 169 |
imports/collections/users/publications.js
File was created | 1 | import { Meteor } from 'meteor/meteor'; | |
2 | import { check, Match } from 'meteor/check' | ||
3 | import { Users } from '/imports/collections/users/index'; | ||
4 | import { Orgs } from '/imports/collections/orgs/index'; | ||
5 | |||
6 | |||
7 | |||
8 | Meteor.publish('users.current', function() { | ||
9 | return Users.find({ | ||
10 | _id: this.userId, | ||
11 | }, { | ||
12 | fields: Users.privateFields, | ||
13 | }); | ||
14 | }); | ||
15 |
imports/server/accounts/creation.js
1 | import _ from 'lodash'; | 1 | import _ from 'lodash'; |
2 | import { Accounts } from 'meteor/accounts-base'; | 2 | import { Accounts } from 'meteor/accounts-base'; |
3 | import { SimpleSchema } from 'meteor/aldeed:simple-schema'; | 3 | import { SimpleSchema } from 'meteor/aldeed:simple-schema'; |
4 | import { ValidatedMethod } from 'meteor/mdg:validated-method'; | 4 | import { ValidatedMethod } from 'meteor/mdg:validated-method'; |
5 | import { Orgs } from '/imports/collections/orgs/index'; | 5 | import { Orgs } from '/imports/collections/orgs/index'; |
6 | import { Users } from '/imports/collections/users/index'; | 6 | import { Users } from '/imports/collections/users/index'; |
7 | 7 | ||
8 | 8 | ||
9 | 9 | ||
10 | Accounts.validateNewUser((user) => { | 10 | Accounts.validateNewUser((user) => { |
11 | return !!user; | 11 | return !!user; |
12 | }); | 12 | }); |
13 | 13 | ||
14 | Accounts.onCreateUser((options, user) => { | 14 | Accounts.onCreateUser((options, user) => { |
15 | console.log(options); | ||
16 | _.assign(user, { | 15 | _.assign(user, { |
17 | firstName: options.profile.firstName, | 16 | firstName: options.profile.firstName, |
18 | lastName: options.profile.lastName, | 17 | lastName: options.profile.lastName, |
19 | phones: [], | 18 | phones: [], |
20 | identities: [], | 19 | identities: [], |
21 | createdAt: new Date().getTime(), | 20 | createdAt: new Date().getTime(), |
22 | }); | 21 | }); |
23 | return user; | 22 | return user; |
24 | }); | 23 | }); |
25 | 24 |
imports/startup/client/routes.js
1 | /* eslint-disable max-len */ | 1 | /* eslint-disable max-len */ |
2 | 2 | ||
3 | import React from 'react'; | 3 | import React from 'react'; |
4 | import { render } from 'react-dom'; | 4 | import { render } from 'react-dom'; |
5 | import { Router, Route, | 5 | import { Router, Route, |
6 | IndexRoute, browserHistory } from 'react-router'; | 6 | IndexRoute, browserHistory } from 'react-router'; |
7 | import { Meteor } from 'meteor/meteor'; | 7 | import { Meteor } from 'meteor/meteor'; |
8 | 8 | ||
9 | /** | 9 | /** |
10 | * General Components | 10 | * General Components |
11 | */ | 11 | */ |
12 | import Index from '/imports/client/views/app/module/Index'; | 12 | import Index from '/imports/client/views/app/module/Index'; |
13 | 13 | ||
14 | /** | 14 | /** |
15 | * Org Components | 15 | * Org Components |
16 | */ | 16 | */ |
17 | 17 | ||
18 | import App from '/imports/client/layouts/OrgApp'; | 18 | import App from '/imports/client/layouts/OrgApp'; |
19 | import OrgIndex from '/imports/client/views/org/module/Index'; | 19 | import { AppModule } from '/imports/client/views/org/app/module/Index'; |
20 | import { orgLoginController } from '/imports/client/views/org/enter/login/index'; | 20 | import { orgLoginController } from '/imports/client/views/org/enter/login/index'; |
21 | import NotFound from '/imports/client/views/org/NotFound'; | ||
22 | import RecoverPassword from '/imports/client/views/org/enter/RecoverPassword'; | 21 | import RecoverPassword from '/imports/client/views/org/enter/RecoverPassword'; |
23 | import ResetPassword from '/imports/client/views/org/enter/ResetPassword'; | 22 | import ResetPassword from '/imports/client/views/org/enter/ResetPassword'; |
24 | import { Orgs } from '/imports/collections/orgs/index'; | 23 | import { Orgs } from '/imports/collections/orgs/index'; |
24 | import NotFound from '/imports/client/views/org/NotFound'; | ||
25 | 25 | ||
26 | /** | 26 | /** |
27 | * NonOrg Components | 27 | * NonOrg Components |
28 | */ | 28 | */ |
29 | import Signup from '/imports/client/views/nonOrg/enter/SignupView'; | 29 | import Signup from '/imports/client/views/nonOrg/enter/SignupView'; |
30 | 30 | ||
31 | /** | 31 | /** |
32 | * Invalid Org Components | 32 | * Invalid Org Components |
33 | */ | 33 | */ |
34 | 34 | ||
35 | const authenticate = (nextState, replace) => { | 35 | const authenticate = (nextState, replace) => { |
36 | if (!Meteor.loggingIn() && !Meteor.userId()) { | 36 | if (!Meteor.loggingIn() && !Meteor.userId()) { |
37 | replace({ | 37 | replace({ |
38 | pathname: '/login', | 38 | pathname: '/login', |
39 | state: { nextPathname: nextState.location.pathname }, | 39 | state: { nextPathname: nextState.location.pathname }, |
40 | }); | 40 | }); |
41 | } | 41 | } |
42 | }; | 42 | }; |
43 | 43 | ||
44 | 44 | ||
45 | const detectOrg = () => { | 45 | const detectOrg = () => { |
46 | orgSlug = ""; | 46 | orgSlug = ""; |
47 | var hostnameArray = document.location.hostname.split( "." ); | 47 | var hostnameArray = document.location.hostname.split( "." ); |
48 | if(hostnameArray[1]=='localhost'){ | 48 | if(hostnameArray[1]=='localhost'){ |
49 | orgSlug = hostnameArray[0]; | 49 | orgSlug = hostnameArray[0]; |
50 | } | 50 | } |
51 | if(orgSlug!=""){ | 51 | if(orgSlug!=""){ |
52 | Meteor.call('checkExistingOrg', {slug:orgSlug}, function(err, res) { | 52 | Meteor.call('checkExistingOrg', {slug:orgSlug}, function(err, res) { |
53 | console.log(res); | ||
54 | if(res){ | 53 | if(res){ |
55 | Session.set('orgId', res._id._str); | 54 | Session.set('orgId', res._id._str); |
56 | render(getOrgRoutes(),document.getElementById('app')); | 55 | render(getOrgRoutes(),document.getElementById('app')); |
57 | }else{ | 56 | }else{ |
58 | render(getInvalidOrgRoute(),document.getElementById('app')); | 57 | render(getInvalidOrgRoute(),document.getElementById('app')); |
59 | } | 58 | } |
60 | }); | 59 | }); |
61 | }else{ | 60 | }else{ |
62 | render(getNonOrgRoutes(),document.getElementById('app')); | 61 | render(getNonOrgRoutes(),document.getElementById('app')); |
63 | } | 62 | } |
64 | } | 63 | } |
65 | const checkSlug = (nextState, replace) => { | 64 | const checkSlug = (nextState, replace) => { |
66 | orgId = Session.get('orgId'); | 65 | orgId = Session.get('orgId'); |
67 | } | 66 | } |
68 | 67 | ||
69 | /** | 68 | /** |
70 | There are three types of routes | 69 | There are three types of routes |
71 | 1)getOrgRoutes: all the routes that should be present for a registered org | 70 | 1)getOrgRoutes: all the routes that should be present for a registered org |
72 | 2)getInvalidOrgRoute: all the routes where someone tries to enter a subdomain which hasn't been registered yet (404 mostly :D) | 71 | 2)getInvalidOrgRoute: all the routes where someone tries to enter a subdomain which hasn't been registered yet (404 mostly :D) |
73 | 3)getNonOrgRoutes: all routes linked to normal site, ie signing up a new org. CHeking out demo and everything internal | 72 | 3)getNonOrgRoutes: all routes linked to normal site, ie signing up a new org. CHeking out demo and everything internal |
74 | **/ | 73 | **/ |
75 | const getOrgRoutes = () => ( | 74 | const getOrgRoutes = () => ( |
76 | <Router history={ browserHistory }> | 75 | <Router history={ browserHistory }> |
77 | <Route path="/" component={ App }> | 76 | <Route path="/" component={ App }> |
78 | <IndexRoute name="index" component={ OrgIndex } /> | 77 | <IndexRoute name="index" component={ AppModule } /> |
79 | <Route name="login" path="/login" component={ orgLoginController } /> | 78 | <Route name="login" path="/login" component={ orgLoginController } /> |
80 | <Route name="recover-password" path="/recover-password" component={ RecoverPassword } /> | 79 | <Route name="recover-password" path="/recover-password" component={ RecoverPassword } /> |
81 | <Route name="reset-password" path="/reset-password/:token" component={ ResetPassword } /> | 80 | <Route name="reset-password" path="/reset-password/:token" component={ ResetPassword } /> |
82 | <Route path="*" component={ NotFound } /> | 81 | <Route path="*" component={ NotFound } /> |
83 | </Route> | 82 | </Route> |
84 | </Router> | 83 | </Router> |
85 | ) | 84 | ) |
86 | 85 | ||
87 | 86 | ||
88 | const getInvalidOrgRoute = () => ( | 87 | const getInvalidOrgRoute = () => ( |
89 | <Router history={ browserHistory }> | 88 | <Router history={ browserHistory }> |
90 | <Route path="/" component={ App }> | 89 | <Route path="/" component={ App }> |
91 | <IndexRoute name="index" component={ NotFound } /> | 90 | <IndexRoute name="index" component={ NotFound } /> |
92 | <Route path="*" component={ NotFound } /> | 91 | <Route path="*" component={ NotFound } /> |
93 | </Route> | 92 | </Route> |
94 | </Router> | 93 | </Router> |
95 | ) | 94 | ) |
96 | 95 | ||
97 | const getNonOrgRoutes = () => ( | 96 | const getNonOrgRoutes = () => ( |
98 | <Router history={ browserHistory }> | 97 | <Router history={ browserHistory }> |
99 | <Route path="/" component={ App }> | 98 | <Route path="/" component={ App }> |
100 | <IndexRoute name="index" component={ Index } onEnter={ checkSlug } /> | 99 | <IndexRoute name="index" component={ Index } /> |
101 | <Route name="signup" path="/signup" component={ Signup } /> | 100 | <Route name="signup" path="/signup" component={ Signup } /> |
102 | <Route path="*" component={ NotFound } /> | 101 | <Route path="*" component={ NotFound } /> |
103 | </Route> | 102 | </Route> |
104 | </Router> | 103 | </Router> |
105 | ) | 104 | ) |
106 | 105 | ||
107 | 106 | ||
108 | Meteor.startup(() => { | 107 | Meteor.startup(() => { |
109 | detectOrg(); | 108 | detectOrg(); |
110 | }); | 109 | }); |
imports/startup/server/accounts/creation.js
1 | import _ from 'lodash'; | 1 | import _ from 'lodash'; |
2 | import { Accounts } from 'meteor/accounts-base'; | 2 | import { Accounts } from 'meteor/accounts-base'; |
3 | import { SimpleSchema } from 'meteor/aldeed:simple-schema'; | 3 | import { SimpleSchema } from 'meteor/aldeed:simple-schema'; |
4 | import { ValidatedMethod } from 'meteor/mdg:validated-method'; | 4 | import { ValidatedMethod } from 'meteor/mdg:validated-method'; |
5 | 5 | ||
6 | import { Orgs } from '/imports/collections/orgs/index'; | ||
7 | import { Users } from '/imports/collections/users/index'; | ||
6 | 8 | ||
7 | 9 | ||
8 | Accounts.validateNewUser((user) => { | 10 | Accounts.validateNewUser((user) => { |
9 | return !!user; | 11 | return !!user; |
10 | }); | 12 | }); |
11 | 13 | ||
12 | Accounts.onCreateUser((options, user) => { | 14 | Accounts.onCreateUser((options, user) => { |
13 | console.log(options); | 15 | console.log(options); |
16 | if(options.orgSlug){ | ||
17 | orgId = Orgs.insert({ | ||
18 | slug: options.orgSlug, | ||
19 | name: options.orgName, | ||
20 | setup: 1, | ||
21 | users: [{ | ||
22 | userId: user._id, | ||
23 | role: Users.roles.ADMIN, | ||
24 | }], | ||
25 | }); | ||
26 | } | ||
27 | console.log(user); | ||
28 | _.assign(user, { | ||
29 | role: Users.roles.ADMIN, | ||
30 | orgId: orgId, | ||
31 | firstName: options.profile.firstName, | ||
32 | lastName: options.profile.lastName, | ||
33 | }); | ||
34 | return user; | ||
14 | }); | 35 | }); |
15 | 36 |
imports/startup/server/api.js
1 | import '../../api/documents/methods.js'; | 1 | import '../../api/documents/methods.js'; |
2 | import '../../api/documents/server/publications.js'; | 2 | import '../../api/documents/server/publications.js'; |
3 | 3 | ||
4 | import '/imports/collections/orgs/publications' | 4 | import '/imports/collections/orgs/publications' |
5 | import '/imports/collections/orgs/methods'; | 5 | import '/imports/collections/orgs/methods'; |
6 | |||
7 | import '/imports/collections/users/publications'; | ||
6 | 8 |
package.json
1 | { | 1 | { |
2 | "name": "application-name", | 2 | "name": "application-name", |
3 | "version": "1.0.0", | 3 | "version": "1.0.0", |
4 | "description": "Application description.", | 4 | "description": "Application description.", |
5 | "scripts": { | 5 | "scripts": { |
6 | "start": "meteor --settings settings-development.json", | 6 | "start": "meteor --settings settings-development.json", |
7 | "test": "meteor test --driver-package practicalmeteor:mocha --port 5000", | 7 | "test": "meteor test --driver-package practicalmeteor:mocha --port 5000", |
8 | "chimp-watch": "chimp --ddp=http://localhost:3000 --watch --mocha --path=tests", | 8 | "chimp-watch": "chimp --ddp=http://localhost:3000 --watch --mocha --path=tests", |
9 | "chimp-test": "chimp --ddp=http://localhost:3000 --mocha --path=tests", | 9 | "chimp-test": "chimp --ddp=http://localhost:3000 --mocha --path=tests", |
10 | "staging": "meteor deploy staging.meteor.com --settings settings-development.json", | 10 | "staging": "meteor deploy staging.meteor.com --settings settings-development.json", |
11 | "production": "meteor deploy production.meteor.com --settings settings-production.json" | 11 | "production": "meteor deploy production.meteor.com --settings settings-production.json" |
12 | }, | 12 | }, |
13 | "devDependencies": { | 13 | "devDependencies": { |
14 | "chimp": "^0.41.2", | 14 | "chimp": "^0.41.2", |
15 | "eslint": "^3.8.1", | 15 | "eslint": "^3.8.1", |
16 | "eslint-config-airbnb": "^12.0.0", | 16 | "eslint-config-airbnb": "^12.0.0", |
17 | "eslint-plugin-import": "^1.16.0", | 17 | "eslint-plugin-import": "^1.16.0", |
18 | "eslint-plugin-jsx-a11y": "^2.2.3", | 18 | "eslint-plugin-jsx-a11y": "^2.2.3", |
19 | "eslint-plugin-meteor": "^4.0.1", | 19 | "eslint-plugin-meteor": "^4.0.1", |
20 | "eslint-plugin-react": "^6.4.1" | 20 | "eslint-plugin-react": "^6.4.1" |
21 | }, | 21 | }, |
22 | "eslintConfig": { | 22 | "eslintConfig": { |
23 | "parserOptions": { | 23 | "parserOptions": { |
24 | "ecmaFeatures": { | 24 | "ecmaFeatures": { |
25 | "jsx": true | 25 | "jsx": true |
26 | } | 26 | } |
27 | }, | 27 | }, |
28 | "plugins": [ | 28 | "plugins": [ |
29 | "meteor", | 29 | "meteor", |
30 | "react" | 30 | "react" |
31 | ], | 31 | ], |
32 | "extends": [ | 32 | "extends": [ |
33 | "airbnb/base", | 33 | "airbnb/base", |
34 | "plugin:meteor/guide", | 34 | "plugin:meteor/guide", |
35 | "plugin:react/recommended" | 35 | "plugin:react/recommended" |
36 | ], | 36 | ], |
37 | "env": { | 37 | "env": { |
38 | "browser": true | 38 | "browser": true |
39 | }, | 39 | }, |
40 | "globals": { | 40 | "globals": { |
41 | "server": false, | 41 | "server": false, |
42 | "browser": false, | 42 | "browser": false, |
43 | "expect": false | 43 | "expect": false |
44 | }, | 44 | }, |
45 | "rules": { | 45 | "rules": { |
46 | "import/no-unresolved": 0, | 46 | "import/no-unresolved": 0, |
47 | "import/no-extraneous-dependencies": 0, | 47 | "import/no-extraneous-dependencies": 0, |
48 | "import/extensions": 0, | 48 | "import/extensions": 0, |
49 | "no-underscore-dangle": [ | 49 | "no-underscore-dangle": [ |
50 | "error", | 50 | "error", |
51 | { | 51 | { |
52 | "allow": [ | 52 | "allow": [ |
53 | "_id", | 53 | "_id", |
54 | "_ensureIndex", | 54 | "_ensureIndex", |
55 | "_verifyEmailToken", | 55 | "_verifyEmailToken", |
56 | "_resetPasswordToken", | 56 | "_resetPasswordToken", |
57 | "_name" | 57 | "_name" |
58 | ] | 58 | ] |
59 | } | 59 | } |
60 | ], | 60 | ], |
61 | "class-methods-use-this": 0 | 61 | "class-methods-use-this": 0 |
62 | } | 62 | } |
63 | }, | 63 | }, |
64 | "dependencies": { | 64 | "dependencies": { |
65 | "babel-runtime": "^6.18.0", | 65 | "babel-runtime": "^6.18.0", |
66 | "bcrypt": "^0.8.7", | 66 | "bcrypt": "^0.8.7", |
67 | "bootstrap": "^3.3.7", | 67 | "bootstrap": "^3.3.7", |
68 | "jquery": "^2.2.4", | 68 | "jquery": "^2.2.4", |
69 | "jquery-validation": "^1.15.1", | 69 | "jquery-validation": "^1.15.1", |
70 | "react": "^15.3.2", | 70 | "react": "^15.3.2", |
71 | "react-addons-pure-render-mixin": "^15.3.2", | 71 | "react-addons-pure-render-mixin": "^15.3.2", |
72 | "react-bootstrap": "^0.30.5", | 72 | "react-bootstrap": "^0.30.5", |
73 | "react-dom": "^15.3.2", | 73 | "react-dom": "^15.3.2", |
74 | "react-komposer": "^1.13.1", | 74 | "react-komposer": "^1.13.1", |
75 | "react-router": "^3.0.0", | 75 | "react-router": "^2.6.1", |
76 | "react-router-bootstrap": "^0.23.1" | 76 | "react-router-bootstrap": "^0.23.1", |
77 | "react-svg": "^2.1.19" | ||
77 | } | 78 | } |
78 | } | 79 | } |
79 | 80 |