Commit d0099dd8829621efd696b2820ac21ec7bc2cf36c

Authored by Deepak
1 parent 13ef5ba8c6
Exists in master

student detail page view

1 <head> 1 <head>
2 <meta charset="utf-8"> 2 <meta charset="utf-8">
3 <title>YoungDesk</title> 3 <title>YoungDesk</title>
4 <meta name="description" content="All your organization's need."> 4 <meta name="description" content="All your organization's need.">
5 <meta name="viewport" content="initial-scale=1, minimal-ui, maximum-scale=1, minimum-scale=1" /> 5 <meta name="viewport" content="initial-scale=1, minimal-ui, maximum-scale=1, minimum-scale=1" />
6 <link rel="shortcut icon" type="image/png" href="/favicon.png?v1" sizes="16x16 32x32 64x64"> 6 <link rel="shortcut icon" type="image/png" href="/favicon.png?v1" sizes="16x16 32x32 64x64">
7 <link rel="apple-touch-icon" sizes="120x120" href="/apple-touch-icon-precomposed.png"> 7 <link rel="apple-touch-icon" sizes="120x120" href="/apple-touch-icon-precomposed.png">
8 <!-- Latest compiled and minified CSS -->
9 <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css">
10
8 <link 11 <link
9 href='https://fonts.googleapis.com/css?family=Alef' 12 href='https://fonts.googleapis.com/css?family=Alef'
10 rel='stylesheet' 13 rel='stylesheet'
11 type='text/css' 14 type='text/css'
12 /> 15 />
13 <link 16 <link
14 href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" 17 href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css"
15 rel="stylesheet" 18 rel="stylesheet"
16 integrity="sha384-T8Gy5hrqNKT+hzMclPo118YTQO6cYprQmhrYwIiQ/3axmI1hQomh7Ud2hPOy8SP1" 19 integrity="sha384-T8Gy5hrqNKT+hzMclPo118YTQO6cYprQmhrYwIiQ/3axmI1hQomh7Ud2hPOy8SP1"
17 crossorigin="anonymous" 20 crossorigin="anonymous"
18 /> 21 />
19 </head> 22 </head>
20 23
21 <body> 24 <body>
22 <div id="app"></div> 25 <div id="app"></div>
23 </body> 26 </body>
24 27
imports/client/app/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 { AppModule } from '/imports/client/views/org/app/module/Index'; 19 import { AppModule } from '/imports/client/views/org/app/module/Index';
20 import { Orgs } from '/imports/collections/orgs/index'; 20 import { Orgs } from '/imports/collections/orgs/index';
21 import { importCsvController } from '/imports/client/views/org/importCsv/index' 21 import { importCsvController } from '/imports/client/views/org/importCsv/index'
22 22
23 //admin
24 import { StudentDataController } from '/imports/client/views/org/admin/students/index'
25
23 26
24 import NotFound from '/imports/client/views/org/NotFound'; 27 import NotFound from '/imports/client/views/org/NotFound';
25 28
26 /** 29 /**
27 * NonOrg Components 30 * NonOrg Components
28 */ 31 */
29 import Signup from '/imports/client/views/nonOrg/enter/SignupView'; 32 import Signup from '/imports/client/views/nonOrg/enter/SignupView';
30 33
31 /** 34 /**
32 * Invalid Org Components 35 * Invalid Org Components
33 */ 36 */
34 37
35 const authenticate = (nextState, replace) => { 38 const authenticate = (nextState, replace) => {
36 if (!Meteor.loggingIn() && !Meteor.userId()) { 39 if (!Meteor.loggingIn() && !Meteor.userId()) {
37 replace({ 40 replace({
38 pathname: '/login', 41 pathname: '/login',
39 state: { nextPathname: nextState.location.pathname }, 42 state: { nextPathname: nextState.location.pathname },
40 }); 43 });
41 } 44 }
42 }; 45 };
43 46
44 47
45 const detectOrg = () => { 48 const detectOrg = () => {
46 orgSlug = ""; 49 orgSlug = "";
47 var hostnameArray = document.location.hostname.split( "." ); 50 var hostnameArray = document.location.hostname.split( "." );
48 if(hostnameArray[1]=='localhost'){ 51 if(hostnameArray[1]=='localhost'){
49 orgSlug = hostnameArray[0]; 52 orgSlug = hostnameArray[0];
50 } 53 }
51 if(orgSlug!=""){ 54 if(orgSlug!=""){
52 Meteor.call('checkExistingOrg', {slug:orgSlug}, function(err, res) { 55 Meteor.call('checkExistingOrg', {slug:orgSlug}, function(err, res) {
53 if(res){ 56 if(res){
54 Session.set('orgId', res._id); 57 Session.set('orgId', res._id);
55 Session.set('orgSlug', orgSlug); 58 Session.set('orgSlug', orgSlug);
56 render(getOrgRoutes(),document.getElementById('app')); 59 render(getOrgRoutes(),document.getElementById('app'));
57 }else{ 60 }else{
58 render(getInvalidOrgRoute(),document.getElementById('app')); 61 render(getInvalidOrgRoute(),document.getElementById('app'));
59 } 62 }
60 }); 63 });
61 }else{ 64 }else{
62 render(getNonOrgRoutes(),document.getElementById('app')); 65 render(getNonOrgRoutes(),document.getElementById('app'));
63 } 66 }
64 } 67 }
65 const checkSlug = (nextState, replace) => { 68 const checkSlug = (nextState, replace) => {
66 orgId = Session.get('orgId'); 69 orgId = Session.get('orgId');
67 } 70 }
68 71
69 /** 72 /**
70 There are three types of routes 73 There are three types of routes
71 1)getOrgRoutes: all the routes that should be present for a registered org 74 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) 75 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 76 3)getNonOrgRoutes: all routes linked to normal site, ie signing up a new org. CHeking out demo and everything internal
74 **/ 77 **/
75 const getOrgRoutes = () => ( 78 const getOrgRoutes = () => (
76 <Router history={ browserHistory }> 79 <Router history={ browserHistory }>
77 <Route path="/" component={ App }> 80 <Route path="/" component={ App }>
78 <IndexRoute name="index" component={ AppModule } /> 81 <IndexRoute name="index" component={ AppModule } />
79 <Route name="import" path="/import" component={ importCsvController } /> 82 <Route name="import" path="/import" component={ importCsvController } />
83 <Route name="student" path="/students" component={ StudentDataController } />
80 <Route path="*" component={ NotFound } /> 84 <Route path="*" component={ NotFound } />
81 </Route> 85 </Route>
82 </Router> 86 </Router>
83 ) 87 )
84 88
85 89
86 const getInvalidOrgRoute = () => ( 90 const getInvalidOrgRoute = () => (
87 <Router history={ browserHistory }> 91 <Router history={ browserHistory }>
88 <Route path="/" component={ App }> 92 <Route path="/" component={ App }>
89 <IndexRoute name="index" component={ NotFound } /> 93 <IndexRoute name="index" component={ NotFound } />
90 <Route path="*" component={ NotFound } /> 94 <Route path="*" component={ NotFound } />
91 </Route> 95 </Route>
92 </Router> 96 </Router>
93 ) 97 )
94 98
95 const getNonOrgRoutes = () => ( 99 const getNonOrgRoutes = () => (
96 <Router history={ browserHistory }> 100 <Router history={ browserHistory }>
97 <Route path="/" component={ App }> 101 <Route path="/" component={ App }>
98 <IndexRoute name="index" component={ Index } /> 102 <IndexRoute name="index" component={ Index } />
99 <Route name="signup" path="/signup" component={ Signup } /> 103 <Route name="signup" path="/signup" component={ Signup } />
100 <Route path="*" component={ NotFound } /> 104 <Route path="*" component={ NotFound } />
101 </Route> 105 </Route>
102 </Router> 106 </Router>
103 ) 107 )
104 108
105 109
106 Meteor.startup(() => { 110 Meteor.startup(() => {
107 detectOrg(); 111 detectOrg();
108 }); 112 });
109 113
imports/client/views/etc/index.js
1 // import { InviteSignupController } from '/imports/client/views/invite/signup/index' 1 // import { InviteSignupController } from '/imports/client/views/invite/signup/index'
2 import _ from 'lodash'; 2 import _ from 'lodash';
3 import { 3 import {
4 composeWithTracker, 4 composeWithTracker,
5 compose, 5 compose,
6 composeAll 6 composeAll
7 } from 'react-komposer'; 7 } from 'react-komposer';
8 import { Loading } from '/imports/client/components/Loading'; 8 import { Loading } from '/imports/client/components/Loading';
9 9
10 import { Orgs } from '/imports/collections/orgs/index'; 10 import { Orgs } from '/imports/collections/orgs/index';
11 import { Users } from '/imports/collections/users/index'; 11 import { Users } from '/imports/collections/users/index';
12 12
13 const meteorTick = (props, onData) => { 13 const meteorTick = (props, onData) => {
14 14
15 const handles = [ 15 const handles = [
16 Meteor.subscribe('users.current') 16 Meteor.subscribe('users.current'),
17 Meteor.subscribe('orgs.current')
17 ]; 18 ];
18 19
19 if(_.every(handles, (handle) => (handle.ready()) )) { 20 if(_.every(handles, (handle) => (handle.ready()) )) {
20 const user = Users.current(); 21 const user = Users.current();
22 const org = Orgs.current();
21 onData(null, { 23 onData(null, {
22 data: { 24 data: {
23 user: user, 25 user: user,
26 org: org
24 }, 27 },
25 }); 28 });
26 } 29 }
27 30
28 return () => { 31 return () => {
29 _.each(handles, (handle) => handle.stop() ); 32 _.each(handles, (handle) => handle.stop() );
30 }; 33 };
31 }; 34 };
32 35
33 36
34 const reduxTick = (props, onData) => { 37 const reduxTick = (props, onData) => {
35 onData(null, { 38 onData(null, {
36 data: {} 39 data: {}
37 }); 40 });
38 }; 41 };
39 42
40 43
41 export const InviteSignupController = composeAll( 44 export const InviteSignupController = composeAll(
42 composeWithTracker(meteorTick, Loading), 45 composeWithTracker(meteorTick, Loading),
43 compose(reduxTick, Loading), 46 compose(reduxTick, Loading),
44 )(InviteSignupView); 47 )(InviteSignupView);
45 48
imports/client/views/etc/signup.js
1 import _ from 'lodash'; 1 import _ from 'lodash';
2 import { Meteor } from 'meteor/meteor'; 2 import { Meteor } from 'meteor/meteor';
3 3
4 import React, { Component } from 'react'; 4 import React, { Component } from 'react';
5 import { Link,browserHistory } from 'react-router'; 5 import { Link,browserHistory } from 'react-router';
6 import { FormGroup,, 6 import { FormGroup,,
7 FormControl,Glyphicon,Button } from 'react-bootstrap'; 7 FormControl,Glyphicon,Button } from 'react-bootstrap';
8 8
9 9
10 export class InviteSignupView extends Component { 10 export class InviteSignupView extends Component {
11 11
12 constructor(props) { 12 constructor(props) {
13 super(props); 13 super(props);
14 this.state = { 14 this.state = {
15 15
16 }; 16 };
17 this.onUpdate = this.onUpdate.bind(this); 17 this.onUpdate = this.onUpdate.bind(this);
18 }; 18 };
19 19
20 onUpdate(key, value) { 20 onUpdate(key, value) {
21 this.setState({[key]: value}); 21 this.setState({[key]: value});
22 }; 22 };
23 23
24 render() { 24 render() {
25 const {user, org} = this.props.data;
25 return ( 26 return (
26 <div className = "enterPane-box"> 27 <div className = "enterPane-box">
27 28
28 </div> 29 </div>
29 ); 30 );
30 }; 31 };
31 32
32 }; 33 };
33 34
imports/client/views/org/admin/students/StudentDataView.js
File was created 1 import _ from 'lodash';
2 import { Meteor } from 'meteor/meteor';
3
4 import React, { Component } from 'react';
5 import { Link,browserHistory } from 'react-router';
6 import { FormGroup,Panel,Table,
7 ButtonToolbar,Modal,
8 FormControl,Glyphicon,Button } from 'react-bootstrap';
9 import { AddStudentForm } from './addStudentForm';
10
11 export class StudentDataView extends Component {
12
13 constructor(props) {
14 super(props);
15 this.state = {
16 show: false
17 };
18 this.showModal = this.showModal.bind(this);
19 this.hideModal = this.hideModal.bind(this);
20 this.onUpdate = this.onUpdate.bind(this);
21 };
22
23 showModal() {
24 this.setState({show: true});
25 }
26
27 hideModal() {
28 this.setState({show: false});
29 }
30 onUpdate(key, value) {
31 this.setState({[key]: value});
32 };
33
34 render() {
35 return (
36 <div className = "enterPane-box">
37 <Panel header="Students Info" bsStyle="primary">
38 <Table striped bordered condensed hover>
39 <thead>
40 <tr>
41 <th>#</th>
42 <th>First Name</th>
43 <th>Last Name</th>
44 </tr>
45 </thead>
46 <tbody>
47 {
48 this.props.data.students.map(function(student, i)
49 {
50 return(
51 <tr>
52 <td>{i+1}</td>
53 <td>{student.firstName}</td>
54 <td>{student.lastName}</td>
55 </tr>
56 )
57 })
58 }
59
60 </tbody>
61 </Table>
62 <ButtonToolbar>
63 <Button bsStyle="primary" onClick={this.showModal}>
64 Add Student
65 </Button>
66 <Modal
67 {...this.props}
68 show={this.state.show}
69 onHide={this.hideModal}
70 dialogClassName="custom-modal"
71 >
72 <Modal.Header closeButton>
73 <Modal.Title id="contained-modal-title-lg">New Student</Modal.Title>
74 </Modal.Header>
75 <Modal.Body>
76 <AddStudentForm />
77 </Modal.Body>
78 <Modal.Footer>
79 <Button onClick={this.hideModal}>Close</Button>
80 </Modal.Footer>
81 </Modal>
82 </ButtonToolbar>
83 </Panel>
84 </div>
85 );
86 };
87
88 };
89
imports/client/views/org/admin/students/addStudentForm.js
File was created 1 import _ from 'lodash';
2 import { Meteor } from 'meteor/meteor';
3
4 import React, { Component } from 'react';
5 import { Link,browserHistory } from 'react-router';
6 import { FormGroup,InputGroup,
7 DropdownButton,MenuItem,ControlLabel,
8 SplitButton,
9 FormControl,Glyphicon,Button } from 'react-bootstrap';
10 import {DatePicker} from 'react-bootstrap-date-picker'
11 import {addStudentManually} from '/imports/collections/students/methods';
12
13 export class AddStudentForm extends Component {
14
15 constructor(props) {
16 super(props);
17 this.state = {
18 firstName: "",
19 lastName: "",
20 middleName: "",
21 dob: "",
22 };
23 this.onUpdate = this.onUpdate.bind(this);
24 this.aFunction = this.aFunction.bind(this);
25 };
26
27 onUpdate(key, value) {
28 this.setState({[key]: value});
29 };
30 aFunction(e){
31 console.log(e);
32 console.log(e);
33 }
34 addStudent(e){
35 e.preventDefault();
36 e.persist();
37 const firstName = this.state.firstName;
38 const middleName = this.state.middleName;
39 const lastName = this.state.lastName;
40 if(firstName==""){
41 Bert.alert('Enter Fist Name', 'danger');
42 } else if(middleName==""){
43 Bert.alert('Enter Middle name!', 'danger');
44 } else{
45 addStudentManually.call({
46 firstName: firstName,
47 middleName: middleName,
48 lastName: lastName
49 }, function (error, result) {
50 console.log(error);
51 console.log(result);
52 });
53 }
54 }
55 render() {
56 return (
57 <form onSubmit={ (e) => this.addStudent(e) }>
58 <FormGroup controlId="formBasicText">
59 <ControlLabel>First Name</ControlLabel>
60 <FormControl
61 type="text"
62 value={this.state.firstName}
63 placeholder="First Name"
64 onChange={e=>this.onUpdate('firstName',e.target.value)}
65 />
66 </FormGroup>
67 <FormGroup controlId="formBasicText">
68 <ControlLabel>Middle Name</ControlLabel>
69 <FormControl
70 type="text"
71 value={this.state.middleName}
72 placeholder="Middle Name"
73 onChange={e=>this.onUpdate('middleName',e.target.value)}
74 />
75 </FormGroup>
76 <FormGroup controlId="formBasicText">
77 <ControlLabel>Last Name</ControlLabel>
78 <FormControl
79 type="text"
80 value={this.state.lastName}
81 placeholder="Last Name"
82 onChange={e=>this.onUpdate('lastName',e.target.value)}
83 />
84 </FormGroup>
85 <Button type="submit" bsStyle="default">Add Student</Button>
86 </form>
87 );
88 };
89
90 };
91
imports/client/views/org/admin/students/index.js
File was created 1 // import { StudentDataController } from '/imports/client/views/org/admin/students/index'
2 import _ from 'lodash';
3 import {
4 composeWithTracker,
5 compose,
6 composeAll
7 } from 'react-komposer';
8 import { Loading } from '/imports/client/components/Loading';
9
10 import { Orgs } from '/imports/collections/orgs/index';
11 import { Users } from '/imports/collections/users/index';
12 import { StudentDataView } from './StudentDataView';
13 import { Students } from '/imports/collections/students/methods'
14
15
16 const meteorTick = (props, onData) => {
17
18 const handles = [
19 Meteor.subscribe('users.current'),
20 Meteor.subscribe('orgs.current'),
21 Meteor.subscribe('users.forMyOrg')
22 ];
23
24 if(_.every(handles, (handle) => (handle.ready()) )) {
25 const user = Users.current();
26 const org = Orgs.current();
27 const students = Users.find({"role":"STUDENT"}).fetch();
28 console.log(students);
29 onData(null, {
30 data: {
31 user: user,
32 org: org,
33 students:students
34 },
35 });
36 }
37
38 return () => {
39 _.each(handles, (handle) => handle.stop() );
40 };
41 };
42
43
44 const reduxTick = (props, onData) => {
45 onData(null, {
46 data: {}
47 });
48 };
49
50
51 export const StudentDataController = composeAll(
52 composeWithTracker(meteorTick, Loading),
53 compose(reduxTick, Loading),
54 )(StudentDataView);
55
imports/client/views/org/app/module/navigation/AuthenticatedNavigation.js
1 import React, { Component } from 'react'; 1 import React, { Component } from 'react';
2 import { browserHistory } from 'react-router'; 2 import { browserHistory } from 'react-router';
3 import { LinkContainer } from 'react-router-bootstrap'; 3 import { LinkContainer } from 'react-router-bootstrap';
4 import { logout } from '/imports/client/app/utils/loginMethods';
4 import { Navbar,Modal, Nav, NavItem, 5 import { Navbar,Modal, Nav, NavItem,
5 Glyphicon, 6 Glyphicon,
6 NavDropdown, MenuItem } from 'react-bootstrap'; 7 NavDropdown, MenuItem } from 'react-bootstrap';
7 import { Meteor } from 'meteor/meteor'; 8 import { Meteor } from 'meteor/meteor';
8 9
9 const handleLogout = () => Meteor.logout(() => browserHistory.push('/login')); 10 const handleLogout = () => Meteor.logout(() => browserHistory.push('/login'));
10 11
11 export class AuthenticatedNavigation extends Component { 12 export class AuthenticatedNavigation extends Component {
12 constructor(props) { 13 constructor(props) {
13 super(props); 14 super(props);
14 this.state = { 15 this.state = {
15 16
16 }; 17 };
17 }; 18 };
18 render(){ 19 render(){
19 const {user} = this.props.data; 20 const {user, org} = this.props.data;
20 return( 21 return(
21 <Navbar inverse> 22 <Navbar inverse collapseOnSelect className="bg-crimson">
22 <Navbar.Header> 23 <Navbar.Header>
23 <Navbar.Brand> 24 <Navbar.Brand>
24 <Glyphicon glyph="star" /> 25 <a href="#"><Glyphicon glyph="link" />{org.name} </a>
25 <a href="#">YOUNGDESK</a>
26 </Navbar.Brand> 26 </Navbar.Brand>
27 <Navbar.Toggle />
27 </Navbar.Header> 28 </Navbar.Header>
28 <Nav> 29 <Navbar.Collapse>
29 <NavItem eventKey={1} href="#">Link</NavItem> 30
30 <NavItem eventKey={2} href="#">Link</NavItem> 31 <Nav pullRight>
31 <NavDropdown eventKey={3} title="Dropdown" id="basic-nav-dropdown"> 32 <NavItem eventKey={1} href="#">
32 <MenuItem eventKey={3.1}>Action</MenuItem> 33 Hello {user.getFullName()}
33 <MenuItem eventKey={3.2}>Another action</MenuItem> 34 </NavItem>
34 <MenuItem eventKey={3.3}>Something else here</MenuItem> 35 <NavItem eventKey={2} href="#">
35 <MenuItem divider /> 36 <div
36 <MenuItem eventKey={3.4}>Separated link</MenuItem> 37 className = "appLayout-topItem"
37 </NavDropdown> 38 onClick = {() => logout()}
39 >
40 logout
41 </div>
42 </NavItem>
38 </Nav> 43 </Nav>
39 </Navbar> 44 </Navbar.Collapse>
45 </Navbar>
40 ); 46 );
41 } 47 }
42 } 48 }
imports/client/views/org/app/module/navigation/index.js
1 // import { InviteSignupController } from '/imports/client/views/invite/signup/index' 1 // import { InviteSignupController } from '/imports/client/views/invite/signup/index'
2 import _ from 'lodash'; 2 import _ from 'lodash';
3 import { 3 import {
4 composeWithTracker, 4 composeWithTracker,
5 compose, 5 compose,
6 composeAll 6 composeAll
7 } from 'react-komposer'; 7 } from 'react-komposer';
8 import { Loading } from '/imports/client/components/Loading'; 8 import { Loading } from '/imports/client/components/Loading';
9 9
10 import { Orgs } from '/imports/collections/orgs/index'; 10 import { Orgs } from '/imports/collections/orgs/index';
11 import { Users } from '/imports/collections/users/index'; 11 import { Users } from '/imports/collections/users/index';
12 12
13 import { AppNavigation } from './AppNavigation'; 13 import { AppNavigation } from './AppNavigation';
14 14
15 const meteorTick = (props, onData) => { 15 const meteorTick = (props, onData) => {
16 16
17 const handles = [ 17 const handles = [
18 Meteor.subscribe('users.current') 18 Meteor.subscribe('users.current'),
19 Meteor.subscribe('orgs.current')
19 ]; 20 ];
20 21
21 if(_.every(handles, (handle) => (handle.ready()) )) { 22 if(_.every(handles, (handle) => (handle.ready()) )) {
22 const user = Users.current(); 23 const user = Users.current();
24 const org = Orgs.current();
23 onData(null, { 25 onData(null, {
24 data: { 26 data: {
25 user: user, 27 user: user,
28 org: org
26 }, 29 },
27 }); 30 });
28 } 31 }
29 32
30 return () => { 33 return () => {
31 _.each(handles, (handle) => handle.stop() ); 34 _.each(handles, (handle) => handle.stop() );
32 }; 35 };
33 }; 36 };
34 37
35 38
36 const reduxTick = (props, onData) => { 39 const reduxTick = (props, onData) => {
37 onData(null, { 40 onData(null, {
38 data: {} 41 data: {}
39 }); 42 });
40 }; 43 };
41 44
42 45
43 export const AppNavigationController = composeAll( 46 export const AppNavigationController = composeAll(
44 composeWithTracker(meteorTick, Loading), 47 composeWithTracker(meteorTick, Loading),
45 compose(reduxTick, Loading), 48 compose(reduxTick, Loading),
46 )(AppNavigation); 49 )(AppNavigation);
47 50
imports/collections/students/index.js
1 // import { Users } from '/imports/collections/users/index'; 1 // import {Students } from '/imports/collections/students/methods'
2 // import { Users } from '/imports/collections/users/index';
3 2
4 import _ from 'lodash'; 3 import _ from 'lodash';
5 import { Meteor } from 'meteor/meteor'; 4 import { Meteor } from 'meteor/meteor';
6 import { Mongo } from 'meteor/mongo'; 5 import { Mongo } from 'meteor/mongo';
7 import { SimpleSchema } from 'meteor/aldeed:simple-schema'; 6 import { SimpleSchema } from 'meteor/aldeed:simple-schema';
8 7
9 import { Orgs } from '/imports/collections/orgs/index'; 8 import { Orgs } from '/imports/collections/orgs/index';
9 import { Users } from '/imports/collections/users/index';
10 10
11 class User { 11 class Student {
12
13 constructor(doc) { 12 constructor(doc) {
14 _.assign(this, doc); 13 _.assign(this, doc);
15 }; 14 };
16 15
17 isEmailVerified() { 16 getUserIds() {
18 return !! _.find(this.emails, x => x.verified); 17 return _.filter(_.map(this.users, 'userId'));
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 }; 18 };
63 }; 19 };
64 20 export { Student };
65 export { User }; 21
66 22 class StudentsCollection extends Mongo.Collection {
67 23 insert(item, callback) {
68 const transform = function(doc) { 24 _.assign(item, {
69 return new User(doc); 25 createdAt: new Date().getTime(),
26 });
27 return super.insert(item, callback);
28 };
70 }; 29 };
71 30
72 export const Users = { 31 export const Students = new StudentsCollection('Students', {
73 32 transform: (item) => {
74 current: function() { 33 return new Student(item);
75 return Meteor.users.findOne({_id: Meteor.userId()}, _.extend({transform: transform}));
76 }, 34 },
35 });
77 36
78 find: function(selector, options) { 37 _.assign(Students, {
79 return Meteor.users.find(selector || {}, _.extend({transform: transform}, options)); 38 allStudents: () => {
39 const user = Users.current();
40 if(!user) return null;
41 return Orgs.find({'users.userId': user._id});
80 }, 42 },
81 43 current: () => {
82 findOne: function(selector, options) { 44 const user = Users.current();
83 return Meteor.users.findOne(selector || {}, _.extend({transform: transform}, options)); 45 if(!user) return null;
46 return Orgs.findOne({_id: user.orgId});
47 },
48 currentOrgUsers: () => {
49 const OrgsArr = Orgs.current();
50 if(!OrgsArr) return null;
51 return OrgsArr.users;
84 }, 52 },
85 53
86 insert: _.bind(Meteor.users.insert, Meteor.users), 54 });
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 55
96 Users.deny({ 56 Students.deny({
97 insert() { return true; }, 57 insert() { return true; },
98 update() { return true; }, 58 update() { return true; },
99 remove() { return true; }, 59 remove() { return true; },
100 }); 60 });
101 61
102 Users.roles = {
103 'STUDENT': 'STUDENT',
104 'TEACHER': 'TEACHER',
105 'ADMIN': 'ADMIN',
106 'PARENT': 'PARENT'
107 };
108 62
109 63 Students.schema = new SimpleSchema({
110 Users.schema = new SimpleSchema({ 64 userId: { type: String },
111 roles: { type: String },
112 orgId: { type: String }, 65 orgId: { type: String },
113 admissionId: { type: String, optional: true }, 66 admissionId: { type: String, optional: true },
114 enrollmentDate: { type: String, optional: true }, 67 enrollmentDate: { type: String, optional: true },
115 address: { type: String, optional: true }, 68 address: { type: String, optional: true },
116 prefix: { type: String, optional: true }, 69 prefix: { type: String, optional: true },
117 firstName: { type: String, optional: true }, 70 firstName: { type: String, optional: true },
118 middlename: { type: String, optional: true }, 71 middlename: { type: String, optional: true },
119 lastName: { type: String, optional: true }, 72 lastName: { type: String, optional: true },
120 gender: { type: String, optional: true }, 73 gender: { type: String, optional: true },
121 dob: { type: String, optional: true }, 74 dob: { type: String, optional: true },
122 rollNo: { type: String, optional: true }, 75 rollNo: { type: String, optional: true },
123 class: { type: String, optional: true }, 76 class: { type: String, optional: true },
124 section: { type: String, optional: true }, 77 section: { type: String, optional: true },
125 bloodGroup: { type: String, optional: true }, 78 bloodGroup: { type: String, optional: true },
126 community: { type: String, optional: true }, 79 community: { type: String, optional: true },
127 nationality: { type: String, optional: true }, 80 nationality: { type: String, optional: true },
128 motherTongue: { type: String, optional: true }, 81 motherTongue: { type: String, optional: true },
129 motherTongue: { type: String, optional: true }, 82 motherTongue: { type: String, optional: true },
130 religion: { type: String, optional: true }, 83 religion: { type: String, optional: true },
131 permanentAddress: { 84 permanentAddress: {
132 type: new SimpleSchema({ 85 type: new SimpleSchema({
133 home: { type: String, optional: true }, 86 home: { type: String, optional: true },
134 street: { type: String, optional: true }, 87 street: { type: String, optional: true },
135 town: { type: String, optional: true }, 88 town: { type: String, optional: true },
136 city: { type: String, optional: true }, 89 city: { type: String, optional: true },
137 state: { type: String, optional: true }, 90 state: { type: String, optional: true },
138 zip: { type: String, optional: true }, 91 zip: { type: String, optional: true },
139 }), 92 }),
93 optional: true
140 }, 94 },
141 parent: { 95 parent: {
142 type: [new SimpleSchema({ 96 type: [new SimpleSchema({
143 id: { type: String, }, 97 id: { type: String, },
144 relatinship: { type: Boolean, }, 98 relatinship: { type: Boolean, },
145 })], 99 })],
146 minCount: 1, 100 optional: true
147 },
148 emails: {
149 type: [new SimpleSchema({
150 address: { type: String, },
151 verified: { type: Boolean, },
152 })],
153 }, 101 },
154 prevInstitute: { 102 prevInstitute: {
155 type: [new SimpleSchema({ 103 type: [new SimpleSchema({
156 name: { type: String, }, 104 name: { type: String, },
157 fromYear: { type: Boolean, }, 105 fromYear: { type: Boolean, },
158 toYear: { type: Boolean, }, 106 toYear: { type: Boolean, },
159 ydId: { type: Boolean, }, 107 ydId: { type: Boolean, },
160 })], 108 })],
161 optional: true 109 optional: true
162 }, 110 },
163 111
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: { 112 services: {
175 type: Object, 113 type: Object,
176 optional: true, 114 optional: true,
177 blackbox: true, 115 blackbox: true,
178 }, 116 },
179 117
180 isMetaUser: { type: Boolean, optional: true }, 118 isMetaUser: { type: Boolean, optional: true },
181 119
182 createdAt: { type: Date, autoValue: function(){return new Date();}} 120 createdAt: { type: Date, autoValue: function(){return new Date();}}
183 121
184 }); 122 });
185 123
186 Users.attachSchema(Users.schema); 124 Students.attachSchema(Students.schema);
187 125
188 Users.privateFields = { 126 Students.privateFields = {
189 orgId: 1, 127 orgId: 1,
190 address: 1, 128 address: 1,
191 129
192 firstName: 1, 130 firstName: 1,
193 lastName: 1, 131 lastName: 1,
imports/collections/students/methods.js
File was created 1 // import { } from '/imports/collections/students/methods';
2 import _ from 'lodash';
3 import { Meteor } from 'meteor/meteor';
4 import { ValidatedMethod } from 'meteor/mdg:validated-method';
5 import { SimpleSchema } from 'meteor/aldeed:simple-schema';
6 import { DDPRateLimiter } from 'meteor/ddp-rate-limiter';
7 import { Bert } from 'meteor/themeteorchef:bert';
8 import { Users } from '/imports/collections/users/index';
9 import { Students } from '/imports/collections/students/index';
10 import { Orgs } from '/imports/collections/orgs/index';
11 export const studentMethods = new ValidatedMethod({
12 name: 'student.method',
13
14 validate: new SimpleSchema({
15 itemId: { type: String },
16 }).validator(),
17
18 run({itemId}) {
19 return {};
20 },
21
22 });
23
24 export const addStudentManually = new ValidatedMethod({
25 name: 'student.addManually',
26
27 validate: new SimpleSchema({
28 firstName: { type: String },
29 middleName: { type: String },
30 lastName: { type: String },
31 }).validator(),
32
33 run({firstName,middleName,lastName}) {
34 console.log(firstName);
35 console.log(middleName);
36 console.log(lastName);
37 const user = Users.findOne({_id: this.userId});
38 orgId = user.orgId;
39 newUserId = Users.insert({
40 username: firstName,
41 firstName: firstName,
42 middleName: middleName,
43 lastName: lastName,
44 orgId: orgId,
45 role: 'STUDENT'
46 });
47 log(newUserId);
48 if(newUserId){
49 Students.insert({
50 userId: newUserId,
51 orgId: orgId,
52 });
53 }
54 return {newUserId};
55 },
56
57 });
58
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 role: { type: String }, 111 role: { type: String },
112 orgId: { type: String }, 112 orgId: { type: String },
113 username: { type: String, optional: true },
113 prefix: { type: String, optional: true }, 114 prefix: { type: String, optional: true },
114 firstName: { type: String, optional: true }, 115 firstName: { type: String, optional: true },
115 middlename: { type: String, optional: true }, 116 middlename: { type: String, optional: true },
116 lastName: { type: String, optional: true }, 117 lastName: { type: String, optional: true },
117 gender: { type: String, optional: true }, 118 gender: { type: String, optional: true },
118 dob: { type: String, optional: true }, 119 dob: { type: String, optional: true },
119 emails: { 120 emails: {
120 type: [new SimpleSchema({ 121 type: [new SimpleSchema({
121 address: { type: String, }, 122 address: { type: String, },
122 verified: { type: Boolean, }, 123 verified: { type: Boolean, },
123 })], 124 })],
125 optional: true
124 }, 126 },
125 phones: { 127 phones: {
126 type: [new SimpleSchema({ 128 type: [new SimpleSchema({
127 country: { type: String, }, 129 country: { type: String, },
128 prefix: { type: String, }, 130 prefix: { type: String, },
129 number: { type: String, }, 131 number: { type: String, },
130 verified: { type: Boolean, }, 132 verified: { type: Boolean, },
131 })], 133 })],
132 optional: true 134 optional: true
133 }, 135 },
134 136
135 services: { 137 services: {
136 type: Object, 138 type: Object,
137 optional: true, 139 optional: true,
138 blackbox: true, 140 blackbox: true,
139 }, 141 },
140 142
141 isMetaUser: { type: Boolean, optional: true }, 143 isMetaUser: { type: Boolean, optional: true },
142 144
143 createdAt: { type: Date, autoValue: function(){return new Date();}} 145 createdAt: { type: Date, autoValue: function(){return new Date();}}
144 146
145 }); 147 });
146 148
147 Users.attachSchema(Users.schema); 149 Users.attachSchema(Users.schema);
148 150
149 Users.privateFields = { 151 Users.privateFields = {
150 orgId: 1, 152 orgId: 1,
151 address: 1, 153 address: 1,
152 154
153 firstName: 1, 155 firstName: 1,
154 lastName: 1, 156 lastName: 1,
155 emails: 1, 157 emails: 1,
156 phones: 1, 158 phones: 1,
157 159
158 isMetaUser: 1, 160 isMetaUser: 1,
159 createdAt: 1, 161 createdAt: 1,
160 }; 162 };
161 163
162 Users.publicFields = { 164 Users.publicFields = {
163 firstName: 1, 165 firstName: 1,
164 lastName: 1, 166 lastName: 1,
165 emails: 1, 167 emails: 1,
166 168
167 createdAt: 1, 169 createdAt: 1,
168 }; 170 };
169 171
imports/collections/users/publications.js
1 import { Meteor } from 'meteor/meteor'; 1 import { Meteor } from 'meteor/meteor';
2 import { check, Match } from 'meteor/check' 2 import { check, Match } from 'meteor/check'
3 import { Users } from '/imports/collections/users/index'; 3 import { Users } from '/imports/collections/users/index';
4 import { Orgs } from '/imports/collections/orgs/index'; 4 import { Orgs } from '/imports/collections/orgs/index';
5 5
6 6
7 7
8 Meteor.publish('users.current', function() { 8 Meteor.publish('users.current', function() {
9 return Users.find({ 9 return Users.find({
10 _id: this.userId, 10 _id: this.userId,
11 }, { 11 }, {
12 fields: Users.privateFields, 12 fields: Users.privateFields,
13 }); 13 });
14 }); 14 });
15 Meteor.publish('users.forMyOrg', function() {
16 const user = Users.findOne({_id: this.userId});
17 if(!user) return [];
18 const org = Orgs.findOne({_id: user.orgId});
19 if(!org) return [];
20
21 return Users.find({
22 orgId: user.orgId,role:"STUDENT"
23 });
24 });
15 25
imports/server/collections.js
1 import '/imports/collections/orgs/publications' 1 import '/imports/collections/orgs/publications'
2 import '/imports/collections/orgs/methods'; 2 import '/imports/collections/orgs/methods';
3 3
4 import '/imports/collections/users/publications'; 4 import '/imports/collections/users/publications';
5
6 import '/imports/collections/students/methods';
5 7
imports/server/fixtures.js
1 import { Meteor } from 'meteor/meteor'; 1 import { Meteor } from 'meteor/meteor';
2 import { Roles } from 'meteor/alanning:roles'; 2 import { Roles } from 'meteor/alanning:roles';
3 import { Accounts } from 'meteor/accounts-base'; 3 import { Accounts } from 'meteor/accounts-base';
4 import { Orgs } from '/imports/collections/orgs/index';
4 5
5 if (!Meteor.isProduction) { 6 if (!Meteor.isProduction) {
6 const users = [{ 7 const users = [{
7 email: 'admin@admin.com', 8 email: 'admin@admin.com',
8 password: 'password', 9 password: 'password',
9 profile: { 10 profile: {
10 name: { first: 'Carl', last: 'Winslow' }, 11 name: { first: 'Carl', last: 'Winslow' },
11 }, 12 },
12 roles: ['admin'], 13 roles: ['admin'],
13 }]; 14 }];
14 15
15 users.forEach(({ email, password, profile, roles }) => { 16 users.forEach(({ email, password, profile, roles }) => {
16 const userExists = Meteor.users.findOne({ 'emails.address': email }); 17 const userExists = Meteor.users.findOne({ 'emails.address': email });
17 18
18 if (!userExists) { 19 if (!userExists) {
19 const userId = Accounts.createUser({ email, password, profile }); 20 const userId = Accounts.createUser({ email, password, profile });
20 Roles.addUsersToRoles(userId, roles); 21 Roles.addUsersToRoles(userId, roles);
22 const org = [{
23 name: 'yd',
24 slug: 'yd',
25 "users.userId": userId
26 }];
27 Orgs.inser
21 } 28 }
22 }); 29 });
23 } 30 }
24 31
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.4.2", 70 "react": "^15.4.2",
71 "react-addons-css-transition-group": "^15.4.2", 71 "react-addons-css-transition-group": "^15.4.2",
72 "react-addons-pure-render-mixin": "^15.3.2", 72 "react-addons-pure-render-mixin": "^15.3.2",
73 "react-addons-transition-group": "^15.4.2", 73 "react-addons-transition-group": "^15.4.2",
74 "react-bootstrap": "^0.30.5", 74 "react-bootstrap": "^0.30.8",
75 "react-bootstrap-date-picker": "^4.0.0",
75 "react-dom": "^15.4.2", 76 "react-dom": "^15.4.2",
76 "react-fontawesome": "^1.5.0", 77 "react-fontawesome": "^1.5.0",
77 "react-komposer": "^1.13.1", 78 "react-komposer": "^1.13.1",
78 "react-router": "^2.6.1", 79 "react-router": "^2.6.1",
79 "react-router-bootstrap": "^0.23.1", 80 "react-router-bootstrap": "^0.23.1",
80 "react-svg": "^2.1.19", 81 "react-svg": "^2.1.19",
81 "reactstrap": "^4.2.0", 82 "reactstrap": "^4.2.0",
82 "velocity-animate": "^1.4.3", 83 "velocity-animate": "^1.4.3",
83 "velocity-react": "^1.2.1" 84 "velocity-react": "^1.2.1"
84 } 85 }
85 } 86 }
86 87
private/fixtures/Orgs-Orgs.csv
File was created 1 key,name,userKeys
2 ADMIN,Admin org,ADMIN
3 BRISBANE,Brisbane Kangaroos,"ADAM,BOB,CHARLIE"
4 PERTH,Perth Sharks,"ADAM,DAVE"
private/fixtures/Users-Users.csv
File was created 1 key,first,last,orgKey,email,isMeta
2 ADMIN,Admin,Adminovich,ADMIN,admin@acme.dev,TRUE
3 ADMIN,Deepak,Jha,YD,deepak@youngdesk.com,TRUE
4