From 21874669aeae1c15fb2b1c417fb20c5eddf9cbae Mon Sep 17 00:00:00 2001 From: Martin Date: Mon, 17 Apr 2017 19:49:52 -0300 Subject: [PATCH 01/10] Upgraded meteor to 1.4.4.1 Upgraded several node modules Moved eslint config to own file Created compose-with-tracker.js for compatibility with react-komposer v2 --- .eslintignore | 1 + .eslintrc.json | 58 +++++++++++++++++ .gitignore | 18 +++++- .meteor/packages | 29 ++++----- .meteor/release | 2 +- .meteor/versions | 32 ++++----- imports/modules/compose-with-tracker.js | 34 ++++++++++ imports/ui/components/Error.js | 17 +++++ imports/ui/containers/AppNavigation.js | 5 +- imports/ui/containers/DocumentsList.js | 6 +- imports/ui/containers/EditDocument.js | 6 +- imports/ui/containers/ViewDocument.js | 6 +- package.json | 86 +++++++------------------ 13 files changed, 192 insertions(+), 108 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc.json create mode 100644 imports/modules/compose-with-tracker.js create mode 100644 imports/ui/components/Error.js diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..f9ced93c --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +packages diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..76bc720a --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,58 @@ +{ + "parser": "babel-eslint", + "parserOptions": { + "ecmaVersion": 6, + "sourceType": "module", + "ecmaFeatures": { + "jsx": true + }, + "allowImportExportEverywhere": true + }, + "plugins": [ + "meteor" + ], + "extends": [ + "airbnb", + "plugin:meteor/recommended" + ], + "rules": { + "import/extensions": "off", + "import/no-extraneous-dependencies": "off", + "import/prefer-default-export": "off", + "no-underscore-dangle": "off", + "class-methods-use-this": "off", + "meteor/no-session": "off", + "object-shorthand": [ + "error", + "always", + { + "avoidQuotes": false + } + ], + "meteor/eventmap-params": [ + "error", + { + "eventParamName": "event", + "templateInstanceParamName": "instance" + } + ], + "meteor/template-names": [ + "off" + ], + "react/jsx-filename-extension": [ + 1, + { + "extensions": [ + ".js", + ".jsx" + ] + } + ], + "react/forbid-prop-types": "off", + "jsx-a11y/no-static-element-interactions": "off", + "prefer-arrow-callback": "off" + }, + "settings": { + "import/resolver": "meteor" + } +} diff --git a/.gitignore b/.gitignore index e9964c3c..9ef033f6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,19 @@ -.DS_Store settings-production.json + +# OSX +# +.DS_Store +.tmp/ + +# IntelliJ +# +build/ +local/ +.idea + +# node.js +# +node_modules/ npm-debug.log +yarn-error.log -node_modules diff --git a/.meteor/packages b/.meteor/packages index ba54c24f..91f5682e 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -8,29 +8,26 @@ meteor-base@1.0.4 # Packages every Meteor app needs to have mobile-experience@1.0.4 # Packages for a great mobile UX mongo@1.1.16 # The database Meteor supports right now reactive-var@1.0.11 # Reactive variable for tracker -session@1.1.7 -tracker@1.1.2 # Meteor's client-side reactive programming library - +tracker # Meteor's client-side reactive programming library standard-minifier-css@1.3.4 # CSS minifier run for production mode -standard-minifier-js@1.2.3 # JS minifier run for production mode +standard-minifier-js@2.0.0 # JS minifier run for production mode es5-shim@4.6.15 # ECMAScript 5 compatibility for older browsers. -ecmascript@0.6.3 # Enable ECMAScript2015+ syntax in app code - -accounts-password@1.3.4 -accounts-base@1.2.15 -check@1.2.5 -audit-argument-checks@1.0.7 -browser-policy@1.1.0 +ecmascript@0.7.2 # Enable ECMAScript2015+ syntax in app code +shell-server@0.2.3 # Server-side component of the `meteor shell` command -fourseven:scss@4.5.0 +accounts-password +accounts-base +check +audit-argument-checks +browser-policy +fourseven:scss aldeed:collection2 alanning:roles themeteorchef:bert -static-html@1.1.11 +static-html xolvio:cleaner practicalmeteor:mocha xolvio:backdoor mdg:validated-method -dburles:factory@1.0.0 -ddp-rate-limiter@1.0.7 -shell-server@0.2.3 +dburles:factory +ddp-rate-limiter diff --git a/.meteor/release b/.meteor/release index 31ce024f..605b4e1f 100644 --- a/.meteor/release +++ b/.meteor/release @@ -1 +1 @@ -METEOR@1.4.3.2 +METEOR@1.4.4.1 diff --git a/.meteor/versions b/.meteor/versions index e2954800..21f4b2e9 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -1,5 +1,5 @@ -accounts-base@1.2.15 -accounts-password@1.3.4 +accounts-base@1.2.16 +accounts-password@1.3.5 alanning:roles@1.2.16 aldeed:collection2@2.10.0 aldeed:collection2-core@1.2.0 @@ -9,11 +9,11 @@ aldeed:simple-schema@1.5.3 allow-deny@1.0.5 audit-argument-checks@1.0.7 autoupdate@1.3.12 -babel-compiler@6.14.1 +babel-compiler@6.18.1 babel-runtime@1.0.1 base64@1.0.10 binary-heap@1.0.10 -blaze@2.3.0 +blaze@2.3.2 blaze-tools@1.0.10 boilerplate-generator@1.0.11 browser-policy@1.1.0 @@ -27,16 +27,16 @@ check@1.2.5 coffeescript@1.12.3_1 dburles:factory@1.1.0 ddp@1.2.5 -ddp-client@1.3.3 +ddp-client@1.3.4 ddp-common@1.2.8 ddp-rate-limiter@1.0.7 -ddp-server@1.3.13 +ddp-server@1.3.14 deps@1.0.12 diff-sequence@1.0.7 -ecmascript@0.6.3 +ecmascript@0.7.2 ecmascript-runtime@0.3.15 ejson@1.0.13 -email@1.1.18 +email@1.2.0 es5-shim@4.6.15 fastclick@1.0.13 fortawesome:fontawesome@4.7.0 @@ -57,12 +57,12 @@ mdg:validation-error@0.5.1 meteor@1.6.1 meteor-base@1.0.4 minifier-css@1.2.16 -minifier-js@1.2.18 +minifier-js@2.0.0 minimongo@1.0.21 mobile-experience@1.0.4 mobile-status-bar@1.0.14 -modules@0.7.9 -modules-runtime@0.7.9 +modules@0.8.1 +modules-runtime@0.7.10 mongo@1.1.16 mongo-id@1.0.6 npm-bcrypt@0.9.2 @@ -77,7 +77,7 @@ practicalmeteor:sinon@1.14.1_2 promise@0.8.8 raix:eventemitter@0.1.3 random@1.0.10 -rate-limit@1.0.7 +rate-limit@1.0.8 reactive-dict@1.1.8 reactive-var@1.0.11 reload@1.1.11 @@ -88,22 +88,22 @@ session@1.1.7 sha@1.0.9 shell-server@0.2.3 spacebars@1.0.13 -spacebars-compiler@1.1.0 +spacebars-compiler@1.1.1 srp@1.0.10 standard-minifier-css@1.3.4 -standard-minifier-js@1.2.3 +standard-minifier-js@2.0.0 static-html@1.2.0 templating@1.3.0 templating-compiler@1.3.0 templating-runtime@1.3.0 -templating-tools@1.1.0 +templating-tools@1.1.1 themeteorchef:bert@2.1.2 tmeasday:test-reporter-helpers@0.2.1 tracker@1.1.2 ui@1.0.12 underscore@1.0.10 url@1.1.0 -webapp@1.3.14 +webapp@1.3.15 webapp-hashing@1.0.9 xolvio:backdoor@0.2.1 xolvio:cleaner@0.3.1 diff --git a/imports/modules/compose-with-tracker.js b/imports/modules/compose-with-tracker.js new file mode 100644 index 00000000..475e3c19 --- /dev/null +++ b/imports/modules/compose-with-tracker.js @@ -0,0 +1,34 @@ +import { Tracker } from 'meteor/tracker'; +import { compose } from 'react-komposer'; +import React from 'react'; +import Loading from '../ui/components/Loading'; +import Error from '../ui/components/Error'; + +const getTrackerLoader = reactiveMapper => ( + (props, onData, env) => { + let trackerCleanup = null; + const handler = Tracker.nonreactive(() => + Tracker.autorun(() => { + // assign the custom clean-up function. + trackerCleanup = reactiveMapper(props, onData, env); + }), + ); + + return () => { + if (typeof trackerCleanup === 'function') trackerCleanup(); + return handler.stop(); + }; + } +); + +const composeWithTracker = (data, pure = true) => { + const composeOptions = { + pure, + loadingHandler: () => , + errorHandler: error => , + }; + + return compose(getTrackerLoader(data), composeOptions); +}; + +export default composeWithTracker; diff --git a/imports/ui/components/Error.js b/imports/ui/components/Error.js new file mode 100644 index 00000000..e151f291 --- /dev/null +++ b/imports/ui/components/Error.js @@ -0,0 +1,17 @@ +import React, { PropTypes } from 'react'; + +const Error = ({ error }) => ( +

+ {error.message} +

+); + +Error.propTypes = { + error: PropTypes.object, +}; + +Error.defaultProps = { + error: { message: '' }, +}; + +export default Error; diff --git a/imports/ui/containers/AppNavigation.js b/imports/ui/containers/AppNavigation.js index 65f743d9..1fb1df68 100644 --- a/imports/ui/containers/AppNavigation.js +++ b/imports/ui/containers/AppNavigation.js @@ -1,7 +1,8 @@ -import { composeWithTracker } from 'react-komposer'; import { Meteor } from 'meteor/meteor'; import AppNavigation from '../components/AppNavigation.js'; +import composeWithTracker from '../../modules/compose-with-tracker'; const composer = (props, onData) => onData(null, { hasUser: Meteor.user() }); -export default composeWithTracker(composer, {}, {}, { pure: false })(AppNavigation); +export default composeWithTracker(composer, false)(AppNavigation); + diff --git a/imports/ui/containers/DocumentsList.js b/imports/ui/containers/DocumentsList.js index 248d63ea..27b4a57c 100644 --- a/imports/ui/containers/DocumentsList.js +++ b/imports/ui/containers/DocumentsList.js @@ -1,8 +1,7 @@ -import { composeWithTracker } from 'react-komposer'; import { Meteor } from 'meteor/meteor'; import Documents from '../../api/documents/documents.js'; import DocumentsList from '../components/DocumentsList.js'; -import Loading from '../components/Loading.js'; +import composeWithTracker from '../../modules/compose-with-tracker'; const composer = (params, onData) => { const subscription = Meteor.subscribe('documents.list'); @@ -12,4 +11,5 @@ const composer = (params, onData) => { } }; -export default composeWithTracker(composer, Loading)(DocumentsList); +export default composeWithTracker(composer)(DocumentsList); + diff --git a/imports/ui/containers/EditDocument.js b/imports/ui/containers/EditDocument.js index e37ed704..eb24311b 100644 --- a/imports/ui/containers/EditDocument.js +++ b/imports/ui/containers/EditDocument.js @@ -1,8 +1,7 @@ import { Meteor } from 'meteor/meteor'; -import { composeWithTracker } from 'react-komposer'; import Documents from '../../api/documents/documents.js'; import EditDocument from '../pages/EditDocument.js'; -import Loading from '../components/Loading.js'; +import composeWithTracker from '../../modules/compose-with-tracker'; const composer = ({ params }, onData) => { const subscription = Meteor.subscribe('documents.view', params._id); @@ -13,4 +12,5 @@ const composer = ({ params }, onData) => { } }; -export default composeWithTracker(composer, Loading)(EditDocument); +export default composeWithTracker(composer)(EditDocument); + diff --git a/imports/ui/containers/ViewDocument.js b/imports/ui/containers/ViewDocument.js index 3af4aeab..1e64a85d 100644 --- a/imports/ui/containers/ViewDocument.js +++ b/imports/ui/containers/ViewDocument.js @@ -1,8 +1,7 @@ import { Meteor } from 'meteor/meteor'; -import { composeWithTracker } from 'react-komposer'; import Documents from '../../api/documents/documents.js'; import ViewDocument from '../pages/ViewDocument.js'; -import Loading from '../components/Loading.js'; +import composeWithTracker from '../../modules/compose-with-tracker'; const composer = ({ params }, onData) => { const subscription = Meteor.subscribe('documents.view', params._id); @@ -13,4 +12,5 @@ const composer = ({ params }, onData) => { } }; -export default composeWithTracker(composer, Loading)(ViewDocument); +export default composeWithTracker(composer)(ViewDocument); + diff --git a/package.json b/package.json index 140497a8..b36de7e0 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "name": "application-name", + "private": true, "version": "1.0.0", "description": "Application description.", "scripts": { @@ -10,69 +11,30 @@ "staging": "meteor deploy staging.meteor.com --settings settings-development.json", "production": "meteor deploy production.meteor.com --settings settings-production.json" }, - "devDependencies": { - "chimp": "^0.41.2", - "eslint": "^3.8.1", - "eslint-config-airbnb": "^12.0.0", - "eslint-plugin-import": "^1.16.0", - "eslint-plugin-jsx-a11y": "^2.2.3", - "eslint-plugin-meteor": "^4.0.1", - "eslint-plugin-react": "^6.4.1" - }, - "eslintConfig": { - "parserOptions": { - "ecmaFeatures": { - "jsx": true - } - }, - "plugins": [ - "meteor", - "react" - ], - "extends": [ - "airbnb/base", - "plugin:meteor/guide", - "plugin:react/recommended" - ], - "env": { - "browser": true - }, - "globals": { - "server": false, - "browser": false, - "expect": false - }, - "rules": { - "import/no-unresolved": 0, - "import/no-extraneous-dependencies": 0, - "import/extensions": 0, - "no-underscore-dangle": [ - "error", - { - "allow": [ - "_id", - "_ensureIndex", - "_verifyEmailToken", - "_resetPasswordToken", - "_name" - ] - } - ], - "class-methods-use-this": 0 - } - }, "dependencies": { - "babel-runtime": "^6.18.0", - "bcrypt": "^0.8.7", + "babel-runtime": "^6.23.0", + "bcrypt": "^1.0.2", "bootstrap": "^3.3.7", - "jquery": "^2.2.4", - "jquery-validation": "^1.15.1", - "react": "^15.3.2", - "react-addons-pure-render-mixin": "^15.3.2", - "react-bootstrap": "^0.30.5", - "react-dom": "^15.3.2", - "react-komposer": "^1.13.1", - "react-router": "^3.0.0", - "react-router-bootstrap": "^0.23.1" + "jquery": "^3.2.1", + "jquery-validation": "^1.16.0", + "meteor-node-stubs": "^0.2.6", + "react": "^15.5.4", + "react-addons-pure-render-mixin": "^15.5.2", + "react-bootstrap": "^0.30.8", + "react-dom": "^15.5.4", + "react-komposer": "^2.0.0", + "react-router-bootstrap": "^0.23.1", + "react-router": "^3.0.4" + }, + "devDependencies": { + "babel-eslint": "^7.2.2", + "chimp": "^0.47.2", + "eslint": "^3.19.0", + "eslint-config-airbnb": "^14.1.0", + "eslint-import-resolver-meteor": "^0.4.0", + "eslint-plugin-import": "^2.2.0", + "eslint-plugin-jsx-a11y": "^4.0.0", + "eslint-plugin-meteor": "^4.0.1", + "eslint-plugin-react": "^6.10.3" } } From 2fc0f824749182767ad6fdbcb8a2780d4759a88e Mon Sep 17 00:00:00 2001 From: Martin Date: Mon, 17 Apr 2017 21:12:41 -0300 Subject: [PATCH 02/10] react-router v4 WIP --- imports/startup/client/routes.js | 39 +++++++----------- imports/ui/components/AppNavigation.js | 12 +++--- .../ui/components/AuthenticatedNavigation.js | 8 ++-- imports/ui/components/PublicNavigation.js | 4 +- imports/ui/layouts/App.js | 41 +++++++++++++++++++ imports/ui/pages/Documents.js | 11 +++-- package.json | 2 +- 7 files changed, 78 insertions(+), 39 deletions(-) diff --git a/imports/startup/client/routes.js b/imports/startup/client/routes.js index b7c71a26..7664e448 100644 --- a/imports/startup/client/routes.js +++ b/imports/startup/client/routes.js @@ -2,19 +2,10 @@ import React from 'react'; import { render } from 'react-dom'; -import { Router, Route, IndexRoute, browserHistory } from 'react-router'; +import { BrowserRouter as Router, Route, browserHistory } from 'react-router-dom'; import { Meteor } from 'meteor/meteor'; import App from '../../ui/layouts/App.js'; -import Documents from '../../ui/pages/Documents.js'; -import NewDocument from '../../ui/pages/NewDocument.js'; -import EditDocument from '../../ui/containers/EditDocument.js'; -import ViewDocument from '../../ui/containers/ViewDocument.js'; -import Index from '../../ui/pages/Index.js'; -import Login from '../../ui/pages/Login.js'; -import NotFound from '../../ui/pages/NotFound.js'; -import RecoverPassword from '../../ui/pages/RecoverPassword.js'; -import ResetPassword from '../../ui/pages/ResetPassword.js'; -import Signup from '../../ui/pages/Signup.js'; + const authenticate = (nextState, replace) => { if (!Meteor.loggingIn() && !Meteor.userId()) { @@ -27,20 +18,20 @@ const authenticate = (nextState, replace) => { Meteor.startup(() => { render( - - - - - - - - - - - - + + + {/* + + + + + + + + + */} , - document.getElementById('react-root') + document.getElementById('react-root'), ); }); diff --git a/imports/ui/components/AppNavigation.js b/imports/ui/components/AppNavigation.js index 319c9362..576165e3 100644 --- a/imports/ui/components/AppNavigation.js +++ b/imports/ui/components/AppNavigation.js @@ -1,6 +1,6 @@ import React from 'react'; -import { Navbar } from 'react-bootstrap'; -import { Link } from 'react-router'; +import { Navbar, Nav, NavItem } from 'react-bootstrap'; +import { Link } from 'react-router-dom'; import PublicNavigation from './PublicNavigation.js'; import AuthenticatedNavigation from './AuthenticatedNavigation.js'; @@ -14,9 +14,11 @@ const AppNavigation = ({ hasUser }) => ( - - { renderNavigation(hasUser) } - +
+ { /*renderNavigation(hasUser)*/ } + Sign Up + Log In +
); diff --git a/imports/ui/components/AuthenticatedNavigation.js b/imports/ui/components/AuthenticatedNavigation.js index 87a0c38a..a38d8183 100644 --- a/imports/ui/components/AuthenticatedNavigation.js +++ b/imports/ui/components/AuthenticatedNavigation.js @@ -1,5 +1,5 @@ import React from 'react'; -import { browserHistory } from 'react-router'; +import { browserHistory } from 'react-router-dom'; import { LinkContainer } from 'react-router-bootstrap'; import { Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap'; import { Meteor } from 'meteor/meteor'; @@ -16,12 +16,12 @@ const AuthenticatedNavigation = () => (
diff --git a/imports/ui/components/PublicNavigation.js b/imports/ui/components/PublicNavigation.js index d04fc80f..a590f554 100644 --- a/imports/ui/components/PublicNavigation.js +++ b/imports/ui/components/PublicNavigation.js @@ -5,10 +5,10 @@ import { Nav, NavItem } from 'react-bootstrap'; const PublicNavigation = () => ( ); diff --git a/imports/ui/layouts/App.js b/imports/ui/layouts/App.js index 1a8c89c1..0c1240d9 100644 --- a/imports/ui/layouts/App.js +++ b/imports/ui/layouts/App.js @@ -1,6 +1,29 @@ +/* eslint-disable max-len */ + +import { Meteor } from 'meteor/meteor'; import React from 'react'; import { Grid } from 'react-bootstrap'; +import { Route } from 'react-router-dom'; import AppNavigation from '../containers/AppNavigation.js'; +import EditDocument from '../containers/EditDocument.js'; +import ViewDocument from '../containers/ViewDocument.js'; +import Documents from '../pages/Documents.js'; +import NewDocument from '../pages/NewDocument.js'; +import Index from '../pages/Index.js'; +import Login from '../pages/Login.js'; +import NotFound from '../pages/NotFound.js'; +import RecoverPassword from '../pages/RecoverPassword.js'; +import ResetPassword from '../pages/ResetPassword.js'; +import Signup from '../pages/Signup.js'; + +const authenticate = (nextState, replace) => { + /* if (!Meteor.loggingIn() && !Meteor.userId()) { + replace({ + pathname: '/login', + state: { nextPathname: nextState.location.pathname }, + }); + } */ +}; const App = ({ children }) => (
@@ -8,9 +31,27 @@ const App = ({ children }) => ( { children } + + + + + {/* + + + + + + + + + */}
); +App.defaultProps = { + children: null, +}; + App.propTypes = { children: React.PropTypes.node, }; diff --git a/imports/ui/pages/Documents.js b/imports/ui/pages/Documents.js index fbfc0001..7914748a 100644 --- a/imports/ui/pages/Documents.js +++ b/imports/ui/pages/Documents.js @@ -1,10 +1,15 @@ import React from 'react'; import { Link } from 'react-router'; -import { Row, Col, Button } from 'react-bootstrap'; +import { Row, Col, Button, Jumbotron } from 'react-bootstrap'; import DocumentsList from '../containers/DocumentsList.js'; -const Documents = () => ( +const Documents = ({ match }) => (
+ +

Document List

+

I should render a document list.

+
+ {/*
@@ -18,7 +23,7 @@ const Documents = () => (
-
+ */}
); diff --git a/package.json b/package.json index b36de7e0..78b36331 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "react-dom": "^15.5.4", "react-komposer": "^2.0.0", "react-router-bootstrap": "^0.23.1", - "react-router": "^3.0.4" + "react-router-dom": "^4.1.1" }, "devDependencies": { "babel-eslint": "^7.2.2", From 7cae80a925d1a99a17ed876c5bf27408de9d24fe Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 18 Apr 2017 02:20:36 -0300 Subject: [PATCH 03/10] Upgraded to react router v4 --- imports/modules/document-editor.js | 5 +- imports/modules/login.js | 7 +- imports/modules/reset-password.js | 4 +- imports/modules/signup.js | 4 +- imports/startup/client/index.js | 12 ++- imports/startup/client/routes.js | 37 ---------- imports/ui/components/AppNavigation.js | 4 +- .../ui/components/AuthenticatedNavigation.js | 17 ++++- imports/ui/components/DocumentsList.js | 29 ++++---- imports/ui/components/PublicNavigation.js | 21 +++++- imports/ui/containers/DocumentsList.js | 4 +- imports/ui/containers/EditDocument.js | 9 +-- imports/ui/containers/ViewDocument.js | 8 +- imports/ui/layouts/App.js | 73 ++++++++++--------- imports/ui/pages/Documents.js | 45 ++++++------ imports/ui/pages/EditDocument.js | 8 +- imports/ui/pages/Login.js | 8 +- imports/ui/pages/NewDocument.js | 4 +- imports/ui/pages/Signup.js | 2 +- imports/ui/pages/ViewDocument.js | 15 ++-- package.json | 1 + 21 files changed, 159 insertions(+), 158 deletions(-) delete mode 100644 imports/startup/client/routes.js diff --git a/imports/modules/document-editor.js b/imports/modules/document-editor.js index c51c3bf8..81799662 100644 --- a/imports/modules/document-editor.js +++ b/imports/modules/document-editor.js @@ -1,6 +1,5 @@ /* eslint-disable no-undef */ -import { browserHistory } from 'react-router'; import { Bert } from 'meteor/themeteorchef:bert'; import { upsertDocument } from '../api/documents/methods.js'; import './validation.js'; @@ -8,7 +7,7 @@ import './validation.js'; let component; const handleUpsert = () => { - const { doc } = component.props; + const { doc, history } = component.props; const confirmation = doc && doc._id ? 'Document updated!' : 'Document added!'; const upsert = { title: document.querySelector('[name="title"]').value.trim(), @@ -23,7 +22,7 @@ const handleUpsert = () => { } else { component.documentEditorForm.reset(); Bert.alert(confirmation, 'success'); - browserHistory.push(`/documents/${response.insertedId || doc._id}`); + history.push(`/documents/${response.insertedId || doc._id}`); } }); }; diff --git a/imports/modules/login.js b/imports/modules/login.js index 6447a77e..f6a94121 100644 --- a/imports/modules/login.js +++ b/imports/modules/login.js @@ -1,6 +1,5 @@ /* eslint-disable no-undef */ -import { browserHistory } from 'react-router'; import { Meteor } from 'meteor/meteor'; import { Bert } from 'meteor/themeteorchef:bert'; import './validation.js'; @@ -17,11 +16,11 @@ const login = () => { } else { Bert.alert('Logged in!', 'success'); - const { location } = component.props; + const { location, history } = component.props; if (location.state && location.state.nextPathname) { - browserHistory.push(location.state.nextPathname); + history.push(location.state.nextPathname); } else { - browserHistory.push('/'); + history.push('/'); } } }); diff --git a/imports/modules/reset-password.js b/imports/modules/reset-password.js index 11b1aaae..600b93f3 100644 --- a/imports/modules/reset-password.js +++ b/imports/modules/reset-password.js @@ -1,6 +1,5 @@ /* eslint-disable no-undef */ -import { browserHistory } from 'react-router'; import { Accounts } from 'meteor/accounts-base'; import { Bert } from 'meteor/themeteorchef:bert'; import './validation.js'; @@ -14,7 +13,8 @@ const handleReset = () => { if (error) { Bert.alert(error.reason, 'danger'); } else { - browserHistory.push('/'); + const { history } = component.props; + history.push('/'); Bert.alert('Password reset!', 'success'); } }); diff --git a/imports/modules/signup.js b/imports/modules/signup.js index ea24dca4..e7631e03 100644 --- a/imports/modules/signup.js +++ b/imports/modules/signup.js @@ -1,6 +1,5 @@ /* eslint-disable no-undef */ -import { browserHistory } from 'react-router'; import { Accounts } from 'meteor/accounts-base'; import { Bert } from 'meteor/themeteorchef:bert'; import './validation.js'; @@ -25,7 +24,8 @@ const signup = () => { if (error) { Bert.alert(error.reason, 'danger'); } else { - browserHistory.push('/'); + const { history } = component.props; + history.push('/'); Bert.alert('Welcome!', 'success'); } }); diff --git a/imports/startup/client/index.js b/imports/startup/client/index.js index dde07191..51cbed09 100644 --- a/imports/startup/client/index.js +++ b/imports/startup/client/index.js @@ -1,5 +1,15 @@ +import { Meteor } from 'meteor/meteor'; +import React from 'react'; +import { render } from 'react-dom'; import { Bert } from 'meteor/themeteorchef:bert'; import 'bootstrap/dist/css/bootstrap.min.css'; -import './routes.js'; +import App from '../../ui/layouts/App.js'; Bert.defaults.style = 'growl-top-right'; + +Meteor.startup(() => { + render( + , + document.getElementById('react-root'), + ); +}); diff --git a/imports/startup/client/routes.js b/imports/startup/client/routes.js deleted file mode 100644 index 7664e448..00000000 --- a/imports/startup/client/routes.js +++ /dev/null @@ -1,37 +0,0 @@ -/* eslint-disable max-len */ - -import React from 'react'; -import { render } from 'react-dom'; -import { BrowserRouter as Router, Route, browserHistory } from 'react-router-dom'; -import { Meteor } from 'meteor/meteor'; -import App from '../../ui/layouts/App.js'; - - -const authenticate = (nextState, replace) => { - if (!Meteor.loggingIn() && !Meteor.userId()) { - replace({ - pathname: '/login', - state: { nextPathname: nextState.location.pathname }, - }); - } -}; - -Meteor.startup(() => { - render( - - - {/* - - - - - - - - - */} - - , - document.getElementById('react-root'), - ); -}); diff --git a/imports/ui/components/AppNavigation.js b/imports/ui/components/AppNavigation.js index 576165e3..0f72e92b 100644 --- a/imports/ui/components/AppNavigation.js +++ b/imports/ui/components/AppNavigation.js @@ -15,9 +15,7 @@ const AppNavigation = ({ hasUser }) => (
- { /*renderNavigation(hasUser)*/ } - Sign Up - Log In + { renderNavigation(hasUser) }
); diff --git a/imports/ui/components/AuthenticatedNavigation.js b/imports/ui/components/AuthenticatedNavigation.js index a38d8183..6e0aeacc 100644 --- a/imports/ui/components/AuthenticatedNavigation.js +++ b/imports/ui/components/AuthenticatedNavigation.js @@ -1,5 +1,5 @@ import React from 'react'; -import { browserHistory } from 'react-router-dom'; +import { BrowserRouter as Router, browserHistory, Link, Route, Redirect } from 'react-router-dom'; import { LinkContainer } from 'react-router-bootstrap'; import { Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap'; import { Meteor } from 'meteor/meteor'; @@ -12,7 +12,7 @@ const userName = () => { return user ? `${name.first} ${name.last}` : ''; }; -const AuthenticatedNavigation = () => ( +/* const AuthenticatedNavigation = () => (
+); */ + +const AuthenticatedNavigation = () => ( +
+ + +
); export default AuthenticatedNavigation; diff --git a/imports/ui/components/DocumentsList.js b/imports/ui/components/DocumentsList.js index 2c36e26b..765a15e8 100644 --- a/imports/ui/components/DocumentsList.js +++ b/imports/ui/components/DocumentsList.js @@ -1,21 +1,22 @@ import React from 'react'; -import { browserHistory } from 'react-router'; import { ListGroup, ListGroupItem, Alert } from 'react-bootstrap'; -const handleNav = (_id) => { - browserHistory.push(`/documents/${_id}`); -} +const handleNav = (history, _id) => { + history.push(`/documents/${_id}`); +}; -const DocumentsList = ({ documents }) => ( - documents.length > 0 ? - {documents.map(({ _id, title }) => ( - handleNav(_id) }> - { title } - - ))} - : - No documents yet. -); +const DocumentsList = ({ documents, history }) => { + return ( + documents.length > 0 ? + {documents.map(({ _id, title }) => ( + handleNav(history, _id) }> + { title } + + ))} + : + No documents yet. + ); +}; DocumentsList.propTypes = { documents: React.PropTypes.array, diff --git a/imports/ui/components/PublicNavigation.js b/imports/ui/components/PublicNavigation.js index a590f554..83fa4410 100644 --- a/imports/ui/components/PublicNavigation.js +++ b/imports/ui/components/PublicNavigation.js @@ -1,8 +1,9 @@ import React from 'react'; +import { Link } from 'react-router-dom'; import { LinkContainer } from 'react-router-bootstrap'; import { Nav, NavItem } from 'react-bootstrap'; -const PublicNavigation = () => ( +/* const PublicNavigation = () => ( +); */ + +/* const PublicNavigation = () => ( + +);*/ + +const PublicNavigation = () => ( +
+ Sign Up + Log In +
); export default PublicNavigation; diff --git a/imports/ui/containers/DocumentsList.js b/imports/ui/containers/DocumentsList.js index 27b4a57c..6ceb1b9c 100644 --- a/imports/ui/containers/DocumentsList.js +++ b/imports/ui/containers/DocumentsList.js @@ -3,11 +3,11 @@ import Documents from '../../api/documents/documents.js'; import DocumentsList from '../components/DocumentsList.js'; import composeWithTracker from '../../modules/compose-with-tracker'; -const composer = (params, onData) => { +const composer = (props, onData) => { const subscription = Meteor.subscribe('documents.list'); if (subscription.ready()) { const documents = Documents.find().fetch(); - onData(null, { documents }); + onData(null, { ...props, documents }); } }; diff --git a/imports/ui/containers/EditDocument.js b/imports/ui/containers/EditDocument.js index eb24311b..ff3b94d8 100644 --- a/imports/ui/containers/EditDocument.js +++ b/imports/ui/containers/EditDocument.js @@ -3,14 +3,13 @@ import Documents from '../../api/documents/documents.js'; import EditDocument from '../pages/EditDocument.js'; import composeWithTracker from '../../modules/compose-with-tracker'; -const composer = ({ params }, onData) => { - const subscription = Meteor.subscribe('documents.view', params._id); +const composer = (props, onData) => { + const subscription = Meteor.subscribe('documents.view', props.match.params._id); if (subscription.ready()) { - const doc = Documents.findOne(params._id); - onData(null, { doc }); + const doc = Documents.findOne(props.match.params._id); + onData(null, { ...props, doc }); } }; export default composeWithTracker(composer)(EditDocument); - diff --git a/imports/ui/containers/ViewDocument.js b/imports/ui/containers/ViewDocument.js index 1e64a85d..8d055ee6 100644 --- a/imports/ui/containers/ViewDocument.js +++ b/imports/ui/containers/ViewDocument.js @@ -3,12 +3,12 @@ import Documents from '../../api/documents/documents.js'; import ViewDocument from '../pages/ViewDocument.js'; import composeWithTracker from '../../modules/compose-with-tracker'; -const composer = ({ params }, onData) => { - const subscription = Meteor.subscribe('documents.view', params._id); +const composer = (props, onData) => { + const subscription = Meteor.subscribe('documents.view', props.match.params._id); if (subscription.ready()) { - const doc = Documents.findOne(params._id); - onData(null, { doc }); + const doc = Documents.findOne(props.match.params._id); + onData(null, { ...props, doc }); } }; diff --git a/imports/ui/layouts/App.js b/imports/ui/layouts/App.js index 0c1240d9..f2f5bd2a 100644 --- a/imports/ui/layouts/App.js +++ b/imports/ui/layouts/App.js @@ -2,8 +2,8 @@ import { Meteor } from 'meteor/meteor'; import React from 'react'; +import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; import { Grid } from 'react-bootstrap'; -import { Route } from 'react-router-dom'; import AppNavigation from '../containers/AppNavigation.js'; import EditDocument from '../containers/EditDocument.js'; import ViewDocument from '../containers/ViewDocument.js'; @@ -16,44 +16,47 @@ import RecoverPassword from '../pages/RecoverPassword.js'; import ResetPassword from '../pages/ResetPassword.js'; import Signup from '../pages/Signup.js'; -const authenticate = (nextState, replace) => { - /* if (!Meteor.loggingIn() && !Meteor.userId()) { - replace({ - pathname: '/login', - state: { nextPathname: nextState.location.pathname }, - }); - } */ -}; - -const App = ({ children }) => ( -
- - - { children } - +const authenticate = (props, component) => { + if (!Meteor.loggingIn() && !Meteor.userId()) { + props.history.push('/login'); + } - - + return component; +}; - {/* - - - - - - - - - */} -
-); +const logout = (history) => { + Meteor.logout((error) => { + if (error) { + console.log(`Error: ${error}`); + return
Logout Failed
; + } -App.defaultProps = { - children: null, + history.push('/'); + return null; + }); }; -App.propTypes = { - children: React.PropTypes.node, -}; +const App = () => ( + +
+ + + + ()} /> + (authenticate(props, ))} /> + (authenticate(props, ))} /> + (authenticate(props, ))} /> + (authenticate(props, ))} /> + ()} /> + (logout(history))} /> + ()} /> + ()} /> + ()} /> + ()} /> + + +
+
+); export default App; diff --git a/imports/ui/pages/Documents.js b/imports/ui/pages/Documents.js index 7914748a..29a3ef84 100644 --- a/imports/ui/pages/Documents.js +++ b/imports/ui/pages/Documents.js @@ -1,30 +1,27 @@ import React from 'react'; -import { Link } from 'react-router'; +import { Link } from 'react-router-dom'; import { Row, Col, Button, Jumbotron } from 'react-bootstrap'; import DocumentsList from '../containers/DocumentsList.js'; -const Documents = ({ match }) => ( -
- -

Document List

-

I should render a document list.

-
- {/* - - -
-

Documents

- - - -
- - -
*/} -
-); +const Documents = (props) => { + return ( +
+ + +
+

Documents

+ + + +
+ + +
+
+ ); +}; export default Documents; diff --git a/imports/ui/pages/EditDocument.js b/imports/ui/pages/EditDocument.js index c736d6bf..4b4c78e4 100644 --- a/imports/ui/pages/EditDocument.js +++ b/imports/ui/pages/EditDocument.js @@ -2,11 +2,11 @@ import React from 'react'; import DocumentEditor from '../components/DocumentEditor'; import NotFound from './NotFound'; -const EditDocument = ({ doc }) => { - return doc ? ( +const EditDocument = (props) => { + return props.doc ? (
-

Editing "{ doc.title }"

- +

Editing "{ props.doc.title }"

+
) : ; }; diff --git a/imports/ui/pages/Login.js b/imports/ui/pages/Login.js index dfaaefe1..5cca8735 100644 --- a/imports/ui/pages/Login.js +++ b/imports/ui/pages/Login.js @@ -1,5 +1,5 @@ import React from 'react'; -import { Link } from 'react-router'; +import { Link } from 'react-router-dom'; import { Row, Col, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap'; import handleLogin from '../../modules/login'; @@ -16,12 +16,12 @@ export default class Login extends React.Component { return (
- +

Login

(this.loginForm = form) } + ref={form => (this.loginForm = form)} className="login" - onSubmit={ this.handleSubmit } + onSubmit={this.handleSubmit} > Email Address diff --git a/imports/ui/pages/NewDocument.js b/imports/ui/pages/NewDocument.js index 05c5795e..4dff6912 100644 --- a/imports/ui/pages/NewDocument.js +++ b/imports/ui/pages/NewDocument.js @@ -1,10 +1,10 @@ import React from 'react'; import DocumentEditor from '../components/DocumentEditor.js'; -const NewDocument = () => ( +const NewDocument = (props) => (

New Document

- +
); diff --git a/imports/ui/pages/Signup.js b/imports/ui/pages/Signup.js index 8895e3e6..3b99baba 100644 --- a/imports/ui/pages/Signup.js +++ b/imports/ui/pages/Signup.js @@ -1,5 +1,5 @@ import React from 'react'; -import { Link } from 'react-router'; +import { Link } from 'react-router-dom'; import { Row, Col, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap'; import handleSignup from '../../modules/signup'; diff --git a/imports/ui/pages/ViewDocument.js b/imports/ui/pages/ViewDocument.js index 21d29c6a..18071a74 100644 --- a/imports/ui/pages/ViewDocument.js +++ b/imports/ui/pages/ViewDocument.js @@ -1,36 +1,35 @@ import React from 'react'; import { ButtonToolbar, ButtonGroup, Button } from 'react-bootstrap'; -import { browserHistory } from 'react-router'; import { Bert } from 'meteor/themeteorchef:bert'; import { removeDocument } from '../../api/documents/methods'; import NotFound from './NotFound'; -const handleEdit = (_id) => { - browserHistory.push(`/documents/${_id}/edit`); +const handleEdit = (history, _id) => { + history.push(`/documents/${_id}/edit`); }; -const handleRemove = (_id) => { +const handleRemove = (history, _id) => { if (confirm('Are you sure? This is permanent!')) { removeDocument.call({ _id }, (error) => { if (error) { Bert.alert(error.reason, 'danger'); } else { Bert.alert('Document deleted!', 'success'); - browserHistory.push('/documents'); + history.push('/documents'); } }); } }; -const ViewDocument = ({ doc }) => { +const ViewDocument = ({ history, doc }) => { return doc ? (

{ doc && doc.title }

- - + +
diff --git a/package.json b/package.json index 78b36331..5b90ba48 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "jquery": "^3.2.1", "jquery-validation": "^1.16.0", "meteor-node-stubs": "^0.2.6", + "prop-types": "^15.5.8", "react": "^15.5.4", "react-addons-pure-render-mixin": "^15.5.2", "react-bootstrap": "^0.30.8", From 7c788b08ea2105b3cbb761b8c152cdc2d0900b73 Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 18 Apr 2017 22:19:40 -0300 Subject: [PATCH 04/10] Implemented PrivateRoute module to replace authenticate function Polished ract-router v4 integration Using ProprTypes from prop-types modules since deprecation from React Added some global overrides to eslint config file --- .eslintrc.json | 4 ++ imports/modules/compose-with-tracker.js | 1 - imports/modules/document-editor.js | 4 +- imports/modules/private-route.js | 36 ++++++++++++ imports/modules/reset-password.js | 7 +-- imports/ui/components/AppNavigation.js | 5 +- imports/ui/components/DocumentEditor.js | 69 +++++++++++++---------- imports/ui/components/DocumentsList.js | 35 ++++++------ imports/ui/components/Error.js | 11 ++-- imports/ui/containers/DocumentsList.js | 2 +- imports/ui/containers/EditDocument.js | 4 +- imports/ui/containers/ViewDocument.js | 2 +- imports/ui/layouts/App.js | 73 +++++++++---------------- imports/ui/pages/Documents.js | 40 +++++++------- imports/ui/pages/EditDocument.js | 18 +++--- imports/ui/pages/Login.js | 8 ++- imports/ui/pages/Logout.js | 38 +++++++++++++ imports/ui/pages/NewDocument.js | 4 +- imports/ui/pages/NotFound.js | 16 +++++- imports/ui/pages/RecoverPassword.js | 12 ++-- imports/ui/pages/ResetPassword.js | 23 +++++--- imports/ui/pages/Signup.js | 14 +++-- imports/ui/pages/ViewDocument.js | 24 +++++--- 23 files changed, 273 insertions(+), 177 deletions(-) create mode 100644 imports/modules/private-route.js create mode 100644 imports/ui/pages/Logout.js diff --git a/.eslintrc.json b/.eslintrc.json index 76bc720a..91df3274 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -54,5 +54,9 @@ }, "settings": { "import/resolver": "meteor" + }, + "globals": { + "window": true, + "document": true } } diff --git a/imports/modules/compose-with-tracker.js b/imports/modules/compose-with-tracker.js index 475e3c19..c95f5406 100644 --- a/imports/modules/compose-with-tracker.js +++ b/imports/modules/compose-with-tracker.js @@ -9,7 +9,6 @@ const getTrackerLoader = reactiveMapper => ( let trackerCleanup = null; const handler = Tracker.nonreactive(() => Tracker.autorun(() => { - // assign the custom clean-up function. trackerCleanup = reactiveMapper(props, onData, env); }), ); diff --git a/imports/modules/document-editor.js b/imports/modules/document-editor.js index 81799662..d5c09bd2 100644 --- a/imports/modules/document-editor.js +++ b/imports/modules/document-editor.js @@ -39,10 +39,10 @@ const validate = () => { }, messages: { title: { - required: 'Need a title in here, Seuss.', + required: 'Need a title in here, thanks!.', }, body: { - required: 'This thneeds a body, please.', + required: 'This needs a body, please.', }, }, submitHandler() { handleUpsert(); }, diff --git a/imports/modules/private-route.js b/imports/modules/private-route.js new file mode 100644 index 00000000..53e2011a --- /dev/null +++ b/imports/modules/private-route.js @@ -0,0 +1,36 @@ +import { Meteor } from 'meteor/meteor'; +import React from 'react'; +import { Route, Redirect } from 'react-router-dom'; +import { PropTypes } from 'prop-types'; + +const PrivateRoute = ({ component: Component, ...rest }) => ( + ( + (!Meteor.loggingIn() && !Meteor.userId()) ? ( + + ) : ( + + ) + )} + /> +); + +PrivateRoute.defaultProps = { + location: null, +}; + +PrivateRoute.propTypes = { + component: PropTypes.oneOfType([ + PropTypes.element, + PropTypes.func, + ]).isRequired, + location: PropTypes.object, +}; + +export default PrivateRoute; diff --git a/imports/modules/reset-password.js b/imports/modules/reset-password.js index 600b93f3..d010804a 100644 --- a/imports/modules/reset-password.js +++ b/imports/modules/reset-password.js @@ -5,15 +5,15 @@ import { Bert } from 'meteor/themeteorchef:bert'; import './validation.js'; let component; -let token; const handleReset = () => { + const { history, match } = component.props; const password = document.querySelector('[name="newPassword"]').value; - Accounts.resetPassword(token, password, (error) => { + + Accounts.resetPassword(match.params.token, password, (error) => { if (error) { Bert.alert(error.reason, 'danger'); } else { - const { history } = component.props; history.push('/'); Bert.alert('Password reset!', 'success'); } @@ -49,6 +49,5 @@ const validate = () => { export default function handleResetPassword(options) { component = options.component; - token = options.token; validate(); } diff --git a/imports/ui/components/AppNavigation.js b/imports/ui/components/AppNavigation.js index 0f72e92b..e86bdea8 100644 --- a/imports/ui/components/AppNavigation.js +++ b/imports/ui/components/AppNavigation.js @@ -1,6 +1,7 @@ import React from 'react'; -import { Navbar, Nav, NavItem } from 'react-bootstrap'; +import { Navbar } from 'react-bootstrap'; import { Link } from 'react-router-dom'; +import { PropTypes } from 'prop-types'; import PublicNavigation from './PublicNavigation.js'; import AuthenticatedNavigation from './AuthenticatedNavigation.js'; @@ -21,7 +22,7 @@ const AppNavigation = ({ hasUser }) => ( ); AppNavigation.propTypes = { - hasUser: React.PropTypes.object, + hasUser: PropTypes.object, }; export default AppNavigation; diff --git a/imports/ui/components/DocumentEditor.js b/imports/ui/components/DocumentEditor.js index 94f0ac6b..dbb78878 100644 --- a/imports/ui/components/DocumentEditor.js +++ b/imports/ui/components/DocumentEditor.js @@ -1,10 +1,12 @@ /* eslint-disable max-len, no-return-assign */ -import React from 'react'; +import React, { Component } from 'react'; import { FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap'; +import { withRouter } from 'react-router-dom'; +import { PropTypes } from 'prop-types'; import documentEditor from '../../modules/document-editor.js'; -export default class DocumentEditor extends React.Component { +class DocumentEditor extends Component { componentDidMount() { documentEditor({ component: this }); setTimeout(() => { document.querySelector('[name="title"]').focus(); }, 0); @@ -12,35 +14,44 @@ export default class DocumentEditor extends React.Component { render() { const { doc } = this.props; - return ( (this.documentEditorForm = form) } - onSubmit={ event => event.preventDefault() } - > - - Title - - - - Body - - - - ); + + return ( +
(this.documentEditorForm = form)} + onSubmit={event => event.preventDefault()} + > + + Title + + + + Body + + + +
+ ); } } +DocumentEditor.defaultProps = { + doc: null, +}; + DocumentEditor.propTypes = { - doc: React.PropTypes.object, + doc: PropTypes.object, }; + +export default withRouter(DocumentEditor); diff --git a/imports/ui/components/DocumentsList.js b/imports/ui/components/DocumentsList.js index 765a15e8..70d97027 100644 --- a/imports/ui/components/DocumentsList.js +++ b/imports/ui/components/DocumentsList.js @@ -1,25 +1,28 @@ import React from 'react'; import { ListGroup, ListGroupItem, Alert } from 'react-bootstrap'; +import { withRouter } from 'react-router-dom'; +import { PropTypes } from 'prop-types'; + +const DocumentsList = ({ documents, history }) => ( + documents.length > 0 ? + {documents.map(({ _id, title }) => ( + history.push(`/documents/${_id}`)}> + { title } + + ))} + : + No documents yet. +); -const handleNav = (history, _id) => { - history.push(`/documents/${_id}`); -}; -const DocumentsList = ({ documents, history }) => { - return ( - documents.length > 0 ? - {documents.map(({ _id, title }) => ( - handleNav(history, _id) }> - { title } - - ))} - : - No documents yet. - ); +DocumentsList.defaultProps = { + documents: [], + history: null, }; DocumentsList.propTypes = { - documents: React.PropTypes.array, + documents: PropTypes.array, + history: PropTypes.object, }; -export default DocumentsList; +export default withRouter(DocumentsList); diff --git a/imports/ui/components/Error.js b/imports/ui/components/Error.js index e151f291..2ed43206 100644 --- a/imports/ui/components/Error.js +++ b/imports/ui/components/Error.js @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import { PropTypes } from 'prop-types'; const Error = ({ error }) => (

@@ -6,12 +7,12 @@ const Error = ({ error }) => (

); -Error.propTypes = { - error: PropTypes.object, -}; - Error.defaultProps = { error: { message: '' }, }; +Error.propTypes = { + error: PropTypes.object, +}; + export default Error; diff --git a/imports/ui/containers/DocumentsList.js b/imports/ui/containers/DocumentsList.js index 6ceb1b9c..14fa9af1 100644 --- a/imports/ui/containers/DocumentsList.js +++ b/imports/ui/containers/DocumentsList.js @@ -7,7 +7,7 @@ const composer = (props, onData) => { const subscription = Meteor.subscribe('documents.list'); if (subscription.ready()) { const documents = Documents.find().fetch(); - onData(null, { ...props, documents }); + onData(null, { documents }); } }; diff --git a/imports/ui/containers/EditDocument.js b/imports/ui/containers/EditDocument.js index ff3b94d8..fc3d0652 100644 --- a/imports/ui/containers/EditDocument.js +++ b/imports/ui/containers/EditDocument.js @@ -7,8 +7,8 @@ const composer = (props, onData) => { const subscription = Meteor.subscribe('documents.view', props.match.params._id); if (subscription.ready()) { - const doc = Documents.findOne(props.match.params._id); - onData(null, { ...props, doc }); + const document = Documents.findOne(props.match.params._id); + onData(null, { document }); } }; diff --git a/imports/ui/containers/ViewDocument.js b/imports/ui/containers/ViewDocument.js index 8d055ee6..298b72a3 100644 --- a/imports/ui/containers/ViewDocument.js +++ b/imports/ui/containers/ViewDocument.js @@ -8,7 +8,7 @@ const composer = (props, onData) => { if (subscription.ready()) { const doc = Documents.findOne(props.match.params._id); - onData(null, { ...props, doc }); + onData(null, { doc }); } }; diff --git a/imports/ui/layouts/App.js b/imports/ui/layouts/App.js index f2f5bd2a..c9e6a4da 100644 --- a/imports/ui/layouts/App.js +++ b/imports/ui/layouts/App.js @@ -1,62 +1,43 @@ /* eslint-disable max-len */ -import { Meteor } from 'meteor/meteor'; import React from 'react'; -import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; +import { BrowserRouter, Route, Switch } from 'react-router-dom'; import { Grid } from 'react-bootstrap'; -import AppNavigation from '../containers/AppNavigation.js'; -import EditDocument from '../containers/EditDocument.js'; -import ViewDocument from '../containers/ViewDocument.js'; -import Documents from '../pages/Documents.js'; -import NewDocument from '../pages/NewDocument.js'; -import Index from '../pages/Index.js'; -import Login from '../pages/Login.js'; -import NotFound from '../pages/NotFound.js'; -import RecoverPassword from '../pages/RecoverPassword.js'; -import ResetPassword from '../pages/ResetPassword.js'; -import Signup from '../pages/Signup.js'; - -const authenticate = (props, component) => { - if (!Meteor.loggingIn() && !Meteor.userId()) { - props.history.push('/login'); - } - - return component; -}; - -const logout = (history) => { - Meteor.logout((error) => { - if (error) { - console.log(`Error: ${error}`); - return
Logout Failed
; - } - - history.push('/'); - return null; - }); -}; +import PrivateRoute from '../../modules/private-route'; +import AppNavigation from '../containers/AppNavigation'; +import EditDocument from '../containers/EditDocument'; +import ViewDocument from '../containers/ViewDocument'; +import Documents from '../pages/Documents'; +import NewDocument from '../pages/NewDocument'; +import Index from '../pages/Index'; +import Login from '../pages/Login'; +import Logout from '../pages/Logout'; +import NotFound from '../pages/NotFound'; +import RecoverPassword from '../pages/RecoverPassword'; +import ResetPassword from '../pages/ResetPassword'; +import Signup from '../pages/Signup'; const App = () => ( - +
- ()} /> - (authenticate(props, ))} /> - (authenticate(props, ))} /> - (authenticate(props, ))} /> - (authenticate(props, ))} /> - ()} /> - (logout(history))} /> - ()} /> - ()} /> - ()} /> - ()} /> + + + + + + + + + + +
-
+ ); export default App; diff --git a/imports/ui/pages/Documents.js b/imports/ui/pages/Documents.js index 29a3ef84..9dfa2b2b 100644 --- a/imports/ui/pages/Documents.js +++ b/imports/ui/pages/Documents.js @@ -1,27 +1,25 @@ import React from 'react'; import { Link } from 'react-router-dom'; -import { Row, Col, Button, Jumbotron } from 'react-bootstrap'; +import { Row, Col, Button } from 'react-bootstrap'; import DocumentsList from '../containers/DocumentsList.js'; -const Documents = (props) => { - return ( -
- - -
-

Documents

- - - -
- - -
-
- ); -}; +const Documents = () => ( +
+ + +
+

Documents

+ + + +
+ + +
+
+); export default Documents; diff --git a/imports/ui/pages/EditDocument.js b/imports/ui/pages/EditDocument.js index 4b4c78e4..4bf5424f 100644 --- a/imports/ui/pages/EditDocument.js +++ b/imports/ui/pages/EditDocument.js @@ -1,18 +1,16 @@ import React from 'react'; +import { PropTypes } from 'prop-types'; import DocumentEditor from '../components/DocumentEditor'; -import NotFound from './NotFound'; -const EditDocument = (props) => { - return props.doc ? ( -
-

Editing "{ props.doc.title }"

- -
- ) : ; -}; +const EditDocument = ({ document }) => ( +
+

Editing "{document.title}"

+ +
+); EditDocument.propTypes = { - doc: React.PropTypes.object, + document: PropTypes.object.isRequired, }; export default EditDocument; diff --git a/imports/ui/pages/Login.js b/imports/ui/pages/Login.js index 5cca8735..45f86c8d 100644 --- a/imports/ui/pages/Login.js +++ b/imports/ui/pages/Login.js @@ -1,9 +1,9 @@ -import React from 'react'; -import { Link } from 'react-router-dom'; +import React, { Component } from 'react'; +import { Link, withRouter } from 'react-router-dom'; import { Row, Col, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap'; import handleLogin from '../../modules/login'; -export default class Login extends React.Component { +class Login extends Component { componentDidMount() { handleLogin({ component: this }); } @@ -52,3 +52,5 @@ export default class Login extends React.Component { ); } } + +export default withRouter(Login); diff --git a/imports/ui/pages/Logout.js b/imports/ui/pages/Logout.js new file mode 100644 index 00000000..7a5eda58 --- /dev/null +++ b/imports/ui/pages/Logout.js @@ -0,0 +1,38 @@ +import { Meteor } from 'meteor/meteor'; +import React from 'react'; +import { Route, Redirect } from 'react-router-dom'; +import { PropTypes } from 'prop-types'; + +const Logout = ({ ...rest }) => { + Meteor.logout((error) => { + if (error) { + return
Logout Failed - Error: {error}
; + } + + return true; + }); + + return ( + ( + + )} + /> + ); +}; + +Logout.defaultProps = { + location: null, +}; + +Logout.propTypes = { + location: PropTypes.object, +}; + +export default Logout; diff --git a/imports/ui/pages/NewDocument.js b/imports/ui/pages/NewDocument.js index 4dff6912..05c5795e 100644 --- a/imports/ui/pages/NewDocument.js +++ b/imports/ui/pages/NewDocument.js @@ -1,10 +1,10 @@ import React from 'react'; import DocumentEditor from '../components/DocumentEditor.js'; -const NewDocument = (props) => ( +const NewDocument = () => (

New Document

- +
); diff --git a/imports/ui/pages/NotFound.js b/imports/ui/pages/NotFound.js index 260a2fbe..205567fe 100644 --- a/imports/ui/pages/NotFound.js +++ b/imports/ui/pages/NotFound.js @@ -1,12 +1,22 @@ import React from 'react'; import { Alert } from 'react-bootstrap'; +import { withRouter } from 'react-router-dom'; +import { PropTypes } from 'prop-types'; -const NotFound = () => ( +const NotFound = ({ location }) => (
-

Error [404]: { window.location.pathname } does not exist.

+

Error [404]: {location.pathname} does not exist.

); -export default NotFound; +NotFound.defaultProps = { + location: null, +}; + +NotFound.propTypes = { + location: PropTypes.object, +}; + +export default withRouter(NotFound); diff --git a/imports/ui/pages/RecoverPassword.js b/imports/ui/pages/RecoverPassword.js index 8562a568..bee5768c 100644 --- a/imports/ui/pages/RecoverPassword.js +++ b/imports/ui/pages/RecoverPassword.js @@ -1,8 +1,8 @@ -import React from 'react'; +import React, { Component } from 'react'; import { Row, Col, Alert, FormGroup, FormControl, Button } from 'react-bootstrap'; import handleRecoverPassword from '../../modules/recover-password'; -export default class RecoverPassword extends React.Component { +class RecoverPassword extends Component { componentDidMount() { handleRecoverPassword({ component: this }); } @@ -15,15 +15,15 @@ export default class RecoverPassword extends React.Component { return (
- +

Recover Password

Enter your email address below to receive a link to reset your password.
(this.recoverPasswordForm = form) } + ref={form => (this.recoverPasswordForm = form)} className="recover-password" - onSubmit={ this.handleSubmit } + onSubmit={this.handleSubmit} > - +

Reset Password

- To reset your password, enter a new one below. You will be logged in - with your new password. + To reset your password, enter a new one below. You will be logged in with your new password. (this.resetPasswordForm = form) } + ref={form => (this.resetPasswordForm = form)} className="reset-password" - onSubmit={ this.handleSubmit } + onSubmit={this.handleSubmit} > New Password @@ -54,5 +57,7 @@ export default class ResetPassword extends React.Component { } ResetPassword.propTypes = { - params: React.PropTypes.object, + match: PropTypes.object.isRequired, }; + +export default withRouter(ResetPassword); diff --git a/imports/ui/pages/Signup.js b/imports/ui/pages/Signup.js index 3b99baba..82e285dd 100644 --- a/imports/ui/pages/Signup.js +++ b/imports/ui/pages/Signup.js @@ -1,9 +1,9 @@ -import React from 'react'; -import { Link } from 'react-router-dom'; +import React, { Component } from 'react'; +import { Link, withRouter } from 'react-router-dom'; import { Row, Col, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap'; import handleSignup from '../../modules/signup'; -export default class Signup extends React.Component { +class Signup extends Component { componentDidMount() { handleSignup({ component: this }); } @@ -16,14 +16,14 @@ export default class Signup extends React.Component { return (
- +

Sign Up

(this.signupForm = form) } onSubmit={ this.handleSubmit } > - + First Name - + Last Name { - history.push(`/documents/${_id}/edit`); -}; - const handleRemove = (history, _id) => { if (confirm('Are you sure? This is permanent!')) { removeDocument.call({ _id }, (error) => { @@ -21,25 +19,33 @@ const handleRemove = (history, _id) => { } }; -const ViewDocument = ({ history, doc }) => { - return doc ? ( +const ViewDocument = ({ doc, history }) => ( + doc ? (

{ doc && doc.title }

- +
{ doc && doc.body }
- ) : ; + ) : ( + + ) +); + +ViewDocument.defaultProps = { + doc: null, + history: null, }; ViewDocument.propTypes = { doc: React.PropTypes.object, + history: PropTypes.object, }; -export default ViewDocument; +export default withRouter(ViewDocument); From d14321b816ac2b9a71e2410712488117a73c65fe Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 18 Apr 2017 22:44:09 -0300 Subject: [PATCH 05/10] Logout must redirect only --- imports/ui/pages/Logout.js | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/imports/ui/pages/Logout.js b/imports/ui/pages/Logout.js index 7a5eda58..736cea36 100644 --- a/imports/ui/pages/Logout.js +++ b/imports/ui/pages/Logout.js @@ -13,17 +13,7 @@ const Logout = ({ ...rest }) => { }); return ( - ( - - )} - /> + ()} /> ); }; From f790691944ee6c30a184667484ebcc5ac8602aab Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 19 Apr 2017 21:45:53 -0300 Subject: [PATCH 06/10] Sync with base 4.15.0 --- .gitignore | 4 +-- .meteor/packages | 27 +++++++++++--------- .meteor/versions | 34 +++++++++++-------------- LICENSE.md | 11 ++++++++ README.md | 4 +-- imports/api/documents/documents.js | 2 +- imports/api/documents/methods.js | 2 +- imports/modules/compose-with-tracker.js | 33 ------------------------ imports/modules/container.js | 6 +++++ imports/modules/get-tracker-loader.js | 20 +++++++++++++++ imports/ui/components/AppNavigation.js | 11 +++++--- imports/ui/components/DocumentsList.js | 14 ++++++++-- imports/ui/components/Error.js | 18 ------------- imports/ui/containers/AppNavigation.js | 8 ------ imports/ui/containers/DocumentsList.js | 15 ----------- imports/ui/containers/EditDocument.js | 15 ----------- imports/ui/containers/ViewDocument.js | 16 ------------ imports/ui/layouts/App.js | 6 ++--- imports/ui/pages/Documents.js | 2 +- imports/ui/pages/EditDocument.js | 27 +++++++++++++++----- imports/ui/pages/NotFound.js | 16 +++--------- imports/ui/pages/ViewDocument.js | 15 ++++++++++- package.json | 27 ++++++++++---------- 23 files changed, 148 insertions(+), 185 deletions(-) create mode 100644 LICENSE.md delete mode 100644 imports/modules/compose-with-tracker.js create mode 100644 imports/modules/container.js create mode 100644 imports/modules/get-tracker-loader.js delete mode 100644 imports/ui/components/Error.js delete mode 100644 imports/ui/containers/AppNavigation.js delete mode 100644 imports/ui/containers/DocumentsList.js delete mode 100644 imports/ui/containers/EditDocument.js delete mode 100644 imports/ui/containers/ViewDocument.js diff --git a/.gitignore b/.gitignore index 9ef033f6..cde5f439 100644 --- a/.gitignore +++ b/.gitignore @@ -7,13 +7,11 @@ settings-production.json # IntelliJ # -build/ -local/ .idea # node.js # -node_modules/ +node_modules npm-debug.log yarn-error.log diff --git a/.meteor/packages b/.meteor/packages index 91f5682e..d151087f 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -8,26 +8,29 @@ meteor-base@1.0.4 # Packages every Meteor app needs to have mobile-experience@1.0.4 # Packages for a great mobile UX mongo@1.1.16 # The database Meteor supports right now reactive-var@1.0.11 # Reactive variable for tracker -tracker # Meteor's client-side reactive programming library +session@1.1.7 +tracker@1.1.2 # Meteor's client-side reactive programming library + standard-minifier-css@1.3.4 # CSS minifier run for production mode standard-minifier-js@2.0.0 # JS minifier run for production mode es5-shim@4.6.15 # ECMAScript 5 compatibility for older browsers. ecmascript@0.7.2 # Enable ECMAScript2015+ syntax in app code -shell-server@0.2.3 # Server-side component of the `meteor shell` command -accounts-password -accounts-base -check -audit-argument-checks -browser-policy -fourseven:scss -aldeed:collection2 +accounts-password@1.3.5 +accounts-base@1.2.16 +check@1.2.5 +audit-argument-checks@1.0.7 +browser-policy@1.1.0 + +fourseven:scss@4.5.0 alanning:roles themeteorchef:bert -static-html +static-html@1.1.11 xolvio:cleaner practicalmeteor:mocha xolvio:backdoor mdg:validated-method -dburles:factory -ddp-rate-limiter +dburles:factory@1.0.0 +ddp-rate-limiter@1.0.7 +shell-server@0.2.3 +aldeed:collection2-core@2.0.0 diff --git a/.meteor/versions b/.meteor/versions index 21f4b2e9..e73eb94f 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -1,15 +1,11 @@ accounts-base@1.2.16 accounts-password@1.3.5 alanning:roles@1.2.16 -aldeed:collection2@2.10.0 -aldeed:collection2-core@1.2.0 -aldeed:schema-deny@1.1.0 -aldeed:schema-index@1.1.1 -aldeed:simple-schema@1.5.3 +aldeed:collection2-core@2.0.0 allow-deny@1.0.5 audit-argument-checks@1.0.7 autoupdate@1.3.12 -babel-compiler@6.18.1 +babel-compiler@6.18.2 babel-runtime@1.0.1 base64@1.0.10 binary-heap@1.0.10 @@ -21,7 +17,7 @@ browser-policy-common@1.0.11 browser-policy-content@1.1.0 browser-policy-framing@1.1.0 caching-compiler@1.1.9 -caching-html-compiler@1.1.0 +caching-html-compiler@1.1.2 callback-hook@1.0.10 check@1.2.5 coffeescript@1.12.3_1 @@ -33,10 +29,10 @@ ddp-rate-limiter@1.0.7 ddp-server@1.3.14 deps@1.0.12 diff-sequence@1.0.7 -ecmascript@0.7.2 +ecmascript@0.7.3 ecmascript-runtime@0.3.15 ejson@1.0.13 -email@1.2.0 +email@1.2.1 es5-shim@4.6.15 fastclick@1.0.13 fortawesome:fontawesome@4.7.0 @@ -53,7 +49,6 @@ livedata@1.0.18 localstorage@1.0.12 logging@1.1.17 mdg:validated-method@1.1.0 -mdg:validation-error@0.5.1 meteor@1.6.1 meteor-base@1.0.4 minifier-css@1.2.16 @@ -61,7 +56,7 @@ minifier-js@2.0.0 minimongo@1.0.21 mobile-experience@1.0.4 mobile-status-bar@1.0.14 -modules@0.8.1 +modules@0.8.2 modules-runtime@0.7.10 mongo@1.1.16 mongo-id@1.0.6 @@ -87,20 +82,21 @@ service-configuration@1.0.11 session@1.1.7 sha@1.0.9 shell-server@0.2.3 -spacebars@1.0.13 -spacebars-compiler@1.1.1 +spacebars@1.0.15 +spacebars-compiler@1.1.2 srp@1.0.10 standard-minifier-css@1.3.4 standard-minifier-js@2.0.0 -static-html@1.2.0 -templating@1.3.0 -templating-compiler@1.3.0 -templating-runtime@1.3.0 -templating-tools@1.1.1 +static-html@1.2.2 +templating@1.3.2 +templating-compiler@1.3.2 +templating-runtime@1.3.2 +templating-tools@1.1.2 themeteorchef:bert@2.1.2 +tmeasday:check-npm-versions@0.3.1 tmeasday:test-reporter-helpers@0.2.1 tracker@1.1.2 -ui@1.0.12 +ui@1.0.13 underscore@1.0.10 url@1.1.0 webapp@1.3.15 diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 00000000..a043f11c --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,11 @@ +MIT + +--- + +Copyright (c) 2014-2017 The Meteor Chef + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index b57f0053..f04512d6 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,11 @@ A starting point for Meteor apps. Base Version - v4.14.0 + v4.15.0 Meteor Version - v1.4.3.2 + v1.4.4.1 diff --git a/imports/api/documents/documents.js b/imports/api/documents/documents.js index 58c3ae4c..c280dc98 100644 --- a/imports/api/documents/documents.js +++ b/imports/api/documents/documents.js @@ -1,5 +1,5 @@ import { Mongo } from 'meteor/mongo'; -import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +import SimpleSchema from 'simpl-schema'; import { Factory } from 'meteor/dburles:factory'; const Documents = new Mongo.Collection('Documents'); diff --git a/imports/api/documents/methods.js b/imports/api/documents/methods.js index 0ded4d74..7468c6e4 100644 --- a/imports/api/documents/methods.js +++ b/imports/api/documents/methods.js @@ -1,4 +1,4 @@ -import { SimpleSchema } from 'meteor/aldeed:simple-schema'; +import SimpleSchema from 'simpl-schema'; import { ValidatedMethod } from 'meteor/mdg:validated-method'; import Documents from './documents'; import rateLimit from '../../modules/rate-limit.js'; diff --git a/imports/modules/compose-with-tracker.js b/imports/modules/compose-with-tracker.js deleted file mode 100644 index c95f5406..00000000 --- a/imports/modules/compose-with-tracker.js +++ /dev/null @@ -1,33 +0,0 @@ -import { Tracker } from 'meteor/tracker'; -import { compose } from 'react-komposer'; -import React from 'react'; -import Loading from '../ui/components/Loading'; -import Error from '../ui/components/Error'; - -const getTrackerLoader = reactiveMapper => ( - (props, onData, env) => { - let trackerCleanup = null; - const handler = Tracker.nonreactive(() => - Tracker.autorun(() => { - trackerCleanup = reactiveMapper(props, onData, env); - }), - ); - - return () => { - if (typeof trackerCleanup === 'function') trackerCleanup(); - return handler.stop(); - }; - } -); - -const composeWithTracker = (data, pure = true) => { - const composeOptions = { - pure, - loadingHandler: () => , - errorHandler: error => , - }; - - return compose(getTrackerLoader(data), composeOptions); -}; - -export default composeWithTracker; diff --git a/imports/modules/container.js b/imports/modules/container.js new file mode 100644 index 00000000..e3f9702d --- /dev/null +++ b/imports/modules/container.js @@ -0,0 +1,6 @@ +import { compose } from 'react-komposer'; +import getTrackerLoader from './get-tracker-loader'; + +export default function container(composer, Component, options = {}) { + return compose(getTrackerLoader(composer), options)(Component); +} diff --git a/imports/modules/get-tracker-loader.js b/imports/modules/get-tracker-loader.js new file mode 100644 index 00000000..d58d3535 --- /dev/null +++ b/imports/modules/get-tracker-loader.js @@ -0,0 +1,20 @@ +import { Tracker } from 'meteor/tracker'; + +const getTrackerLoader = reactiveMapper => ( + (props, onData, env) => { + let trackerCleanup = null; + + const handler = Tracker.nonreactive(() => + Tracker.autorun(() => { + trackerCleanup = reactiveMapper(props, onData, env); + }), + ); + + return () => { + if (typeof trackerCleanup === 'function') trackerCleanup(); + return handler.stop(); + }; + } +); + +export default getTrackerLoader; diff --git a/imports/ui/components/AppNavigation.js b/imports/ui/components/AppNavigation.js index e86bdea8..4b2658fe 100644 --- a/imports/ui/components/AppNavigation.js +++ b/imports/ui/components/AppNavigation.js @@ -1,9 +1,11 @@ +import { Meteor } from 'meteor/meteor'; import React from 'react'; import { Navbar } from 'react-bootstrap'; import { Link } from 'react-router-dom'; import { PropTypes } from 'prop-types'; import PublicNavigation from './PublicNavigation.js'; import AuthenticatedNavigation from './AuthenticatedNavigation.js'; +import container from '../../modules/container'; const renderNavigation = hasUser => (hasUser ? : ); @@ -15,9 +17,9 @@ const AppNavigation = ({ hasUser }) => ( -
+ { renderNavigation(hasUser) } -
+ ); @@ -25,4 +27,7 @@ AppNavigation.propTypes = { hasUser: PropTypes.object, }; -export default AppNavigation; +export default container((props, onData) => { + onData(null, { hasUser: Meteor.user() }); +}, AppNavigation); + diff --git a/imports/ui/components/DocumentsList.js b/imports/ui/components/DocumentsList.js index 70d97027..ed10fa47 100644 --- a/imports/ui/components/DocumentsList.js +++ b/imports/ui/components/DocumentsList.js @@ -1,7 +1,11 @@ +import { Meteor } from 'meteor/meteor'; import React from 'react'; import { ListGroup, ListGroupItem, Alert } from 'react-bootstrap'; import { withRouter } from 'react-router-dom'; import { PropTypes } from 'prop-types'; +import Documents from '../../api/documents/documents'; +import container from '../../modules/container'; +import Loading from '../components/Loading'; const DocumentsList = ({ documents, history }) => ( documents.length > 0 ? @@ -14,7 +18,6 @@ const DocumentsList = ({ documents, history }) => ( No documents yet. ); - DocumentsList.defaultProps = { documents: [], history: null, @@ -25,4 +28,11 @@ DocumentsList.propTypes = { history: PropTypes.object, }; -export default withRouter(DocumentsList); +export default withRouter(container((props, onData) => { + const subscription = Meteor.subscribe('documents.list'); + if (subscription.ready()) { + const documents = Documents.find().fetch(); + onData(null, { documents }); + } +}, DocumentsList, { loadingHandler: () => })); + diff --git a/imports/ui/components/Error.js b/imports/ui/components/Error.js deleted file mode 100644 index 2ed43206..00000000 --- a/imports/ui/components/Error.js +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import { PropTypes } from 'prop-types'; - -const Error = ({ error }) => ( -

- {error.message} -

-); - -Error.defaultProps = { - error: { message: '' }, -}; - -Error.propTypes = { - error: PropTypes.object, -}; - -export default Error; diff --git a/imports/ui/containers/AppNavigation.js b/imports/ui/containers/AppNavigation.js deleted file mode 100644 index 1fb1df68..00000000 --- a/imports/ui/containers/AppNavigation.js +++ /dev/null @@ -1,8 +0,0 @@ -import { Meteor } from 'meteor/meteor'; -import AppNavigation from '../components/AppNavigation.js'; -import composeWithTracker from '../../modules/compose-with-tracker'; - -const composer = (props, onData) => onData(null, { hasUser: Meteor.user() }); - -export default composeWithTracker(composer, false)(AppNavigation); - diff --git a/imports/ui/containers/DocumentsList.js b/imports/ui/containers/DocumentsList.js deleted file mode 100644 index 14fa9af1..00000000 --- a/imports/ui/containers/DocumentsList.js +++ /dev/null @@ -1,15 +0,0 @@ -import { Meteor } from 'meteor/meteor'; -import Documents from '../../api/documents/documents.js'; -import DocumentsList from '../components/DocumentsList.js'; -import composeWithTracker from '../../modules/compose-with-tracker'; - -const composer = (props, onData) => { - const subscription = Meteor.subscribe('documents.list'); - if (subscription.ready()) { - const documents = Documents.find().fetch(); - onData(null, { documents }); - } -}; - -export default composeWithTracker(composer)(DocumentsList); - diff --git a/imports/ui/containers/EditDocument.js b/imports/ui/containers/EditDocument.js deleted file mode 100644 index fc3d0652..00000000 --- a/imports/ui/containers/EditDocument.js +++ /dev/null @@ -1,15 +0,0 @@ -import { Meteor } from 'meteor/meteor'; -import Documents from '../../api/documents/documents.js'; -import EditDocument from '../pages/EditDocument.js'; -import composeWithTracker from '../../modules/compose-with-tracker'; - -const composer = (props, onData) => { - const subscription = Meteor.subscribe('documents.view', props.match.params._id); - - if (subscription.ready()) { - const document = Documents.findOne(props.match.params._id); - onData(null, { document }); - } -}; - -export default composeWithTracker(composer)(EditDocument); diff --git a/imports/ui/containers/ViewDocument.js b/imports/ui/containers/ViewDocument.js deleted file mode 100644 index 298b72a3..00000000 --- a/imports/ui/containers/ViewDocument.js +++ /dev/null @@ -1,16 +0,0 @@ -import { Meteor } from 'meteor/meteor'; -import Documents from '../../api/documents/documents.js'; -import ViewDocument from '../pages/ViewDocument.js'; -import composeWithTracker from '../../modules/compose-with-tracker'; - -const composer = (props, onData) => { - const subscription = Meteor.subscribe('documents.view', props.match.params._id); - - if (subscription.ready()) { - const doc = Documents.findOne(props.match.params._id); - onData(null, { doc }); - } -}; - -export default composeWithTracker(composer)(ViewDocument); - diff --git a/imports/ui/layouts/App.js b/imports/ui/layouts/App.js index c9e6a4da..2bcbf5e9 100644 --- a/imports/ui/layouts/App.js +++ b/imports/ui/layouts/App.js @@ -4,9 +4,9 @@ import React from 'react'; import { BrowserRouter, Route, Switch } from 'react-router-dom'; import { Grid } from 'react-bootstrap'; import PrivateRoute from '../../modules/private-route'; -import AppNavigation from '../containers/AppNavigation'; -import EditDocument from '../containers/EditDocument'; -import ViewDocument from '../containers/ViewDocument'; +import AppNavigation from '../components/AppNavigation'; +import EditDocument from '../pages/EditDocument'; +import ViewDocument from '../pages/ViewDocument'; import Documents from '../pages/Documents'; import NewDocument from '../pages/NewDocument'; import Index from '../pages/Index'; diff --git a/imports/ui/pages/Documents.js b/imports/ui/pages/Documents.js index 9dfa2b2b..43f496aa 100644 --- a/imports/ui/pages/Documents.js +++ b/imports/ui/pages/Documents.js @@ -1,7 +1,7 @@ import React from 'react'; import { Link } from 'react-router-dom'; import { Row, Col, Button } from 'react-bootstrap'; -import DocumentsList from '../containers/DocumentsList.js'; +import DocumentsList from '../components/DocumentsList'; const Documents = () => (
diff --git a/imports/ui/pages/EditDocument.js b/imports/ui/pages/EditDocument.js index 4bf5424f..e8a09458 100644 --- a/imports/ui/pages/EditDocument.js +++ b/imports/ui/pages/EditDocument.js @@ -1,16 +1,31 @@ +import { Meteor } from 'meteor/meteor'; import React from 'react'; +import { withRouter } from 'react-router-dom'; import { PropTypes } from 'prop-types'; +import Documents from '../../api/documents/documents'; import DocumentEditor from '../components/DocumentEditor'; +import NotFound from './NotFound'; +import container from '../../modules/container'; +import Loading from '../components/Loading'; -const EditDocument = ({ document }) => ( +const EditDocument = ({ doc }) => (doc ? (
-

Editing "{document.title}"

- +

Editing "{doc.title}"

+
-); +) : ); EditDocument.propTypes = { - document: PropTypes.object.isRequired, + doc: PropTypes.object.isRequired, }; -export default EditDocument; +export default withRouter(container((props, onData) => { + const documentId = props.match.params._id; + const subscription = Meteor.subscribe('documents.view', documentId); + + if (subscription.ready()) { + const doc = Documents.findOne(documentId); + onData(null, { doc }); + } +}, EditDocument, { loadingHandler: () => })); + diff --git a/imports/ui/pages/NotFound.js b/imports/ui/pages/NotFound.js index 205567fe..260a2fbe 100644 --- a/imports/ui/pages/NotFound.js +++ b/imports/ui/pages/NotFound.js @@ -1,22 +1,12 @@ import React from 'react'; import { Alert } from 'react-bootstrap'; -import { withRouter } from 'react-router-dom'; -import { PropTypes } from 'prop-types'; -const NotFound = ({ location }) => ( +const NotFound = () => (
-

Error [404]: {location.pathname} does not exist.

+

Error [404]: { window.location.pathname } does not exist.

); -NotFound.defaultProps = { - location: null, -}; - -NotFound.propTypes = { - location: PropTypes.object, -}; - -export default withRouter(NotFound); +export default NotFound; diff --git a/imports/ui/pages/ViewDocument.js b/imports/ui/pages/ViewDocument.js index a3997de9..03f5419d 100644 --- a/imports/ui/pages/ViewDocument.js +++ b/imports/ui/pages/ViewDocument.js @@ -1,10 +1,14 @@ +import { Meteor } from 'meteor/meteor'; import React from 'react'; import { ButtonToolbar, ButtonGroup, Button } from 'react-bootstrap'; import { withRouter } from 'react-router-dom'; import { PropTypes } from 'prop-types'; import { Bert } from 'meteor/themeteorchef:bert'; +import Documents from '../../api/documents/documents'; import { removeDocument } from '../../api/documents/methods'; import NotFound from './NotFound'; +import container from '../../modules/container'; +import Loading from '../components/Loading'; const handleRemove = (history, _id) => { if (confirm('Are you sure? This is permanent!')) { @@ -48,4 +52,13 @@ ViewDocument.propTypes = { history: PropTypes.object, }; -export default withRouter(ViewDocument); +export default withRouter(container((props, onData) => { + const documentId = props.match.params._id; + const subscription = Meteor.subscribe('documents.view', documentId); + + if (subscription.ready()) { + const doc = Documents.findOne(documentId); + onData(null, { doc }); + } +}, ViewDocument, { loadingHandler: () => })); + diff --git a/package.json b/package.json index 5b90ba48..9eda4a55 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "application-name", - "private": true, "version": "1.0.0", "description": "Application description.", + "license": "MIT", "scripts": { "start": "meteor --settings settings-development.json", "test": "meteor test --driver-package practicalmeteor:mocha --port 5000", @@ -15,27 +15,28 @@ "babel-runtime": "^6.23.0", "bcrypt": "^1.0.2", "bootstrap": "^3.3.7", - "jquery": "^3.2.1", - "jquery-validation": "^1.16.0", + "jquery": "^2.2.4", + "jquery-validation": "^1.15.1", "meteor-node-stubs": "^0.2.6", "prop-types": "^15.5.8", "react": "^15.5.4", "react-addons-pure-render-mixin": "^15.5.2", - "react-bootstrap": "^0.30.8", + "react-bootstrap": "^0.30.9", "react-dom": "^15.5.4", "react-komposer": "^2.0.0", - "react-router-bootstrap": "^0.23.1", - "react-router-dom": "^4.1.1" + "react-router-dom": "^4.1.1", + "react-router-bootstrap": "^0.23.2", + "simpl-schema": "^0.2.3" }, "devDependencies": { "babel-eslint": "^7.2.2", - "chimp": "^0.47.2", - "eslint": "^3.19.0", - "eslint-config-airbnb": "^14.1.0", - "eslint-import-resolver-meteor": "^0.4.0", - "eslint-plugin-import": "^2.2.0", - "eslint-plugin-jsx-a11y": "^4.0.0", + "chimp": "^0.41.2", + "eslint": "^3.8.1", + "eslint-config-airbnb": "^12.0.0", + "eslint-plugin-import": "^1.16.0", + "eslint-plugin-jsx-a11y": "^2.2.3", "eslint-plugin-meteor": "^4.0.1", - "eslint-plugin-react": "^6.10.3" + "eslint-plugin-react": "^6.4.1", + "eslint-import-resolver-meteor": "^0.4.0" } } From 3954e9d2d45d0606950947ed6eddb4d1dcc9fb04 Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 19 Apr 2017 22:39:10 -0300 Subject: [PATCH 07/10] Upgrade react-router-bootstrap to 0.24.2 Removed unneeded Logout component --- imports/ui/components/AppNavigation.js | 1 - .../ui/components/AuthenticatedNavigation.js | 32 ++++++++----------- imports/ui/components/PublicNavigation.js | 21 +----------- imports/ui/layouts/App.js | 2 -- imports/ui/pages/Logout.js | 28 ---------------- package.json | 2 +- 6 files changed, 15 insertions(+), 71 deletions(-) delete mode 100644 imports/ui/pages/Logout.js diff --git a/imports/ui/components/AppNavigation.js b/imports/ui/components/AppNavigation.js index 4b2658fe..38040bf4 100644 --- a/imports/ui/components/AppNavigation.js +++ b/imports/ui/components/AppNavigation.js @@ -30,4 +30,3 @@ AppNavigation.propTypes = { export default container((props, onData) => { onData(null, { hasUser: Meteor.user() }); }, AppNavigation); - diff --git a/imports/ui/components/AuthenticatedNavigation.js b/imports/ui/components/AuthenticatedNavigation.js index 6e0aeacc..ff9de095 100644 --- a/imports/ui/components/AuthenticatedNavigation.js +++ b/imports/ui/components/AuthenticatedNavigation.js @@ -1,18 +1,17 @@ import React from 'react'; -import { BrowserRouter as Router, browserHistory, Link, Route, Redirect } from 'react-router-dom'; +import { withRouter } from 'react-router-dom'; +import { PropTypes } from 'prop-types'; import { LinkContainer } from 'react-router-bootstrap'; import { Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap'; import { Meteor } from 'meteor/meteor'; -const handleLogout = () => Meteor.logout(() => browserHistory.push('/login')); - const userName = () => { const user = Meteor.user(); const name = user && user.profile ? user.profile.name : ''; return user ? `${name.first} ${name.last}` : ''; }; -/* const AuthenticatedNavigation = () => ( +const AuthenticatedNavigation = ({ history }) => (
-
-); */ - -const AuthenticatedNavigation = () => ( -
- -
); -export default AuthenticatedNavigation; +AuthenticatedNavigation.defaultProps = { + history: null, +}; + +AuthenticatedNavigation.propTypes = { + history: PropTypes.object, +}; + +export default withRouter(AuthenticatedNavigation); diff --git a/imports/ui/components/PublicNavigation.js b/imports/ui/components/PublicNavigation.js index 83fa4410..a590f554 100644 --- a/imports/ui/components/PublicNavigation.js +++ b/imports/ui/components/PublicNavigation.js @@ -1,9 +1,8 @@ import React from 'react'; -import { Link } from 'react-router-dom'; import { LinkContainer } from 'react-router-bootstrap'; import { Nav, NavItem } from 'react-bootstrap'; -/* const PublicNavigation = () => ( +const PublicNavigation = () => ( -); */ - -/* const PublicNavigation = () => ( - -);*/ - -const PublicNavigation = () => ( -
- Sign Up - Log In -
); export default PublicNavigation; diff --git a/imports/ui/layouts/App.js b/imports/ui/layouts/App.js index 2bcbf5e9..4ff32ceb 100644 --- a/imports/ui/layouts/App.js +++ b/imports/ui/layouts/App.js @@ -11,7 +11,6 @@ import Documents from '../pages/Documents'; import NewDocument from '../pages/NewDocument'; import Index from '../pages/Index'; import Login from '../pages/Login'; -import Logout from '../pages/Logout'; import NotFound from '../pages/NotFound'; import RecoverPassword from '../pages/RecoverPassword'; import ResetPassword from '../pages/ResetPassword'; @@ -29,7 +28,6 @@ const App = () => ( - diff --git a/imports/ui/pages/Logout.js b/imports/ui/pages/Logout.js deleted file mode 100644 index 736cea36..00000000 --- a/imports/ui/pages/Logout.js +++ /dev/null @@ -1,28 +0,0 @@ -import { Meteor } from 'meteor/meteor'; -import React from 'react'; -import { Route, Redirect } from 'react-router-dom'; -import { PropTypes } from 'prop-types'; - -const Logout = ({ ...rest }) => { - Meteor.logout((error) => { - if (error) { - return
Logout Failed - Error: {error}
; - } - - return true; - }); - - return ( - ()} /> - ); -}; - -Logout.defaultProps = { - location: null, -}; - -Logout.propTypes = { - location: PropTypes.object, -}; - -export default Logout; diff --git a/package.json b/package.json index 9eda4a55..9bb8df42 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "react-dom": "^15.5.4", "react-komposer": "^2.0.0", "react-router-dom": "^4.1.1", - "react-router-bootstrap": "^0.23.2", + "react-router-bootstrap": "^0.24.2", "simpl-schema": "^0.2.3" }, "devDependencies": { From 41f13dee68da97d041db2ec27316a42e019bb3a2 Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 2 May 2017 16:38:15 -0300 Subject: [PATCH 08/10] Merged PR#244 to avoid using profile fields on user registration Also added the profile "registered" for all users, so every user has a default role. --- imports/api/users/server/publications.js | 13 +++++++++++++ imports/modules/get-tracker-loader.js | 1 + .../startup/server/accounts/on-create-user.js | 16 ++++++++++++++++ imports/startup/server/api.js | 1 + imports/startup/server/index.js | 1 + imports/ui/components/AppNavigation.js | 5 ++++- imports/ui/components/AuthenticatedNavigation.js | 2 +- imports/ui/pages/Index.js | 2 +- 8 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 imports/api/users/server/publications.js create mode 100644 imports/startup/server/accounts/on-create-user.js diff --git a/imports/api/users/server/publications.js b/imports/api/users/server/publications.js new file mode 100644 index 00000000..7e247b18 --- /dev/null +++ b/imports/api/users/server/publications.js @@ -0,0 +1,13 @@ +import { Meteor } from 'meteor/meteor'; + +Meteor.publish('users.info', function userInfoPublish() { + if (!this.userId) { + return this.ready(); + } + + return Meteor.users.find(this.userId, { + fields: { + name: 1, + }, + }); +}); diff --git a/imports/modules/get-tracker-loader.js b/imports/modules/get-tracker-loader.js index d58d3535..8f3b0864 100644 --- a/imports/modules/get-tracker-loader.js +++ b/imports/modules/get-tracker-loader.js @@ -18,3 +18,4 @@ const getTrackerLoader = reactiveMapper => ( ); export default getTrackerLoader; + diff --git a/imports/startup/server/accounts/on-create-user.js b/imports/startup/server/accounts/on-create-user.js new file mode 100644 index 00000000..8c5326b1 --- /dev/null +++ b/imports/startup/server/accounts/on-create-user.js @@ -0,0 +1,16 @@ +import { Accounts } from 'meteor/accounts-base'; + +Accounts.onCreateUser((options, user) => { + const profile = options.profile; + const newUser = user; + + if (profile) { + newUser.name = { first: profile.name.first, last: profile.name.last }; + } + + if (options.email !== 'admin@admin.com') { + newUser.roles = ['registered']; + } + + return newUser; +}); diff --git a/imports/startup/server/api.js b/imports/startup/server/api.js index d284bbba..212f1dba 100644 --- a/imports/startup/server/api.js +++ b/imports/startup/server/api.js @@ -1,2 +1,3 @@ import '../../api/documents/methods.js'; import '../../api/documents/server/publications.js'; +import '../../api/users/server/publications.js'; diff --git a/imports/startup/server/index.js b/imports/startup/server/index.js index 800e1e63..b6217ebd 100644 --- a/imports/startup/server/index.js +++ b/imports/startup/server/index.js @@ -1,4 +1,5 @@ import './accounts/email-templates'; +import './accounts/on-create-user'; import './browser-policy'; import './fixtures'; import './api'; diff --git a/imports/ui/components/AppNavigation.js b/imports/ui/components/AppNavigation.js index 38040bf4..fdb8b9a9 100644 --- a/imports/ui/components/AppNavigation.js +++ b/imports/ui/components/AppNavigation.js @@ -28,5 +28,8 @@ AppNavigation.propTypes = { }; export default container((props, onData) => { - onData(null, { hasUser: Meteor.user() }); + const subscription = Meteor.subscribe('users.info'); + if (subscription.ready()) { + onData(null, { hasUser: Meteor.user() }); + } }, AppNavigation); diff --git a/imports/ui/components/AuthenticatedNavigation.js b/imports/ui/components/AuthenticatedNavigation.js index ff9de095..866c69b9 100644 --- a/imports/ui/components/AuthenticatedNavigation.js +++ b/imports/ui/components/AuthenticatedNavigation.js @@ -7,7 +7,7 @@ import { Meteor } from 'meteor/meteor'; const userName = () => { const user = Meteor.user(); - const name = user && user.profile ? user.profile.name : ''; + const name = user ? user.name : ''; return user ? `${name.first} ${name.last}` : ''; }; diff --git a/imports/ui/pages/Index.js b/imports/ui/pages/Index.js index a5aa841e..86e1e1bd 100644 --- a/imports/ui/pages/Index.js +++ b/imports/ui/pages/Index.js @@ -7,7 +7,7 @@ const Index = () => (

Base

A starting point for Meteor applications.

Read the Documentation

-

Currently at v4.14.0

+

Currently at v4.15.0

); From 1bb8d7fb7ad1752fc72db871a601d628e89d6adf Mon Sep 17 00:00:00 2001 From: Martin Date: Tue, 2 May 2017 16:38:15 -0300 Subject: [PATCH 09/10] Merged PR#244 to avoid using profile fields on user registration Also added the role "registered" for all new users, so every user has a default role. --- imports/api/users/server/publications.js | 13 +++++++++++++ imports/modules/get-tracker-loader.js | 1 + .../startup/server/accounts/on-create-user.js | 16 ++++++++++++++++ imports/startup/server/api.js | 1 + imports/startup/server/index.js | 1 + imports/ui/components/AppNavigation.js | 5 ++++- imports/ui/components/AuthenticatedNavigation.js | 2 +- imports/ui/pages/Index.js | 2 +- 8 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 imports/api/users/server/publications.js create mode 100644 imports/startup/server/accounts/on-create-user.js diff --git a/imports/api/users/server/publications.js b/imports/api/users/server/publications.js new file mode 100644 index 00000000..7e247b18 --- /dev/null +++ b/imports/api/users/server/publications.js @@ -0,0 +1,13 @@ +import { Meteor } from 'meteor/meteor'; + +Meteor.publish('users.info', function userInfoPublish() { + if (!this.userId) { + return this.ready(); + } + + return Meteor.users.find(this.userId, { + fields: { + name: 1, + }, + }); +}); diff --git a/imports/modules/get-tracker-loader.js b/imports/modules/get-tracker-loader.js index d58d3535..8f3b0864 100644 --- a/imports/modules/get-tracker-loader.js +++ b/imports/modules/get-tracker-loader.js @@ -18,3 +18,4 @@ const getTrackerLoader = reactiveMapper => ( ); export default getTrackerLoader; + diff --git a/imports/startup/server/accounts/on-create-user.js b/imports/startup/server/accounts/on-create-user.js new file mode 100644 index 00000000..8c5326b1 --- /dev/null +++ b/imports/startup/server/accounts/on-create-user.js @@ -0,0 +1,16 @@ +import { Accounts } from 'meteor/accounts-base'; + +Accounts.onCreateUser((options, user) => { + const profile = options.profile; + const newUser = user; + + if (profile) { + newUser.name = { first: profile.name.first, last: profile.name.last }; + } + + if (options.email !== 'admin@admin.com') { + newUser.roles = ['registered']; + } + + return newUser; +}); diff --git a/imports/startup/server/api.js b/imports/startup/server/api.js index d284bbba..212f1dba 100644 --- a/imports/startup/server/api.js +++ b/imports/startup/server/api.js @@ -1,2 +1,3 @@ import '../../api/documents/methods.js'; import '../../api/documents/server/publications.js'; +import '../../api/users/server/publications.js'; diff --git a/imports/startup/server/index.js b/imports/startup/server/index.js index 800e1e63..b6217ebd 100644 --- a/imports/startup/server/index.js +++ b/imports/startup/server/index.js @@ -1,4 +1,5 @@ import './accounts/email-templates'; +import './accounts/on-create-user'; import './browser-policy'; import './fixtures'; import './api'; diff --git a/imports/ui/components/AppNavigation.js b/imports/ui/components/AppNavigation.js index 38040bf4..fdb8b9a9 100644 --- a/imports/ui/components/AppNavigation.js +++ b/imports/ui/components/AppNavigation.js @@ -28,5 +28,8 @@ AppNavigation.propTypes = { }; export default container((props, onData) => { - onData(null, { hasUser: Meteor.user() }); + const subscription = Meteor.subscribe('users.info'); + if (subscription.ready()) { + onData(null, { hasUser: Meteor.user() }); + } }, AppNavigation); diff --git a/imports/ui/components/AuthenticatedNavigation.js b/imports/ui/components/AuthenticatedNavigation.js index ff9de095..866c69b9 100644 --- a/imports/ui/components/AuthenticatedNavigation.js +++ b/imports/ui/components/AuthenticatedNavigation.js @@ -7,7 +7,7 @@ import { Meteor } from 'meteor/meteor'; const userName = () => { const user = Meteor.user(); - const name = user && user.profile ? user.profile.name : ''; + const name = user ? user.name : ''; return user ? `${name.first} ${name.last}` : ''; }; diff --git a/imports/ui/pages/Index.js b/imports/ui/pages/Index.js index a5aa841e..86e1e1bd 100644 --- a/imports/ui/pages/Index.js +++ b/imports/ui/pages/Index.js @@ -7,7 +7,7 @@ const Index = () => (

Base

A starting point for Meteor applications.

Read the Documentation

-

Currently at v4.14.0

+

Currently at v4.15.0

); From 6af12d3c525fc817351a074269869b310cc3f12f Mon Sep 17 00:00:00 2001 From: Martin Date: Fri, 5 May 2017 18:20:42 -0300 Subject: [PATCH 10/10] Put all client code in imports/client folder to avoid server restarts See comment https://github.com/meteor/meteor/issues/6576#issuecomment-292527085 --- imports/{ => client}/ui/components/AppNavigation.js | 2 +- .../{ => client}/ui/components/AuthenticatedNavigation.js | 0 imports/{ => client}/ui/components/DocumentEditor.js | 2 +- imports/{ => client}/ui/components/DocumentsList.js | 4 ++-- imports/{ => client}/ui/components/Loading.js | 0 imports/{ => client}/ui/components/PublicNavigation.js | 0 imports/{ => client}/ui/layouts/App.js | 2 +- imports/{ => client}/ui/pages/Documents.js | 0 imports/{ => client}/ui/pages/EditDocument.js | 4 ++-- imports/{ => client}/ui/pages/Index.js | 0 imports/{ => client}/ui/pages/Login.js | 2 +- imports/{ => client}/ui/pages/NewDocument.js | 0 imports/{ => client}/ui/pages/NotFound.js | 0 imports/{ => client}/ui/pages/RecoverPassword.js | 2 +- imports/{ => client}/ui/pages/ResetPassword.js | 2 +- imports/{ => client}/ui/pages/Signup.js | 2 +- imports/{ => client}/ui/pages/ViewDocument.js | 6 +++--- imports/startup/client/index.js | 2 +- package.json | 2 +- 19 files changed, 16 insertions(+), 16 deletions(-) rename imports/{ => client}/ui/components/AppNavigation.js (94%) rename imports/{ => client}/ui/components/AuthenticatedNavigation.js (100%) rename imports/{ => client}/ui/components/DocumentEditor.js (95%) rename imports/{ => client}/ui/components/DocumentsList.js (90%) rename imports/{ => client}/ui/components/Loading.js (100%) rename imports/{ => client}/ui/components/PublicNavigation.js (100%) rename imports/{ => client}/ui/layouts/App.js (96%) rename imports/{ => client}/ui/pages/Documents.js (100%) rename imports/{ => client}/ui/pages/EditDocument.js (89%) rename imports/{ => client}/ui/pages/Index.js (100%) rename imports/{ => client}/ui/pages/Login.js (96%) rename imports/{ => client}/ui/pages/NewDocument.js (100%) rename imports/{ => client}/ui/pages/NotFound.js (100%) rename imports/{ => client}/ui/pages/RecoverPassword.js (94%) rename imports/{ => client}/ui/pages/ResetPassword.js (96%) rename imports/{ => client}/ui/pages/Signup.js (97%) rename imports/{ => client}/ui/pages/ViewDocument.js (91%) diff --git a/imports/ui/components/AppNavigation.js b/imports/client/ui/components/AppNavigation.js similarity index 94% rename from imports/ui/components/AppNavigation.js rename to imports/client/ui/components/AppNavigation.js index fdb8b9a9..d2aa978d 100644 --- a/imports/ui/components/AppNavigation.js +++ b/imports/client/ui/components/AppNavigation.js @@ -5,7 +5,7 @@ import { Link } from 'react-router-dom'; import { PropTypes } from 'prop-types'; import PublicNavigation from './PublicNavigation.js'; import AuthenticatedNavigation from './AuthenticatedNavigation.js'; -import container from '../../modules/container'; +import container from '../../../modules/container'; const renderNavigation = hasUser => (hasUser ? : ); diff --git a/imports/ui/components/AuthenticatedNavigation.js b/imports/client/ui/components/AuthenticatedNavigation.js similarity index 100% rename from imports/ui/components/AuthenticatedNavigation.js rename to imports/client/ui/components/AuthenticatedNavigation.js diff --git a/imports/ui/components/DocumentEditor.js b/imports/client/ui/components/DocumentEditor.js similarity index 95% rename from imports/ui/components/DocumentEditor.js rename to imports/client/ui/components/DocumentEditor.js index dbb78878..3cea5821 100644 --- a/imports/ui/components/DocumentEditor.js +++ b/imports/client/ui/components/DocumentEditor.js @@ -4,7 +4,7 @@ import React, { Component } from 'react'; import { FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap'; import { withRouter } from 'react-router-dom'; import { PropTypes } from 'prop-types'; -import documentEditor from '../../modules/document-editor.js'; +import documentEditor from '../../../modules/document-editor.js'; class DocumentEditor extends Component { componentDidMount() { diff --git a/imports/ui/components/DocumentsList.js b/imports/client/ui/components/DocumentsList.js similarity index 90% rename from imports/ui/components/DocumentsList.js rename to imports/client/ui/components/DocumentsList.js index ed10fa47..26f72ecd 100644 --- a/imports/ui/components/DocumentsList.js +++ b/imports/client/ui/components/DocumentsList.js @@ -3,8 +3,8 @@ import React from 'react'; import { ListGroup, ListGroupItem, Alert } from 'react-bootstrap'; import { withRouter } from 'react-router-dom'; import { PropTypes } from 'prop-types'; -import Documents from '../../api/documents/documents'; -import container from '../../modules/container'; +import Documents from '../../../api/documents/documents'; +import container from '../../../modules/container'; import Loading from '../components/Loading'; const DocumentsList = ({ documents, history }) => ( diff --git a/imports/ui/components/Loading.js b/imports/client/ui/components/Loading.js similarity index 100% rename from imports/ui/components/Loading.js rename to imports/client/ui/components/Loading.js diff --git a/imports/ui/components/PublicNavigation.js b/imports/client/ui/components/PublicNavigation.js similarity index 100% rename from imports/ui/components/PublicNavigation.js rename to imports/client/ui/components/PublicNavigation.js diff --git a/imports/ui/layouts/App.js b/imports/client/ui/layouts/App.js similarity index 96% rename from imports/ui/layouts/App.js rename to imports/client/ui/layouts/App.js index 4ff32ceb..b7ec52f7 100644 --- a/imports/ui/layouts/App.js +++ b/imports/client/ui/layouts/App.js @@ -3,7 +3,7 @@ import React from 'react'; import { BrowserRouter, Route, Switch } from 'react-router-dom'; import { Grid } from 'react-bootstrap'; -import PrivateRoute from '../../modules/private-route'; +import PrivateRoute from '../../../modules/private-route'; import AppNavigation from '../components/AppNavigation'; import EditDocument from '../pages/EditDocument'; import ViewDocument from '../pages/ViewDocument'; diff --git a/imports/ui/pages/Documents.js b/imports/client/ui/pages/Documents.js similarity index 100% rename from imports/ui/pages/Documents.js rename to imports/client/ui/pages/Documents.js diff --git a/imports/ui/pages/EditDocument.js b/imports/client/ui/pages/EditDocument.js similarity index 89% rename from imports/ui/pages/EditDocument.js rename to imports/client/ui/pages/EditDocument.js index e8a09458..75a06c70 100644 --- a/imports/ui/pages/EditDocument.js +++ b/imports/client/ui/pages/EditDocument.js @@ -2,10 +2,10 @@ import { Meteor } from 'meteor/meteor'; import React from 'react'; import { withRouter } from 'react-router-dom'; import { PropTypes } from 'prop-types'; -import Documents from '../../api/documents/documents'; +import Documents from '../../../api/documents/documents'; import DocumentEditor from '../components/DocumentEditor'; import NotFound from './NotFound'; -import container from '../../modules/container'; +import container from '../../../modules/container'; import Loading from '../components/Loading'; const EditDocument = ({ doc }) => (doc ? ( diff --git a/imports/ui/pages/Index.js b/imports/client/ui/pages/Index.js similarity index 100% rename from imports/ui/pages/Index.js rename to imports/client/ui/pages/Index.js diff --git a/imports/ui/pages/Login.js b/imports/client/ui/pages/Login.js similarity index 96% rename from imports/ui/pages/Login.js rename to imports/client/ui/pages/Login.js index 45f86c8d..14442e04 100644 --- a/imports/ui/pages/Login.js +++ b/imports/client/ui/pages/Login.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import { Link, withRouter } from 'react-router-dom'; import { Row, Col, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap'; -import handleLogin from '../../modules/login'; +import handleLogin from '../../../modules/login'; class Login extends Component { componentDidMount() { diff --git a/imports/ui/pages/NewDocument.js b/imports/client/ui/pages/NewDocument.js similarity index 100% rename from imports/ui/pages/NewDocument.js rename to imports/client/ui/pages/NewDocument.js diff --git a/imports/ui/pages/NotFound.js b/imports/client/ui/pages/NotFound.js similarity index 100% rename from imports/ui/pages/NotFound.js rename to imports/client/ui/pages/NotFound.js diff --git a/imports/ui/pages/RecoverPassword.js b/imports/client/ui/pages/RecoverPassword.js similarity index 94% rename from imports/ui/pages/RecoverPassword.js rename to imports/client/ui/pages/RecoverPassword.js index bee5768c..cebccc4f 100644 --- a/imports/ui/pages/RecoverPassword.js +++ b/imports/client/ui/pages/RecoverPassword.js @@ -1,6 +1,6 @@ import React, { Component } from 'react'; import { Row, Col, Alert, FormGroup, FormControl, Button } from 'react-bootstrap'; -import handleRecoverPassword from '../../modules/recover-password'; +import handleRecoverPassword from '../../../modules/recover-password'; class RecoverPassword extends Component { componentDidMount() { diff --git a/imports/ui/pages/ResetPassword.js b/imports/client/ui/pages/ResetPassword.js similarity index 96% rename from imports/ui/pages/ResetPassword.js rename to imports/client/ui/pages/ResetPassword.js index f9971d08..d5fdf183 100644 --- a/imports/ui/pages/ResetPassword.js +++ b/imports/client/ui/pages/ResetPassword.js @@ -4,7 +4,7 @@ import React, { Component } from 'react'; import { withRouter } from 'react-router-dom'; import { PropTypes } from 'prop-types'; import { Row, Col, Alert, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap'; -import handleResetPassword from '../../modules/reset-password'; +import handleResetPassword from '../../../modules/reset-password'; class ResetPassword extends Component { componentDidMount() { diff --git a/imports/ui/pages/Signup.js b/imports/client/ui/pages/Signup.js similarity index 97% rename from imports/ui/pages/Signup.js rename to imports/client/ui/pages/Signup.js index 82e285dd..bcee8376 100644 --- a/imports/ui/pages/Signup.js +++ b/imports/client/ui/pages/Signup.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import { Link, withRouter } from 'react-router-dom'; import { Row, Col, FormGroup, ControlLabel, FormControl, Button } from 'react-bootstrap'; -import handleSignup from '../../modules/signup'; +import handleSignup from '../../../modules/signup'; class Signup extends Component { componentDidMount() { diff --git a/imports/ui/pages/ViewDocument.js b/imports/client/ui/pages/ViewDocument.js similarity index 91% rename from imports/ui/pages/ViewDocument.js rename to imports/client/ui/pages/ViewDocument.js index 03f5419d..821d1d65 100644 --- a/imports/ui/pages/ViewDocument.js +++ b/imports/client/ui/pages/ViewDocument.js @@ -4,10 +4,10 @@ import { ButtonToolbar, ButtonGroup, Button } from 'react-bootstrap'; import { withRouter } from 'react-router-dom'; import { PropTypes } from 'prop-types'; import { Bert } from 'meteor/themeteorchef:bert'; -import Documents from '../../api/documents/documents'; -import { removeDocument } from '../../api/documents/methods'; +import Documents from '../../../api/documents/documents'; +import { removeDocument } from '../../../api/documents/methods'; import NotFound from './NotFound'; -import container from '../../modules/container'; +import container from '../../../modules/container'; import Loading from '../components/Loading'; const handleRemove = (history, _id) => { diff --git a/imports/startup/client/index.js b/imports/startup/client/index.js index 51cbed09..f7ccb052 100644 --- a/imports/startup/client/index.js +++ b/imports/startup/client/index.js @@ -3,7 +3,7 @@ import React from 'react'; import { render } from 'react-dom'; import { Bert } from 'meteor/themeteorchef:bert'; import 'bootstrap/dist/css/bootstrap.min.css'; -import App from '../../ui/layouts/App.js'; +import App from '../../client/ui/layouts/App.js'; Bert.defaults.style = 'growl-top-right'; diff --git a/package.json b/package.json index 9bb8df42..74973a48 100644 --- a/package.json +++ b/package.json @@ -24,8 +24,8 @@ "react-bootstrap": "^0.30.9", "react-dom": "^15.5.4", "react-komposer": "^2.0.0", - "react-router-dom": "^4.1.1", "react-router-bootstrap": "^0.24.2", + "react-router-dom": "^4.1.1", "simpl-schema": "^0.2.3" }, "devDependencies": {