Commit d0099dd8829621efd696b2820ac21ec7bc2cf36c
1 parent
13ef5ba8c6
Exists in
master
student detail page view
Showing
18 changed files
with
406 additions
and
130 deletions
Show diff stats
client/main.html
... | ... | @@ -5,6 +5,9 @@ |
5 | 5 | <meta name="viewport" content="initial-scale=1, minimal-ui, maximum-scale=1, minimum-scale=1" /> |
6 | 6 | <link rel="shortcut icon" type="image/png" href="/favicon.png?v1" sizes="16x16 32x32 64x64"> |
7 | 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 | 11 | <link |
9 | 12 | href='https://fonts.googleapis.com/css?family=Alef' |
10 | 13 | rel='stylesheet' | ... | ... |
imports/client/app/routes.js
... | ... | @@ -20,6 +20,9 @@ import { AppModule } from '/imports/client/views/org/app/ |
20 | 20 | import { Orgs } from '/imports/collections/orgs/index'; |
21 | 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 | 27 | import NotFound from '/imports/client/views/org/NotFound'; |
25 | 28 | |
... | ... | @@ -77,6 +80,7 @@ const getOrgRoutes = () => ( |
77 | 80 | <Route path="/" component={ App }> |
78 | 81 | <IndexRoute name="index" component={ AppModule } /> |
79 | 82 | <Route name="import" path="/import" component={ importCsvController } /> |
83 | + <Route name="student" path="/students" component={ StudentDataController } /> | |
80 | 84 | <Route path="*" component={ NotFound } /> |
81 | 85 | </Route> |
82 | 86 | </Router> | ... | ... |
imports/client/views/etc/index.js
... | ... | @@ -13,14 +13,17 @@ import { Users } from '/imports/collections/users/index |
13 | 13 | const meteorTick = (props, onData) => { |
14 | 14 | |
15 | 15 | const handles = [ |
16 | - Meteor.subscribe('users.current') | |
16 | + Meteor.subscribe('users.current'), | |
17 | + Meteor.subscribe('orgs.current') | |
17 | 18 | ]; |
18 | 19 | |
19 | 20 | if(_.every(handles, (handle) => (handle.ready()) )) { |
20 | 21 | const user = Users.current(); |
22 | + const org = Orgs.current(); | |
21 | 23 | onData(null, { |
22 | 24 | data: { |
23 | 25 | user: user, |
26 | + org: org | |
24 | 27 | }, |
25 | 28 | }); |
26 | 29 | } | ... | ... |
imports/client/views/etc/signup.js
imports/client/views/org/admin/students/StudentDataView.js
... | ... | @@ -0,0 +1,88 @@ |
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 | +}; | ... | ... |
imports/client/views/org/admin/students/addStudentForm.js
... | ... | @@ -0,0 +1,90 @@ |
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 | +}; | ... | ... |
imports/client/views/org/admin/students/index.js
... | ... | @@ -0,0 +1,54 @@ |
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); | ... | ... |
imports/client/views/org/app/module/navigation/AuthenticatedNavigation.js
1 | -import React, { Component } from 'react'; | |
2 | -import { browserHistory } from 'react-router'; | |
3 | -import { LinkContainer } from 'react-router-bootstrap'; | |
1 | +import React, { Component } from 'react'; | |
2 | +import { browserHistory } from 'react-router'; | |
3 | +import { LinkContainer } from 'react-router-bootstrap'; | |
4 | +import { logout } from '/imports/client/app/utils/loginMethods'; | |
4 | 5 | import { Navbar,Modal, Nav, NavItem, |
5 | 6 | Glyphicon, |
6 | - NavDropdown, MenuItem } from 'react-bootstrap'; | |
7 | -import { Meteor } from 'meteor/meteor'; | |
7 | + NavDropdown, MenuItem } from 'react-bootstrap'; | |
8 | +import { Meteor } from 'meteor/meteor'; | |
8 | 9 | |
9 | 10 | const handleLogout = () => Meteor.logout(() => browserHistory.push('/login')); |
10 | 11 | |
... | ... | @@ -16,27 +17,32 @@ export class AuthenticatedNavigation extends Component { |
16 | 17 | }; |
17 | 18 | }; |
18 | 19 | render(){ |
19 | - const {user} = this.props.data; | |
20 | + const {user, org} = this.props.data; | |
20 | 21 | return( |
21 | - <Navbar inverse> | |
22 | + <Navbar inverse collapseOnSelect className="bg-crimson"> | |
22 | 23 | <Navbar.Header> |
23 | 24 | <Navbar.Brand> |
24 | - <Glyphicon glyph="star" /> | |
25 | - <a href="#">YOUNGDESK</a> | |
25 | + <a href="#"><Glyphicon glyph="link" />{org.name} </a> | |
26 | 26 | </Navbar.Brand> |
27 | + <Navbar.Toggle /> | |
27 | 28 | </Navbar.Header> |
28 | - <Nav> | |
29 | - <NavItem eventKey={1} href="#">Link</NavItem> | |
30 | - <NavItem eventKey={2} href="#">Link</NavItem> | |
31 | - <NavDropdown eventKey={3} title="Dropdown" id="basic-nav-dropdown"> | |
32 | - <MenuItem eventKey={3.1}>Action</MenuItem> | |
33 | - <MenuItem eventKey={3.2}>Another action</MenuItem> | |
34 | - <MenuItem eventKey={3.3}>Something else here</MenuItem> | |
35 | - <MenuItem divider /> | |
36 | - <MenuItem eventKey={3.4}>Separated link</MenuItem> | |
37 | - </NavDropdown> | |
29 | + <Navbar.Collapse> | |
30 | + | |
31 | + <Nav pullRight> | |
32 | + <NavItem eventKey={1} href="#"> | |
33 | + Hello {user.getFullName()} | |
34 | + </NavItem> | |
35 | + <NavItem eventKey={2} href="#"> | |
36 | + <div | |
37 | + className = "appLayout-topItem" | |
38 | + onClick = {() => logout()} | |
39 | + > | |
40 | + logout | |
41 | + </div> | |
42 | + </NavItem> | |
38 | 43 | </Nav> |
39 | - </Navbar> | |
44 | + </Navbar.Collapse> | |
45 | + </Navbar> | |
40 | 46 | ); |
41 | 47 | } |
42 | 48 | } | ... | ... |
imports/client/views/org/app/module/navigation/index.js
... | ... | @@ -15,14 +15,17 @@ import { AppNavigation } from './AppNavigation'; |
15 | 15 | const meteorTick = (props, onData) => { |
16 | 16 | |
17 | 17 | const handles = [ |
18 | - Meteor.subscribe('users.current') | |
18 | + Meteor.subscribe('users.current'), | |
19 | + Meteor.subscribe('orgs.current') | |
19 | 20 | ]; |
20 | 21 | |
21 | 22 | if(_.every(handles, (handle) => (handle.ready()) )) { |
22 | 23 | const user = Users.current(); |
24 | + const org = Orgs.current(); | |
23 | 25 | onData(null, { |
24 | 26 | data: { |
25 | 27 | user: user, |
28 | + org: org | |
26 | 29 | }, |
27 | 30 | }); |
28 | 31 | } | ... | ... |
imports/collections/students/index.js
1 | -// import { Users } from '/imports/collections/users/index'; | |
2 | -// import { Users } from '/imports/collections/users/index'; | |
1 | +// import {Students } from '/imports/collections/students/methods' | |
3 | 2 | |
4 | 3 | import _ from 'lodash'; |
5 | 4 | import { Meteor } from 'meteor/meteor'; |
... | ... | @@ -7,108 +6,62 @@ import { Mongo } from 'meteor/mongo'; |
7 | 6 | import { SimpleSchema } from 'meteor/aldeed:simple-schema'; |
8 | 7 | |
9 | 8 | import { Orgs } from '/imports/collections/orgs/index'; |
9 | +import { Users } from '/imports/collections/users/index'; | |
10 | 10 | |
11 | -class User { | |
12 | - | |
11 | +class Student { | |
13 | 12 | constructor(doc) { |
14 | 13 | _.assign(this, doc); |
15 | 14 | }; |
16 | 15 | |
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`; | |
16 | + getUserIds() { | |
17 | + return _.filter(_.map(this.users, 'userId')); | |
62 | 18 | }; |
63 | 19 | }; |
64 | - | |
65 | -export { User }; | |
66 | - | |
67 | - | |
68 | -const transform = function(doc) { | |
69 | - return new User(doc); | |
20 | +export { Student }; | |
21 | + | |
22 | +class StudentsCollection extends Mongo.Collection { | |
23 | + insert(item, callback) { | |
24 | + _.assign(item, { | |
25 | + createdAt: new Date().getTime(), | |
26 | + }); | |
27 | + return super.insert(item, callback); | |
28 | + }; | |
70 | 29 | }; |
71 | 30 | |
72 | -export const Users = { | |
73 | - | |
74 | - current: function() { | |
75 | - return Meteor.users.findOne({_id: Meteor.userId()}, _.extend({transform: transform})); | |
31 | +export const Students = new StudentsCollection('Students', { | |
32 | + transform: (item) => { | |
33 | + return new Student(item); | |
76 | 34 | }, |
35 | +}); | |
77 | 36 | |
78 | - find: function(selector, options) { | |
79 | - return Meteor.users.find(selector || {}, _.extend({transform: transform}, options)); | |
37 | +_.assign(Students, { | |
38 | + allStudents: () => { | |
39 | + const user = Users.current(); | |
40 | + if(!user) return null; | |
41 | + return Orgs.find({'users.userId': user._id}); | |
80 | 42 | }, |
81 | - | |
82 | - findOne: function(selector, options) { | |
83 | - return Meteor.users.findOne(selector || {}, _.extend({transform: transform}, options)); | |
43 | + current: () => { | |
44 | + const user = Users.current(); | |
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), | |
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 | - | |
54 | +}); | |
95 | 55 | |
96 | -Users.deny({ | |
56 | +Students.deny({ | |
97 | 57 | insert() { return true; }, |
98 | 58 | update() { return true; }, |
99 | 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 | - | |
110 | -Users.schema = new SimpleSchema({ | |
111 | - roles: { type: String }, | |
63 | +Students.schema = new SimpleSchema({ | |
64 | + userId: { type: String }, | |
112 | 65 | orgId: { type: String }, |
113 | 66 | admissionId: { type: String, optional: true }, |
114 | 67 | enrollmentDate: { type: String, optional: true }, |
... | ... | @@ -137,19 +90,14 @@ Users.schema = new SimpleSchema({ |
137 | 90 | state: { type: String, optional: true }, |
138 | 91 | zip: { type: String, optional: true }, |
139 | 92 | }), |
93 | + optional: true | |
140 | 94 | }, |
141 | 95 | parent: { |
142 | 96 | type: [new SimpleSchema({ |
143 | 97 | id: { type: String, }, |
144 | 98 | relatinship: { type: Boolean, }, |
145 | 99 | })], |
146 | - minCount: 1, | |
147 | - }, | |
148 | - emails: { | |
149 | - type: [new SimpleSchema({ | |
150 | - address: { type: String, }, | |
151 | - verified: { type: Boolean, }, | |
152 | - })], | |
100 | + optional: true | |
153 | 101 | }, |
154 | 102 | prevInstitute: { |
155 | 103 | type: [new SimpleSchema({ |
... | ... | @@ -161,16 +109,6 @@ Users.schema = new SimpleSchema({ |
161 | 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 | 112 | services: { |
175 | 113 | type: Object, |
176 | 114 | optional: true, |
... | ... | @@ -183,9 +121,9 @@ Users.schema = new SimpleSchema({ |
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 | 127 | orgId: 1, |
190 | 128 | address: 1, |
191 | 129 | |
... | ... | @@ -198,7 +136,7 @@ Users.privateFields = { |
198 | 136 | createdAt: 1, |
199 | 137 | }; |
200 | 138 | |
201 | -Users.publicFields = { | |
139 | +Students.publicFields = { | |
202 | 140 | firstName: 1, |
203 | 141 | lastName: 1, |
204 | 142 | emails: 1, | ... | ... |
imports/collections/students/methods.js
... | ... | @@ -0,0 +1,57 @@ |
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 | +}); | ... | ... |
imports/collections/users/index.js
... | ... | @@ -108,8 +108,9 @@ Users.roles = { |
108 | 108 | |
109 | 109 | |
110 | 110 | Users.schema = new SimpleSchema({ |
111 | - role: { type: String }, | |
111 | + role: { type: String }, | |
112 | 112 | orgId: { type: String }, |
113 | + username: { type: String, optional: true }, | |
113 | 114 | prefix: { type: String, optional: true }, |
114 | 115 | firstName: { type: String, optional: true }, |
115 | 116 | middlename: { type: String, optional: true }, |
... | ... | @@ -121,6 +122,7 @@ Users.schema = new SimpleSchema({ |
121 | 122 | address: { type: String, }, |
122 | 123 | verified: { type: Boolean, }, |
123 | 124 | })], |
125 | + optional: true | |
124 | 126 | }, |
125 | 127 | phones: { |
126 | 128 | type: [new SimpleSchema({ | ... | ... |
imports/collections/users/publications.js
... | ... | @@ -12,3 +12,13 @@ Meteor.publish('users.current', function() { |
12 | 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 | +}); | ... | ... |
imports/server/collections.js
imports/server/fixtures.js
1 | -import { Meteor } from 'meteor/meteor'; | |
2 | -import { Roles } from 'meteor/alanning:roles'; | |
3 | -import { Accounts } from 'meteor/accounts-base'; | |
1 | +import { Meteor } from 'meteor/meteor'; | |
2 | +import { Roles } from 'meteor/alanning:roles'; | |
3 | +import { Accounts } from 'meteor/accounts-base'; | |
4 | +import { Orgs } from '/imports/collections/orgs/index'; | |
4 | 5 | |
5 | 6 | if (!Meteor.isProduction) { |
6 | 7 | const users = [{ |
... | ... | @@ -18,6 +19,12 @@ if (!Meteor.isProduction) { |
18 | 19 | if (!userExists) { |
19 | 20 | const userId = Accounts.createUser({ email, password, profile }); |
20 | 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 | } | ... | ... |
package.json
... | ... | @@ -71,7 +71,8 @@ |
71 | 71 | "react-addons-css-transition-group": "^15.4.2", |
72 | 72 | "react-addons-pure-render-mixin": "^15.3.2", |
73 | 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 | 76 | "react-dom": "^15.4.2", |
76 | 77 | "react-fontawesome": "^1.5.0", |
77 | 78 | "react-komposer": "^1.13.1", | ... | ... |
private/fixtures/Orgs-Orgs.csv
private/fixtures/Users-Users.csv