Commit ff976df496e33f361138c9cde5a52d80a4634dea

Authored by Deepak
1 parent 6a2e30e8d0
Exists in master

added orgs publications

.meteor/.finished-upgraders
... ... @@ -14,3 +14,4 @@ notices-for-facebook-graph-api-2
14 14 1.3.5-remove-old-dev-bundle-link
15 15 1.4.0-remove-old-dev-bundle-link
16 16 1.4.1-add-shell-server-package
  17 +1.4.3-split-account-service-packages
... ...
... ... @@ -6,21 +6,21 @@
6 6  
7 7 meteor-base@1.0.4 # Packages every Meteor app needs to have
8 8 mobile-experience@1.0.4 # Packages for a great mobile UX
9   -mongo@1.1.14 # The database Meteor supports right now
  9 +mongo@1.1.15 # The database Meteor supports right now
10 10 reactive-var@1.0.11 # Reactive variable for tracker
11 11 session@1.1.7
12   -tracker@1.1.1 # Meteor's client-side reactive programming library
  12 +tracker@1.1.2 # Meteor's client-side reactive programming library
13 13  
14   -standard-minifier-css@1.3.2 # CSS minifier run for production mode
15   -standard-minifier-js@1.2.1 # JS minifier run for production mode
  14 +standard-minifier-css@1.3.3 # CSS minifier run for production mode
  15 +standard-minifier-js@1.2.2 # JS minifier run for production mode
16 16 es5-shim@4.6.15 # ECMAScript 5 compatibility for older browsers.
17   -ecmascript@0.6.1 # Enable ECMAScript2015+ syntax in app code
  17 +ecmascript@0.6.3 # Enable ECMAScript2015+ syntax in app code
18 18  
19   -accounts-password@1.3.3
  19 +accounts-password@1.3.4
20 20 accounts-base@1.2.14
21   -check@1.2.4
  21 +check
22 22 audit-argument-checks@1.0.7
23   -browser-policy@1.0.9
  23 +browser-policy@1.1.0
24 24  
25 25 fourseven:scss
26 26 aldeed:collection2
... ... @@ -33,4 +33,5 @@ xolvio:backdoor
33 33 mdg:validated-method
34 34 dburles:factory@1.0.0
35 35 ddp-rate-limiter@1.0.6
36   -shell-server@0.2.1
  36 +shell-server@0.2.2
  37 +aldeed:simple-schema
... ...
1   -METEOR@1.4.2.3
  1 +METEOR@1.4.3.1
... ...
1 1 accounts-base@1.2.14
2   -accounts-password@1.3.3
3   -alanning:roles@1.2.15
  2 +accounts-password@1.3.4
  3 +alanning:roles@1.2.16
4 4 aldeed:collection2@2.10.0
5 5 aldeed:collection2-core@1.2.0
6 6 aldeed:schema-deny@1.1.0
... ... @@ -9,65 +9,65 @@ aldeed:simple-schema@1.5.3
9 9 allow-deny@1.0.5
10 10 audit-argument-checks@1.0.7
11 11 autoupdate@1.3.12
12   -babel-compiler@6.13.0
  12 +babel-compiler@6.14.1
13 13 babel-runtime@1.0.1
14 14 base64@1.0.10
15 15 binary-heap@1.0.10
16   -blaze@2.2.0
  16 +blaze@2.3.0
17 17 blaze-tools@1.0.10
18 18 boilerplate-generator@1.0.11
19   -browser-policy@1.0.9
  19 +browser-policy@1.1.0
20 20 browser-policy-common@1.0.11
21   -browser-policy-content@1.0.12
22   -browser-policy-framing@1.0.12
  21 +browser-policy-content@1.1.0
  22 +browser-policy-framing@1.1.0
23 23 caching-compiler@1.1.9
24   -caching-html-compiler@1.0.7
  24 +caching-html-compiler@1.1.0
25 25 callback-hook@1.0.10
26   -check@1.2.4
27   -coffeescript@1.11.1_4
  26 +check@1.2.5
  27 +coffeescript@1.12.3_1
28 28 dburles:factory@1.1.0
29 29 ddp@1.2.5
30   -ddp-client@1.3.2
  30 +ddp-client@1.3.3
31 31 ddp-common@1.2.8
32 32 ddp-rate-limiter@1.0.6
33   -ddp-server@1.3.12
  33 +ddp-server@1.3.13
34 34 deps@1.0.12
35 35 diff-sequence@1.0.7
36   -ecmascript@0.6.1
  36 +ecmascript@0.6.3
37 37 ecmascript-runtime@0.3.15
38 38 ejson@1.0.13
39 39 email@1.1.18
40 40 es5-shim@4.6.15
41 41 fastclick@1.0.13
42 42 fortawesome:fontawesome@4.7.0
43   -fourseven:scss@3.10.1
  43 +fourseven:scss@3.13.0
44 44 geojson-utils@1.0.10
45 45 hot-code-push@1.0.4
46 46 html-tools@1.0.11
47 47 htmljs@1.0.11
48   -http@1.2.10
  48 +http@1.2.11
49 49 id-map@1.0.9
50 50 jquery@1.11.10
51   -launch-screen@1.1.0
  51 +launch-screen@1.1.1
52 52 livedata@1.0.18
53 53 localstorage@1.0.12
54   -logging@1.1.16
  54 +logging@1.1.17
55 55 mdg:validated-method@1.1.0
56 56 mdg:validation-error@0.5.1
57   -meteor@1.6.0
  57 +meteor@1.6.1
58 58 meteor-base@1.0.4
59   -minifier-css@1.2.15
60   -minifier-js@1.2.15
61   -minimongo@1.0.19
  59 +minifier-css@1.2.16
  60 +minifier-js@1.2.18
  61 +minimongo@1.0.20
62 62 mobile-experience@1.0.4
63   -mobile-status-bar@1.0.13
64   -modules@0.7.7
65   -modules-runtime@0.7.7
66   -mongo@1.1.14
  63 +mobile-status-bar@1.0.14
  64 +modules@0.7.9
  65 +modules-runtime@0.7.9
  66 +mongo@1.1.15
67 67 mongo-id@1.0.6
68 68 npm-bcrypt@0.9.2
69   -npm-mongo@2.2.11_2
70   -observe-sequence@1.0.14
  69 +npm-mongo@2.2.16_1
  70 +observe-sequence@1.0.15
71 71 ordered-dict@1.0.9
72 72 practicalmeteor:chai@2.1.0_1
73 73 practicalmeteor:loglevel@1.2.0_2
... ... @@ -86,24 +86,24 @@ routepolicy@1.0.12
86 86 service-configuration@1.0.11
87 87 session@1.1.7
88 88 sha@1.0.9
89   -shell-server@0.2.1
  89 +shell-server@0.2.3
90 90 spacebars@1.0.13
91   -spacebars-compiler@1.0.13
  91 +spacebars-compiler@1.1.0
92 92 srp@1.0.10
93   -standard-minifier-css@1.3.2
94   -standard-minifier-js@1.2.1
95   -static-html@1.1.13
96   -templating@1.2.15
97   -templating-compiler@1.2.15
98   -templating-runtime@1.2.15
99   -templating-tools@1.0.5
  93 +standard-minifier-css@1.3.4
  94 +standard-minifier-js@1.2.3
  95 +static-html@1.2.0
  96 +templating@1.3.0
  97 +templating-compiler@1.3.0
  98 +templating-runtime@1.3.0
  99 +templating-tools@1.1.0
100 100 themeteorchef:bert@2.1.1
101 101 tmeasday:test-reporter-helpers@0.2.1
102   -tracker@1.1.1
  102 +tracker@1.1.2
103 103 ui@1.0.12
104 104 underscore@1.0.10
105   -url@1.0.11
106   -webapp@1.3.12
  105 +url@1.1.0
  106 +webapp@1.3.13
107 107 webapp-hashing@1.0.9
108 108 xolvio:backdoor@0.2.1
109 109 xolvio:cleaner@0.3.1
... ...
imports/client/components/ActionButton.js
... ... @@ -0,0 +1,41 @@
  1 +// import { ActionButton } from '/imports/client/components/actionButton/actionButton';
  2 +import _ from 'lodash';
  3 +import React, { Component } from 'react';
  4 +import { Loading } from '/imports/client/components/Loading';
  5 +
  6 +import classNames from 'classnames';
  7 +
  8 +/*
  9 + <ActionButton
  10 + loading = {this.state.loading}
  11 + onAction = {() => this.onSend()}
  12 + // error = {this.state.error}
  13 + >
  14 + Send invite
  15 + </ActionButton>
  16 +*/
  17 +
  18 +export class ActionButton extends Component {
  19 +
  20 +
  21 + render() {
  22 + if(this.props.loading) {
  23 + return (
  24 + <div className = {this.props.className || ""}>
  25 + <Loading/>
  26 + </div>
  27 + );
  28 + }
  29 +
  30 + return (
  31 + <div
  32 + className = {this.props.className || ""}
  33 + onClick = {() => (this.props.onAction && this.props.onAction())}
  34 + >
  35 + {this.props.children}
  36 + </div>
  37 + );
  38 + };
  39 +};
  40 +
  41 +
... ...
imports/client/components/Avatar.js
... ... @@ -0,0 +1,30 @@
  1 +// import { Avatar } from '/imports/client/components/Avatar';
  2 +import _ from 'lodash';
  3 +import React, { Component } from 'react';
  4 +import classNames from 'classnames';
  5 +
  6 +
  7 +
  8 +export class Avatar extends Component {
  9 +
  10 +
  11 + render() {
  12 + const user = this.props.user;
  13 +
  14 + return (
  15 + <div
  16 + className = {classNames(
  17 + "avatar-box",
  18 + this.props.small && "avatar-small"
  19 + )}
  20 + style={_.assign({
  21 + backgroundImage: `url(${user.getAvatarUrl()})`,
  22 + width: this.props.size + 'px',
  23 + height: this.props.size + 'px',
  24 + }, this.props.style || {})}
  25 + />
  26 + );
  27 + };
  28 +};
  29 +
  30 +
... ...
imports/client/components/Icon.js
... ... @@ -0,0 +1,15 @@
  1 +import React, { Component } from 'react';
  2 +
  3 +export class Icon extends Component {
  4 + render() {
  5 + if(this.props.fa)
  6 + return <i className = {"icon icon-fa icon-fa-" + this.props.fa}></i>
  7 + if(this.props.ion)
  8 + return <i className = {"icon icon-ion icon-ion-" + this.props.ion}></i>
  9 + if(this.props.material)
  10 + return <i className = {"icon icon-material icon-material-" + this.props.material}></i>
  11 + if(this.props.simple)
  12 + return <i className = {"icon icon-simple icon-" + this.props.simple}></i>
  13 + return <i></i>
  14 + };
  15 +};
... ...
imports/client/components/Loading.js
... ... @@ -0,0 +1,44 @@
  1 +// import { Loading } from '/imports/client/components/Loading';
  2 +import React from 'react';
  3 +
  4 +
  5 +
  6 +export class Loading extends React.Component {
  7 +
  8 + render() {
  9 + return (
  10 + <div className = "loading-box">
  11 + <div className = "loading-content">
  12 + <svg
  13 + version = "1.1"
  14 + className = "loading-icon"
  15 + xmlns = "http://www.w3.org/2000/svg"
  16 + x = "0px"
  17 + y = "0px"
  18 + width = "40px"
  19 + height = "40px"
  20 + viewBox = "0 0 40 40"
  21 + enableBackground = "new 0 0 40 40"
  22 + >
  23 + <path
  24 + opacity = "1.0"
  25 + fill = "#fff"
  26 + d = "M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946,
  27 + 14.946,14.946s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201,
  28 + 5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634c0-6.425,
  29 + 5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834,
  30 + 26.541,26.626,31.749,20.201,31.749z"
  31 + />
  32 + <path
  33 + fill = "#0080ff"
  34 + d = "M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0
  35 + C22.32,8.481,24.301,9.057,26.013,10.047z"
  36 + />
  37 + </svg>
  38 + </div>
  39 + </div>
  40 + );
  41 + };
  42 +
  43 +};
  44 +
... ...
imports/client/components/Logic.js
... ... @@ -0,0 +1,34 @@
  1 +import _ from 'lodash';
  2 +import React, { Component } from 'react';
  3 +
  4 +
  5 +const instance = (value) => (
  6 + _.isFunction(value) ? value() : (value || null)
  7 +);
  8 +
  9 +
  10 +export class If extends Component {
  11 +
  12 + render() {
  13 + return this.props.if ? instance(this.props.then) : instance(this.props.else);
  14 + };
  15 +
  16 +};
  17 +
  18 +
  19 +export class Case extends Component {
  20 +
  21 + render() {
  22 + const val = this.props.switch;
  23 + for(let i = 0; i < 999; ++i) {
  24 + if(this.props['case' + i] === undefined) return instance(this.props.else);
  25 + if(this.props['case' + i] === val) return instance(this.props['then' + i]);
  26 + }
  27 + return null;
  28 + };
  29 +
  30 +};
  31 +
  32 +
  33 +
  34 +
... ...
imports/client/components/VerificationNeeded.js
... ... @@ -0,0 +1,20 @@
  1 +
  2 +import React, { Component } from 'react';
  3 +
  4 +export class VerificationNeeded extends Component {
  5 +
  6 + render() {
  7 + if(! this.props.verify) {
  8 + return (
  9 + <div>
  10 + {this.props.message}
  11 + </div>
  12 + );
  13 + }
  14 +
  15 + return this.props.children;
  16 + };
  17 +
  18 +};
  19 +
  20 +
... ...
imports/client/components/validationMethods.js
... ... @@ -0,0 +1,69 @@
  1 +export default class Validation{
  2 +
  3 + validateEmail (value) {
  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,}))$/;
  6 + return re.test(value);
  7 + };
  8 +
  9 +
  10 + noSpecialChars(str){
  11 + str = String(str);
  12 + return !/[~`!#$%\^&*+=\-\[\]\\';,/{}|\\":<>\?]/g.test(str);
  13 + }
  14 +
  15 + noQwertysAllowed (str){
  16 + str = String(str);
  17 + str = str.toLowerCase();
  18 + if(str.toLowerCase().IndexOf("qwerty") >-1){
  19 + return false;
  20 + } else{
  21 + return true;
  22 + }
  23 + }
  24 +
  25 + passwordValidation (str){
  26 + str = String(str);
  27 + if(str.length <6){
  28 + return false;
  29 + } else{
  30 + return true;
  31 + }
  32 + }
  33 +
  34 + isNumberOnly(str){
  35 + str = String(str);
  36 + if(!/^\d+$/.test(str)){
  37 + return false;
  38 + }else {
  39 + return true;
  40 + }
  41 + }
  42 +
  43 + isValidACN(str){
  44 + str = String(str);
  45 + console.log(str);
  46 + if(/^\d+$/.test(str) && str.length ==9){
  47 + return true;
  48 + } else{
  49 + return false;
  50 + }
  51 + }
  52 + containsNumbers(str){
  53 + str = String(str);
  54 + if(/\d/g.test(str)){
  55 + return true;
  56 + }else{
  57 + return false;
  58 + }
  59 + }
  60 +
  61 + isValidShortCode(str){
  62 + str = String(str);
  63 + if(containsNoSpecialCharacters(str) && !containsNumbers(str) && str.length <5){
  64 + return true;
  65 + } else{
  66 + return false;
  67 + }
  68 + }
  69 +};
... ...
imports/collections/orgs/index.js
... ... @@ -0,0 +1,113 @@
  1 +// import { Orgs } from '/imports/collections/orgs/index';
  2 +
  3 +import _ from 'lodash';
  4 +import { Mongo } from 'meteor/mongo';
  5 +import { SimpleSchema } from 'meteor/aldeed:simple-schema';
  6 +
  7 +import { Users } from '/imports/collections/users/index';
  8 +
  9 +class Org {
  10 + constructor(doc) {
  11 + _.assign(this, doc);
  12 + };
  13 +
  14 + getUserIds() {
  15 + return _.filter(_.map(this.users, 'userId'));
  16 + };
  17 +
  18 + getInvitationIds() {
  19 + return _.filter(_.map(this.users, 'invitationId'));
  20 + };
  21 +
  22 + areDetailsDone() {
  23 + return (
  24 + this.name && this.name.length &&
  25 + this.shortCode && this.shortCode.length &&
  26 + this.acn && this.acn.length
  27 + );
  28 + };
  29 +
  30 + ifCurrentUserIsAdmin(){
  31 + const user = Users.current();
  32 + if(!user) return null;
  33 + for(let i = 0; i < this.users.length; ++i) {
  34 + if(
  35 + (this.users[i].role == "SECRETARY")
  36 + && this.users[i].userId == user._id
  37 + ) {
  38 + return true;
  39 + }
  40 + }
  41 + return false;
  42 + }
  43 +
  44 +
  45 +};
  46 +export { Org };
  47 +
  48 +class OrgsCollection extends Mongo.Collection {
  49 + insert(item, callback) {
  50 + _.assign(item, {
  51 + createdAt: new Date().getTime(),
  52 + });
  53 + return super.insert(item, callback);
  54 + };
  55 +};
  56 +
  57 +export const Orgs = new OrgsCollection('Orgs', {
  58 + transform: (item) => {
  59 + return new Org(item);
  60 + },
  61 +});
  62 +
  63 +_.assign(Orgs, {
  64 + allOrgsCurrentUser: () => {
  65 + const user = Users.current();
  66 + if(!user) return null;
  67 + return Orgs.find({'users.userId': user._id});
  68 + },
  69 + current: () => {
  70 + const user = Users.current();
  71 + if(!user) return null;
  72 + return Orgs.findOne({_id: user.orgId});
  73 + },
  74 + currentOrgUsers: () => {
  75 + const OrgsArr = Orgs.current();
  76 + if(!OrgsArr) return null;
  77 + return OrgsArr.users;
  78 + },
  79 +
  80 +});
  81 +
  82 +Orgs.deny({
  83 + insert() { return true; },
  84 + update() { return true; },
  85 + remove() { return true; },
  86 +});
  87 +
  88 +Orgs.schema = new SimpleSchema({
  89 +
  90 + name: { type: String, },
  91 + slug: { type: String, optional: true},
  92 + address: { type: String, optional: true},
  93 + users: {
  94 + type: [new SimpleSchema({
  95 + userId: { type: String, optional: true},
  96 + invitationId: { type: String, optional: true},
  97 + role: { type: String, },
  98 + email: { type: String, optional: true},
  99 + })],
  100 + },
  101 + createdAt: { type: Date, autoValue: function(){return new Date();}},
  102 +
  103 +});
  104 +
  105 +
  106 +
  107 +Orgs.attachSchema(Orgs.schema);
  108 +
  109 +Orgs.publicFields = {
  110 + name: 1,
  111 + slug: 1,
  112 + createdAt: 1,
  113 +};
... ...
imports/collections/orgs/publications.js
... ... @@ -0,0 +1,17 @@
  1 +import { Meteor } from 'meteor/meteor';
  2 +import { check, Match } from 'meteor/check'
  3 +
  4 +import { Orgs } from '/imports/collections/orgs/index';
  5 +import { Users } from '/imports/collections/users/index';
  6 +
  7 +Meteor.publish('orgs.current', function () {
  8 + const user = Users.findOne({_id: this.userId});
  9 + if(!user) return [];
  10 +
  11 + return Orgs.find({_id: user.orgId});
  12 +});
  13 +
  14 +Meteor.publish('allOrgsSlug', function () {
  15 + console.log(Orgs.find({},{fields: Orgs.publicFields}).fetch());
  16 + return Orgs.find({},{fields: Orgs.publicFields});
  17 +});
... ...
imports/collections/users/index.js
... ... @@ -0,0 +1,207 @@
  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 },
  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 +};
... ...
imports/modules/signup.js
1 1 /* eslint-disable no-undef */
2 2  
3   -import { browserHistory } from 'react-router';
4   -import { Accounts } from 'meteor/accounts-base';
5   -import { Bert } from 'meteor/themeteorchef:bert';
6   -import './validation.js';
  3 +import { browserHistory } from 'react-router';
  4 +import { Accounts } from 'meteor/accounts-base';
  5 +import { Bert } from 'meteor/themeteorchef:bert';
  6 +import { Loading } from '/imports/client/components/Loading';
  7 +import './validation.js';
7 8  
8 9 let component;
9 10  
... ...
imports/server/accounts/creation.js
... ... @@ -0,0 +1,24 @@
  1 +import _ from 'lodash';
  2 +import { Accounts } from 'meteor/accounts-base';
  3 +import { SimpleSchema } from 'meteor/aldeed:simple-schema';
  4 +import { ValidatedMethod } from 'meteor/mdg:validated-method';
  5 +import { Orgs } from '/imports/collections/orgs/index';
  6 +import { Users } from '/imports/collections/users/index';
  7 +
  8 +
  9 +
  10 +Accounts.validateNewUser((user) => {
  11 + return !!user;
  12 +});
  13 +
  14 +Accounts.onCreateUser((options, user) => {
  15 + console.log(options);
  16 + _.assign(user, {
  17 + firstName: options.profile.firstName,
  18 + lastName: options.profile.lastName,
  19 + phones: [],
  20 + identities: [],
  21 + createdAt: new Date().getTime(),
  22 + });
  23 + return user;
  24 +});
... ...
imports/startup/client/routes.js
... ... @@ -24,10 +24,18 @@ const authenticate = (nextState, replace) =&gt; {
24 24 });
25 25 }
26 26 };
  27 +const detectOrg = () => {
  28 + var hostnameArray = document.location.hostname.split( "." );
  29 + if(hostnameArray[1]=='localhost'){
  30 + orgSlug = hostnameArray[0];
  31 + }else{
  32 + orgSlug = hostnameArray[0];
  33 + }
  34 +
  35 +}
  36 +
27 37  
28 38 Meteor.startup(() => {
29   - var hostnameArray = document.location.hostname.split( "." );
30   -
31 39  
32 40 render(
33 41 <Router history={ browserHistory }>
... ...
imports/startup/server/accounts/creation.js
... ... @@ -0,0 +1,14 @@
  1 +import _ from 'lodash';
  2 +import { Accounts } from 'meteor/accounts-base';
  3 +import { SimpleSchema } from 'meteor/aldeed:simple-schema';
  4 +import { ValidatedMethod } from 'meteor/mdg:validated-method';
  5 +
  6 +
  7 +
  8 +Accounts.validateNewUser((user) => {
  9 + return !!user;
  10 +});
  11 +
  12 +Accounts.onCreateUser((options, user) => {
  13 + console.log(options);
  14 +});
... ...
imports/startup/server/accounts/resetPassword.js
... ... @@ -0,0 +1,31 @@
  1 +import _ from 'lodash';
  2 +import { Accounts } from 'meteor/accounts-base';
  3 +
  4 +
  5 +Accounts.emailTemplates.resetPassword = {
  6 + subject() {
  7 + return '[Blok8] Reset Your Password';
  8 + },
  9 + text(user, url) {
  10 + const userEmail = user.emails[0].address;
  11 + const theUrl = Meteor.absoluteUrl(`?enter=reset&token=${_.last(url.split('/'))}`);
  12 + // const theUrl = decodeURI(`\u003D`);
  13 +
  14 + return (
  15 +`
  16 +Hello, ${user.firstName}!
  17 +
  18 +
  19 +A password reset has been requested for the account related to this address.
  20 +To reset the password, visit the following link:
  21 +
  22 +${theUrl}
  23 +
  24 +If you did not request this reset, please ignore this email.
  25 +
  26 +`
  27 + );
  28 + },
  29 +};
  30 +
  31 +
... ...
imports/startup/server/accounts/verifyEmail.js
... ... @@ -0,0 +1,29 @@
  1 +import _ from 'lodash';
  2 +import { Accounts } from 'meteor/accounts-base';
  3 +
  4 +Accounts.config({
  5 + sendVerificationEmail: true
  6 +});
  7 +
  8 +Accounts.emailTemplates.verifyEmail = {
  9 + subject() {
  10 + return '[Blok8] Verify Your Email Address';
  11 + },
  12 + text(user, url) {
  13 + const theUrl = Meteor.absoluteUrl(`back/verifyEmail/${_.last(url.split('/'))}`);
  14 +
  15 + return (
  16 +`
  17 +Hello, ${user.firstName}!
  18 +
  19 +
  20 +To verify your email address, visit the following link:
  21 +
  22 +${theUrl}
  23 +
  24 +If you did not request this verification, please ignore this email.
  25 +
  26 +`
  27 + );
  28 + },
  29 +};
... ...
imports/startup/server/index.js
1 1 import './accounts/email-templates';
  2 +import './accounts/creation';
2 3 import './browser-policy';
3 4 import './fixtures';
4 5 import './api';
  6 +
  7 +
  8 +
  9 +import '/imports/collections/orgs/publications'
... ...
imports/ui/pages/Signup.js
1   -import React from 'react';
2   -import { Link } from 'react-router';
3   -import { Row, Col, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap';
4   -import handleSignup from '../../modules/signup';
  1 +import React from 'react';
  2 +import { Link } from 'react-router';
  3 +import { Row, Col, FormGroup,
  4 + ControlLabel, FormControl,
  5 + InputGroup, Button } from 'react-bootstrap';
  6 +import handleSignup from '../../modules/signup';
  7 +import { Orgs } from '/imports/collections/orgs/index';
5 8  
6 9 export default class Signup extends React.Component {
  10 + constructor(props) {
  11 + super(props);
  12 + this.state = {
  13 + newSlug: ""
  14 + };
  15 + }
  16 + componentWillMount(){
  17 + Meteor.subscribe('allOrgsSlug');
  18 + }
  19 +
7 20 componentDidMount() {
8 21 handleSignup({ component: this });
9 22 }
... ... @@ -11,7 +24,10 @@ export default class Signup extends React.Component {
11 24 handleSubmit(event) {
12 25 event.preventDefault();
13 26 }
14   -
  27 + checkExistingOrgSlug(e) {
  28 + searchOrg = Orgs.find({}).fetch();
  29 + console.log(searchOrg);
  30 + }
15 31 render() {
16 32 return (
17 33 <div className="Signup">
... ... @@ -22,6 +38,23 @@ export default class Signup extends React.Component {
22 38 ref={ form => (this.signupForm = form) }
23 39 onSubmit={ this.handleSubmit }
24 40 >
  41 + <Row>
  42 + <Col xs={ 12 } sm={ 12 }>
  43 + <FormGroup controlId="formValidationError2">
  44 + <ControlLabel>Organisation name</ControlLabel>
  45 + <InputGroup>
  46 + <FormControl
  47 + type="text"
  48 + ref="orgSlug"
  49 + name="orgSlug"
  50 + placeholder="School Name"
  51 + onChange = {(e) => this.checkExistingOrgSlug(e)}
  52 + />
  53 + <InputGroup.Addon>@yd.com</InputGroup.Addon>
  54 + </InputGroup>
  55 + </FormGroup>
  56 + </Col>
  57 + </Row>
25 58 <Row>
26 59 <Col xs={ 6 } sm={ 6 }>
27 60 <FormGroup>
... ...