From f0c912bf1f2a4157f8583e1922edfd5247346701 Mon Sep 17 00:00:00 2001 From: tmcdeveloper Date: Wed, 20 Apr 2016 20:55:53 -0500 Subject: [PATCH] add method tests and airbnb linting via eslint --- .meteor/packages | 2 + .meteor/versions | 15 ++--- imports/api/documents/documents.js | 16 ++++- imports/api/documents/documents.tests.js | 13 ++++ imports/api/documents/methods.js | 24 ++++---- imports/api/documents/methods.tests.js | 42 +++++++++++++ imports/api/documents/server/publications.js | 4 +- imports/modules/get-input-value.js | 6 +- imports/modules/login.js | 32 +++++----- imports/modules/recover-password.js | 24 ++++---- imports/modules/reset-password.js | 40 ++++++------ imports/modules/signup.js | 58 +++++++++--------- imports/startup/client/index.js | 2 +- imports/startup/client/routes.js | 38 ++++++++++++ imports/startup/client/routes.jsx | 38 ------------ imports/startup/server/accounts/email-templates.js | 26 ++++---- imports/startup/server/fixtures.js | 16 ++--- imports/ui/components/add-document.js | 20 +++--- imports/ui/components/app-navigation.js | 4 +- imports/ui/components/authenticated-navigation.js | 12 ++-- imports/ui/components/document.js | 57 +++++++++++++++++ imports/ui/components/documents-list.js | 71 +++------------------- imports/ui/components/public-navigation.js | 2 +- imports/ui/containers/app-navigation.js | 6 +- imports/ui/containers/documents-list.js | 12 ++-- imports/ui/layouts/app.js | 4 +- imports/ui/pages/documents.js | 2 +- imports/ui/pages/index.js | 2 +- imports/ui/pages/login.js | 12 +++- imports/ui/pages/not-found.js | 2 +- imports/ui/pages/recover-password.js | 8 ++- imports/ui/pages/reset-password.js | 9 ++- imports/ui/pages/signup.js | 4 +- package.json | 43 +++++++++++-- tests/login.js | 35 ++++++----- tests/not-found.js | 13 ++-- tests/reset-password.js | 34 ----------- tests/signup.js | 33 +++++----- 38 files changed, 436 insertions(+), 345 deletions(-) create mode 100644 imports/api/documents/documents.tests.js create mode 100644 imports/api/documents/methods.tests.js create mode 100644 imports/startup/client/routes.js delete mode 100644 imports/startup/client/routes.jsx create mode 100644 imports/ui/components/document.js delete mode 100644 tests/reset-password.js diff --git a/.meteor/packages b/.meteor/packages index 2d5fbed..01c9a38 100644 --- a/.meteor/packages +++ b/.meteor/packages @@ -36,3 +36,5 @@ practicalmeteor:mocha xolvio:backdoor xolvio:email-stub mdg:validated-method +dburles:factory +aldeed:simple-schema diff --git a/.meteor/versions b/.meteor/versions index dee4d7b..acef870 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -25,6 +25,7 @@ caching-html-compiler@1.0.5 callback-hook@1.0.7 check@1.1.3 coffeescript@1.0.16 +dburles:factory@0.4.2 ddp@1.2.4 ddp-client@1.2.4 ddp-common@1.2.4 @@ -38,8 +39,8 @@ ejson@1.0.10 email@1.0.11 es5-shim@4.5.9 fastclick@1.0.10 -fortawesome:fontawesome@4.4.0_1 -fourseven:scss@3.4.1 +fortawesome:fontawesome@4.5.0 +fourseven:scss@3.4.3 geojson-utils@1.0.7 hot-code-push@1.0.3 html-tools@1.0.8 @@ -51,7 +52,7 @@ launch-screen@1.0.10 livedata@1.0.17 localstorage@1.0.8 logging@1.0.11 -mdg:validated-method@1.0.2 +mdg:validated-method@1.1.0 mdg:validation-error@0.5.1 meteor@1.1.13 meteor-base@1.0.3 @@ -70,14 +71,14 @@ observe-sequence@1.0.10 ordered-dict@1.0.6 practicalmeteor:chai@2.1.0_1 practicalmeteor:loglevel@1.2.0_2 -practicalmeteor:mocha@2.1.0_8 +practicalmeteor:mocha@2.4.5_1 practicalmeteor:mocha-core@0.1.4 practicalmeteor:sinon@1.14.1_2 promise@0.6.6 raix:eventemitter@0.1.3 random@1.0.8 rate-limit@1.0.3 -react-meteor-data@0.2.7 +react-meteor-data@0.2.9 reactive-dict@1.1.6 reactive-var@1.0.8 reload@1.1.7 @@ -104,6 +105,6 @@ underscore@1.0.7 url@1.0.8 webapp@1.2.7 webapp-hashing@1.0.8 -xolvio:backdoor@0.1.2 -xolvio:cleaner@0.2.0 +xolvio:backdoor@0.2.0 +xolvio:cleaner@0.3.0 xolvio:email-stub@0.2.0 diff --git a/imports/api/documents/documents.js b/imports/api/documents/documents.js index eb8f3c0..d7d4061 100644 --- a/imports/api/documents/documents.js +++ b/imports/api/documents/documents.js @@ -1,3 +1,17 @@ import { Mongo } from 'meteor/mongo'; +import faker from 'faker'; -export const Documents = new Mongo.Collection( 'Documents' ); +export const Documents = new Mongo.Collection('Documents'); + +Documents.schema = new SimpleSchema({ + title: { + type: String, + label: 'The title of the document.', + }, +}); + +Documents.attachSchema(Documents.schema); + +Factory.define('document', Documents, { + title: () => faker.hacker.phrase(), +}); diff --git a/imports/api/documents/documents.tests.js b/imports/api/documents/documents.tests.js new file mode 100644 index 0000000..c03abb8 --- /dev/null +++ b/imports/api/documents/documents.tests.js @@ -0,0 +1,13 @@ +/* eslint-env mocha */ +/* eslint-disable func-names, prefer-arrow-callback */ + +import { chai } from 'meteor/practicalmeteor:chai'; +import { Documents } from './documents.js'; + +const { assert } = chai; + +describe('Documents collection', function () { + it('registers the collection with Mongo properly', function () { + assert.equal(typeof Documents, 'object'); + }); +}); diff --git a/imports/api/documents/methods.js b/imports/api/documents/methods.js index e744293..d565c36 100644 --- a/imports/api/documents/methods.js +++ b/imports/api/documents/methods.js @@ -3,30 +3,30 @@ import { Documents } from './documents'; export const insertDocument = new ValidatedMethod({ name: 'documents.insert', validate: new SimpleSchema({ - title: { type: String } + title: { type: String }, }).validator(), - run( document ) { - Documents.insert( document ); - } + run(document) { + Documents.insert(document); + }, }); export const updateDocument = new ValidatedMethod({ name: 'documents.update', validate: new SimpleSchema({ _id: { type: String }, - 'update.title': { type: String, optional: true } + 'update.title': { type: String, optional: true }, }).validator(), - run( { _id, update } ) { - Documents.update( _id, { $set: update } ); - } + run({ _id, update }) { + Documents.update(_id, { $set: update }); + }, }); export const removeDocument = new ValidatedMethod({ name: 'documents.remove', validate: new SimpleSchema({ - _id: { type: String } + _id: { type: String }, }).validator(), - run( { _id } ) { - Documents.remove( _id ); - } + run({ _id }) { + Documents.remove(_id); + }, }); diff --git a/imports/api/documents/methods.tests.js b/imports/api/documents/methods.tests.js new file mode 100644 index 0000000..fdf754d --- /dev/null +++ b/imports/api/documents/methods.tests.js @@ -0,0 +1,42 @@ +/* eslint-env mocha */ +/* eslint-disable func-names, prefer-arrow-callback */ + +import { assert } from 'meteor/practicalmeteor:chai'; +import { resetDatabase } from 'meteor/xolvio:cleaner'; +import { Documents } from './documents.js'; +import { insertDocument, updateDocument, removeDocument } from './methods.js'; + +describe('Documents methods', function () { + beforeEach(function () { + if (Meteor.isServer) { + resetDatabase(); + } + }); + + it('inserts a document into the Documents collection', function () { + insertDocument.call({ title: 'You can\'t arrest me, I\'m the Cake Boss!' }); + const getDocument = Documents.findOne({ title: 'You can\'t arrest me, I\'m the Cake Boss!' }); + assert.equal(getDocument.title, 'You can\'t arrest me, I\'m the Cake Boss!'); + }); + + it('updates a document in the Documents collection', function () { + const { _id } = Factory.create('document'); + + updateDocument.call({ + _id, + update: { + title: 'You can\'t arrest me, I\'m the Cake Boss!', + }, + }); + + const getDocument = Documents.findOne(_id); + assert.equal(getDocument.title, 'You can\'t arrest me, I\'m the Cake Boss!'); + }); + + it('removes a document from the Documents collection', function () { + const { _id } = Factory.create('document'); + removeDocument.call({ _id }); + const getDocument = Documents.findOne(_id); + assert.equal(getDocument, undefined); + }); +}); diff --git a/imports/api/documents/server/publications.js b/imports/api/documents/server/publications.js index f48f0c8..fbf7262 100644 --- a/imports/api/documents/server/publications.js +++ b/imports/api/documents/server/publications.js @@ -1,5 +1,3 @@ import { Documents } from '../documents'; -Meteor.publish( 'documents', function() { - return Documents.find(); -}); +Meteor.publish('documents', () => Documents.find()); diff --git a/imports/modules/get-input-value.js b/imports/modules/get-input-value.js index bf66d97..1469c26 100644 --- a/imports/modules/get-input-value.js +++ b/imports/modules/get-input-value.js @@ -1,4 +1,4 @@ -export const getInputValue = ( component, ref, nested ) => { - let element = component.refs[ ref ]; +export const getInputValue = (component, ref, nested) => { + const element = component.refs[ref]; return nested ? element.refs.input.value : element.value; -} +}; diff --git a/imports/modules/login.js b/imports/modules/login.js index 0751e6b..6ab1291 100644 --- a/imports/modules/login.js +++ b/imports/modules/login.js @@ -4,44 +4,44 @@ let component; const _handleLogin = () => { // component value is accessed via nested refs. - const email = component.refs.emailAddress.refs.input.value, - password = component.refs.password.value; + const email = component.refs.emailAddress.refs.input.value; + const password = component.refs.password.value; - Meteor.loginWithPassword( email, password, ( error ) => { - if ( error ) { - Bert.alert( error.reason, 'warning' ); + Meteor.loginWithPassword(email, password, (error) => { + if (error) { + Bert.alert(error.reason, 'warning'); } else { - browserHistory.push( '/' ); - Bert.alert( 'Logged in!', 'success' ); + browserHistory.push('/'); + Bert.alert('Logged in!', 'success'); } }); }; const _validate = () => { - $( component.refs.login ).validate({ + $(component.refs.login).validate({ rules: { emailAddress: { required: true, - email: true + email: true, }, password: { - required: true - } + required: true, + }, }, messages: { emailAddress: { required: 'Need an email address here.', - email: 'Is this email address legit?' + email: 'Is this email address legit?', }, password: { - required: 'Need a password here.' - } + required: 'Need a password here.', + }, }, - submitHandler() { _handleLogin(); } + submitHandler() { _handleLogin(); }, }); }; -export const handleLogin = ( options ) => { +export const handleLogin = (options) => { component = options.component; _validate(); }; diff --git a/imports/modules/recover-password.js b/imports/modules/recover-password.js index e2299fc..b26d5f1 100644 --- a/imports/modules/recover-password.js +++ b/imports/modules/recover-password.js @@ -4,35 +4,35 @@ let component; const _handleRecovery = () => { Accounts.forgotPassword({ - email: getInputValue( component, 'emailAddress', true ) - }, ( error ) => { - if ( error ) { - Bert.alert( error.reason, 'warning' ); + email: getInputValue(component, 'emailAddress', true), + }, (error) => { + if (error) { + Bert.alert(error.reason, 'warning'); } else { - Bert.alert( 'Check your inbox for a reset link!', 'success' ); + Bert.alert('Check your inbox for a reset link!', 'success'); } }); }; const _validate = () => { - $( component.refs.recoverPassword ).validate({ + $(component.refs.recoverPassword).validate({ rules: { emailAddress: { required: true, - email: true - } + email: true, + }, }, messages: { emailAddress: { required: 'Need an email address here.', - email: 'Is this email address legit?' - } + email: 'Is this email address legit?', + }, }, - submitHandler() { _handleRecovery(); } + submitHandler() { _handleRecovery(); }, }); }; -export const handleRecoverPassword = ( options ) => { +export const handleRecoverPassword = (options) => { component = options.component; _validate(); }; diff --git a/imports/modules/reset-password.js b/imports/modules/reset-password.js index f334cdb..bee21f5 100644 --- a/imports/modules/reset-password.js +++ b/imports/modules/reset-password.js @@ -1,50 +1,50 @@ import { getInputValue } from './get-input-value'; import { browserHistory } from 'react-router'; -let component, - token; +let component; +let token; const _handleReset = () => { - const password = getInputValue( component, 'newPassword', true ); - Accounts.resetPassword( token, password, ( error ) => { - if ( error ) { - Bert.alert( error.reason, 'danger' ); + const password = getInputValue(component, 'newPassword', true); + Accounts.resetPassword(token, password, (error) => { + if (error) { + Bert.alert(error.reason, 'danger'); } else { - browserHistory.push( '/' ); - Bert.alert( 'Password reset!', 'success' ); + browserHistory.push('/'); + Bert.alert('Password reset!', 'success'); } }); }; const _validate = () => { - $( component.refs.resetPassword ).validate({ + $(component.refs.resetPassword).validate({ rules: { newPassword: { required: true, - minlength: 6 + minlength: 6, }, repeatNewPassword: { required: true, minlength: 6, - equalTo: '[name="newPassword"]' - } + equalTo: '[name="newPassword"]', + }, }, messages: { newPassword: { - required: "Enter a new password, please.", - minlength: "Use at least six characters, please." + required: 'Enter a new password, please.', + minlength: 'Use at least six characters, please.', }, repeatNewPassword: { - required: "Repeat your new password, please.", - equalTo: "Hmm, your passwords don't match. Try again?" - } + required: 'Repeat your new password, please.', + equalTo: 'Hmm, your passwords don\'t match. Try again?', + }, }, - submitHandler() { _handleReset(); } + submitHandler() { _handleReset(); }, }); }; -export const handleResetPassword = ( options ) => { +export const handleResetPassword = (options) => { component = options.component; - token = options.token; + token = options.token; _validate(); }; diff --git a/imports/modules/signup.js b/imports/modules/signup.js index 3fc5fe5..aefae57 100644 --- a/imports/modules/signup.js +++ b/imports/modules/signup.js @@ -3,71 +3,69 @@ import { getInputValue } from './get-input-value'; let component; -const _getUserData = () => { - return { - email: getInputValue( component, 'emailAddress', true ), - password: getInputValue( component, 'password', true ), - profile: { - name: { - first: getInputValue( component, 'firstName', true ), - last: getInputValue( component, 'lastName', true ) - } - } - }; -}; +const _getUserData = () => ({ + email: getInputValue(component, 'emailAddress', true), + password: getInputValue(component, 'password', true), + profile: { + name: { + first: getInputValue(component, 'firstName', true), + last: getInputValue(component, 'lastName', true), + }, + }, +}); const _handleSignup = () => { const user = _getUserData(); - Accounts.createUser( user, ( error ) => { - if ( error ) { - Bert.alert( error.reason, 'danger' ); + Accounts.createUser(user, (error) => { + if (error) { + Bert.alert(error.reason, 'danger'); } else { - browserHistory.push( '/' ); - Bert.alert( 'Welcome!', 'success' ); + browserHistory.push('/'); + Bert.alert('Welcome!', 'success'); } }); }; const _validate = () => { - $( component.refs.signup ).validate({ + $(component.refs.signup).validate({ rules: { firstName: { - required: true + required: true, }, lastName: { - required: true + required: true, }, emailAddress: { required: true, - email: true + email: true, }, password: { required: true, - minlength: 6 - } + minlength: 6, + }, }, messages: { firstName: { - required: 'First name?' + required: 'First name?', }, lastName: { - required: 'Last name?' + required: 'Last name?', }, emailAddress: { required: 'Need an email address here.', - email: 'Is this email address legit?' + email: 'Is this email address legit?', }, password: { required: 'Need a password here.', - minlength: 'Use at least six characters, please.' - } + minlength: 'Use at least six characters, please.', + }, }, - submitHandler() { _handleSignup(); } + submitHandler() { _handleSignup(); }, }); }; -export const handleSignup = ( options ) => { +export const handleSignup = (options) => { component = options.component; _validate(); }; diff --git a/imports/startup/client/index.js b/imports/startup/client/index.js index fd28136..d861493 100644 --- a/imports/startup/client/index.js +++ b/imports/startup/client/index.js @@ -1,3 +1,3 @@ -import './routes.jsx'; +import './routes.js'; Bert.defaults.style = 'growl-top-right'; diff --git a/imports/startup/client/routes.js b/imports/startup/client/routes.js new file mode 100644 index 0000000..e745042 --- /dev/null +++ b/imports/startup/client/routes.js @@ -0,0 +1,38 @@ +import React from 'react'; +import { render } from 'react-dom'; +import { Router, Route, Redirect, IndexRoute, browserHistory } from 'react-router'; + +import { App } from '../../ui/layouts/app'; +import { Documents } from '../../ui/pages/documents'; +import { Index } from '../../ui/pages/index'; +import { Login } from '../../ui/pages/login'; +import { NotFound } from '../../ui/pages/not-found'; +import { RecoverPassword } from '../../ui/pages/recover-password'; +import { ResetPassword } from '../../ui/pages/reset-password'; +import { Signup } from '../../ui/pages/signup'; + +const requireAuth = (nextState, replace) => { + if (!Meteor.loggingIn() && !Meteor.user()) { + replace({ + pathname: '/login', + state: { nextPathName: nextState.location.pathname }, + }); + } +}; + +Meteor.startup(() => { + render( + + + + + + + + + + + , + document.getElementById('react-root') + ); +}); diff --git a/imports/startup/client/routes.jsx b/imports/startup/client/routes.jsx deleted file mode 100644 index 40183e7..0000000 --- a/imports/startup/client/routes.jsx +++ /dev/null @@ -1,38 +0,0 @@ -import React from 'react'; -import { render } from 'react-dom'; -import { Router, Route, Redirect, IndexRoute, browserHistory } from 'react-router'; - -import { App } from '../../ui/layouts/app'; -import { Documents } from '../../ui/pages/documents'; -import { Index } from '../../ui/pages/index'; -import { Login } from '../../ui/pages/login'; -import { NotFound } from '../../ui/pages/not-found'; -import { RecoverPassword } from '../../ui/pages/recover-password'; -import { ResetPassword } from '../../ui/pages/reset-password'; -import { Signup } from '../../ui/pages/signup'; - -const requireAuth = ( nextState, replace ) => { - if ( !Meteor.loggingIn() && !Meteor.user() ) { - replace({ - pathname: '/login', - state: { nextPathName: nextState.location.pathname } - }); - } -}; - -Meteor.startup( () => { - render( - - - - - - - - - - - , - document.getElementById( 'react-root' ) - ); -}); diff --git a/imports/startup/server/accounts/email-templates.js b/imports/startup/server/accounts/email-templates.js index 9ee1ee5..ac5f017 100644 --- a/imports/startup/server/accounts/email-templates.js +++ b/imports/startup/server/accounts/email-templates.js @@ -1,19 +1,23 @@ -const name = 'Application Name', - email = '', - from = `${ name } ${ email }`, - emailTemplates = Accounts.emailTemplates; +const name = 'Application Name'; +const email = ''; +const from = `${name} ${email}`; +const emailTemplates = Accounts.emailTemplates; emailTemplates.siteName = name; -emailTemplates.from = from; +emailTemplates.from = from; emailTemplates.resetPassword = { subject() { - return `[${ name }] Reset Your Password`; + return `[${name}] Reset Your Password`; }, - text( user, url ) { - let userEmail = user.emails[ 0 ].address, - urlWithoutHash = url.replace( '#/', '' ); + text(user, url) { + const userEmail = user.emails[0].address; + const urlWithoutHash = url.replace('#/', ''); - return `A password reset has been requested for the account related to this address (${ userEmail }). To reset the password, visit the following link:\n\n${ urlWithoutHash }\n\n If you did not request this reset, please ignore this email. If you feel something is wrong, please contact our support team: ${ email }.`; - } + return `A password reset has been requested for the account related to this + address (${userEmail}). To reset the password, visit the following link: + \n\n${urlWithoutHash}\n\n If you did not request this reset, please ignore + this email. If you feel something is wrong, please contact our support team: + ${email}.`; + }, }; diff --git a/imports/startup/server/fixtures.js b/imports/startup/server/fixtures.js index 47351fe..11a4c6b 100644 --- a/imports/startup/server/fixtures.js +++ b/imports/startup/server/fixtures.js @@ -2,18 +2,14 @@ const users = [{ email: 'admin@admin.com', password: 'password', profile: { - name: { first: 'Carl', last: 'Winslow' } - } + name: { first: 'Carl', last: 'Winslow' }, + }, }]; -users.forEach( ( { email, password, profile } ) => { - const userExists = Meteor.users.findOne( { 'emails.address': email } ); +users.forEach(({ email, password, profile }) => { + const userExists = Meteor.users.findOne({ 'emails.address': email }); - if ( !userExists ) { - Accounts.createUser({ - email: email, - password: password, - profile: profile - }); + if (!userExists) { + Accounts.createUser({ email, password, profile }); } }); diff --git a/imports/ui/components/add-document.js b/imports/ui/components/add-document.js index d1d42a1..43596fd 100644 --- a/imports/ui/components/add-document.js +++ b/imports/ui/components/add-document.js @@ -2,19 +2,19 @@ import React from 'react'; import { Row, Col, ListGroup, ListGroupItem, Input, Alert } from 'react-bootstrap'; import { insertDocument } from '../../api/documents/methods.js'; -const handleInsertDocument = ( event ) => { - const target = event.target, - title = target.value.trim(); +const handleInsertDocument = (event) => { + const target = event.target; + const title = target.value.trim(); - if ( title !== '' && event.keyCode === 13 ) { + if (title !== '' && event.keyCode === 13) { insertDocument.call({ - title: title - }, ( error, response ) => { - if ( error ) { - Bert.alert( error.reason, 'danger' ); + title, + }, (error) => { + if (error) { + Bert.alert(error.reason, 'danger'); } else { target.value = ''; - Bert.alert( 'Document added!', 'success' ); + Bert.alert('Document added!', 'success'); } }); } @@ -26,4 +26,4 @@ export const AddDocument = () => ( onKeyUp={ handleInsertDocument } placeholder="Type a document title and press enter..." /> -) +); diff --git a/imports/ui/components/app-navigation.js b/imports/ui/components/app-navigation.js index 4b59706..1fb623d 100644 --- a/imports/ui/components/app-navigation.js +++ b/imports/ui/components/app-navigation.js @@ -5,7 +5,7 @@ import { PublicNavigation } from './public-navigation'; import { AuthenticatedNavigation } from './authenticated-navigation'; export class AppNavigation extends React.Component { - renderNavigation( hasUser ) { + renderNavigation(hasUser) { return hasUser ? : ; } @@ -18,7 +18,7 @@ export class AppNavigation extends React.Component { - { this.renderNavigation( this.props.hasUser ) } + { this.renderNavigation(this.props.hasUser) } ; } diff --git a/imports/ui/components/authenticated-navigation.js b/imports/ui/components/authenticated-navigation.js index daf036f..da4e9eb 100644 --- a/imports/ui/components/authenticated-navigation.js +++ b/imports/ui/components/authenticated-navigation.js @@ -3,16 +3,12 @@ import { browserHistory } from 'react-router'; import { IndexLinkContainer, LinkContainer } from 'react-router-bootstrap'; import { Nav, NavItem, NavDropdown, MenuItem } from 'react-bootstrap'; -const handleLogout = () => { - return Meteor.logout( () => browserHistory.push( '/login' ) ); -}; +const handleLogout = () => Meteor.logout(() => browserHistory.push('/login')); const userName = () => { const user = Meteor.user(); - if ( user ) { - const name = user && user.profile ? user.profile.name : ''; - return `${ name.first } ${ name.last }`; - } + const name = user && user.profile ? user.profile.name : ''; + return user ? `${name.first} ${name.last}` : ''; }; export const AuthenticatedNavigation = () => ( @@ -31,4 +27,4 @@ export const AuthenticatedNavigation = () => ( -) +); diff --git a/imports/ui/components/document.js b/imports/ui/components/document.js new file mode 100644 index 0000000..a181d40 --- /dev/null +++ b/imports/ui/components/document.js @@ -0,0 +1,57 @@ +import React from 'react'; +import { Row, Col, ListGroupItem, Input, Button } from 'react-bootstrap'; +import { updateDocument, removeDocument } from '../../api/documents/methods.js'; + +const handleUpdateDocument = (documentId, event) => { + const title = event.target.value.trim(); + if (title !== '' && event.keyCode === 13) { + updateDocument.call({ + _id: documentId, + update: { title }, + }, (error) => { + if (error) { + Bert.alert(error.reason, 'danger'); + } else { + Bert.alert('Document updated!', 'success'); + } + }); + } +}; + +const handleRemoveDocument = (documentId, event) => { + event.preventDefault(); + if (confirm('Are you sure? This is permanent.')) { + removeDocument.call({ + _id: documentId, + }, (error) => { + if (error) { + Bert.alert(error.reason, 'danger'); + } else { + Bert.alert('Document removed!', 'success'); + } + }); + } +}; + +export const Document = ({ document }) => ( + + + + + + + + + + +); diff --git a/imports/ui/components/documents-list.js b/imports/ui/components/documents-list.js index e8621e5..43bc48f 100644 --- a/imports/ui/components/documents-list.js +++ b/imports/ui/components/documents-list.js @@ -1,63 +1,12 @@ import React from 'react'; -import { Row, Col, ListGroup, ListGroupItem, Input, Button, Alert } from 'react-bootstrap'; -import { updateDocument, removeDocument } from '../../api/documents/methods.js'; +import { Row, Col, ListGroup, Alert } from 'react-bootstrap'; +import { Document } from './document.js'; -const handleUpdateDocument = ( documentId, event ) => { - const title = event.target.value.trim(); - if ( title !== '' && event.keyCode === 13 ) { - updateDocument.call({ - _id: documentId, - update: { title: title } - }, ( error, response ) => { - if ( error ) { - Bert.alert( error.reason, 'danger' ); - } - }); - } -}; - -const handleRemoveDocument = ( documentId, event ) => { - event.preventDefault(); - if ( confirm( 'Are you sure? This is permanent.' ) ) { - removeDocument.call({ - _id: documentId - }, ( error, response ) => { - if ( error ) { - Bert.alert( error.reason, 'danger' ); - } else { - Bert.alert( 'Document removed!', 'success' ); - } - }); - } -}; - -export const DocumentsList = ( { documents } ) => { - if ( documents.length > 0 ) { - return - {documents.map( ( { _id, title } ) => { - return - - - - - - - - - ; - })} - ; - } else { - return No documents yet.; - } -}; +export const DocumentsList = ({ documents }) => ( + documents.length > 0 ? + {documents.map((doc) => ( + + ))} + : + No documents yet. +); diff --git a/imports/ui/components/public-navigation.js b/imports/ui/components/public-navigation.js index d2147bf..a1f4e99 100644 --- a/imports/ui/components/public-navigation.js +++ b/imports/ui/components/public-navigation.js @@ -11,4 +11,4 @@ export const PublicNavigation = () => ( Log In -) +); diff --git a/imports/ui/containers/app-navigation.js b/imports/ui/containers/app-navigation.js index 834840a..21470a0 100644 --- a/imports/ui/containers/app-navigation.js +++ b/imports/ui/containers/app-navigation.js @@ -1,8 +1,8 @@ import { composeWithTracker } from 'react-komposer'; import { AppNavigation } from '../components/app-navigation'; -const composer = ( props, onData ) => { - onData( null, { hasUser: Meteor.user() } ); +const composer = (props, onData) => { + onData(null, { hasUser: Meteor.user() }); }; -export default composeWithTracker( composer, {}, {}, { pure: false } )( AppNavigation ); +export default composeWithTracker(composer, {}, {}, { pure: false })(AppNavigation); diff --git a/imports/ui/containers/documents-list.js b/imports/ui/containers/documents-list.js index 6ab90dc..178c4cd 100644 --- a/imports/ui/containers/documents-list.js +++ b/imports/ui/containers/documents-list.js @@ -3,12 +3,12 @@ import { composeWithTracker } from 'react-komposer'; import { Documents } from '../../api/documents/documents.js'; import { DocumentsList } from '../components/documents-list.js'; -const composer = ( params, onReady ) => { - const subscription = Meteor.subscribe( 'documents' ); - if ( subscription.ready() ) { - let documents = Documents.find().fetch(); - onReady( null, { documents } ); +const composer = (params, onReady) => { + const subscription = Meteor.subscribe('documents'); + if (subscription.ready()) { + const documents = Documents.find().fetch(); + onReady(null, { documents }); } }; -export default composeWithTracker( composer )( DocumentsList ); +export default composeWithTracker(composer)(DocumentsList); diff --git a/imports/ui/layouts/app.js b/imports/ui/layouts/app.js index ff254fe..65ebee9 100644 --- a/imports/ui/layouts/app.js +++ b/imports/ui/layouts/app.js @@ -6,7 +6,7 @@ export const App = React.createClass({ contextTypes: { router() { return React.PropTypes.func.isRequired; - } + }, }, render() { const { isActive } = this.context.router; @@ -16,5 +16,5 @@ export const App = React.createClass({ { this.props.children } ; - } + }, }); diff --git a/imports/ui/pages/documents.js b/imports/ui/pages/documents.js index 587372e..e4ff86b 100644 --- a/imports/ui/pages/documents.js +++ b/imports/ui/pages/documents.js @@ -11,4 +11,4 @@ export const Documents = () => ( -) +); diff --git a/imports/ui/pages/index.js b/imports/ui/pages/index.js index db9b464..1d75ae2 100644 --- a/imports/ui/pages/index.js +++ b/imports/ui/pages/index.js @@ -8,4 +8,4 @@ export const Index = () => (

Read the Documentation

Currently at v4.0.0

-) +); diff --git a/imports/ui/pages/login.js b/imports/ui/pages/login.js index 76bbc21..c7b10de 100644 --- a/imports/ui/pages/login.js +++ b/imports/ui/pages/login.js @@ -5,10 +5,10 @@ import { handleLogin } from '../../modules/login'; export class Login extends React.Component { componentDidMount() { - handleLogin( { component: this } ); + handleLogin({ component: this }); } - handleSubmit( event ) { + handleSubmit(event) { event.preventDefault(); } @@ -29,7 +29,13 @@ export class Login extends React.Component { Password Forgot Password? - + diff --git a/imports/ui/pages/not-found.js b/imports/ui/pages/not-found.js index 630f74f..d4d0412 100644 --- a/imports/ui/pages/not-found.js +++ b/imports/ui/pages/not-found.js @@ -6,4 +6,4 @@ export const NotFound = () => (

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

-) +); diff --git a/imports/ui/pages/recover-password.js b/imports/ui/pages/recover-password.js index 70fe682..882c771 100644 --- a/imports/ui/pages/recover-password.js +++ b/imports/ui/pages/recover-password.js @@ -4,10 +4,10 @@ import { handleRecoverPassword } from '../../modules/recover-password'; export class RecoverPassword extends React.Component { componentDidMount() { - handleRecoverPassword( { component: this } ); + handleRecoverPassword({ component: this }); } - handleSubmit( event ) { + handleSubmit(event) { event.preventDefault(); } @@ -15,7 +15,9 @@ export class RecoverPassword extends React.Component { return

Recover Password

- Enter your email address below to receive a link to reset your password. + + Enter your email address below to receive a link to reset your password. +

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. +