Commit 39d8f536dc5551e3902d03d21d74903cfa54243b

Authored by Deepak
1 parent b48d5cb1c8
Exists in master

some more cleamup

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
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