Commit 48c0461d6bbc120885949c8cb3bf03cb56588034
1 parent
cc8fd8a946
Exists in
master
some more file restructuring
Showing
13 changed files
with
271 additions
and
121 deletions
Show diff stats
client/main.html
1 | 1 | <head> |
2 | 2 | <meta charset="utf-8"> |
3 | - <title>Application Name</title> | |
4 | - <meta name="description" content="A description for the application."> | |
3 | + <title>YoungDesk</title> | |
4 | + <meta name="description" content="All your organization's need."> | |
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 | + <link | |
9 | + href='https://fonts.googleapis.com/css?family=Alef' | |
10 | + rel='stylesheet' | |
11 | + type='text/css' | |
12 | + /> | |
13 | + <link | |
14 | + href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" | |
15 | + rel="stylesheet" | |
16 | + integrity="sha384-T8Gy5hrqNKT+hzMclPo118YTQO6cYprQmhrYwIiQ/3axmI1hQomh7Ud2hPOy8SP1" | |
17 | + crossorigin="anonymous" | |
18 | + /> | |
8 | 19 | </head> |
9 | 20 | |
10 | 21 | <body> |
11 | - <div id="react-root"></div> | |
22 | + <div id="app"></div> | |
12 | 23 | </body> | ... | ... |
imports/client/views/org/enter/Login.js
... | ... | @@ -1,54 +0,0 @@ |
1 | -import React from 'react'; | |
2 | -import { Link } from 'react-router'; | |
3 | -import { Row, Col, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap'; | |
4 | -import handleLogin from './module/login'; | |
5 | - | |
6 | -export default class Login extends React.Component { | |
7 | - componentDidMount() { | |
8 | - handleLogin({ component: this }); | |
9 | - } | |
10 | - | |
11 | - handleSubmit(event) { | |
12 | - event.preventDefault(); | |
13 | - } | |
14 | - | |
15 | - render() { | |
16 | - return ( | |
17 | - <div className="Login"> | |
18 | - <Row> | |
19 | - <Col xs={ 12 } sm={ 6 } md={ 4 }> | |
20 | - <h4 className="page-header">Login</h4> | |
21 | - <form | |
22 | - ref={ form => (this.loginForm = form) } | |
23 | - className="login" | |
24 | - onSubmit={ this.handleSubmit } | |
25 | - > | |
26 | - <FormGroup> | |
27 | - <ControlLabel>Email Address</ControlLabel> | |
28 | - <FormControl | |
29 | - type="email" | |
30 | - ref="emailAddress" | |
31 | - name="emailAddress" | |
32 | - placeholder="Email Address" | |
33 | - /> | |
34 | - </FormGroup> | |
35 | - <FormGroup> | |
36 | - <ControlLabel> | |
37 | - <span className="pull-left">Password</span> | |
38 | - <Link className="pull-right" to="/recover-password">Forgot Password?</Link> | |
39 | - </ControlLabel> | |
40 | - <FormControl | |
41 | - type="password" | |
42 | - ref="password" | |
43 | - name="password" | |
44 | - placeholder="Password" | |
45 | - /> | |
46 | - </FormGroup> | |
47 | - <Button type="submit" bsStyle="success">Login</Button> | |
48 | - </form> | |
49 | - </Col> | |
50 | - </Row> | |
51 | - </div> | |
52 | - ); | |
53 | - } | |
54 | -} |
imports/client/views/org/enter/login/LoginView.js
... | ... | @@ -0,0 +1,54 @@ |
1 | +import React from 'react'; | |
2 | +import { Link } from 'react-router'; | |
3 | +import { Row, Col, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap'; | |
4 | +import handleLogin from './login'; | |
5 | + | |
6 | +export default class Login extends React.Component { | |
7 | + componentDidMount() { | |
8 | + handleLogin({ component: this }); | |
9 | + } | |
10 | + | |
11 | + handleSubmit(event) { | |
12 | + event.preventDefault(); | |
13 | + } | |
14 | + | |
15 | + render() { | |
16 | + return ( | |
17 | + <div className="Login"> | |
18 | + <Row> | |
19 | + <Col xs={ 12 } sm={ 6 } md={ 4 }> | |
20 | + <h4 className="page-header">Login</h4> | |
21 | + <form | |
22 | + ref={ form => (this.loginForm = form) } | |
23 | + className="login" | |
24 | + onSubmit={ this.handleSubmit } | |
25 | + > | |
26 | + <FormGroup> | |
27 | + <ControlLabel>Email Address</ControlLabel> | |
28 | + <FormControl | |
29 | + type="email" | |
30 | + ref="emailAddress" | |
31 | + name="emailAddress" | |
32 | + placeholder="Email Address" | |
33 | + /> | |
34 | + </FormGroup> | |
35 | + <FormGroup> | |
36 | + <ControlLabel> | |
37 | + <span className="pull-left">Password</span> | |
38 | + <Link className="pull-right" to="/recover-password">Forgot Password?</Link> | |
39 | + </ControlLabel> | |
40 | + <FormControl | |
41 | + type="password" | |
42 | + ref="password" | |
43 | + name="password" | |
44 | + placeholder="Password" | |
45 | + /> | |
46 | + </FormGroup> | |
47 | + <Button type="submit" bsStyle="success">Login</Button> | |
48 | + </form> | |
49 | + </Col> | |
50 | + </Row> | |
51 | + </div> | |
52 | + ); | |
53 | + } | |
54 | +} | ... | ... |
imports/client/views/org/enter/login/login.js
... | ... | @@ -0,0 +1,57 @@ |
1 | +/* eslint-disable no-undef */ | |
2 | + | |
3 | +import { browserHistory } from 'react-router'; | |
4 | +import { Meteor } from 'meteor/meteor'; | |
5 | +import { Bert } from 'meteor/themeteorchef:bert'; | |
6 | +import '/imports/client/components/validation'; | |
7 | + | |
8 | +let component; | |
9 | + | |
10 | +const login = () => { | |
11 | + const email = document.querySelector('[name="emailAddress"]').value; | |
12 | + const password = document.querySelector('[name="password"]').value; | |
13 | + | |
14 | + Meteor.loginWithPassword(email, password, (error) => { | |
15 | + if (error) { | |
16 | + Bert.alert(error.reason, 'warning'); | |
17 | + } else { | |
18 | + Bert.alert('Logged in!', 'success'); | |
19 | + | |
20 | + const { location } = component.props; | |
21 | + if (location.state && location.state.nextPathname) { | |
22 | + browserHistory.push(location.state.nextPathname); | |
23 | + } else { | |
24 | + browserHistory.push('/'); | |
25 | + } | |
26 | + } | |
27 | + }); | |
28 | +}; | |
29 | + | |
30 | +const validate = () => { | |
31 | + $(component.loginForm).validate({ | |
32 | + rules: { | |
33 | + emailAddress: { | |
34 | + required: true, | |
35 | + email: true, | |
36 | + }, | |
37 | + password: { | |
38 | + required: true, | |
39 | + }, | |
40 | + }, | |
41 | + messages: { | |
42 | + emailAddress: { | |
43 | + required: 'Need an email address here.', | |
44 | + email: 'Is this email address legit?', | |
45 | + }, | |
46 | + password: { | |
47 | + required: 'Need a password here.', | |
48 | + }, | |
49 | + }, | |
50 | + submitHandler() { login(); }, | |
51 | + }); | |
52 | +}; | |
53 | + | |
54 | +export default function handleLogin(options) { | |
55 | + component = options.component; | |
56 | + validate(); | |
57 | +} | ... | ... |
imports/client/views/org/enter/module/login.js
... | ... | @@ -1,57 +0,0 @@ |
1 | -/* eslint-disable no-undef */ | |
2 | - | |
3 | -import { browserHistory } from 'react-router'; | |
4 | -import { Meteor } from 'meteor/meteor'; | |
5 | -import { Bert } from 'meteor/themeteorchef:bert'; | |
6 | -import '/imports/client/components/validation'; | |
7 | - | |
8 | -let component; | |
9 | - | |
10 | -const login = () => { | |
11 | - const email = document.querySelector('[name="emailAddress"]').value; | |
12 | - const password = document.querySelector('[name="password"]').value; | |
13 | - | |
14 | - Meteor.loginWithPassword(email, password, (error) => { | |
15 | - if (error) { | |
16 | - Bert.alert(error.reason, 'warning'); | |
17 | - } else { | |
18 | - Bert.alert('Logged in!', 'success'); | |
19 | - | |
20 | - const { location } = component.props; | |
21 | - if (location.state && location.state.nextPathname) { | |
22 | - browserHistory.push(location.state.nextPathname); | |
23 | - } else { | |
24 | - browserHistory.push('/'); | |
25 | - } | |
26 | - } | |
27 | - }); | |
28 | -}; | |
29 | - | |
30 | -const validate = () => { | |
31 | - $(component.loginForm).validate({ | |
32 | - rules: { | |
33 | - emailAddress: { | |
34 | - required: true, | |
35 | - email: true, | |
36 | - }, | |
37 | - password: { | |
38 | - required: true, | |
39 | - }, | |
40 | - }, | |
41 | - messages: { | |
42 | - emailAddress: { | |
43 | - required: 'Need an email address here.', | |
44 | - email: 'Is this email address legit?', | |
45 | - }, | |
46 | - password: { | |
47 | - required: 'Need a password here.', | |
48 | - }, | |
49 | - }, | |
50 | - submitHandler() { login(); }, | |
51 | - }); | |
52 | -}; | |
53 | - | |
54 | -export default function handleLogin(options) { | |
55 | - component = options.component; | |
56 | - validate(); | |
57 | -} |
imports/client/views/org/module/Index.js
imports/client/views/org/module/navigation/AppNavigation.js
... | ... | @@ -0,0 +1,27 @@ |
1 | +import React from 'react'; | |
2 | +import { Navbar } from 'react-bootstrap'; | |
3 | +import { Link } from 'react-router'; | |
4 | +import PublicNavigation from './PublicNavigation.js'; | |
5 | +import AuthenticatedNavigation from './AuthenticatedNavigation.js'; | |
6 | + | |
7 | +const renderNavigation = hasUser => (hasUser ? <AuthenticatedNavigation /> : <PublicNavigation />); | |
8 | + | |
9 | +const AppNavigation = ({ hasUser }) => ( | |
10 | + <Navbar> | |
11 | + <Navbar.Header> | |
12 | + <Navbar.Brand> | |
13 | + <Link to="/">Application Name</Link> | |
14 | + </Navbar.Brand> | |
15 | + <Navbar.Toggle /> | |
16 | + </Navbar.Header> | |
17 | + <Navbar.Collapse> | |
18 | + { renderNavigation(hasUser) } | |
19 | + </Navbar.Collapse> | |
20 | + </Navbar> | |
21 | +); | |
22 | + | |
23 | +AppNavigation.propTypes = { | |
24 | + hasUser: React.PropTypes.object, | |
25 | +}; | |
26 | + | |
27 | +export default AppNavigation; | ... | ... |
imports/client/views/org/module/navigation/AuthenticatedNavigation.js
... | ... | @@ -0,0 +1,30 @@ |
1 | +import React from 'react'; | |
2 | +import { browserHistory } from 'react-router'; | |
3 | +import { LinkContainer } from 'react-router-bootstrap'; | |
4 | +import { Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap'; | |
5 | +import { Meteor } from 'meteor/meteor'; | |
6 | + | |
7 | +const handleLogout = () => Meteor.logout(() => browserHistory.push('/login')); | |
8 | + | |
9 | +const userName = () => { | |
10 | + const user = Meteor.user(); | |
11 | + const name = user && user.profile ? user.profile.name : ''; | |
12 | + return user ? `${name.first} ${name.last}` : ''; | |
13 | +}; | |
14 | + | |
15 | +const AuthenticatedNavigation = () => ( | |
16 | + <div> | |
17 | + <Nav> | |
18 | + <LinkContainer to="/documents"> | |
19 | + <NavItem eventKey={ 2 } href="/documents">Documents</NavItem> | |
20 | + </LinkContainer> | |
21 | + </Nav> | |
22 | + <Nav pullRight> | |
23 | + <NavDropdown eventKey={ 3 } title={ userName() } id="basic-nav-dropdown"> | |
24 | + <MenuItem eventKey={ 3.1 } onClick={ handleLogout }>Logout</MenuItem> | |
25 | + </NavDropdown> | |
26 | + </Nav> | |
27 | + </div> | |
28 | +); | |
29 | + | |
30 | +export default AuthenticatedNavigation; | ... | ... |
imports/client/views/org/module/navigation/Loading.js
... | ... | @@ -0,0 +1,30 @@ |
1 | +import React from 'react'; | |
2 | + | |
3 | +const Loading = () => ( | |
4 | + <svg | |
5 | + version="1.1" | |
6 | + className="Loading" | |
7 | + xmlns="http://www.w3.org/2000/svg" | |
8 | + x="0px" | |
9 | + y="0px" | |
10 | + width="40px" | |
11 | + height="40px" | |
12 | + viewBox="0 0 40 40" | |
13 | + enableBackground="new 0 0 40 40"> | |
14 | + <path | |
15 | + opacity="1.0" | |
16 | + fill="#eee" | |
17 | + d="M20.201,5.169c-8.254,0-14.946,6.692-14.946,14.946c0,8.255,6.692,14.946, | |
18 | + 14.946,14.946s14.946-6.691,14.946-14.946C35.146,11.861,28.455,5.169,20.201, | |
19 | + 5.169z M20.201,31.749c-6.425,0-11.634-5.208-11.634-11.634c0-6.425, | |
20 | + 5.209-11.634,11.634-11.634c6.425,0,11.633,5.209,11.633,11.634C31.834, | |
21 | + 26.541,26.626,31.749,20.201,31.749z"/> | |
22 | + <path | |
23 | + fill="#da5347" | |
24 | + d="M26.013,10.047l1.654-2.866c-2.198-1.272-4.743-2.012-7.466-2.012h0v3.312h0 | |
25 | + C22.32,8.481,24.301,9.057,26.013,10.047z"> | |
26 | + </path> | |
27 | + </svg> | |
28 | +); | |
29 | + | |
30 | +export default Loading; | ... | ... |
imports/client/views/org/module/navigation/PublicNavigation.js
... | ... | @@ -0,0 +1,16 @@ |
1 | +import React from 'react'; | |
2 | +import { LinkContainer } from 'react-router-bootstrap'; | |
3 | +import { Nav, NavItem } from 'react-bootstrap'; | |
4 | + | |
5 | +const PublicNavigation = () => ( | |
6 | + <Nav pullRight> | |
7 | + <LinkContainer to="signup"> | |
8 | + <NavItem eventKey={ 1 } href="/signup">Sign Up</NavItem> | |
9 | + </LinkContainer> | |
10 | + <LinkContainer to="login"> | |
11 | + <NavItem eventKey={ 2 } href="/login">Log In</NavItem> | |
12 | + </LinkContainer> | |
13 | + </Nav> | |
14 | +); | |
15 | + | |
16 | +export default PublicNavigation; | ... | ... |
imports/client/views/org/module/navigation/index.js
... | ... | @@ -0,0 +1,7 @@ |
1 | +import { composeWithTracker } from 'react-komposer'; | |
2 | +import { Meteor } from 'meteor/meteor'; | |
3 | +import AppNavigation from '../components/AppNavigation.js'; | |
4 | + | |
5 | +const composer = (props, onData) => onData(null, { hasUser: Meteor.user() }); | |
6 | + | |
7 | +export default composeWithTracker(composer, {}, {}, { pure: false })(AppNavigation); | ... | ... |
imports/startup/client/routes.js
... | ... | @@ -4,15 +4,33 @@ import React from 'react'; |
4 | 4 | import { render } from 'react-dom'; |
5 | 5 | import { Router, Route, IndexRoute, browserHistory } from 'react-router'; |
6 | 6 | import { Meteor } from 'meteor/meteor'; |
7 | -import App from '/imports/client/layouts/OrgApp'; | |
7 | + | |
8 | +/** | |
9 | + * General Components | |
10 | + */ | |
8 | 11 | import Index from '/imports/client/views/app/module/Index'; |
9 | -import Login from '/imports/client/views/org/enter/Login'; | |
12 | + | |
13 | +/** | |
14 | + * Org Components | |
15 | + */ | |
16 | + | |
17 | +import App from '/imports/client/layouts/OrgApp'; | |
18 | +import Login from '/imports/client/views/org/enter/login/LoginView'; | |
10 | 19 | import NotFound from '/imports/client/views/org/NotFound'; |
11 | 20 | import RecoverPassword from '/imports/client/views/org/enter/RecoverPassword'; |
12 | 21 | import ResetPassword from '/imports/client/views/org/enter/ResetPassword'; |
13 | -import Signup from '/imports/client/views/nonOrg/enter/SignupView'; | |
14 | 22 | import { Orgs } from '/imports/collections/orgs/index'; |
15 | 23 | |
24 | +/** | |
25 | + * NonOrg Components | |
26 | + */ | |
27 | +import Signup from '/imports/client/views/nonOrg/enter/SignupView'; | |
28 | + | |
29 | +/** | |
30 | + * Invalid Org Components | |
31 | + */ | |
32 | + | |
33 | + | |
16 | 34 | |
17 | 35 | const authenticate = (nextState, replace) => { |
18 | 36 | if (!Meteor.loggingIn() && !Meteor.userId()) { |
... | ... | @@ -24,7 +42,7 @@ const authenticate = (nextState, replace) => { |
24 | 42 | }; |
25 | 43 | |
26 | 44 | |
27 | -const detectOrg = (nextState, replace) => { | |
45 | +const detectOrg = () => { | |
28 | 46 | orgSlug = ""; |
29 | 47 | var hostnameArray = document.location.hostname.split( "." ); |
30 | 48 | if(hostnameArray[1]=='localhost'){ |
... | ... | @@ -35,13 +53,13 @@ const detectOrg = (nextState, replace) => { |
35 | 53 | console.log(res); |
36 | 54 | if(res){ |
37 | 55 | Session.set('orgId', res._id._str); |
38 | - render(getOrgRoutes(),document.getElementById('react-root')); | |
56 | + render(getOrgRoutes(),document.getElementById('app')); | |
39 | 57 | }else{ |
40 | - render(getInvalidOrgRoute(),document.getElementById('react-root')); | |
58 | + render(getInvalidOrgRoute(),document.getElementById('app')); | |
41 | 59 | } |
42 | 60 | }); |
43 | 61 | }else{ |
44 | - render(getNonOrgRoutes(),document.getElementById('react-root')); | |
62 | + render(getNonOrgRoutes(),document.getElementById('app')); | |
45 | 63 | } |
46 | 64 | } |
47 | 65 | const checkSlug = (nextState, replace) => { | ... | ... |
imports/startup/server/browser-policy.js
1 | 1 | import { BrowserPolicy } from 'meteor/browser-policy-common'; |
2 | 2 | // e.g., BrowserPolicy.content.allowOriginForAll( 's3.amazonaws.com' ); |
3 | 3 | BrowserPolicy.content.allowFontOrigin("data:"); |
4 | + | |
5 | +BrowserPolicy.content.disallowEval(); | |
6 | + | |
7 | +BrowserPolicy.framing.allowAll(); | |
8 | +BrowserPolicy.content.allowInlineScripts(); | |
9 | +BrowserPolicy.content.allowInlineStyles(); | |
10 | +BrowserPolicy.content.allowSameOriginForAll(); | |
11 | +BrowserPolicy.content.allowDataUrlForAll(); | |
12 | +BrowserPolicy.content.allowOriginForAll('*'); | |
13 | +BrowserPolicy.content.allowOriginForAll('http://*'); | |
14 | +BrowserPolicy.content.allowOriginForAll('https://*'); | ... | ... |