├── .gitignore
├── app
├── .meteor
│ ├── .gitignore
│ ├── release
│ ├── platforms
│ ├── .finished-upgraders
│ ├── .id
│ ├── packages
│ └── versions
├── lib
│ └── _namespace.jsx
├── scss.json
├── client
│ ├── stylesheets
│ │ └── main.scss
│ ├── components
│ │ ├── layouts
│ │ │ └── main
│ │ │ │ ├── MainLayout.jsx
│ │ │ │ ├── MainFooter.jsx
│ │ │ │ └── MainHeader.jsx
│ │ ├── public
│ │ │ └── Home.jsx
│ │ ├── users
│ │ │ ├── AuthErrors.jsx
│ │ │ └── UserLogin.jsx
│ │ └── general
│ │ │ └── FormInput.jsx
│ ├── head.html
│ └── routes.jsx
├── server
│ └── bootstrap.jsx
└── tests
│ └── jasmine
│ └── client
│ └── unit
│ ├── spec_helpers.js
│ └── UserLogin_spec.js
├── environments
├── build
│ └── settings.json
├── local
│ └── settings.json
└── production
│ └── settings.json
├── run.sh
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | .idea/
--------------------------------------------------------------------------------
/app/.meteor/.gitignore:
--------------------------------------------------------------------------------
1 | local
2 |
--------------------------------------------------------------------------------
/app/.meteor/release:
--------------------------------------------------------------------------------
1 | METEOR@1.1.0.3
2 |
--------------------------------------------------------------------------------
/app/.meteor/platforms:
--------------------------------------------------------------------------------
1 | server
2 | browser
3 |
--------------------------------------------------------------------------------
/app/lib/_namespace.jsx:
--------------------------------------------------------------------------------
1 | // This is the namespace for all components.
2 | C = {};
--------------------------------------------------------------------------------
/environments/build/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "public": {},
3 | "private": {}
4 | }
--------------------------------------------------------------------------------
/environments/local/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "public": {},
3 | "private": {}
4 | }
--------------------------------------------------------------------------------
/environments/production/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "public": {},
3 | "private": {}
4 | }
--------------------------------------------------------------------------------
/app/scss.json:
--------------------------------------------------------------------------------
1 | {
2 | "enableAutoprefixer": true,
3 | "autoprefixerOptions": {
4 | "browsers": ["> 5%"],
5 | "cascade": false
6 | }
7 | }
--------------------------------------------------------------------------------
/app/client/stylesheets/main.scss:
--------------------------------------------------------------------------------
1 | @import '.meteor/local/build/programs/server/assets/packages/reywood_bootstrap3-sass/bootstrap';
2 |
3 | // NAVBAR
4 | .navbar {
5 | margin-bottom: 0px;
6 | }
--------------------------------------------------------------------------------
/app/.meteor/.finished-upgraders:
--------------------------------------------------------------------------------
1 | # This file contains information which helps Meteor properly upgrade your
2 | # app when you run 'meteor update'. You should check it into version control
3 | # with your project.
4 |
5 | notices-for-0.9.0
6 | notices-for-0.9.1
7 | 0.9.4-platform-file
8 | notices-for-facebook-graph-api-2
9 |
--------------------------------------------------------------------------------
/app/client/components/layouts/main/MainLayout.jsx:
--------------------------------------------------------------------------------
1 | C.MainLayout = React.createClass({
2 | render() {
3 | return (
4 |
5 | {this.props.header}
6 |
7 | {this.props.content}
8 |
9 | {this.props.footer}
10 |
11 | )
12 | }
13 | });
--------------------------------------------------------------------------------
/app/server/bootstrap.jsx:
--------------------------------------------------------------------------------
1 | if(Meteor.isServer) {
2 |
3 | Meteor.startup(() => {
4 |
5 | if (Meteor.users.find().count() === 0) {
6 | Accounts.createUser({
7 | email: "ryancswapp@gmail.com",
8 | password: "foodbars"
9 | });
10 | }
11 |
12 | });
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/app/.meteor/.id:
--------------------------------------------------------------------------------
1 | # This file contains a token that is unique to your project.
2 | # Check it into your repository along with the rest of this directory.
3 | # It can be used for purposes such as:
4 | # - ensuring you don't accidentally deploy one app on top of another
5 | # - providing package authors with aggregated statistics
6 |
7 | 1fhfeq51kibzrp1keyvk7
8 |
--------------------------------------------------------------------------------
/app/client/components/layouts/main/MainFooter.jsx:
--------------------------------------------------------------------------------
1 | C.MainFooter = React.createClass({
2 | render() {
3 | return (
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | )
13 | }
14 | });
--------------------------------------------------------------------------------
/app/tests/jasmine/client/unit/spec_helpers.js:
--------------------------------------------------------------------------------
1 | TestUtils = React.addons.TestUtils;
2 | Simulate = TestUtils.Simulate;
3 |
4 |
5 | renderComponent = function (comp, props) {
6 | return TestUtils.renderIntoDocument(
7 | React.createElement(comp, props)
8 | );
9 | };
10 |
11 | simulateClickOn = function($el) {
12 | React.addons.TestUtils.Simulate.click($el[0]);
13 | };
14 |
15 |
--------------------------------------------------------------------------------
/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | #export VELOCITY_DEBUG=0
4 |
5 | # these are about to get canned
6 | #export JASMINE_CLIENT_UNIT=0
7 | #export JASMINE_SERVER_UNIT=0
8 | #
9 | #export JASMINE_CLIENT_INTEGRATION=1
10 | #export JASMINE_SERVER_INTEGRATION=1
11 | #export CUCUMBER=1
12 | #
13 | #if [ "$1" = "--test" ]; then
14 | # export CUCUMBER_TAIL=1;
15 | #fi
16 |
17 | cd app
18 | meteor $1 --settings ../environments/local/settings.json
--------------------------------------------------------------------------------
/app/client/components/public/Home.jsx:
--------------------------------------------------------------------------------
1 | C.Home = React.createClass({
2 | render() {
3 | return (
4 |
5 |
6 |
React Meteor Template
7 |
A starting point for React apps built on Meteor
8 |
9 |
10 | )
11 | }
12 | });
--------------------------------------------------------------------------------
/app/client/head.html:
--------------------------------------------------------------------------------
1 |
2 | React Meteor Template
3 |
4 |
5 |
6 |
7 |
11 |
--------------------------------------------------------------------------------
/app/client/routes.jsx:
--------------------------------------------------------------------------------
1 | FlowRouter.route("/", {
2 | name: 'Home',
3 | subscriptions(params) {
4 |
5 | },
6 | action(params) {
7 | renderMainLayoutWith();
8 | }
9 | });
10 |
11 | FlowRouter.route("/login", {
12 | name: "Login",
13 | subscriptions(params) {
14 |
15 | },
16 | action(params) {
17 | renderMainLayoutWith();
18 | }
19 | });
20 |
21 | function renderMainLayoutWith(component) {
22 | ReactLayout.render(C.MainLayout, {
23 | header: ,
24 | content: component,
25 | footer:
26 | });
27 | }
--------------------------------------------------------------------------------
/app/client/components/users/AuthErrors.jsx:
--------------------------------------------------------------------------------
1 | C.AuthErrors = React.createClass({
2 | propTypes: {
3 | errors: React.PropTypes.object
4 | },
5 | render() {
6 | if (this.props.errors) {
7 | return (
8 |
9 | {
10 | _.values(this.props.errors).map((errorMessage) => {
11 | return - {errorMessage}
;
12 | })
13 | }
14 |
15 | )
16 | }
17 | }
18 | });
--------------------------------------------------------------------------------
/app/.meteor/packages:
--------------------------------------------------------------------------------
1 | # Meteor packages used by this project, one per line.
2 | # Check this file (and the other files in this directory) into your repository.
3 | #
4 | # 'meteor add' and 'meteor remove' will edit this file for you,
5 | # but you can also edit it by hand.
6 |
7 | meteor-platform
8 | react
9 | kadira:flow-router
10 | kadira:react-layout
11 | meteorhacks:flow-layout
12 | aldeed:collection2
13 | matb33:collection-hooks
14 | dburles:collection-helpers
15 | underscore
16 | fourseven:scss
17 | reywood:bootstrap3-sass
18 | http
19 | accounts-password
20 |
21 | ## I have commented out the testing packages because I don't like them
22 | ## to run while I'm developing. The more tests you add the slower your
23 | ## app gets.
24 |
25 | # sanjo:jasmine
26 | # velocity:html-reporter
27 |
--------------------------------------------------------------------------------
/app/tests/jasmine/client/unit/UserLogin_spec.js:
--------------------------------------------------------------------------------
1 | describe("UserLogin", function () {
2 | var defProps, renderWithProps, component, el, $el;
3 |
4 | beforeEach(function() {
5 | defProps = {
6 |
7 | };
8 | renderWithProps = function(props) {
9 | component = renderComponent(C.UserLogin, props);
10 | el = React.findDOMNode(component);
11 | $el = $(el);
12 | };
13 | });
14 |
15 | // Text
16 |
17 | it("should have the title Login", function() {
18 | renderWithProps({});
19 | expect($el.find('h1').text()).toBe('Login');
20 | });
21 |
22 | // State
23 |
24 | it("should have a default state that holds an empty error object", function() {
25 | renderWithProps({});
26 | expect(component.state.errors).toEqual({});
27 | });
28 |
29 | });
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Meteor Template
2 |
3 | This is a boilerplate template for a Meteor.js app that uses React.js as the view layer
4 |
5 | ## NOTE
6 |
7 | The first time you run this app it will fail. This is because it is using the reywood:bootstrap3-sass package. If you restart the app after it crashes it will then work from that point on. Check out the "To use" section [here](https://atmospherejs.com/reywood/bootstrap3-sass) for more info.
8 |
9 | ## Install
10 |
11 | Run the following to get the bash file to work:
12 |
13 | ```
14 | chmod +x ./run.sh
15 | ```
16 |
17 | Now you can start the app with the following command:
18 |
19 | ```
20 | ./run.sh
21 | ```
22 |
23 | ## Included Packages
24 |
25 | react
26 |
27 | meteorhacks:flow-router
28 |
29 | kadira:react-layout
30 |
31 | meteorhacks:flow-layout
32 |
33 | aldeed:collection2
34 |
35 | matb33:collection-hooks
36 |
37 | dburles:collection-helpers
38 |
39 | underscore
40 |
41 | fourseven:scss
42 |
43 | reywood:bootstrap3-sass
44 |
45 | http
46 |
47 | accounts-password
48 |
49 | sanjo:jasmine
50 |
51 | velocity:html-reporter
52 |
53 | ## Included Components
54 |
55 | MainLayout
56 |
57 | MainHeader
58 |
59 | MainFooter
60 |
61 | UserLogin
62 |
63 | FormInput
64 |
65 | AuthErrors
66 |
--------------------------------------------------------------------------------
/app/.meteor/versions:
--------------------------------------------------------------------------------
1 | accounts-base@1.2.0
2 | accounts-password@1.1.1
3 | aldeed:collection2@2.3.3
4 | aldeed:simple-schema@1.3.3
5 | autoupdate@1.2.1
6 | babel-compiler@5.8.3_1
7 | babel-runtime@0.1.3
8 | base64@1.0.3
9 | binary-heap@1.0.3
10 | blaze@2.1.2
11 | blaze-tools@1.0.3
12 | boilerplate-generator@1.0.3
13 | callback-hook@1.0.3
14 | check@1.0.5
15 | coffeescript@1.0.6
16 | cosmos:browserify@0.5.0
17 | dburles:collection-helpers@1.0.3
18 | ddp@1.1.0
19 | deps@1.0.7
20 | ejson@1.0.6
21 | email@1.0.6
22 | fastclick@1.0.3
23 | fourseven:scss@3.2.0
24 | geojson-utils@1.0.3
25 | html-tools@1.0.4
26 | htmljs@1.0.4
27 | http@1.1.0
28 | id-map@1.0.3
29 | jquery@1.11.3_2
30 | json@1.0.3
31 | jsx@0.1.5
32 | kadira:react-layout@1.2.0
33 | launch-screen@1.0.2
34 | livedata@1.0.13
35 | localstorage@1.0.3
36 | logging@1.0.7
37 | matb33:collection-hooks@0.7.13
38 | meteor@1.1.6
39 | meteor-platform@1.2.2
40 | meteorhacks:flow-layout@1.4.2
41 | meteorhacks:flow-router@1.19.0
42 | minifiers@1.1.5
43 | minimongo@1.0.8
44 | mobile-status-bar@1.0.3
45 | mongo@1.1.0
46 | npm-bcrypt@0.7.8_2
47 | observe-sequence@1.0.6
48 | ordered-dict@1.0.3
49 | random@1.0.3
50 | react@0.1.4
51 | react-meteor-data@0.1.2
52 | react-runtime@0.13.3_2
53 | react-runtime-dev@0.13.3_2
54 | react-runtime-prod@0.13.3_1
55 | reactive-dict@1.1.0
56 | reactive-var@1.0.5
57 | reload@1.1.3
58 | retry@1.0.3
59 | reywood:bootstrap3-sass@3.3.5_1
60 | routepolicy@1.0.5
61 | service-configuration@1.0.4
62 | session@1.1.0
63 | sha@1.0.3
64 | spacebars@1.0.6
65 | spacebars-compiler@1.0.6
66 | srp@1.0.3
67 | templating@1.1.1
68 | tracker@1.0.7
69 | ui@1.0.6
70 | underscore@1.0.3
71 | url@1.0.4
72 | webapp@1.2.0
73 | webapp-hashing@1.0.3
74 |
--------------------------------------------------------------------------------
/app/client/components/general/FormInput.jsx:
--------------------------------------------------------------------------------
1 | C.FormInput = React.createClass({
2 | propTypes: {
3 | hasError: React.PropTypes.bool,
4 | label: React.PropTypes.string,
5 | type: React.PropTypes.string,
6 | name: React.PropTypes.string,
7 | value: React.PropTypes.string,
8 | onKeyUp: React.PropTypes.func,
9 | onBlur: React.PropTypes.func
10 | },
11 | shouldComponentUpdate() {
12 | return true;
13 | },
14 | render() {
15 | const {type, label, name, value, onKeyUp, onBlur } = this.props;
16 | let inputType;
17 |
18 | var className = "form-group";
19 | if (this.props.hasError) {
20 | className += " has-error";
21 | }
22 |
23 | switch (type) {
24 | case "textarea":
25 | inputType = (
26 |
27 | );
28 | break;
29 | default:
30 | inputType = (
31 |
32 | );
33 | break;
34 | }
35 |
36 |
37 | return (
38 |
39 | { label === "none" ? "" : }
40 | { inputType }
41 |
42 | )
43 |
44 | }
45 | });
--------------------------------------------------------------------------------
/app/client/components/layouts/main/MainHeader.jsx:
--------------------------------------------------------------------------------
1 | C.MainHeader = React.createClass({
2 | mixins: [ReactMeteorData],
3 | getMeteorData() {
4 | return {
5 | currentUser: Meteor.user()
6 | }
7 | },
8 | handleLogout() {
9 | Meteor.logout();
10 | },
11 | render() {
12 | let loginButton;
13 | let { currentUser } = this.data;
14 |
15 | if (currentUser) {
16 | loginButton = (
17 | Logout
18 | )
19 | } else {
20 | loginButton = (
21 | Login
22 | )
23 | }
24 |
25 | return (
26 |
46 | )
47 | }
48 | });
--------------------------------------------------------------------------------
/app/client/components/users/UserLogin.jsx:
--------------------------------------------------------------------------------
1 | C.UserLogin = React.createClass({
2 | mixins: [],
3 | PropTypes: {
4 |
5 | },
6 | getInitialState() {
7 | return {
8 | errors: {}
9 | }
10 | },
11 | getMeteorData() {
12 | return {
13 |
14 | }
15 | },
16 | onSubmit(event) {
17 | event.preventDefault();
18 |
19 | var email = $(event.target).find("[name=email]").val();
20 | var password = $(event.target).find("[name=password]").val();
21 |
22 | var errors = {};
23 |
24 | if (!email) {
25 | errors.email = "Email required"
26 | }
27 |
28 | if (!password) {
29 | errors.password = "Password required"
30 | }
31 |
32 | this.setState({
33 | errors: errors
34 | });
35 |
36 | if (! _.isEmpty(errors)) {
37 | return;
38 | }
39 |
40 | Meteor.loginWithPassword(email, password, (err) => {
41 | if (err) {
42 | this.setState({
43 | errors: {'none': err.reason}
44 | });
45 |
46 | return;
47 | } else {
48 | FlowRouter.go('Home');
49 | }
50 | });
51 | },
52 | render() {
53 | return (
54 |
55 |
56 |
57 |
Login
58 |
59 |
65 |
66 |
67 |
68 | )
69 | }
70 | });
71 |
--------------------------------------------------------------------------------