diff --git a/client/main.js b/client/main.js
index 090ed9e..d6d9069 100644
--- a/client/main.js
+++ b/client/main.js
@@ -1 +1 @@
-import '/imports/startup/client';
+import '/imports/client/app/index';
diff --git a/imports/client/app/index.js b/imports/client/app/index.js
new file mode 100644
index 0000000..e9ffe89
--- /dev/null
+++ b/imports/client/app/index.js
@@ -0,0 +1,37 @@
+import _ from 'lodash';
+import moment from 'moment';
+import { Meteor } from 'meteor/meteor';
+import { Router, browserHistory } from 'react-router';
+
+import { Orgs } from '/imports/collections/orgs/index';
+import { Users } from '/imports/collections/users/index';;
+
+
+import { Bert } from 'meteor/themeteorchef:bert';
+import './routes.js';
+import './shelf.js';
+// import 'react-quill/dist/quill.snow.css';
+
+Bert.defaults = {
+ hideDelay: 3500,
+ // Accepts: a number in milliseconds.
+ style: 'fixed-top',
+ // Accepts: fixed-top, fixed-bottom, growl-top-left, growl-top-right,
+ // growl-bottom-left, growl-bottom-right.
+ type: 'default'
+ // Accepts: default, success, info, warning, danger.
+};
+
+_.assign(window, {
+ _,
+});
+
+if(Meteor.settings.public.environment === 'development') {
+ _.assign(window, {
+ Meteor,
+ Shelf,
+
+ Orgs,
+ Users,
+ });
+}
diff --git a/imports/client/app/routes.js b/imports/client/app/routes.js
new file mode 100644
index 0000000..b2cea51
--- /dev/null
+++ b/imports/client/app/routes.js
@@ -0,0 +1,104 @@
+/* eslint-disable max-len */
+
+import React from 'react';
+import { render } from 'react-dom';
+import { Router, Route,
+ IndexRoute, browserHistory } from 'react-router';
+import { Meteor } from 'meteor/meteor';
+
+/**
+ * General Components
+ */
+import Index from '/imports/client/views/app/module/Index';
+
+/**
+ * Org Components
+ */
+
+import { App } from '/imports/client/layouts/OrgApp';
+import { AppModule } from '/imports/client/views/org/app/module/Index';
+import { Orgs } from '/imports/collections/orgs/index';
+import NotFound from '/imports/client/views/org/NotFound';
+
+/**
+ * NonOrg Components
+ */
+import Signup from '/imports/client/views/nonOrg/enter/SignupView';
+
+/**
+ * Invalid Org Components
+ */
+
+const authenticate = (nextState, replace) => {
+ if (!Meteor.loggingIn() && !Meteor.userId()) {
+ replace({
+ pathname: '/login',
+ state: { nextPathname: nextState.location.pathname },
+ });
+ }
+};
+
+
+const detectOrg = () => {
+ orgSlug = "";
+ var hostnameArray = document.location.hostname.split( "." );
+ if(hostnameArray[1]=='localhost'){
+ orgSlug = hostnameArray[0];
+ }
+ if(orgSlug!=""){
+ Meteor.call('checkExistingOrg', {slug:orgSlug}, function(err, res) {
+ if(res){
+ Session.set('orgId', res._id._str);
+ Session.set('orgSlug', orgSlug);
+ render(getOrgRoutes(),document.getElementById('app'));
+ }else{
+ render(getInvalidOrgRoute(),document.getElementById('app'));
+ }
+ });
+ }else{
+ render(getNonOrgRoutes(),document.getElementById('app'));
+ }
+}
+const checkSlug = (nextState, replace) => {
+ orgId = Session.get('orgId');
+}
+
+/**
+There are three types of routes
+1)getOrgRoutes: all the routes that should be present for a registered org
+2)getInvalidOrgRoute: all the routes where someone tries to enter a subdomain which hasn't been registered yet (404 mostly :D)
+3)getNonOrgRoutes: all routes linked to normal site, ie signing up a new org. CHeking out demo and everything internal
+**/
+const getOrgRoutes = () => (
+
+
+
+
+
+
+)
+
+
+const getInvalidOrgRoute = () => (
+
+
+
+
+
+
+)
+
+const getNonOrgRoutes = () => (
+
+
+
+
+
+
+
+)
+
+
+Meteor.startup(() => {
+ detectOrg();
+});
diff --git a/imports/client/app/shelf.js b/imports/client/app/shelf.js
new file mode 100644
index 0000000..51b03cd
--- /dev/null
+++ b/imports/client/app/shelf.js
@@ -0,0 +1,12 @@
+import { ReactiveVar } from 'meteor/reactive-var'
+
+
+window.Shelf = {};
+
+Shelf.layout = new ReactiveVar({});
+// {
+// bulb: new ReactiveVar(''), // Active menu tab
+// subbulb: new ReactiveVar(''), // Active submenu tab
+// };
+
+
diff --git a/imports/client/app/utils/changePassword.js b/imports/client/app/utils/changePassword.js
new file mode 100644
index 0000000..d551843
--- /dev/null
+++ b/imports/client/app/utils/changePassword.js
@@ -0,0 +1,7 @@
+import $ from 'jquery';
+import 'jquery-validation';
+import { Accounts } from 'meteor/accounts-base';
+import { Bert } from 'meteor/themeteorchef:bert';
+import { getInputValue } from './get-input-value';
+
+let component;
diff --git a/imports/client/app/utils/get-input-value.js b/imports/client/app/utils/get-input-value.js
new file mode 100644
index 0000000..31d71cc
--- /dev/null
+++ b/imports/client/app/utils/get-input-value.js
@@ -0,0 +1,5 @@
+// TODO WTF: what is this thing? -H
+
+import ReactDOM from 'react-dom';
+
+export const getInputValue = (component) => ReactDOM.findDOMNode(component).value;
diff --git a/imports/client/app/utils/login.js b/imports/client/app/utils/login.js
new file mode 100644
index 0000000..aa10ac6
--- /dev/null
+++ b/imports/client/app/utils/login.js
@@ -0,0 +1,70 @@
+import $ from 'jquery';
+import 'jquery-validation';
+import { browserHistory } from 'react-router';
+import { Meteor } from 'meteor/meteor';
+import { Bert } from 'meteor/themeteorchef:bert';
+import { getInputValue } from './get-input-value';
+
+let component;
+
+const login = () => {
+ const email = getInputValue(component.refs.emailAddress);
+ const password = getInputValue(component.refs.password);
+
+ Meteor.call('checkEmailVerification', email, ( error, data ) => {
+ if ( error ) {
+ Bert.alert( error.reason, 'danger' );
+ }
+ else {
+ if ( data == "verified" ) {
+ Meteor.loginWithPassword(email, password, (error) => {
+ if ( error ) {
+ Bert.alert(error.reason, 'warning');
+ } else {
+ Bert.alert('Logged in!', 'success');
+
+ const { location } = component.props;
+ if (location.state && location.state.nextPathname) {
+ browserHistory.push(location.state.nextPathname);
+ } else {
+ browserHistory.push('/');
+ }
+ }
+ });
+ } else if ( data == "unverified" ){
+ Bert.alert("Check your email for a verification link");
+ } else {
+ Bert.alert("Either email or password is incorrect");
+ }
+ }
+ });
+};
+
+const validate = () => {
+ $(component.refs.login).validate({
+ rules: {
+ emailAddress: {
+ required: true,
+ email: true,
+ },
+ password: {
+ required: true,
+ },
+ },
+ messages: {
+ emailAddress: {
+ required: 'Need an email address here.',
+ email: 'Is this email address legit?',
+ },
+ password: {
+ required: 'Need a password here.',
+ },
+ },
+ submitHandler() { login(); },
+ });
+};
+
+export const handleLogin = (options) => {
+ component = options.component;
+ validate();
+};
diff --git a/imports/client/app/utils/loginMethods.js b/imports/client/app/utils/loginMethods.js
new file mode 100644
index 0000000..a969d58
--- /dev/null
+++ b/imports/client/app/utils/loginMethods.js
@@ -0,0 +1,10 @@
+import { browserHistory } from 'react-router';
+
+
+export const logout = () => {
+ Meteor.logout();
+ browserHistory.push('/');
+};
+
+
+
diff --git a/imports/client/app/utils/rate-limit.js b/imports/client/app/utils/rate-limit.js
new file mode 100644
index 0000000..498d782
--- /dev/null
+++ b/imports/client/app/utils/rate-limit.js
@@ -0,0 +1,18 @@
+import { _ } from 'meteor/underscore';
+import { Meteor } from 'meteor/meteor';
+import { DDPRateLimiter } from 'meteor/ddp-rate-limiter';
+
+const fetchMethodNames = (methods) => _.pluck(methods, 'name');
+
+const assignLimits = ({ methods, limit, timeRange }) => {
+ const methodNames = fetchMethodNames(methods);
+
+ if (Meteor.isServer) {
+ DDPRateLimiter.addRule({
+ name(name) { return _.contains(methodNames, name); },
+ connectionId() { return true; },
+ }, limit, timeRange);
+ }
+};
+
+export const rateLimit = (options) => assignLimits(options);
diff --git a/imports/client/app/utils/recover-password.js b/imports/client/app/utils/recover-password.js
new file mode 100644
index 0000000..e2c846b
--- /dev/null
+++ b/imports/client/app/utils/recover-password.js
@@ -0,0 +1,42 @@
+import $ from 'jquery';
+import 'jquery-validation';
+import { Accounts } from 'meteor/accounts-base';
+import { Bert } from 'meteor/themeteorchef:bert';
+import { getInputValue } from './get-input-value';
+
+let component;
+
+const handleRecovery = () => {
+ Accounts.forgotPassword({
+ email: getInputValue(component.refs.emailAddress),
+ }, (error) => {
+ if (error) {
+ Bert.alert(error.reason, 'warning');
+ } else {
+ Bert.alert('Check your inbox for a reset link!', 'success');
+ }
+ });
+};
+
+const validate = () => {
+ $(component.refs.recoverPassword).validate({
+ rules: {
+ emailAddress: {
+ required: true,
+ email: true,
+ },
+ },
+ messages: {
+ emailAddress: {
+ required: 'Need an email address here.',
+ email: 'Is this email address legit?',
+ },
+ },
+ submitHandler() { handleRecovery(); },
+ });
+};
+
+export const handleRecoverPassword = (options) => {
+ component = options.component;
+ validate();
+};
diff --git a/imports/client/app/utils/reset-password.js b/imports/client/app/utils/reset-password.js
new file mode 100644
index 0000000..9d18e9b
--- /dev/null
+++ b/imports/client/app/utils/reset-password.js
@@ -0,0 +1,54 @@
+import $ from 'jquery';
+import 'jquery-validation';
+import { browserHistory } from 'react-router';
+import { Accounts } from 'meteor/accounts-base';
+import { Bert } from 'meteor/themeteorchef:bert';
+import { getInputValue } from './get-input-value';
+
+let component;
+let token;
+
+const handleReset = () => {
+ const password = getInputValue(component.refs.newPassword);
+ Accounts.resetPassword(token, password, (error) => {
+ if (error) {
+ Bert.alert(error.reason, 'danger');
+ } else {
+ browserHistory.push('/');
+ Bert.alert('Password reset!', 'success');
+ }
+ });
+};
+
+const validate = () => {
+ $(component.refs.resetPassword).validate({
+ rules: {
+ newPassword: {
+ required: true,
+ minlength: 6,
+ },
+ repeatNewPassword: {
+ required: true,
+ minlength: 6,
+ equalTo: '[name="newPassword"]',
+ },
+ },
+ messages: {
+ newPassword: {
+ required: 'Enter a new password, please.',
+ minlength: 'Use at least six characters, please.',
+ },
+ repeatNewPassword: {
+ required: 'Repeat your new password, please.',
+ equalTo: 'Hmm, your passwords don\'t match. Try again?',
+ },
+ },
+ submitHandler() { handleReset(); },
+ });
+};
+
+export const handleResetPassword = (options) => {
+ component = options.component;
+ token = options.token;
+ validate();
+};
diff --git a/imports/client/app/utils/setQueryParam.js b/imports/client/app/utils/setQueryParam.js
new file mode 100644
index 0000000..eddb1a2
--- /dev/null
+++ b/imports/client/app/utils/setQueryParam.js
@@ -0,0 +1,9 @@
+import _ from 'lodash';
+
+export const setQueryParam = (location, query) => ({
+ pathname: location.pathname,
+ hash: location.hash,
+ query: _.assign({}, location.query, query),
+});
+
+
diff --git a/imports/client/app/utils/signup.js b/imports/client/app/utils/signup.js
new file mode 100644
index 0000000..39b07c9
--- /dev/null
+++ b/imports/client/app/utils/signup.js
@@ -0,0 +1,76 @@
+import $ from 'jquery';
+import 'jquery-validation';
+import { browserHistory } from 'react-router';
+import { Accounts } from 'meteor/accounts-base';
+import { Bert } from 'meteor/themeteorchef:bert';
+import { getInputValue } from './get-input-value';
+
+let component;
+
+const getUserData = () => ({
+ email: getInputValue(component.refs.emailAddress),
+ password: getInputValue(component.refs.password),
+ profile: {
+ name: {
+ first: getInputValue(component.refs.firstName),
+ last: getInputValue(component.refs.lastName),
+ },
+ },
+});
+
+const signUp = () => {
+ const user = getUserData();
+
+ Accounts.createUser(user, (error) => {
+ if (error) {
+ Bert.alert(error.reason, 'danger');
+ } else {
+ Bert.alert( 'Welcome!', 'success' );
+ Session.set('signedEmail', user.email);
+ browserHistory.push('/users/verify');
+ }
+ });
+};
+
+const validate = () => {
+ $(component.refs.signup).validate({
+ rules: {
+ firstName: {
+ required: true,
+ },
+ lastName: {
+ required: true,
+ },
+ emailAddress: {
+ required: true,
+ email: true,
+ },
+ password: {
+ required: true,
+ minlength: 6,
+ },
+ },
+ messages: {
+ firstName: {
+ required: 'First name?',
+ },
+ lastName: {
+ required: 'Last name?',
+ },
+ emailAddress: {
+ required: 'Need an email address here.',
+ email: 'Is this email address legit?',
+ },
+ password: {
+ required: 'Need a password here.',
+ minlength: 'Use at least six characters, please.',
+ },
+ },
+ submitHandler() { signUp(); },
+ });
+};
+
+export const handleSignup = (options) => {
+ component = options.component;
+ validate();
+};
diff --git a/imports/client/assets/css/icons/icomoon/styles.css b/imports/client/assets/css/icons/icomoon/styles.css
index beca53d..65eccd5 100644
--- a/imports/client/assets/css/icons/icomoon/styles.css
+++ b/imports/client/assets/css/icons/icomoon/styles.css
@@ -2,7 +2,7 @@
font-family: 'icomoon';
src:url('fonts/icomoon.eot?3p0rtw');
src:url('fonts/icomoon.eot?#iefix3p0rtw') format('embedded-opentype'),
- url('fonts/icomoon.woff?3p0rtw') format('woff'),
+ url('fonts/icomoon.woff?3p0rtw') format('font-woff'),
url('fonts/icomoon.ttf?3p0rtw') format('truetype'),
url('fonts/icomoon.svg?3p0rtw#icomoon') format('svg');
font-weight: normal;
diff --git a/imports/client/layouts/OrgApp.js b/imports/client/layouts/OrgApp.js
index 2974b4d..687b44a 100644
--- a/imports/client/layouts/OrgApp.js
+++ b/imports/client/layouts/OrgApp.js
@@ -1,18 +1,24 @@
-import React from 'react';
-import { Grid } from 'react-bootstrap';
-import AppNavigation from '/imports/client/views/org/app/module/navigation/AppNavigation';
+import React, { Component } from 'react';
+import { Grid } from 'react-bootstrap';
+import {AppNavigationController} from '/imports/client/views/org/app/module/navigation/index';
+/**
+ * user based redirection will take place here
+ */
+ export class App extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
-const App = ({ children }) => (
-
-);
-
-App.propTypes = {
- children: React.PropTypes.node,
-};
-
-export default App;
+ };
+ };
+ render(){
+ return (
+
+
+
+ { this.props.children }
+
+
+ )
+ }
+ }
diff --git a/imports/client/views/etc/index.js b/imports/client/views/etc/index.js
index 9098c73..6579f02 100644
--- a/imports/client/views/etc/index.js
+++ b/imports/client/views/etc/index.js
@@ -5,22 +5,22 @@ import {
compose,
composeAll
} from 'react-komposer';
-import { InviteSignupView } from './InviteSignupView';
import { Loading } from '/imports/client/components/Loading';
-import { Invitations } from '/imports/collections/invitations/index';
import { Orgs } from '/imports/collections/orgs/index';
+import { Users } from '/imports/collections/users/index';
const meteorTick = (props, onData) => {
const handles = [
- Meteor.subscribe('invitations.withToken')
+ Meteor.subscribe('users.current')
];
if(_.every(handles, (handle) => (handle.ready()) )) {
- const invitation = Invitations.findOne({});
+ const user = Users.current();
onData(null, {
data: {
+ user: user,
},
});
}
diff --git a/imports/client/views/org/app/module/AppLayout.js b/imports/client/views/org/app/module/AppLayout.js
index fcaa68d..3458058 100644
--- a/imports/client/views/org/app/module/AppLayout.js
+++ b/imports/client/views/org/app/module/AppLayout.js
@@ -5,21 +5,22 @@ import { Link } from 'react-router';
import { Avatar } from '/imports/client/components/Avatar';
import { Icon } from '/imports/client/components/Icon';
import classNames from 'classnames';
+import { EnterModule } from '/imports/client/views/org/enter/module/index';
+// import { VerifyModule } from '/imports/client/views/verify/module/index';
export class AppLayout extends Component {
-
-
-
-
-
render() {
+ console.log(this.props);
const {user} = this.props.data;
if(!user) {
return (
-
+
);
}
return (
diff --git a/imports/client/views/org/app/module/navigation/AppNavigation.js b/imports/client/views/org/app/module/navigation/AppNavigation.js
index ff33f9a..c280710 100644
--- a/imports/client/views/org/app/module/navigation/AppNavigation.js
+++ b/imports/client/views/org/app/module/navigation/AppNavigation.js
@@ -1,30 +1,54 @@
-import React from 'react';
+import React, { Component } from 'react';
import { Navbar } from 'react-bootstrap';
import { Link } from 'react-router';
-import PublicNavigation from './PublicNavigation.js';
-import AuthenticatedNavigation from './AuthenticatedNavigation.js';
+import {PublicNavigation} from './PublicNavigation.js';
+import {AuthenticatedNavigation} from './AuthenticatedNavigation.js';
import '/imports/client/assets/css/icons/icomoon/styles.css';
import '/imports/client/assets/css/bootstrap.css';
import '/imports/client/assets/css/core.css';
import '/imports/client/assets/css/components.css';
import '/imports/client/assets/css/colors.css';
-const renderNavigation = hasUser => (hasUser ? : );
-const AppNavigation = ({ hasUser }) => (
-
-
-
- Home
-
-
-
-
- { renderNavigation(hasUser) }
-
-
-);
+import '/imports/client/assets/css/colors.css';
+export class AppNavigation extends Component {
-AppNavigation.propTypes = {
- hasUser: React.PropTypes.object,
-};
+ constructor(props) {
+ super(props);
+ this.state = {
+
+ };
+ };
+
+ onUpdate(key, value) {
+ this.setState({[key]: value});
+ };
+ render() {
+ const {user} = this.props.data;
+ if(user){
+ return(
+
+ )
+ }else{
+ return(
+
+
+
+ Application Name
+
+
+
+
+
+
+
-export default AppNavigation;
+ )
+ }
+
+ return (
+
+ );
+ };
+
+};
diff --git a/imports/client/views/org/app/module/navigation/AuthenticatedNavigation.js b/imports/client/views/org/app/module/navigation/AuthenticatedNavigation.js
index 87a0c38..5f1c2f1 100644
--- a/imports/client/views/org/app/module/navigation/AuthenticatedNavigation.js
+++ b/imports/client/views/org/app/module/navigation/AuthenticatedNavigation.js
@@ -1,30 +1,303 @@
-import React from 'react';
-import { browserHistory } from 'react-router';
-import { LinkContainer } from 'react-router-bootstrap';
-import { Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap';
-import { Meteor } from 'meteor/meteor';
+import React, { Component } from 'react';
+import { browserHistory } from 'react-router';
+import { LinkContainer } from 'react-router-bootstrap';
+import { Nav, NavItem,
+ NavDropdown, MenuItem } from 'react-bootstrap';
+import { Meteor } from 'meteor/meteor';
const handleLogout = () => Meteor.logout(() => browserHistory.push('/login'));
-const userName = () => {
- const user = Meteor.user();
- const name = user && user.profile ? user.profile.name : '';
- return user ? `${name.first} ${name.last}` : '';
-};
+export class AuthenticatedNavigation extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
-const AuthenticatedNavigation = () => (
+ };
+ };
+render(){
+ const {user} = this.props.data;
+ return(
-
-
+
+
+
+
+
+
+
+ -
+
+
+ Git updates
+
+
+
+
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+ Add full font overrides for popovers and tooltips
+
36 minutes ago
+
+
+
+ -
+
+
+
+
Chris Arney created a new
Design branch
+
2 hours ago
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+ Have Carousel ignore keyboard events
+
Dec 12, 05:46
+
+
+
+
+
+
+
+
+
+
+
Hello {`${user.firstName} ${user.lastName}`}!
+
Online
+
+
+ -
+
+
+ Activity
+
+
+
+
+
+
+
+ -
+
+
+
+
Taylor Swift mentioned you in a post "Angular JS. Tips and tricks"
+
4 minutes ago
+
+
+
+ -
+
+
+
+ Special offers have been sent to subscribed users by
Donna Gordon
+
36 minutes ago
+
+
+
+ -
+
+
+
+
Chris Arney created a new
Design branch in
Limitless repository
+
2 hours ago
+
+
+
+ -
+
+
+
+ Shipping cost to the Netherlands has been reduced, database updated
+
Feb 8, 11:30
+
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
January, 2016 - 1320 new users, 3284 orders, $49,390 revenue
+
Feb 1, 05:46
+
+
+
+
+
+
+ -
+
+
+ Messages
+
+
+
+
+
+
+
+ -
+
+

+
5
+
+
+
+
+
+ -
+
+

+
4
+
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
+
);
-
-export default AuthenticatedNavigation;
+}
+}
diff --git a/imports/client/views/org/app/module/navigation/PublicNavigation.js b/imports/client/views/org/app/module/navigation/PublicNavigation.js
index d04fc80..82cf700 100644
--- a/imports/client/views/org/app/module/navigation/PublicNavigation.js
+++ b/imports/client/views/org/app/module/navigation/PublicNavigation.js
@@ -1,16 +1,27 @@
-import React from 'react';
-import { LinkContainer } from 'react-router-bootstrap';
-import { Nav, NavItem } from 'react-bootstrap';
+import React, { Component } from 'react';
+import { LinkContainer } from 'react-router-bootstrap';
+import { setQueryParam } from '/imports/client/app/utils/setQueryParam';
+import { browserHistory } from 'react-router';
+import { Nav, NavItem } from 'react-bootstrap';
-const PublicNavigation = () => (
-
-);
-export default PublicNavigation;
+export class PublicNavigation extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+
+ };
+ };
+render(){
+ console.log(this.props);
+ var mainSite = document.location.hostname.split( "." )[1];
+ var signup = `http://${mainSite}/signup`;
+ return(
+
+ )
+}
+}
diff --git a/imports/client/views/org/app/module/navigation/index.js b/imports/client/views/org/app/module/navigation/index.js
index 65f743d..0965b10 100644
--- a/imports/client/views/org/app/module/navigation/index.js
+++ b/imports/client/views/org/app/module/navigation/index.js
@@ -1,7 +1,46 @@
-import { composeWithTracker } from 'react-komposer';
-import { Meteor } from 'meteor/meteor';
-import AppNavigation from '../components/AppNavigation.js';
+// import { InviteSignupController } from '/imports/client/views/invite/signup/index'
+import _ from 'lodash';
+import {
+ composeWithTracker,
+ compose,
+ composeAll
+ } from 'react-komposer';
+import { Loading } from '/imports/client/components/Loading';
-const composer = (props, onData) => onData(null, { hasUser: Meteor.user() });
+import { Orgs } from '/imports/collections/orgs/index';
+import { Users } from '/imports/collections/users/index';
-export default composeWithTracker(composer, {}, {}, { pure: false })(AppNavigation);
+import { AppNavigation } from './AppNavigation';
+
+const meteorTick = (props, onData) => {
+
+ const handles = [
+ Meteor.subscribe('users.current')
+ ];
+
+ if(_.every(handles, (handle) => (handle.ready()) )) {
+ const user = Users.current();
+ onData(null, {
+ data: {
+ user: user,
+ },
+ });
+ }
+
+ return () => {
+ _.each(handles, (handle) => handle.stop() );
+ };
+};
+
+
+const reduxTick = (props, onData) => {
+ onData(null, {
+ data: {}
+ });
+};
+
+
+export const AppNavigationController = composeAll(
+ composeWithTracker(meteorTick, Loading),
+ compose(reduxTick, Loading),
+)(AppNavigation);
diff --git a/imports/client/views/org/enter/ForgotPane.js b/imports/client/views/org/enter/ForgotPane.js
new file mode 100644
index 0000000..47292ac
--- /dev/null
+++ b/imports/client/views/org/enter/ForgotPane.js
@@ -0,0 +1,69 @@
+import React from 'react';
+import { Link } from 'react-router';
+import { ActionButton } from '/imports/client/components/ActionButton';
+import { setQueryParam } from '/imports/client/app/utils/setQueryParam';
+import { Button, Form, FormGroup, Label, Input, FormText, Col } from 'reactstrap';
+import { Alert } from 'reactstrap';
+import 'velocity-animate';
+import 'velocity-animate/velocity.ui';
+import { VelocityComponent, VelocityTransitionGroup, velocityHelpers } from 'velocity-react';
+import ReactSVG from 'react-svg'
+
+export class ForgotPane extends React.Component {
+
+ render() {
+ return (
+
+
+
+
+
+
+
+
+ Reset your password
+
+
+ { this.props.data.error }
+
+
+ { this.props.data.message }
+
+
+
+
+
+
+ );
+ }
+}
diff --git a/imports/client/views/org/enter/LoginPane.js b/imports/client/views/org/enter/LoginPane.js
new file mode 100644
index 0000000..729f8d0
--- /dev/null
+++ b/imports/client/views/org/enter/LoginPane.js
@@ -0,0 +1,78 @@
+import React from 'react';
+import { Link } from 'react-router';
+import { ActionButton } from '/imports/client/components/ActionButton';
+import { setQueryParam } from '/imports/client/app/utils/setQueryParam';
+import { Button, Form, FormGroup, Label, Input, FormText, Col } from 'reactstrap';
+import { Alert } from 'reactstrap';
+import 'velocity-animate';
+import 'velocity-animate/velocity.ui';
+import { VelocityComponent, VelocityTransitionGroup, velocityHelpers } from 'velocity-react';
+import ReactSVG from 'react-svg'
+
+
+export class LoginPane extends React.Component {
+
+ render() {
+ return (
+
+
+
+
+
+
+
+
+ Login
+
+
+ { this.props.data.error }
+
+
+ { this.props.data.message }
+
+
+
+
+
+
+ );
+ }
+}
diff --git a/imports/client/views/org/enter/RecoverPassword.js b/imports/client/views/org/enter/RecoverPassword.js
deleted file mode 100644
index ba4adc5..0000000
--- a/imports/client/views/org/enter/RecoverPassword.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import React from 'react';
-import { Row, Col, Alert, FormGroup, FormControl, Button } from 'react-bootstrap';
-import handleRecoverPassword from './module/recover-password';
-
-export default class RecoverPassword extends React.Component {
- componentDidMount() {
- handleRecoverPassword({ component: this });
- }
-
- handleSubmit(event) {
- event.preventDefault();
- }
-
- render() {
- return (
-
-
-
- Recover Password
-
- Enter your email address below to receive a link to reset your password.
-
-
-
-
-
- );
- }
-}
diff --git a/imports/client/views/org/enter/ResetPane.js b/imports/client/views/org/enter/ResetPane.js
new file mode 100644
index 0000000..bd2a9b4
--- /dev/null
+++ b/imports/client/views/org/enter/ResetPane.js
@@ -0,0 +1,63 @@
+import React from 'react';
+import { Link } from 'react-router';
+import { ActionButton } from '/imports/client/components/ActionButton';
+import { setQueryParam } from '/imports/client/app/utils/setQueryParam';
+import { Button, Form, FormGroup, Label, Input, FormText, Col } from 'reactstrap';
+import { Alert } from 'reactstrap';
+import 'velocity-animate';
+import 'velocity-animate/velocity.ui';
+import { VelocityComponent, VelocityTransitionGroup, velocityHelpers } from 'velocity-react';
+import ReactSVG from 'react-svg'
+
+
+export class ResetPane extends React.Component {
+
+ render() {
+ return (
+
+
+
+
+
+
+
+
+ Set new password
+
+
+ { this.props.data.error }
+
+
+ { this.props.data.message }
+
+
+
+
+
+
+ );
+ }
+}
diff --git a/imports/client/views/org/enter/ResetPassword.js b/imports/client/views/org/enter/ResetPassword.js
deleted file mode 100644
index c4893aa..0000000
--- a/imports/client/views/org/enter/ResetPassword.js
+++ /dev/null
@@ -1,58 +0,0 @@
-import React from 'react';
-import { Row, Col, Alert, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap';
-import handleResetPassword from './module/reset-password';
-
-export default class ResetPassword extends React.Component {
- componentDidMount() {
- handleResetPassword({ component: this, token: this.props.params.token });
- }
-
- handleSubmit(event) {
- event.preventDefault();
- }
-
- render() {
- return (
-
-
-
- Reset Password
-
- To reset your password, enter a new one below. You will be logged in
- with your new password.
-
-
-
-
-
- );
- }
-}
-
-ResetPassword.propTypes = {
- params: React.PropTypes.object,
-};
diff --git a/imports/client/views/org/enter/SignupPane.js b/imports/client/views/org/enter/SignupPane.js
new file mode 100644
index 0000000..df7056a
--- /dev/null
+++ b/imports/client/views/org/enter/SignupPane.js
@@ -0,0 +1,91 @@
+import React from 'react';
+import { Link } from 'react-router';
+import { ActionButton } from '/imports/client/components/ActionButton';
+import { setQueryParam } from '/imports/client/app/utils/setQueryParam';
+import { Button, Form, FormGroup, Label, Input, FormText, Col } from 'reactstrap';
+import 'velocity-animate';
+import 'velocity-animate/velocity.ui';
+import { VelocityComponent, VelocityTransitionGroup, velocityHelpers } from 'velocity-react';
+import ReactSVG from 'react-svg'
+
+
+export class SignupPane extends React.Component {
+
+ render() {
+ return (
+
+
+
+
+
+
+
+
+ Start a free 30-day trial
+
+
+
+
+
+ Already have an account? Log in.
+
+
+
+
+
+ );
+ }
+}
diff --git a/imports/client/views/org/enter/_old/check-email.js b/imports/client/views/org/enter/_old/check-email.js
new file mode 100644
index 0000000..c1b5b2c
--- /dev/null
+++ b/imports/client/views/org/enter/_old/check-email.js
@@ -0,0 +1,24 @@
+import React from 'react';
+import { Link } from 'react-router';
+import { Row, Col } from 'react-bootstrap';
+
+export class CheckEmail extends React.Component {
+ handleSubmit(event) {
+ event.preventDefault();
+ }
+
+ render() {
+ const signedEmail = Session.get('signedEmail', '');
+
+ return
+
+
+

+
Verify Your Email
+
We sent a verification email to {signedEmail}. Click the link in the email to get started!
+
Email did not arrive or want to use a different email?
+
+
+
;
+ }
+}
diff --git a/imports/client/views/org/enter/_old/recover-password.js b/imports/client/views/org/enter/_old/recover-password.js
new file mode 100644
index 0000000..10017ce
--- /dev/null
+++ b/imports/client/views/org/enter/_old/recover-password.js
@@ -0,0 +1,35 @@
+import React from 'react';
+import { Row, Col, Alert, FormGroup, FormControl, Button } from 'react-bootstrap';
+import { handleRecoverPassword } from '../../modules/recover-password';
+
+export class RecoverPassword extends React.Component {
+ componentDidMount() {
+ handleRecoverPassword({ component: this });
+ }
+
+ handleSubmit(event) {
+ event.preventDefault();
+ }
+
+ render() {
+ return
+
+ Recover Password
+
+ Enter your email address below to receive a link to reset your password.
+
+
+
+
;
+ }
+}
diff --git a/imports/client/views/org/enter/_old/reset-password.js b/imports/client/views/org/enter/_old/reset-password.js
new file mode 100644
index 0000000..ca52b17
--- /dev/null
+++ b/imports/client/views/org/enter/_old/reset-password.js
@@ -0,0 +1,53 @@
+import React from 'react';
+import { Row, Col, Alert, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap';
+import { handleResetPassword } from '../../modules/reset-password';
+
+export class ResetPassword extends React.Component {
+ componentDidMount() {
+ handleResetPassword({
+ component: this,
+ token: this.props.params.token,
+ });
+ }
+
+ handleSubmit(event) {
+ event.preventDefault();
+ }
+
+ render() {
+ return
+
+ Reset Password
+
+ To reset your password, enter a new one below. You will be logged in
+with your new password.
+
+
+
+
;
+ }
+}
+
+ResetPassword.propTypes = {
+ params: React.PropTypes.object,
+};
diff --git a/imports/client/views/org/enter/_old/signup.js b/imports/client/views/org/enter/_old/signup.js
new file mode 100644
index 0000000..16acb67
--- /dev/null
+++ b/imports/client/views/org/enter/_old/signup.js
@@ -0,0 +1,68 @@
+import React from 'react';
+import { Link } from 'react-router';
+import { Row, Col, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap';
+import { handleSignup } from '../../modules/signup';
+
+export class Signup extends React.Component {
+ componentDidMount() {
+ handleSignup({ component: this });
+ }
+
+ handleSubmit(event) {
+ event.preventDefault();
+ }
+
+ render() {
+ return
+
+ Sign Up
+
+ Already have an account? Log In.
+
+
;
+ }
+}
diff --git a/imports/client/views/org/enter/login/LoginView.js b/imports/client/views/org/enter/login/LoginView.js
deleted file mode 100644
index 31f67bf..0000000
--- a/imports/client/views/org/enter/login/LoginView.js
+++ /dev/null
@@ -1,56 +0,0 @@
-import React,{ Component } from 'react';
-import { Link } from 'react-router';
-import { Row, Col, FormGroup,
- ControlLabel, FormControl,
- Button } from 'react-bootstrap';
-import handleLogin from './login';
-
-export class LoginView extends React.Component {
- componentDidMount() {
- handleLogin({ component: this });
- }
-
- handleSubmit(event) {
- event.preventDefault();
- }
-
- render() {
- return (
-
-
-
- Login
-
-
-
-
- );
- }
-}
diff --git a/imports/client/views/org/enter/login/index.js b/imports/client/views/org/enter/login/index.js
deleted file mode 100644
index 4959901..0000000
--- a/imports/client/views/org/enter/login/index.js
+++ /dev/null
@@ -1,40 +0,0 @@
-// import { InviteSignupController } from '/imports/client/views/invite/signup/index'
-import _ from 'lodash';
-import {
- composeWithTracker,
- compose,
- composeAll
- } from 'react-komposer';
-import { Loading } from '/imports/client/components/Loading';
-import { Orgs } from '/imports/collections/orgs/index';
-import { LoginView } from './LoginView'
-
-const meteorTick = (props, onData) => {
-
- const handles = [
- ];
-
- if(_.every(handles, (handle) => (handle.ready()) )) {
- onData(null, {
- data: {
- },
- });
- }
-
- return () => {
- _.each(handles, (handle) => handle.stop() );
- };
-};
-
-
-const reduxTick = (props, onData) => {
- onData(null, {
- data: {}
- });
-};
-
-
-export const orgLoginController = composeAll(
- composeWithTracker(meteorTick, Loading),
- compose(reduxTick, Loading),
-)(LoginView);
diff --git a/imports/client/views/org/enter/login/login.js b/imports/client/views/org/enter/login/login.js
deleted file mode 100644
index a83a0d3..0000000
--- a/imports/client/views/org/enter/login/login.js
+++ /dev/null
@@ -1,57 +0,0 @@
-/* eslint-disable no-undef */
-
-import { browserHistory } from 'react-router';
-import { Meteor } from 'meteor/meteor';
-import { Bert } from 'meteor/themeteorchef:bert';
-import '/imports/client/components/validation';
-
-let component;
-
-const login = () => {
- const email = document.querySelector('[name="emailAddress"]').value;
- const password = document.querySelector('[name="password"]').value;
-
- Meteor.loginWithPassword(email, password, (error) => {
- if (error) {
- Bert.alert(error.reason, 'warning');
- } else {
- Bert.alert('Logged in!', 'success');
-
- const { location } = component.props;
- if (location.state && location.state.nextPathname) {
- browserHistory.push(location.state.nextPathname);
- } else {
- browserHistory.push('/');
- }
- }
- });
-};
-
-const validate = () => {
- $(component.loginForm).validate({
- rules: {
- emailAddress: {
- required: true,
- email: true,
- },
- password: {
- required: true,
- },
- },
- messages: {
- emailAddress: {
- required: 'Need an email address here.',
- email: 'Is this email address legit?',
- },
- password: {
- required: 'Need a password here.',
- },
- },
- submitHandler() { login(); },
- });
-};
-
-export default function handleLogin(options) {
- component = options.component;
- validate();
-}
diff --git a/imports/client/views/org/enter/module/EnterLayout.js b/imports/client/views/org/enter/module/EnterLayout.js
new file mode 100644
index 0000000..7a5a45b
--- /dev/null
+++ b/imports/client/views/org/enter/module/EnterLayout.js
@@ -0,0 +1,166 @@
+import _ from 'lodash';
+import { Meteor } from 'meteor/meteor';
+import { SimpleSchema } from 'meteor/aldeed:simple-schema';
+import { Bert } from 'meteor/themeteorchef:bert';
+
+import React from 'react';
+import { Container, Row, Col } from 'reactstrap';
+import { Link } from 'react-router';
+import { If, Case } from '/imports/client/components/Logic';
+
+import { LoginPane } from '/imports/client/views/org/enter/LoginPane';
+import { ForgotPane } from '/imports/client/views/org/enter/ForgotPane';
+import { ResetPane } from '/imports/client/views/org/enter/ResetPane';
+import Validation from '/imports/validation/validationMethods';
+
+// const signupSchemaValidator = new SimpleSchema({
+// email: { type: String, regEx: SimpleSchema.RegEx.Email},
+// firstName: { type: String, },
+// lastName: { type: String, },
+// password: { type: String, min: 6},
+// }).validator();
+
+let validation = new Validation();
+
+export class EnterLayout extends React.Component {
+
+
+ constructor(props) {
+ super(props);
+ this.state = {
+ email: '',
+ password: '',
+ firstName: '',
+ lastName: '',
+ orgName: '',
+ loading: false,
+ error: '',
+ message: '',
+ };
+ };
+
+ componentWillReceiveProps(nextProps) {
+ console.log(this.props.pane);
+ console.log("this.props.pane");
+ if(this.props.pane !== nextProps.pane) {
+ this.onClearState();
+ }
+ };
+
+
+ onClearState(loading) {
+ this.setState({
+ loading: loading || false,
+ error: '',
+ message: '',
+ });
+ };
+
+ onUpdate(key, value) {
+ this.setState({[key]: value});
+ };
+
+ onForgot(e) {
+ e.preventDefault();
+ this.onClearState(true);
+
+ Accounts.forgotPassword({email: this.state.email || '...'}, (error) => {
+ this.onClearState();
+ if(error) {
+ this.setState({error: 'An error occured.'});
+ } else {
+ this.setState({message: 'Reset email has been sent. Check your inbox.'});
+ }
+ });
+ };
+
+ onReset(e) {
+ e.preventDefault();
+ this.onClearState(true);
+ if(!validation.passwordValidation(this.state.password)){
+ Bert.alert('Password must be a minimum of 6 characters in length.', 'danger');
+ this.onClearState();
+ return false;
+ }else if(!validation.noQwertysAllowed(this.state.password)){
+ Bert.alert('No qwertys allowed!', 'danger');
+ this.onClearState();
+ return false;
+ } else{
+ Accounts.resetPassword(
+ this.props.location.query.token,
+ this.state.password,
+ (error) => {
+ this.onClearState();
+ if(error) {
+ this.setState({error: 'An error occured.'});
+ }
+ }
+ );
+ }
+ };
+
+ onLogin(e) {
+ e.preventDefault();
+ this.onClearState(true);
+ if(this.state.email.trim() == '' || !validation.validateEmail(this.state.email)){
+ this.onClearState();
+ Bert.alert('Please enter a valid email address!', 'danger');
+ return false;
+ }
+ if(this.state.password.trim() == ''){
+ Bert.alert('Please enter your password!', 'danger');
+ this.onClearState();
+ return false;
+ }
+ Meteor.loginWithPassword(
+ this.state.email,
+ this.state.password,
+ (e, r) => {
+ this.onClearState();
+ if(e) {
+ this.setState({error: 'Wrong email or password.'})
+ }
+ }
+ );
+ };
+
+ render() {
+ return (
+
+
+
+ (
+ this.onUpdate(...a)}
+ onForgot = {(...a) => this.onForgot(...a)}
+ />
+ )}
+ case1 = "reset"
+ then1 = {() => (
+ this.onUpdate(...a)}
+ onReset = {(...a) => this.onReset(...a)}
+ />
+ )}
+ else = {() => (
+ this.onUpdate(...a)}
+ onLogin = {(...a) => this.onLogin(...a)}
+ />
+ )}
+ />
+
+
+
+ );
+ };
+};
diff --git a/imports/client/views/org/enter/module/index.js b/imports/client/views/org/enter/module/index.js
new file mode 100644
index 0000000..f529f43
--- /dev/null
+++ b/imports/client/views/org/enter/module/index.js
@@ -0,0 +1,46 @@
+// import { EnterModule } from '/imports/client/views/enter/module/index'
+import {
+ composeWithTracker,
+ compose,
+ composeAll
+ } from 'react-komposer';
+import { EnterLayout } from './EnterLayout';
+import { Loading } from '/imports/client/components/Loading';
+
+
+const meteorTick = (props, onData) => {
+
+ const handles = [
+ ];
+
+ if(_.every(handles, (handle) => (handle.ready()) )) {
+ onData(null, {
+ location: props.location,
+ data: {
+ },
+ });
+ }
+
+ return () => {
+ _.each(handles, (handle) => handle.stop() );
+ };
+};
+
+
+const reduxTick = (props, onData) => {
+ onData(null, {
+ data: {}
+ });
+};
+
+
+export const EnterModule = composeAll(
+ composeWithTracker(meteorTick, Loading),
+ compose(reduxTick, Loading),
+)(EnterLayout);
+
+
+
+
+
+
diff --git a/imports/client/views/org/enter/module/recover-password.js b/imports/client/views/org/enter/module/recover-password.js
deleted file mode 100644
index 60aa93a..0000000
--- a/imports/client/views/org/enter/module/recover-password.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/* eslint-disable no-undef */
-
-import { Accounts } from 'meteor/accounts-base';
-import { Bert } from 'meteor/themeteorchef:bert';
-import '/imports/client/components/validation';
-
-let component;
-
-const handleRecovery = () => {
- Accounts.forgotPassword({
- email: document.querySelector('[name="emailAddress"]').value,
- }, (error) => {
- if (error) {
- Bert.alert(error.reason, 'warning');
- } else {
- Bert.alert('Check your inbox for a reset link!', 'success');
- }
- });
-};
-
-const validate = () => {
- $(component.recoverPasswordForm).validate({
- rules: {
- emailAddress: {
- required: true,
- email: true,
- },
- },
- messages: {
- emailAddress: {
- required: 'Need an email address here.',
- email: 'Is this email address legit?',
- },
- },
- submitHandler() { handleRecovery(); },
- });
-};
-
-export default function handleRecoverPassword(options) {
- component = options.component;
- validate();
-}
diff --git a/imports/client/views/org/enter/module/reset-password.js b/imports/client/views/org/enter/module/reset-password.js
deleted file mode 100644
index 614a18e..0000000
--- a/imports/client/views/org/enter/module/reset-password.js
+++ /dev/null
@@ -1,54 +0,0 @@
-/* eslint-disable no-undef */
-
-import { browserHistory } from 'react-router';
-import { Accounts } from 'meteor/accounts-base';
-import { Bert } from 'meteor/themeteorchef:bert';
-import '/imports/client/components/validation';
-
-let component;
-let token;
-
-const handleReset = () => {
- const password = document.querySelector('[name="newPassword"]').value;
- Accounts.resetPassword(token, password, (error) => {
- if (error) {
- Bert.alert(error.reason, 'danger');
- } else {
- browserHistory.push('/');
- Bert.alert('Password reset!', 'success');
- }
- });
-};
-
-const validate = () => {
- $(component.resetPasswordForm).validate({
- rules: {
- newPassword: {
- required: true,
- minlength: 6,
- },
- repeatNewPassword: {
- required: true,
- minlength: 6,
- equalTo: '[name="newPassword"]',
- },
- },
- messages: {
- newPassword: {
- required: 'Enter a new password, please.',
- minlength: 'Use at least six characters, please.',
- },
- repeatNewPassword: {
- required: 'Repeat your new password, please.',
- equalTo: 'Hmm, your passwords don\'t match. Try again?',
- },
- },
- submitHandler() { handleReset(); },
- });
-};
-
-export default function handleResetPassword(options) {
- component = options.component;
- token = options.token;
- validate();
-}
diff --git a/imports/client/views/org/enter_1/RecoverPassword.js b/imports/client/views/org/enter_1/RecoverPassword.js
new file mode 100644
index 0000000..ba4adc5
--- /dev/null
+++ b/imports/client/views/org/enter_1/RecoverPassword.js
@@ -0,0 +1,43 @@
+import React from 'react';
+import { Row, Col, Alert, FormGroup, FormControl, Button } from 'react-bootstrap';
+import handleRecoverPassword from './module/recover-password';
+
+export default class RecoverPassword extends React.Component {
+ componentDidMount() {
+ handleRecoverPassword({ component: this });
+ }
+
+ handleSubmit(event) {
+ event.preventDefault();
+ }
+
+ render() {
+ return (
+
+
+
+ Recover Password
+
+ Enter your email address below to receive a link to reset your password.
+
+
+
+
+
+ );
+ }
+}
diff --git a/imports/client/views/org/enter_1/ResetPassword.js b/imports/client/views/org/enter_1/ResetPassword.js
new file mode 100644
index 0000000..c4893aa
--- /dev/null
+++ b/imports/client/views/org/enter_1/ResetPassword.js
@@ -0,0 +1,58 @@
+import React from 'react';
+import { Row, Col, Alert, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap';
+import handleResetPassword from './module/reset-password';
+
+export default class ResetPassword extends React.Component {
+ componentDidMount() {
+ handleResetPassword({ component: this, token: this.props.params.token });
+ }
+
+ handleSubmit(event) {
+ event.preventDefault();
+ }
+
+ render() {
+ return (
+
+
+
+ Reset Password
+
+ To reset your password, enter a new one below. You will be logged in
+ with your new password.
+
+
+
+
+
+ );
+ }
+}
+
+ResetPassword.propTypes = {
+ params: React.PropTypes.object,
+};
diff --git a/imports/client/views/org/enter_1/login/LoginView.js b/imports/client/views/org/enter_1/login/LoginView.js
new file mode 100644
index 0000000..31f67bf
--- /dev/null
+++ b/imports/client/views/org/enter_1/login/LoginView.js
@@ -0,0 +1,56 @@
+import React,{ Component } from 'react';
+import { Link } from 'react-router';
+import { Row, Col, FormGroup,
+ ControlLabel, FormControl,
+ Button } from 'react-bootstrap';
+import handleLogin from './login';
+
+export class LoginView extends React.Component {
+ componentDidMount() {
+ handleLogin({ component: this });
+ }
+
+ handleSubmit(event) {
+ event.preventDefault();
+ }
+
+ render() {
+ return (
+
+
+
+ Login
+
+
+
+
+ );
+ }
+}
diff --git a/imports/client/views/org/enter_1/login/index.js b/imports/client/views/org/enter_1/login/index.js
new file mode 100644
index 0000000..a196396
--- /dev/null
+++ b/imports/client/views/org/enter_1/login/index.js
@@ -0,0 +1,40 @@
+// import { orgLoginController } from '/imports/client/views/org/enter/login/index';
+import _ from 'lodash';
+import {
+ composeWithTracker,
+ compose,
+ composeAll
+ } from 'react-komposer';
+import { Loading } from '/imports/client/components/Loading';
+import { Orgs } from '/imports/collections/orgs/index';
+import { LoginView } from './LoginView'
+
+const meteorTick = (props, onData) => {
+
+ const handles = [
+ ];
+
+ if(_.every(handles, (handle) => (handle.ready()) )) {
+ onData(null, {
+ data: {
+ },
+ });
+ }
+
+ return () => {
+ _.each(handles, (handle) => handle.stop() );
+ };
+};
+
+
+const reduxTick = (props, onData) => {
+ onData(null, {
+ data: {}
+ });
+};
+
+
+export const orgLoginController = composeAll(
+ composeWithTracker(meteorTick, Loading),
+ compose(reduxTick, Loading),
+)(LoginView);
diff --git a/imports/client/views/org/enter_1/login/login.js b/imports/client/views/org/enter_1/login/login.js
new file mode 100644
index 0000000..a83a0d3
--- /dev/null
+++ b/imports/client/views/org/enter_1/login/login.js
@@ -0,0 +1,57 @@
+/* eslint-disable no-undef */
+
+import { browserHistory } from 'react-router';
+import { Meteor } from 'meteor/meteor';
+import { Bert } from 'meteor/themeteorchef:bert';
+import '/imports/client/components/validation';
+
+let component;
+
+const login = () => {
+ const email = document.querySelector('[name="emailAddress"]').value;
+ const password = document.querySelector('[name="password"]').value;
+
+ Meteor.loginWithPassword(email, password, (error) => {
+ if (error) {
+ Bert.alert(error.reason, 'warning');
+ } else {
+ Bert.alert('Logged in!', 'success');
+
+ const { location } = component.props;
+ if (location.state && location.state.nextPathname) {
+ browserHistory.push(location.state.nextPathname);
+ } else {
+ browserHistory.push('/');
+ }
+ }
+ });
+};
+
+const validate = () => {
+ $(component.loginForm).validate({
+ rules: {
+ emailAddress: {
+ required: true,
+ email: true,
+ },
+ password: {
+ required: true,
+ },
+ },
+ messages: {
+ emailAddress: {
+ required: 'Need an email address here.',
+ email: 'Is this email address legit?',
+ },
+ password: {
+ required: 'Need a password here.',
+ },
+ },
+ submitHandler() { login(); },
+ });
+};
+
+export default function handleLogin(options) {
+ component = options.component;
+ validate();
+}
diff --git a/imports/client/views/org/enter_1/module/recover-password.js b/imports/client/views/org/enter_1/module/recover-password.js
new file mode 100644
index 0000000..60aa93a
--- /dev/null
+++ b/imports/client/views/org/enter_1/module/recover-password.js
@@ -0,0 +1,42 @@
+/* eslint-disable no-undef */
+
+import { Accounts } from 'meteor/accounts-base';
+import { Bert } from 'meteor/themeteorchef:bert';
+import '/imports/client/components/validation';
+
+let component;
+
+const handleRecovery = () => {
+ Accounts.forgotPassword({
+ email: document.querySelector('[name="emailAddress"]').value,
+ }, (error) => {
+ if (error) {
+ Bert.alert(error.reason, 'warning');
+ } else {
+ Bert.alert('Check your inbox for a reset link!', 'success');
+ }
+ });
+};
+
+const validate = () => {
+ $(component.recoverPasswordForm).validate({
+ rules: {
+ emailAddress: {
+ required: true,
+ email: true,
+ },
+ },
+ messages: {
+ emailAddress: {
+ required: 'Need an email address here.',
+ email: 'Is this email address legit?',
+ },
+ },
+ submitHandler() { handleRecovery(); },
+ });
+};
+
+export default function handleRecoverPassword(options) {
+ component = options.component;
+ validate();
+}
diff --git a/imports/client/views/org/enter_1/module/reset-password.js b/imports/client/views/org/enter_1/module/reset-password.js
new file mode 100644
index 0000000..614a18e
--- /dev/null
+++ b/imports/client/views/org/enter_1/module/reset-password.js
@@ -0,0 +1,54 @@
+/* eslint-disable no-undef */
+
+import { browserHistory } from 'react-router';
+import { Accounts } from 'meteor/accounts-base';
+import { Bert } from 'meteor/themeteorchef:bert';
+import '/imports/client/components/validation';
+
+let component;
+let token;
+
+const handleReset = () => {
+ const password = document.querySelector('[name="newPassword"]').value;
+ Accounts.resetPassword(token, password, (error) => {
+ if (error) {
+ Bert.alert(error.reason, 'danger');
+ } else {
+ browserHistory.push('/');
+ Bert.alert('Password reset!', 'success');
+ }
+ });
+};
+
+const validate = () => {
+ $(component.resetPasswordForm).validate({
+ rules: {
+ newPassword: {
+ required: true,
+ minlength: 6,
+ },
+ repeatNewPassword: {
+ required: true,
+ minlength: 6,
+ equalTo: '[name="newPassword"]',
+ },
+ },
+ messages: {
+ newPassword: {
+ required: 'Enter a new password, please.',
+ minlength: 'Use at least six characters, please.',
+ },
+ repeatNewPassword: {
+ required: 'Repeat your new password, please.',
+ equalTo: 'Hmm, your passwords don\'t match. Try again?',
+ },
+ },
+ submitHandler() { handleReset(); },
+ });
+};
+
+export default function handleResetPassword(options) {
+ component = options.component;
+ token = options.token;
+ validate();
+}
diff --git a/imports/startup/client/index.js b/imports/startup/client/index.js
deleted file mode 100644
index dde0719..0000000
--- a/imports/startup/client/index.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import { Bert } from 'meteor/themeteorchef:bert';
-import 'bootstrap/dist/css/bootstrap.min.css';
-import './routes.js';
-
-Bert.defaults.style = 'growl-top-right';
diff --git a/imports/startup/client/routes.js b/imports/startup/client/routes.js
deleted file mode 100644
index 1dfcb3e..0000000
--- a/imports/startup/client/routes.js
+++ /dev/null
@@ -1,109 +0,0 @@
-/* eslint-disable max-len */
-
-import React from 'react';
-import { render } from 'react-dom';
-import { Router, Route,
- IndexRoute, browserHistory } from 'react-router';
-import { Meteor } from 'meteor/meteor';
-
-/**
- * General Components
- */
-import Index from '/imports/client/views/app/module/Index';
-
-/**
- * Org Components
- */
-
-import App from '/imports/client/layouts/OrgApp';
-import { AppModule } from '/imports/client/views/org/app/module/Index';
-import { orgLoginController } from '/imports/client/views/org/enter/login/index';
-import RecoverPassword from '/imports/client/views/org/enter/RecoverPassword';
-import ResetPassword from '/imports/client/views/org/enter/ResetPassword';
-import { Orgs } from '/imports/collections/orgs/index';
-import NotFound from '/imports/client/views/org/NotFound';
-
-/**
- * NonOrg Components
- */
-import Signup from '/imports/client/views/nonOrg/enter/SignupView';
-
-/**
- * Invalid Org Components
- */
-
-const authenticate = (nextState, replace) => {
- if (!Meteor.loggingIn() && !Meteor.userId()) {
- replace({
- pathname: '/login',
- state: { nextPathname: nextState.location.pathname },
- });
- }
-};
-
-
-const detectOrg = () => {
- orgSlug = "";
- var hostnameArray = document.location.hostname.split( "." );
- if(hostnameArray[1]=='localhost'){
- orgSlug = hostnameArray[0];
- }
- if(orgSlug!=""){
- Meteor.call('checkExistingOrg', {slug:orgSlug}, function(err, res) {
- if(res){
- Session.set('orgId', res._id._str);
- render(getOrgRoutes(),document.getElementById('app'));
- }else{
- render(getInvalidOrgRoute(),document.getElementById('app'));
- }
- });
- }else{
- render(getNonOrgRoutes(),document.getElementById('app'));
- }
-}
-const checkSlug = (nextState, replace) => {
- orgId = Session.get('orgId');
-}
-
-/**
-There are three types of routes
-1)getOrgRoutes: all the routes that should be present for a registered org
-2)getInvalidOrgRoute: all the routes where someone tries to enter a subdomain which hasn't been registered yet (404 mostly :D)
-3)getNonOrgRoutes: all routes linked to normal site, ie signing up a new org. CHeking out demo and everything internal
-**/
-const getOrgRoutes = () => (
-
-
-
-
-
-
-
-
-
-)
-
-
-const getInvalidOrgRoute = () => (
-
-
-
-
-
-
-)
-
-const getNonOrgRoutes = () => (
-
-
-
-
-
-
-
-)
-
-
-Meteor.startup(() => {
- detectOrg();
-});
diff --git a/imports/validation/validationMethods.js b/imports/validation/validationMethods.js
new file mode 100644
index 0000000..d5b0ba5
--- /dev/null
+++ b/imports/validation/validationMethods.js
@@ -0,0 +1,101 @@
+export default class Validation{
+
+ validateEmail (value) {
+ // regex from http://stackoverflow.com/questions/46155/validate-email-address-in-javascript
+ 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,}))$/;
+ return re.test(value);
+ };
+
+ // containsNoSpecialCharacters(str){
+ // return !/[~`!#$%\^&*+=\-\[\]\\';,/{}|\\":<>\?]/g.test(str);
+ // }
+
+ noSpecialChars(str){
+ str = String(str);
+ return !/[~`!#$%\^&*+=\-\[\]\\';,/{}|\\":<>\?]/g.test(str);
+ }
+
+ noQwertysAllowed (str){
+ str = str.toLowerCase();
+ if(str.toLowerCase().indexOf("qwerty") >-1){
+ return false;
+ } else{
+ return true;
+ }
+ }
+
+ passwordValidation (str){
+ if(str.length <6){
+ return false;
+ } else{
+ return true;
+ }
+ }
+
+ isNumberOnly(str){
+ if(!/^\d+$/.test(str)){
+ return false;
+ }else {
+ return true;
+ }
+ }
+ isPositiveNotZeroNumber(str){
+ str = parseFloat(str);
+ if(str <=0){
+ return false;
+ }else {
+ return true;
+ }
+ }
+ isNumeric(n) {
+ return !isNaN(parseFloat(n)) && isFinite(n);
+ }
+
+ isValidACN(str){
+ str = String(str);
+ //Remove any whitespace.
+ str = str.replace(/\s+/g, '');
+ console.log(str);
+ console.log(str.length);
+ if(/^\d+$/.test(str) && str.length ==9){
+ return true;
+ } else{
+ return false;
+ }
+ }
+ isValidShortCode(str){
+ str = String(str);
+ console.log(str);
+ if(str.length < 5 && str.length >2){
+ return true;
+ } else{
+ return false;
+ }
+ }
+ containsNumbers (str){
+ if(/\d/g.test(str)){
+ return true;
+ }else{
+ return false;
+ }
+ }
+ isInt(n){
+ console.log(typeof Number(n));
+ return Number(n) % 1 === 0;
+ }
+
+ isFloat(n){
+ return Number(n) % 1 !== 0;
+ }
+ decimalPlaces(num) {
+ num = parseFloat(num);
+ var match = (''+num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
+ if (!match) { return 0; }
+ return Math.max(
+ 0,
+ // Number of digits right of decimal point.
+ (match[1] ? match[1].length : 0)
+ // Adjust for scientific notation.
+ - (match[2] ? +match[2] : 0));
+ }
+};
diff --git a/package.json b/package.json
index 607925b..5de9f9b 100644
--- a/package.json
+++ b/package.json
@@ -68,12 +68,17 @@
"jquery": "^2.2.4",
"jquery-validation": "^1.15.1",
"react": "^15.3.2",
+ "react-addons-css-transition-group": "^15.4.2",
"react-addons-pure-render-mixin": "^15.3.2",
+ "react-addons-transition-group": "^15.4.2",
"react-bootstrap": "^0.30.5",
"react-dom": "^15.3.2",
"react-komposer": "^1.13.1",
"react-router": "^2.6.1",
"react-router-bootstrap": "^0.23.1",
- "react-svg": "^2.1.19"
+ "react-svg": "^2.1.19",
+ "reactstrap": "^4.2.0",
+ "velocity-animate": "^1.4.3",
+ "velocity-react": "^1.2.1"
}
}