Commit 3540345c5009ccf30a86af176b91dc70978e17b5

Authored by themeteorchef
1 parent 5251e2b22b
Exists in master

handful of fixes

- Bump Meteor to 1.4.2.
- Bump all NPM packages to latest available versions.
- Correct a few ESLint errors that were spotted.
- Change casing of file names for components and containers to PascalCase.
- Bump version of Base and Meteor in package.json and Index.js component.
- Deprecate get-input-value.js module in favor of direct DOM selection via JS.
.meteor/.finished-upgraders
1 # This file contains information which helps Meteor properly upgrade your 1 # This file contains information which helps Meteor properly upgrade your
2 # app when you run 'meteor update'. You should check it into version control 2 # app when you run 'meteor update'. You should check it into version control
3 # with your project. 3 # with your project.
4 4
5 notices-for-0.9.0 5 notices-for-0.9.0
6 notices-for-0.9.1 6 notices-for-0.9.1
7 0.9.4-platform-file 7 0.9.4-platform-file
8 notices-for-facebook-graph-api-2 8 notices-for-facebook-graph-api-2
9 1.2.0-standard-minifiers-package 9 1.2.0-standard-minifiers-package
10 1.2.0-meteor-platform-split 10 1.2.0-meteor-platform-split
11 1.2.0-cordova-changes 11 1.2.0-cordova-changes
12 1.2.0-breaking-changes 12 1.2.0-breaking-changes
13 1.3.0-split-minifiers-package 13 1.3.0-split-minifiers-package
14 1.3.5-remove-old-dev-bundle-link 14 1.3.5-remove-old-dev-bundle-link
15 1.4.0-remove-old-dev-bundle-link 15 1.4.0-remove-old-dev-bundle-link
16 1.4.1-add-shell-server-package
16 17
1 # Meteor packages used by this project, one per line. 1 # Meteor packages used by this project, one per line.
2 # Check this file (and the other files in this directory) into your repository. 2 # Check this file (and the other files in this directory) into your repository.
3 # 3 #
4 # 'meteor add' and 'meteor remove' will edit this file for you, 4 # 'meteor add' and 'meteor remove' will edit this file for you,
5 # but you can also edit it by hand. 5 # but you can also edit it by hand.
6 6
7 meteor-base@1.0.4 # Packages every Meteor app needs to have 7 meteor-base@1.0.4 # Packages every Meteor app needs to have
8 mobile-experience@1.0.4 # Packages for a great mobile UX 8 mobile-experience@1.0.4 # Packages for a great mobile UX
9 mongo@1.1.10 # The database Meteor supports right now 9 mongo@1.1.14 # The database Meteor supports right now
10 reactive-var@1.0.10 # Reactive variable for tracker 10 reactive-var@1.0.11 # Reactive variable for tracker
11 session@1.1.6 11 session@1.1.7
12 tracker@1.1.0 # Meteor's client-side reactive programming library 12 tracker@1.1.1 # Meteor's client-side reactive programming library
13 13
14 standard-minifier-css@1.1.8 # CSS minifier run for production mode 14 standard-minifier-css@1.3.2 # CSS minifier run for production mode
15 standard-minifier-js@1.1.8 # JS minifier run for production mode 15 standard-minifier-js@1.2.1 # JS minifier run for production mode
16 es5-shim@4.6.13 # ECMAScript 5 compatibility for older browsers. 16 es5-shim@4.6.15 # ECMAScript 5 compatibility for older browsers.
17 ecmascript@0.5.7 # Enable ECMAScript2015+ syntax in app code 17 ecmascript@0.5.9 # Enable ECMAScript2015+ syntax in app code
18 18
19 accounts-password@1.2.12 19 accounts-password@1.3.1
20 accounts-base@1.2.9 20 accounts-base@1.2.14
21 check@1.2.3 21 check@1.2.4
22 audit-argument-checks@1.0.7 22 audit-argument-checks@1.0.7
23 browser-policy@1.0.9 23 browser-policy@1.0.9
24 24
25 fourseven:scss 25 fourseven:scss
26 aldeed:collection2 26 aldeed:collection2
27 alanning:roles 27 alanning:roles
28 themeteorchef:bert 28 themeteorchef:bert
29 static-html@1.1.11 29 static-html@1.1.11
30 xolvio:cleaner 30 xolvio:cleaner
31 practicalmeteor:mocha 31 practicalmeteor:mocha
32 xolvio:backdoor 32 xolvio:backdoor
33 mdg:validated-method 33 mdg:validated-method
34 dburles:factory@1.0.0 34 dburles:factory@1.0.0
35 ddp-rate-limiter@1.0.5 35 ddp-rate-limiter@1.0.6
36 shell-server
36 37
1 METEOR@1.4.0.1 1 METEOR@1.4.2
2 2
1 accounts-base@1.2.10 1 accounts-base@1.2.14
2 accounts-password@1.2.14 2 accounts-password@1.3.1
3 alanning:roles@1.2.15 3 alanning:roles@1.2.15
4 aldeed:collection2@2.9.1 4 aldeed:collection2@2.10.0
5 aldeed:collection2-core@1.1.1 5 aldeed:collection2-core@1.2.0
6 aldeed:schema-deny@1.0.1 6 aldeed:schema-deny@1.1.0
7 aldeed:schema-index@1.0.1 7 aldeed:schema-index@1.1.0
8 aldeed:simple-schema@1.5.3 8 aldeed:simple-schema@1.5.3
9 allow-deny@1.0.5 9 allow-deny@1.0.5
10 audit-argument-checks@1.0.7 10 audit-argument-checks@1.0.7
11 autoupdate@1.2.11 11 autoupdate@1.3.12
12 babel-compiler@6.9.0 12 babel-compiler@6.13.0
13 babel-runtime@0.1.10 13 babel-runtime@0.1.12
14 base64@1.0.9 14 base64@1.0.10
15 binary-heap@1.0.9 15 binary-heap@1.0.10
16 blaze@2.1.8 16 blaze@2.1.9
17 blaze-tools@1.0.9 17 blaze-tools@1.0.10
18 boilerplate-generator@1.0.9 18 boilerplate-generator@1.0.11
19 browser-policy@1.0.9 19 browser-policy@1.0.9
20 browser-policy-common@1.0.10 20 browser-policy-common@1.0.11
21 browser-policy-content@1.0.11 21 browser-policy-content@1.0.12
22 browser-policy-framing@1.0.11 22 browser-policy-framing@1.0.12
23 caching-compiler@1.0.6 23 caching-compiler@1.1.8
24 caching-html-compiler@1.0.6 24 caching-html-compiler@1.0.7
25 callback-hook@1.0.9 25 callback-hook@1.0.10
26 check@1.2.3 26 check@1.2.4
27 coffeescript@1.1.4 27 coffeescript@1.11.1_2
28 dburles:factory@1.1.0 28 dburles:factory@1.1.0
29 ddp@1.2.5 29 ddp@1.2.5
30 ddp-client@1.2.9 30 ddp-client@1.3.2
31 ddp-common@1.2.6 31 ddp-common@1.2.7
32 ddp-rate-limiter@1.0.5 32 ddp-rate-limiter@1.0.6
33 ddp-server@1.2.10 33 ddp-server@1.3.11
34 deps@1.0.12 34 deps@1.0.12
35 diff-sequence@1.0.6 35 diff-sequence@1.0.7
36 ecmascript@0.5.7 36 ecmascript@0.5.9
37 ecmascript-runtime@0.3.13 37 ecmascript-runtime@0.3.15
38 ejson@1.0.12 38 ejson@1.0.13
39 email@1.1.16 39 email@1.1.18
40 es5-shim@4.6.13 40 es5-shim@4.6.15
41 fastclick@1.0.12 41 fastclick@1.0.13
42 fortawesome:fontawesome@4.5.0 42 fortawesome:fontawesome@4.6.3
43 fourseven:scss@3.8.1 43 fourseven:scss@3.10.0
44 geojson-utils@1.0.9 44 geojson-utils@1.0.10
45 hot-code-push@1.0.4 45 hot-code-push@1.0.4
46 html-tools@1.0.10 46 html-tools@1.0.11
47 htmljs@1.0.10 47 htmljs@1.0.11
48 http@1.1.8 48 http@1.2.10
49 id-map@1.0.8 49 id-map@1.0.9
50 jquery@1.11.9 50 jquery@1.11.10
51 launch-screen@1.0.12 51 launch-screen@1.1.0
52 livedata@1.0.18 52 livedata@1.0.18
53 localstorage@1.0.11 53 localstorage@1.0.12
54 logging@1.1.14 54 logging@1.1.16
55 mdg:validated-method@1.1.0 55 mdg:validated-method@1.1.0
56 mdg:validation-error@0.5.1 56 mdg:validation-error@0.5.1
57 meteor@1.2.16 57 meteor@1.6.0
58 meteor-base@1.0.4 58 meteor-base@1.0.4
59 minifier-css@1.2.13 59 minifier-css@1.2.15
60 minifier-js@1.2.13 60 minifier-js@1.2.15
61 minimongo@1.0.17 61 minimongo@1.0.18
62 mobile-experience@1.0.4 62 mobile-experience@1.0.4
63 mobile-status-bar@1.0.12 63 mobile-status-bar@1.0.13
64 modules@0.7.5 64 modules@0.7.7
65 modules-runtime@0.7.5 65 modules-runtime@0.7.7
66 mongo@1.1.10 66 mongo@1.1.14
67 mongo-id@1.0.5 67 mongo-id@1.0.6
68 npm-bcrypt@0.8.7_1 68 npm-bcrypt@0.9.2
69 npm-mongo@1.5.45 69 npm-mongo@2.2.11_2
70 observe-sequence@1.0.12 70 observe-sequence@1.0.14
71 ordered-dict@1.0.8 71 ordered-dict@1.0.9
72 practicalmeteor:chai@2.1.0_1 72 practicalmeteor:chai@2.1.0_1
73 practicalmeteor:loglevel@1.2.0_2 73 practicalmeteor:loglevel@1.2.0_2
74 practicalmeteor:mocha@2.4.5_6 74 practicalmeteor:mocha@2.4.5_6
75 practicalmeteor:mocha-core@1.0.1 75 practicalmeteor:mocha-core@1.0.1
76 practicalmeteor:sinon@1.14.1_2 76 practicalmeteor:sinon@1.14.1_2
77 promise@0.8.3 77 promise@0.8.8
78 raix:eventemitter@0.1.3 78 raix:eventemitter@0.1.3
79 random@1.0.10 79 random@1.0.10
80 rate-limit@1.0.5 80 rate-limit@1.0.6
81 reactive-dict@1.1.8 81 reactive-dict@1.1.8
82 reactive-var@1.0.10 82 reactive-var@1.0.11
83 reload@1.1.10 83 reload@1.1.11
84 retry@1.0.8 84 retry@1.0.9
85 routepolicy@1.0.11 85 routepolicy@1.0.12
86 service-configuration@1.0.10 86 service-configuration@1.0.11
87 session@1.1.6 87 session@1.1.7
88 sha@1.0.8 88 sha@1.0.9
89 spacebars@1.0.12 89 shell-server@0.2.1
90 spacebars-compiler@1.0.12 90 spacebars@1.0.13
91 srp@1.0.9 91 spacebars-compiler@1.0.13
92 standard-minifier-css@1.1.8 92 srp@1.0.10
93 standard-minifier-js@1.1.8 93 standard-minifier-css@1.3.2
94 static-html@1.1.11 94 standard-minifier-js@1.2.1
95 templating@1.1.14 95 static-html@1.1.13
96 templating-tools@1.0.4 96 templating@1.2.15
97 templating-compiler@1.2.15
98 templating-runtime@1.2.15
99 templating-tools@1.0.5
97 themeteorchef:bert@2.1.1 100 themeteorchef:bert@2.1.1
98 tmeasday:test-reporter-helpers@0.2.1 101 tmeasday:test-reporter-helpers@0.2.1
99 tracker@1.1.0 102 tracker@1.1.1
100 ui@1.0.11 103 ui@1.0.12
101 underscore@1.0.9 104 underscore@1.0.10
102 url@1.0.10 105 url@1.0.11
103 webapp@1.3.10 106 webapp@1.3.12
104 webapp-hashing@1.0.9 107 webapp-hashing@1.0.9
105 xolvio:backdoor@0.2.0 108 xolvio:backdoor@0.2.1
106 xolvio:cleaner@0.3.1 109 xolvio:cleaner@0.3.1
107 110
1 # The Meteor Chef - Base 1 # The Meteor Chef - Base
2 A starting point for Meteor apps. 2 A starting point for Meteor apps.
3 3
4 <table> 4 <table>
5 <tbody> 5 <tbody>
6 <tr> 6 <tr>
7 <th>Base Version</th> 7 <th>Base Version</th>
8 <td>v4.7.0</td> 8 <td>v4.8.0</td>
9 </tr> 9 </tr>
10 <tr> 10 <tr>
11 <th>Meteor Version</th> 11 <th>Meteor Version</th>
12 <td>v1.4.0.1</td> 12 <td>v1.4.2</td>
13 </tr> 13 </tr>
14 </tbody> 14 </tbody>
15 </table> 15 </table>
16 16
17 [Read the Documentation](http://themeteorchef.com/base) 17 [Read the Documentation](http://themeteorchef.com/base)
18 18
imports/api/documents/documents.js
1 import faker from 'faker'; 1 if (Meteor.isClient) import faker from 'faker';
2 import { Mongo } from 'meteor/mongo'; 2 import { Mongo } from 'meteor/mongo';
3 import { SimpleSchema } from 'meteor/aldeed:simple-schema'; 3 import { SimpleSchema } from 'meteor/aldeed:simple-schema';
4 import { Factory } from 'meteor/dburles:factory'; 4 import { Factory } from 'meteor/dburles:factory';
5 5
6 export const Documents = new Mongo.Collection('Documents'); 6 export const Documents = new Mongo.Collection('Documents');
7 7
8 Documents.allow({ 8 Documents.allow({
9 insert: () => false, 9 insert: () => false,
10 update: () => false, 10 update: () => false,
11 remove: () => false, 11 remove: () => false,
12 }); 12 });
13 13
14 Documents.deny({ 14 Documents.deny({
15 insert: () => true, 15 insert: () => true,
16 update: () => true, 16 update: () => true,
17 remove: () => true, 17 remove: () => true,
18 }); 18 });
19 19
20 Documents.schema = new SimpleSchema({ 20 Documents.schema = new SimpleSchema({
21 title: { 21 title: {
22 type: String, 22 type: String,
23 label: 'The title of the document.', 23 label: 'The title of the document.',
24 }, 24 },
25 }); 25 });
26 26
27 Documents.attachSchema(Documents.schema); 27 Documents.attachSchema(Documents.schema);
28 28
29 Factory.define('document', Documents, { 29 Factory.define('document', Documents, {
30 title: () => faker.hacker.phrase(), 30 title: () => faker.hacker.phrase(),
31 }); 31 });
32 32
imports/api/documents/methods.js
1 import { Documents } from './documents';
2 import { SimpleSchema } from 'meteor/aldeed:simple-schema'; 1 import { SimpleSchema } from 'meteor/aldeed:simple-schema';
3 import { ValidatedMethod } from 'meteor/mdg:validated-method'; 2 import { ValidatedMethod } from 'meteor/mdg:validated-method';
3 import { Documents } from './documents';
4 import { rateLimit } from '../../modules/rate-limit.js'; 4 import { rateLimit } from '../../modules/rate-limit.js';
5 5
6 export const insertDocument = new ValidatedMethod({ 6 export const insertDocument = new ValidatedMethod({
7 name: 'documents.insert', 7 name: 'documents.insert',
8 validate: new SimpleSchema({ 8 validate: new SimpleSchema({
9 title: { type: String }, 9 title: { type: String },
10 }).validator(), 10 }).validator(),
11 run(document) { 11 run(document) {
12 Documents.insert(document); 12 Documents.insert(document);
13 }, 13 },
14 }); 14 });
15 15
16 export const updateDocument = new ValidatedMethod({ 16 export const updateDocument = new ValidatedMethod({
17 name: 'documents.update', 17 name: 'documents.update',
18 validate: new SimpleSchema({ 18 validate: new SimpleSchema({
19 _id: { type: String }, 19 _id: { type: String },
20 'update.title': { type: String, optional: true }, 20 'update.title': { type: String, optional: true },
21 }).validator(), 21 }).validator(),
22 run({ _id, update }) { 22 run({ _id, update }) {
23 Documents.update(_id, { $set: update }); 23 Documents.update(_id, { $set: update });
24 }, 24 },
25 }); 25 });
26 26
27 export const removeDocument = new ValidatedMethod({ 27 export const removeDocument = new ValidatedMethod({
28 name: 'documents.remove', 28 name: 'documents.remove',
29 validate: new SimpleSchema({ 29 validate: new SimpleSchema({
30 _id: { type: String }, 30 _id: { type: String },
31 }).validator(), 31 }).validator(),
32 run({ _id }) { 32 run({ _id }) {
33 Documents.remove(_id); 33 Documents.remove(_id);
34 }, 34 },
35 }); 35 });
36 36
37 rateLimit({ 37 rateLimit({
38 methods: [ 38 methods: [
39 insertDocument, 39 insertDocument,
40 updateDocument, 40 updateDocument,
41 removeDocument, 41 removeDocument,
42 ], 42 ],
43 limit: 5, 43 limit: 5,
44 timeRange: 1000, 44 timeRange: 1000,
45 }); 45 });
imports/modules/get-input-value.js
1 import ReactDOM from 'react-dom'; File was deleted
2
3 export const getInputValue = (component) => ReactDOM.findDOMNode(component).value;
4 1 import ReactDOM from 'react-dom';
imports/startup/client/routes.js
1 import React from 'react'; 1 import React from 'react';
2 import { render } from 'react-dom'; 2 import { render } from 'react-dom';
3 import { Router, Route, IndexRoute, browserHistory } from 'react-router'; 3 import { Router, Route, IndexRoute, browserHistory } from 'react-router';
4 import { Meteor } from 'meteor/meteor'; 4 import { Meteor } from 'meteor/meteor';
5 import { App } from '../../ui/layouts/app'; 5 import { App } from '../../ui/layouts/App.js';
6 import { Documents } from '../../ui/pages/documents'; 6 import { Documents } from '../../ui/pages/Documents.js';
7 import { Index } from '../../ui/pages/index'; 7 import { Index } from '../../ui/pages/Index.js';
8 import { Login } from '../../ui/pages/login'; 8 import { Login } from '../../ui/pages/Login.js';
9 import { NotFound } from '../../ui/pages/not-found'; 9 import { NotFound } from '../../ui/pages/NotFound.js';
10 import { RecoverPassword } from '../../ui/pages/recover-password'; 10 import { RecoverPassword } from '../../ui/pages/RecoverPassword.js';
11 import { ResetPassword } from '../../ui/pages/reset-password'; 11 import { ResetPassword } from '../../ui/pages/ResetPassword.js';
12 import { Signup } from '../../ui/pages/signup'; 12 import { Signup } from '../../ui/pages/Signup.js';
13 13
14 const requireAuth = (nextState, replace) => { 14 const requireAuth = (nextState, replace) => {
15 if (!Meteor.loggingIn() && !Meteor.userId()) { 15 if (!Meteor.loggingIn() && !Meteor.userId()) {
16 replace({ 16 replace({
17 pathname: '/login', 17 pathname: '/login',
18 state: { nextPathname: nextState.location.pathname }, 18 state: { nextPathname: nextState.location.pathname },
19 }); 19 });
20 } 20 }
21 }; 21 };
22 22
23 Meteor.startup(() => { 23 Meteor.startup(() => {
24 render( 24 render(
25 <Router history={ browserHistory }> 25 <Router history={ browserHistory }>
26 <Route path="/" component={ App }> 26 <Route path="/" component={ App }>
27 <IndexRoute name="index" component={ Index } onEnter={ requireAuth } /> 27 <IndexRoute name="index" component={ Index } onEnter={ requireAuth } />
28 <Route name="documents" path="/documents" component={ Documents } onEnter={ requireAuth } /> 28 <Route name="documents" path="/documents" component={ Documents } onEnter={ requireAuth } />
29 <Route name="login" path="/login" component={ Login } /> 29 <Route name="login" path="/login" component={ Login } />
30 <Route name="recover-password" path="/recover-password" component={ RecoverPassword } /> 30 <Route name="recover-password" path="/recover-password" component={ RecoverPassword } />
31 <Route name="reset-password" path="/reset-password/:token" component={ ResetPassword } /> 31 <Route name="reset-password" path="/reset-password/:token" component={ ResetPassword } />
32 <Route name="signup" path="/signup" component={ Signup } /> 32 <Route name="signup" path="/signup" component={ Signup } />
33 <Route path="*" component={ NotFound } /> 33 <Route path="*" component={ NotFound } />
34 </Route> 34 </Route>
35 </Router>, 35 </Router>,
36 document.getElementById('react-root') 36 document.getElementById('react-root')
37 ); 37 );
38 }); 38 });
39 39
imports/ui/components/AddDocument.js
File was created 1 import React from 'react';
2 import { FormGroup, FormControl } from 'react-bootstrap';
3 import { Bert } from 'meteor/themeteorchef:bert';
4 import { insertDocument } from '../../api/documents/methods.js';
5
6 const handleInsertDocument = (event) => {
7 const target = event.target;
8 const title = target.value.trim();
9
10 if (title !== '' && event.keyCode === 13) {
11 insertDocument.call({
12 title,
13 }, (error) => {
14 if (error) {
15 Bert.alert(error.reason, 'danger');
16 } else {
17 target.value = '';
18 Bert.alert('Document added!', 'success');
19 }
20 });
21 }
22 };
23
24 const AddDocument = () => (
25 <FormGroup>
26 <FormControl
27 type="text"
28 onKeyUp={ handleInsertDocument }
29 placeholder="Type a document title and press enter..."
30 />
31 </FormGroup>
32 );
33
34 export default AddDocument;
35
imports/ui/components/AppNavigation.js
File was created 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;
28
imports/ui/components/AuthenticatedNavigation.js
File was created 1 import React from 'react';
2 import { browserHistory } from 'react-router';
3 import { IndexLinkContainer, 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 <IndexLinkContainer to="/">
19 <NavItem eventKey={ 1 } href="/">Index</NavItem>
20 </IndexLinkContainer>
21 <LinkContainer to="/documents">
22 <NavItem eventKey={ 2 } href="/documents">Documents</NavItem>
23 </LinkContainer>
24 </Nav>
25 <Nav pullRight>
26 <NavDropdown eventKey={ 3 } title={ userName() } id="basic-nav-dropdown">
27 <MenuItem eventKey={ 3.1 } onClick={ handleLogout }>Logout</MenuItem>
28 </NavDropdown>
29 </Nav>
30 </div>
31 );
32
33 export default AuthenticatedNavigation;
34
imports/ui/components/DocumentsList.js
File was created 1 import React from 'react';
2 import { ListGroup, Alert } from 'react-bootstrap';
3 import { Document } from './Document.js';
4
5 const DocumentsList = ({ documents }) => (
6 documents.length > 0 ? <ListGroup className="documents-list">
7 {documents.map(doc => (
8 <Document key={ doc._id } document={ doc } />
9 ))}
10 </ListGroup> :
11 <Alert bsStyle="warning">No documents yet.</Alert>
12 );
13
14 DocumentsList.propTypes = {
15 documents: React.PropTypes.array,
16 };
17
18 export default DocumentsList;
19
imports/ui/components/PublicNavigation.js
File was created 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;
17
imports/ui/components/add-document.js
1 import React from 'react'; File was deleted
2 import { FormGroup, FormControl } from 'react-bootstrap';
3 import { Bert } from 'meteor/themeteorchef:bert';
4 import { insertDocument } from '../../api/documents/methods.js';
5
6 const handleInsertDocument = (event) => {
7 const target = event.target;
8 const title = target.value.trim();
9
10 if (title !== '' && event.keyCode === 13) {
11 insertDocument.call({
12 title,
13 }, (error) => {
14 if (error) {
15 Bert.alert(error.reason, 'danger');
16 } else {
17 target.value = '';
18 Bert.alert('Document added!', 'success');
19 }
20 });
21 }
22 };
23
24 export const AddDocument = () => (
25 <FormGroup>
26 <FormControl
27 type="text"
28 onKeyUp={ handleInsertDocument }
29 placeholder="Type a document title and press enter..."
30 />
31 </FormGroup>
32 );
33 1 import React from 'react';
imports/ui/components/app-navigation.js
1 import React from 'react'; File was deleted
2 import { Navbar } from 'react-bootstrap';
3 import { Link } from 'react-router';
4 import { PublicNavigation } from './public-navigation';
5 import { AuthenticatedNavigation } from './authenticated-navigation';
6
7 export class AppNavigation extends React.Component {
8 renderNavigation(hasUser) {
9 return hasUser ? <AuthenticatedNavigation /> : <PublicNavigation />;
10 }
11
12 render() {
13 return <Navbar>
14 <Navbar.Header>
15 <Navbar.Brand>
16 <Link to="/">Application Name</Link>
17 </Navbar.Brand>
18 <Navbar.Toggle />
19 </Navbar.Header>
20 <Navbar.Collapse>
21 { this.renderNavigation(this.props.hasUser) }
22 </Navbar.Collapse>
23 </Navbar>;
24 }
25 }
26
27 AppNavigation.propTypes = {
28 hasUser: React.PropTypes.object,
29 };
30 1 import React from 'react';
imports/ui/components/authenticated-navigation.js
1 import React from 'react'; File was deleted
2 import { browserHistory } from 'react-router';
3 import { IndexLinkContainer, 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 export const AuthenticatedNavigation = () => (
16 <div>
17 <Nav>
18 <IndexLinkContainer to="/">
19 <NavItem eventKey={ 1 } href="/">Index</NavItem>
20 </IndexLinkContainer>
21 <LinkContainer to="/documents">
22 <NavItem eventKey={ 2 } href="/documents">Documents</NavItem>
23 </LinkContainer>
24 </Nav>
25 <Nav pullRight>
26 <NavDropdown eventKey={ 3 } title={ userName() } id="basic-nav-dropdown">
27 <MenuItem eventKey={ 3.1 } onClick={ handleLogout }>Logout</MenuItem>
28 </NavDropdown>
29 </Nav>
30 </div>
31 );
32 1 import React from 'react';
imports/ui/components/document.js
1 import React from 'react'; 1 import React from 'react';
2 import { Row, Col, ListGroupItem, FormControl, Button } from 'react-bootstrap'; 2 import { Row, Col, ListGroupItem, FormControl, Button } from 'react-bootstrap';
3 import { Bert } from 'meteor/themeteorchef:bert'; 3 import { Bert } from 'meteor/themeteorchef:bert';
4 import { updateDocument, removeDocument } from '../../api/documents/methods.js'; 4 import { updateDocument, removeDocument } from '../../api/documents/methods.js';
5 5
6 const handleUpdateDocument = (documentId, event) => { 6 const handleUpdateDocument = (documentId, event) => {
7 const title = event.target.value.trim(); 7 const title = event.target.value.trim();
8 if (title !== '' && event.keyCode === 13) { 8 if (title !== '' && event.keyCode === 13) {
9 updateDocument.call({ 9 updateDocument.call({
10 _id: documentId, 10 _id: documentId,
11 update: { title }, 11 update: { title },
12 }, (error) => { 12 }, (error) => {
13 if (error) { 13 if (error) {
14 Bert.alert(error.reason, 'danger'); 14 Bert.alert(error.reason, 'danger');
15 } else { 15 } else {
16 Bert.alert('Document updated!', 'success'); 16 Bert.alert('Document updated!', 'success');
17 } 17 }
18 }); 18 });
19 } 19 }
20 }; 20 };
21 21
22 const handleRemoveDocument = (documentId, event) => { 22 const handleRemoveDocument = (documentId, event) => {
23 event.preventDefault(); 23 event.preventDefault();
24 // this should be replaced with a styled solution so for now we will 24 // this should be replaced with a styled solution so for now we will
25 // disable the eslint `no-alert` 25 // disable the eslint `no-alert`
26 // eslint-disable-next-line no-alert 26 // eslint-disable-next-line no-alert
27 if (confirm('Are you sure? This is permanent.')) { 27 if (confirm('Are you sure? This is permanent.')) {
28 removeDocument.call({ 28 removeDocument.call({
29 _id: documentId, 29 _id: documentId,
30 }, (error) => { 30 }, (error) => {
31 if (error) { 31 if (error) {
32 Bert.alert(error.reason, 'danger'); 32 Bert.alert(error.reason, 'danger');
33 } else { 33 } else {
34 Bert.alert('Document removed!', 'success'); 34 Bert.alert('Document removed!', 'success');
35 } 35 }
36 }); 36 });
37 } 37 }
38 }; 38 };
39 39
40 export const Document = ({ document }) => ( 40 const Document = ({ document }) => (
41 <ListGroupItem key={ document._id }> 41 <ListGroupItem key={ document._id }>
42 <Row> 42 <Row>
43 <Col xs={ 8 } sm={ 10 }> 43 <Col xs={ 8 } sm={ 10 }>
44 <FormControl 44 <FormControl
45 type="text" 45 type="text"
46 defaultValue={ document.title } 46 defaultValue={ document.title }
47 onKeyUp={ handleUpdateDocument.bind(this, document._id) } 47 onKeyUp={ handleUpdateDocument.bind(this, document._id) }
48 /> 48 />
49 </Col> 49 </Col>
50 <Col xs={ 4 } sm={ 2 }> 50 <Col xs={ 4 } sm={ 2 }>
51 <Button 51 <Button
52 bsStyle="danger" 52 bsStyle="danger"
53 className="btn-block" 53 className="btn-block"
54 onClick={ handleRemoveDocument.bind(this, document._id) }> 54 onClick={ handleRemoveDocument.bind(this, document._id) }>
55 Remove 55 Remove
56 </Button> 56 </Button>
57 </Col> 57 </Col>
58 </Row> 58 </Row>
59 </ListGroupItem> 59 </ListGroupItem>
60 ); 60 );
61
62 Document.propTypes = {
63 document: React.PropTypes.object,
64 };
65
66 export default Document;
61 67
imports/ui/components/documents-list.js
1 import React from 'react'; File was deleted
2 import { ListGroup, Alert } from 'react-bootstrap';
3 import { Document } from './document.js';
4
5 export const DocumentsList = ({ documents }) => (
6 documents.length > 0 ? <ListGroup className="documents-list">
7 {documents.map((doc) => (
8 <Document key={ doc._id } document={ doc } />
9 ))}
10 </ListGroup> :
11 <Alert bsStyle="warning">No documents yet.</Alert>
12 );
13
14 DocumentsList.propTypes = {
15 documents: React.PropTypes.array,
16 };
17 1 import React from 'react';
imports/ui/components/loading.js
1 import React from 'react'; 1 import React from 'react';
2 2
3 export const Loading = () => ( 3 const Loading = () => (
4 <svg 4 <svg
5 version="1.1" 5 version="1.1"
6 className="loading" 6 className="loading"
7 xmlns="http://www.w3.org/2000/svg" 7 xmlns="http://www.w3.org/2000/svg"
8 x="0px" 8 x="0px"
9 y="0px" 9 y="0px"
10 width="40px" 10 width="40px"
11 height="40px" 11 height="40px"
12 viewBox="0 0 40 40" 12 viewBox="0 0 40 40"
13 enableBackground="new 0 0 40 40"> 13 enableBackground="new 0 0 40 40">
14 <path 14 <path
15 opacity="1.0" 15 opacity="1.0"
16 fill="#eee" 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, 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, 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, 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, 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"/> 21 26.541,26.626,31.749,20.201,31.749z"/>
22 <path 22 <path
23 fill="#da5347" 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 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"> 25 C22.32,8.481,24.301,9.057,26.013,10.047z">
26 </path> 26 </path>
27 </svg> 27 </svg>
28 ); 28 );
29
30 export default Loading;
29 31
imports/ui/components/public-navigation.js
1 import React from 'react'; File was deleted
2 import { LinkContainer } from 'react-router-bootstrap';
3 import { Nav, NavItem } from 'react-bootstrap';
4
5 export 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 1 import React from 'react';
imports/ui/containers/AppNavigation.js
File was created 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);
8
imports/ui/containers/DocumentsList.js
File was created 1 import { composeWithTracker } from 'react-komposer';
2 import { Meteor } from 'meteor/meteor';
3 import { Documents } from '../../api/documents/documents.js';
4 import { DocumentsList } from '../components/DocumentsList.js';
5 import { Loading } from '../components/Loading.js';
6
7 const composer = (params, onData) => {
8 const subscription = Meteor.subscribe('documents');
9 if (subscription.ready()) {
10 const documents = Documents.find().fetch();
11 onData(null, { documents });
12 }
13 };
14
15 export default composeWithTracker(composer, Loading)(DocumentsList);
16
imports/ui/containers/app-navigation.js
1 import { composeWithTracker } from 'react-komposer'; File was deleted
2 import { Meteor } from 'meteor/meteor';
3 import { AppNavigation } from '../components/app-navigation';
4
5 const composer = (props, onData) => {
6 onData(null, { hasUser: Meteor.user() });
7 };
8
9 export default composeWithTracker(composer, {}, {}, { pure: false })(AppNavigation);
10 1 import { composeWithTracker } from 'react-komposer';
imports/ui/containers/documents-list.js
1 import { composeWithTracker } from 'react-komposer'; File was deleted
2 import { Documents } from '../../api/documents/documents.js';
3 import { DocumentsList } from '../components/documents-list.js';
4 import { Loading } from '../components/loading.js';
5 import { Meteor } from 'meteor/meteor';
6
7 const composer = (params, onData) => {
8 const subscription = Meteor.subscribe('documents');
9 if (subscription.ready()) {
10 const documents = Documents.find().fetch();
11 onData(null, { documents });
12 }
13 };
14
15 export default composeWithTracker(composer, Loading)(DocumentsList);
16 1 import { composeWithTracker } from 'react-komposer';
imports/ui/layouts/app.js
1 import React from 'react'; 1 import React from 'react';
2 import { Grid } from 'react-bootstrap'; 2 import { Grid } from 'react-bootstrap';
3 import AppNavigation from '../containers/app-navigation'; 3 import AppNavigation from '../containers/AppNavigation.js';
4 4
5 export const App = React.createClass({ 5 const App = ({ children }) => (
6 propTypes: { 6 <div>
7 children: React.PropTypes.element.isRequired, 7 <AppNavigation />
8 }, 8 <Grid>
9 render() { 9 { children }
10 return <div> 10 </Grid>
11 <AppNavigation /> 11 </div>
12 <Grid> 12 );
13 { this.props.children } 13
14 </Grid> 14 App.propTypes = {
15 </div>; 15 children: React.PropTypes.node,
16 }, 16 };
17 }); 17
18 export default App;
18 19
imports/ui/pages/NotFound.js
File was created 1 import React from 'react';
2 import { Alert } from 'react-bootstrap';
3
4 const NotFound = () => (
5 <Alert bsStyle="danger">
6 <p><strong>Error [404]</strong>: { window.location.pathname } does not exist.</p>
7 </Alert>
8 );
9
10 export default NotFound;
11
imports/ui/pages/RecoverPassword.js
File was created 1 import React from 'react';
2 import { Row, Col, Alert, FormGroup, FormControl, Button } from 'react-bootstrap';
3 import { handleRecoverPassword } from '../../modules/recover-password';
4
5 export default class RecoverPassword extends React.Component {
6 componentDidMount() {
7 handleRecoverPassword({ component: this });
8 }
9
10 handleSubmit() {
11 this.preventDefault();
12 }
13
14 render() {
15 return (<Row>
16 <Col xs={ 12 } sm={ 6 } md={ 4 }>
17 <h4 className="page-header">Recover Password</h4>
18 <Alert bsStyle="info">
19 Enter your email address below to receive a link to reset your password.
20 </Alert>
21 <form ref="recoverPassword" className="recover-password" onSubmit={ this.handleSubmit }>
22 <FormGroup>
23 <FormControl
24 type="email"
25 ref="emailAddress"
26 name="emailAddress"
27 placeholder="Email Address"
28 />
29 </FormGroup>
30 <Button type="submit" bsStyle="success">Recover Password</Button>
31 </form>
32 </Col>
33 </Row>);
34 }
35 }
36
imports/ui/pages/ResetPassword.js
File was created 1 import React from 'react';
2 import { Row, Col, Alert, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap';
3 import { handleResetPassword } from '../../modules/reset-password';
4
5 export default class ResetPassword extends React.Component {
6 componentDidMount() {
7 handleResetPassword({ component: this, token: this.props.params.token });
8 }
9
10 handleSubmit() {
11 this.preventDefault();
12 }
13
14 render() {
15 return (<Row>
16 <Col xs={ 12 } sm={ 6 } md={ 4 }>
17 <h4 className="page-header">Reset Password</h4>
18 <Alert bsStyle="info">
19 To reset your password, enter a new one below. You will be logged in
20 with your new password.
21 </Alert>
22 <form ref="resetPassword" className="reset-password" onSubmit={ this.handleSubmit }>
23 <FormGroup>
24 <ControlLabel>New Password</ControlLabel>
25 <FormControl
26 type="password"
27 ref="newPassword"
28 name="newPassword"
29 placeholder="New Password"
30 />
31 </FormGroup>
32 <FormGroup>
33 <ControlLabel>Repeat New Password</ControlLabel>
34 <FormControl
35 type="password"
36 ref="repeatNewPassword"
37 name="repeatNewPassword"
38 placeholder="Repeat New Password"
39 />
40 </FormGroup>
41 <Button type="submit" bsStyle="success">Reset Password &amp; Login</Button>
42 </form>
43 </Col>
44 </Row>);
45 }
46 }
47
48 ResetPassword.propTypes = {
49 params: React.PropTypes.object,
50 };
51
imports/ui/pages/documents.js
1 import React from 'react'; 1 import React from 'react';
2 import { Row, Col } from 'react-bootstrap'; 2 import { Row, Col } from 'react-bootstrap';
3 import DocumentsList from '../containers/documents-list.js'; 3 import DocumentsList from '../containers/DocumentsList.js';
4 import { AddDocument } from '../components/add-document.js'; 4 import { AddDocument } from '../components/AddDocument.js';
5 5
6 export const Documents = () => ( 6 const Documents = () => (
7 <Row> 7 <Row>
8 <Col xs={ 12 }> 8 <Col xs={ 12 }>
9 <h4 className="page-header">Documents</h4> 9 <h4 className="page-header">Documents</h4>
10 <AddDocument /> 10 <AddDocument />
11 <DocumentsList /> 11 <DocumentsList />
12 </Col> 12 </Col>
13 </Row> 13 </Row>
14 ); 14 );
15
16 export default Documents;
15 17
imports/ui/pages/index.js
1 import React from 'react'; 1 import React from 'react';
2 import { Jumbotron } from 'react-bootstrap'; 2 import { Jumbotron } from 'react-bootstrap';
3 3
4 export const Index = () => ( 4 const Index = () => (
5 <Jumbotron className="text-center"> 5 <Jumbotron className="text-center">
6 <h2>Base</h2> 6 <h2>Base</h2>
7 <p>A starting point for Meteor applications.</p> 7 <p>A starting point for Meteor applications.</p>
8 <p><a className="btn btn-success" href="https://themeteorchef.com/base" role="button">Read the Documentation</a></p> 8 <p><a className="btn btn-success" href="https://themeteorchef.com/base" role="button">Read the Documentation</a></p>
9 <p style={ { fontSize: '16px', color: '#aaa' } }>Currently at v4.7.0</p> 9 <p style={ { fontSize: '16px', color: '#aaa' } }>Currently at v4.8.0</p>
10 </Jumbotron> 10 </Jumbotron>
11 ); 11 );
12
13 export default Index;
12 14
imports/ui/pages/login.js
1 import React from 'react'; 1 import React from 'react';
2 import { Link } from 'react-router'; 2 import { Link } from 'react-router';
3 import { Row, Col, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap'; 3 import { Row, Col, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap';
4 import { handleLogin } from '../../modules/login'; 4 import { handleLogin } from '../../modules/login';
5 5
6 export class Login extends React.Component { 6 export default class Login extends React.Component {
7 componentDidMount() { 7 componentDidMount() {
8 handleLogin({ component: this }); 8 handleLogin({ component: this });
9 } 9 }
10 10
11 handleSubmit(event) { 11 handleSubmit() {
12 event.preventDefault(); 12 this.preventDefault();
13 } 13 }
14 14
15 render() { 15 render() {
16 return <Row> 16 return (<Row>
17 <Col xs={ 12 } sm={ 6 } md={ 4 }> 17 <Col xs={ 12 } sm={ 6 } md={ 4 }>
18 <h4 className="page-header">Login</h4> 18 <h4 className="page-header">Login</h4>
19 <form ref="login" className="login" onSubmit={ this.handleSubmit }> 19 <form ref="login" className="login" onSubmit={ this.handleSubmit }>
20 <FormGroup> 20 <FormGroup>
21 <ControlLabel>Email Address</ControlLabel> 21 <ControlLabel>Email Address</ControlLabel>
22 <FormControl 22 <FormControl
23 type="email" 23 type="email"
24 ref="emailAddress" 24 ref="emailAddress"
25 name="emailAddress" 25 name="emailAddress"
26 placeholder="Email Address" 26 placeholder="Email Address"
27 /> 27 />
28 </FormGroup> 28 </FormGroup>
29 <FormGroup> 29 <FormGroup>
30 <ControlLabel> 30 <ControlLabel>
31 <span className="pull-left">Password</span> 31 <span className="pull-left">Password</span>
32 <Link className="pull-right" to="/recover-password">Forgot Password?</Link> 32 <Link className="pull-right" to="/recover-password">Forgot Password?</Link>
33 </ControlLabel> 33 </ControlLabel>
34 <FormControl 34 <FormControl
35 type="password" 35 type="password"
36 ref="password" 36 ref="password"
37 name="password" 37 name="password"
38 placeholder="Password" 38 placeholder="Password"
39 /> 39 />
40 </FormGroup> 40 </FormGroup>
41 <Button type="submit" bsStyle="success">Login</Button> 41 <Button type="submit" bsStyle="success">Login</Button>
42 </form> 42 </form>
43 </Col> 43 </Col>
44 </Row>; 44 </Row>);
45 } 45 }
46 } 46 }
47 47
imports/ui/pages/not-found.js
1 import React from 'react'; File was deleted
2 import { Alert } from 'react-bootstrap';
3
4 export const NotFound = () => (
5 <Alert bsStyle="danger">
6 <p><strong>Error [404]</strong>: { window.location.pathname } does not exist.</p>
7 </Alert>
8 );
9 1 import React from 'react';
imports/ui/pages/recover-password.js
1 import React from 'react'; File was deleted
2 import { Row, Col, Alert, FormGroup, FormControl, Button } from 'react-bootstrap';
3 import { handleRecoverPassword } from '../../modules/recover-password';
4
5 export class RecoverPassword extends React.Component {
6 componentDidMount() {
7 handleRecoverPassword({ component: this });
8 }
9
10 handleSubmit(event) {
11 event.preventDefault();
12 }
13
14 render() {
15 return <Row>
16 <Col xs={ 12 } sm={ 6 } md={ 4 }>
17 <h4 className="page-header">Recover Password</h4>
18 <Alert bsStyle="info">
19 Enter your email address below to receive a link to reset your password.
20 </Alert>
21 <form ref="recoverPassword" className="recover-password" onSubmit={ this.handleSubmit }>
22 <FormGroup>
23 <FormControl
24 type="email"
25 ref="emailAddress"
26 name="emailAddress"
27 placeholder="Email Address"
28 />
29 </FormGroup>
30 <Button type="submit" bsStyle="success">Recover Password</Button>
31 </form>
32 </Col>
33 </Row>;
34 }
35 }
36 1 import React from 'react';
imports/ui/pages/reset-password.js
1 import React from 'react'; File was deleted
2 import { Row, Col, Alert, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap';
3 import { handleResetPassword } from '../../modules/reset-password';
4
5 export class ResetPassword extends React.Component {
6 componentDidMount() {
7 handleResetPassword({
8 component: this,
9 token: this.props.params.token,
10 });
11 }
12
13 handleSubmit(event) {
14 event.preventDefault();
15 }
16
17 render() {
18 return <Row>
19 <Col xs={ 12 } sm={ 6 } md={ 4 }>
20 <h4 className="page-header">Reset Password</h4>
21 <Alert bsStyle="info">
22 To reset your password, enter a new one below. You will be logged in
23 with your new password.
24 </Alert>
25 <form ref="resetPassword" className="reset-password" onSubmit={ this.handleSubmit }>
26 <FormGroup>
27 <ControlLabel>New Password</ControlLabel>
28 <FormControl
29 type="password"
30 ref="newPassword"
31 name="newPassword"
32 placeholder="New Password"
33 />
34 </FormGroup>
35 <FormGroup>
36 <ControlLabel>Repeat New Password</ControlLabel>
37 <FormControl
38 type="password"
39 ref="repeatNewPassword"
40 name="repeatNewPassword"
41 placeholder="Repeat New Password"
42 />
43 </FormGroup>
44 <Button type="submit" bsStyle="success">Reset Password &amp; Login</Button>
45 </form>
46 </Col>
47 </Row>;
48 }
49 }
50
51 ResetPassword.propTypes = {
52 params: React.PropTypes.object,
53 };
54 1 import React from 'react';
imports/ui/pages/signup.js
1 import React from 'react'; 1 import React from 'react';
2 import { Link } from 'react-router'; 2 import { Link } from 'react-router';
3 import { Row, Col, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap'; 3 import { Row, Col, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap';
4 import { handleSignup } from '../../modules/signup'; 4 import { handleSignup } from '../../modules/signup';
5 5
6 export class Signup extends React.Component { 6 export default class Signup extends React.Component {
7 componentDidMount() { 7 componentDidMount() {
8 handleSignup({ component: this }); 8 handleSignup({ component: this });
9 } 9 }
10 10
11 handleSubmit(event) { 11 handleSubmit() {
12 event.preventDefault(); 12 this.preventDefault();
13 } 13 }
14 14
15 render() { 15 render() {
16 return <Row> 16 return (<Row>
17 <Col xs={ 12 } sm={ 6 } md={ 4 }> 17 <Col xs={ 12 } sm={ 6 } md={ 4 }>
18 <h4 className="page-header">Sign Up</h4> 18 <h4 className="page-header">Sign Up</h4>
19 <form ref="signup" className="signup" onSubmit={ this.handleSubmit }> 19 <form ref="signup" className="signup" onSubmit={ this.handleSubmit }>
20 <Row> 20 <Row>
21 <Col xs={ 6 } sm={ 6 }> 21 <Col xs={ 6 } sm={ 6 }>
22 <FormGroup> 22 <FormGroup>
23 <ControlLabel>First Name</ControlLabel> 23 <ControlLabel>First Name</ControlLabel>
24 <FormControl 24 <FormControl
25 type="text" 25 type="text"
26 ref="firstName" 26 ref="firstName"
27 name="firstName" 27 name="firstName"
28 placeholder="First Name" 28 placeholder="First Name"
29 /> 29 />
30 </FormGroup> 30 </FormGroup>
31 </Col> 31 </Col>
32 <Col xs={ 6 } sm={ 6 }> 32 <Col xs={ 6 } sm={ 6 }>
33 <FormGroup> 33 <FormGroup>
34 <ControlLabel>Last Name</ControlLabel> 34 <ControlLabel>Last Name</ControlLabel>
35 <FormControl 35 <FormControl
36 type="text" 36 type="text"
37 ref="lastName" 37 ref="lastName"
38 name="lastName" 38 name="lastName"
39 placeholder="Last Name" 39 placeholder="Last Name"
40 /> 40 />
41 </FormGroup> 41 </FormGroup>
42 </Col> 42 </Col>
43 </Row> 43 </Row>
44 <FormGroup> 44 <FormGroup>
45 <ControlLabel>Email Address</ControlLabel> 45 <ControlLabel>Email Address</ControlLabel>
46 <FormControl 46 <FormControl
47 type="text" 47 type="text"
48 ref="emailAddress" 48 ref="emailAddress"
49 name="emailAddress" 49 name="emailAddress"
50 placeholder="Email Address" 50 placeholder="Email Address"
51 /> 51 />
52 </FormGroup> 52 </FormGroup>
53 <FormGroup> 53 <FormGroup>
54 <ControlLabel>Password</ControlLabel> 54 <ControlLabel>Password</ControlLabel>
55 <FormControl 55 <FormControl
56 type="password" 56 type="password"
57 ref="password" 57 ref="password"
58 name="password" 58 name="password"
59 placeholder="Password" 59 placeholder="Password"
60 /> 60 />
61 </FormGroup> 61 </FormGroup>
62 <Button type="submit" bsStyle="success">Sign Up</Button> 62 <Button type="submit" bsStyle="success">Sign Up</Button>
63 </form> 63 </form>
64 <p>Already have an account? <Link to="/login">Log In</Link>.</p> 64 <p>Already have an account? <Link to="/login">Log In</Link>.</p>
65 </Col> 65 </Col>
66 </Row>; 66 </Row>);
67 } 67 }
68 } 68 }
69 69
1 { 1 {
2 "name": "application-name", 2 "name": "application-name",
3 "version": "1.0.0", 3 "version": "1.0.0",
4 "description": "Application description.", 4 "description": "Application description.",
5 "scripts": { 5 "scripts": {
6 "start": "meteor --settings settings-development.json", 6 "start": "meteor --settings settings-development.json",
7 "test": "meteor test --driver-package practicalmeteor:mocha --port 5000", 7 "test": "meteor test --driver-package practicalmeteor:mocha --port 5000",
8 "chimp-watch": "chimp --ddp=http://localhost:3000 --watch --mocha --path=tests", 8 "chimp-watch": "chimp --ddp=http://localhost:3000 --watch --mocha --path=tests",
9 "chimp-test": "chimp --ddp=http://localhost:3000 --mocha --path=tests", 9 "chimp-test": "chimp --ddp=http://localhost:3000 --mocha --path=tests",
10 "staging": "meteor deploy staging.meteor.com --settings settings-development.json", 10 "staging": "meteor deploy staging.meteor.com --settings settings-development.json",
11 "production": "meteor deploy production.meteor.com --settings settings-production.json" 11 "production": "meteor deploy production.meteor.com --settings settings-production.json"
12 }, 12 },
13 "devDependencies": { 13 "devDependencies": {
14 "chimp": "^0.39.1", 14 "chimp": "^0.41.2",
15 "eslint": "^2.13.1", 15 "eslint": "^3.8.1",
16 "eslint-config-airbnb": "^9.0.1", 16 "eslint-config-airbnb": "^12.0.0",
17 "eslint-plugin-jsx-a11y": "^1.5.5", 17 "eslint-plugin-import": "^1.16.0",
18 "eslint-plugin-meteor": "^3.6.0", 18 "eslint-plugin-jsx-a11y": "^2.2.3",
19 "eslint-plugin-react": "^5.2.2", 19 "eslint-plugin-meteor": "^4.0.1",
20 "eslint-plugin-react": "^6.4.1",
20 "faker": "^3.1.0" 21 "faker": "^3.1.0"
21 }, 22 },
22 "eslintConfig": { 23 "eslintConfig": {
23 "parserOptions": { 24 "parserOptions": {
24 "ecmaFeatures": { 25 "ecmaFeatures": {
25 "jsx": true 26 "jsx": true
26 } 27 }
27 }, 28 },
28 "plugins": [ 29 "plugins": [
29 "meteor", 30 "meteor",
30 "react" 31 "react"
31 ], 32 ],
32 "extends": [ 33 "extends": [
33 "airbnb/base", 34 "airbnb/base",
34 "plugin:meteor/guide", 35 "plugin:meteor/guide",
35 "plugin:react/recommended" 36 "plugin:react/recommended"
36 ], 37 ],
38 "env": {
39 "browser": true
40 },
37 "globals": { 41 "globals": {
38 "server": false, 42 "server": false,
39 "browser": false, 43 "browser": false,
40 "expect": false 44 "expect": false
41 }, 45 },
42 "rules": { 46 "rules": {
43 "import/no-unresolved": 0, 47 "import/no-unresolved": 0,
48 "import/no-extraneous-dependencies": 0,
49 "import/extensions": 0,
44 "no-underscore-dangle": [ 50 "no-underscore-dangle": [
45 "error", 51 "error",
46 { 52 {
47 "allow": [ 53 "allow": [
48 "_id", 54 "_id",
49 "_ensureIndex", 55 "_ensureIndex",
50 "_verifyEmailToken", 56 "_verifyEmailToken",
51 "_resetPasswordToken", 57 "_resetPasswordToken",
52 "_name" 58 "_name"
53 ] 59 ]
54 } 60 }
55 ] 61 ]
56 } 62 }
57 }, 63 },
58 "dependencies": { 64 "dependencies": {
65 "bcrypt": "^0.8.7",
59 "bootstrap": "^3.3.7", 66 "bootstrap": "^3.3.7",
60 "jquery": "^2.2.4", 67 "jquery": "^3.1.1",
61 "jquery-validation": "^1.15.1", 68 "jquery-validation": "^1.15.1",
62 "react": "^15.3.0", 69 "react": "^15.3.2",
63 "react-addons-pure-render-mixin": "^15.2.1", 70 "react-addons-pure-render-mixin": "^15.3.2",
64 "react-bootstrap": "^0.30.2", 71 "react-bootstrap": "^0.30.5",
65 "react-dom": "^15.3.0", 72 "react-dom": "^15.3.2",
66 "react-komposer": "^1.13.1", 73 "react-komposer": "^1.13.1",
67 "react-router": "^2.6.1", 74 "react-router": "^3.0.0",
68 "react-router-bootstrap": "^0.23.1" 75 "react-router-bootstrap": "^0.23.1"
69 } 76 }
70 } 77 }
71 78