Commit 3540345c5009ccf30a86af176b91dc70978e17b5
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.
Showing
37 changed files
with
418 additions
and
393 deletions
Show diff stats
.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 |
.meteor/packages
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 |
.meteor/release
1 | METEOR@1.4.0.1 | 1 | METEOR@1.4.2 |
2 | 2 |
.meteor/versions
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 |
README.md
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 & 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 & 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 |
package.json
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 |