diff --git a/.babelrc b/.babelrc
index b7ba315..342a80c 100644
--- a/.babelrc
+++ b/.babelrc
@@ -1,15 +1,31 @@
{
"env": {
- "server": {
+ "node": {
"presets": [ "es2015-node6" ],
"plugins": [
"add-module-exports"
]
},
- "client": {
- "presets": [ "es2015", "react" ],
+ "node-jsx": {
+ "presets": [ "es2015-node6" ],
"plugins": [
- "add-module-exports"
+ "add-module-exports",
+ ["transform-react-jsx", { "pragma": "h" }],
+ ["jsx-node/babel/alias", {
+ "lowline": "lodash",
+ "preact": "jsx-node"
+ }],
+ ["jsx-node/babel/stringify"]
+ ]
+ },
+ "rollup": {
+ "include": [
+ "node_modules/preact/**",
+ "client/**"
+ ],
+ "presets": [ "es2015-rollup" ],
+ "plugins": [
+ ["transform-react-jsx", { "pragma":"h" }]
]
}
}
diff --git a/.eslintrc b/.eslintrc
index ca97434..709de85 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,52 +1,14 @@
{
- "extends": "airbnb-base",
-
- "parserOptions": {
- "sourceType": "strict"
- },
-
- "env": {
- "mocha": true
- },
-
"rules": {
- "semi": [ 2, "never" ],
- "import/no-extraneous-dependencies": ["error", {"devDependencies": true, "optionalDependencies": false, "peerDependencies": false}],
- "new-cap": 0,
- "no-mixed-operators": 0,
- "no-cond-assign": 0,
- "guard-for-in": 0,
- "global-require": 0,
- "no-underscore-dangle": 0,
- "object-shorthand": 0,
- "default-case": 0,
- "one-var": 0,
- "prefer-rest-params": 0,
- "no-unused-vars": [ 2, { "args": "none" } ],
- "no-alert": 0,
- "quote-props": 0,
- "no-nested-ternary": 0,
- "no-use-before-define": [2, { "functions": false, "classes": true }],
- "consistent-return": 0,
- "no-eval": 0,
- "prefer-arrow-callback": 0,
- "array-bracket-spacing": 0,
- "no-console": 0,
- "indent": [ 2, 2, { "SwitchCase": 1 }],
- "max-len": 0,
- "comma-dangle": 0,
- "no-param-reassign": 0,
- "prefer-template": 0,
- "curly": 0,
+ "arrow-parens": [2, "always"],
+ "class-methods-use-this": 0,
"func-names": 0,
+ "import/no-unresolved": [2, { "ignore": ["^[^./]"] }],
+ "no-console": [1, { "allow": ["warn", "error", "info"] }],
+ "no-empty": [2, { "allowEmptyCatch": true }],
+ "no-mixed-operators": 0,
+ "no-param-reassign": 0,
"no-shadow": 0,
- "spaced-comment": 0,
- "strict": [ 2, "global" ]
- },
-
- "globals": {
- "PWD": true,
- "ENV": true,
- "location": true
+ "no-underscore-dangle": 0
}
}
diff --git a/.gitignore b/.gitignore
index 76772cd..0aa8205 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,7 +31,9 @@ npm-debug.log
# Bower dependency directory
bower_components
-*.marko.js
+.tern-port
+
+/build
/dump
diff --git a/client/.eslintrc b/client/.eslintrc
index 2349eb6..5601a6f 100644
--- a/client/.eslintrc
+++ b/client/.eslintrc
@@ -1,49 +1,25 @@
{
- "extends": "airbnb",
+ "extends": [
+ "airbnb",
+ "../.eslintrc"
+ ],
"rules": {
- "semi": [ 2, "never" ],
- "no-confusing-arrow": 0,
+ "react/react-in-jsx-scope": 0,
"react/prop-types": 0,
- "guard-for-in": 0,
- "global-require": 0,
- "no-underscore-dangle": 0,
- "object-shorthand": 0,
- "default-case": 0,
- "one-var": 0,
- "prefer-rest-params": 0,
- "no-unused-vars": [ 2, { "args": "none" } ],
- "no-alert": 0,
- "quote-props": 0,
- "no-nested-ternary": 0,
- "no-use-before-define": [2, { "functions": false, "classes": true }],
- "consistent-return": 0,
- "no-eval": 0,
- "prefer-arrow-callback": 0,
- "array-bracket-spacing": 0,
- "no-console": 0,
- "indent": [ 2, 2, { "SwitchCase": 1 }],
- "max-len": 0,
- "comma-dangle": 0,
- "no-param-reassign": 0,
- "prefer-template": 0,
- "curly": 0,
- "func-names": 0,
- "no-shadow": 0,
- "spaced-comment": 0,
- "strict": [ 2, "global" ]
+ "react/no-unknown-property": 0,
+ "jsx-a11y/label-has-for": 0
},
-
+
"env": {
"browser": true
},
"globals": {
- "ENV": true,
- "google": true,
- "INITIAL_STATE": true,
- "INITIAL_CONTEXT": true,
- "PWD": true,
- "$": true
- }
+ "ga": true,
+ "$": true,
+ "_": true,
+ "Backbone": true,
+ "INITIAL_CONTEXT": true
+ }
}
diff --git a/client/app.js b/client/app.js
deleted file mode 100644
index 0d71957..0000000
--- a/client/app.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import { $ } from 'dollr'
-
-import './process'
-
-import Timer from './components/Timer'
-
-$(() => {
- // request permission on page load
- if (!Notification) {
- alert('Desktop notifications not available in your browser. Try Chromium, Chrome or Firefox.')
- return
- }
-
- if (Notification.permission !== 'granted')
- Notification.requestPermission()
-
- const timer = $('.timer')
-
- Timer.render().replace(timer).getWidget()
-})
diff --git a/client/app.jsx b/client/app.jsx
new file mode 100644
index 0000000..a8e237f
--- /dev/null
+++ b/client/app.jsx
@@ -0,0 +1,15 @@
+import { h, render } from 'preact';
+import Layout from './components/Layout.jsx';
+
+// request permission on page load
+if (!Notification) {
+ alert('Desktop notifications not available in your browser. Try Chromium, Chrome or Firefox.');
+}
+
+if (Notification.permission !== 'granted') {
+ Notification.requestPermission();
+}
+
+render((
+
+), null, document.getElementById('app'));
diff --git a/client/components/Layout.jsx b/client/components/Layout.jsx
new file mode 100644
index 0000000..4387010
--- /dev/null
+++ b/client/components/Layout.jsx
@@ -0,0 +1,12 @@
+import { h } from 'preact';
+
+import Timer from './Timer.jsx';
+
+export default () => (
+
+
+ Pomodoro Time!
+
+
+
+);
diff --git a/client/components/Timer.jsx b/client/components/Timer.jsx
new file mode 100644
index 0000000..3a31efd
--- /dev/null
+++ b/client/components/Timer.jsx
@@ -0,0 +1,109 @@
+import { h, Component } from 'preact';
+
+import { bindAll } from 'lowline';
+
+import timeFilter from '../util/time-filter';
+
+const length = 25 * 60 * 1000;
+
+export default class Timer extends Component {
+ constructor() {
+ super();
+
+ this.state = {
+ time: length,
+ totalTime: length,
+ startTime: undefined,
+ };
+
+ bindAll(this, ['start', 'pause', 'reset', 'updateTimer', 'end']);
+ }
+
+ componentDidMount() {
+ this.reset();
+ }
+
+ start() {
+ this.setState({
+ startTime: Date.now(),
+ });
+
+ this.interval = setInterval(this.updateTimer.bind(this), 10);
+ }
+
+ pause() {
+ clearInterval(this.interval);
+ }
+
+ reset() {
+ clearInterval(this.interval);
+
+ this.setState({
+ time: length,
+ totalTime: length,
+ startTime: undefined,
+ });
+ }
+
+ updateTimer() {
+ let time = this.state.totalTime - (Date.now() - this.state.startTime);
+
+ if (time <= 0) {
+ this.pause();
+
+ this.end();
+
+ time = 0;
+ }
+
+ document.title = timeFilter(time).slice(0, 5);
+
+ this.setState({
+ time,
+ });
+ }
+
+ end() {
+ const data = {
+ startTime: this.state.startTime,
+ endTime: new Date(),
+ };
+
+ document.title = 'Pling!';
+
+ if (Notification.permission !== 'granted') {
+ Notification.requestPermission();
+ } else {
+ const notification = new Notification('Pomodoro complete!', {
+ icon: 'https://www.planetnatural.com/wp-content/uploads/2014/03/tomato-supplies.jpg',
+ body: 'Time for a break!',
+ });
+ }
+
+ fetch('/api/pomodoros', {
+ method: 'POST',
+ body: JSON.stringify(data),
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ })
+ .then((response) => response.json())
+ .then((json) => {
+ console.log('succes');
+ });
+ }
+
+ render(props, state) {
+ return (
+
+
{timeFilter(state.time || 0)}
+
+
+
+
+
+
+ );
+ }
+}
diff --git a/client/components/Timer/index.js b/client/components/Timer/index.js
deleted file mode 100644
index d5b0ffd..0000000
--- a/client/components/Timer/index.js
+++ /dev/null
@@ -1,93 +0,0 @@
-import markoWidgets from 'marko-widgets'
-import template from './template.marko'
-
-import timeFilter from '../../util/time-filter'
-
-const length = 25 * 60 * 1000
-
-export default markoWidgets.defineComponent({
- template,
-
- componentDidMount() {
- this.reset()
- },
-
- start(e) {
- this.setState({
- startTime: Date.now()
- })
-
- this.interval = setInterval(this.updateTimer.bind(this), 10)
- },
-
- pause(e) {
- clearInterval(this.interval)
- },
-
- reset(e) {
- clearInterval(this.interval)
-
- this.setState({
- time: length,
- totalTime: length,
- startTime: undefined
- })
- },
-
- updateTimer() {
- let time = this.state.totalTime - (Date.now() - this.state.startTime)
-
- if (time <= 0) {
- this.pause()
-
- this.end()
-
- time = 0
- }
-
- document.title = timeFilter(time).slice(0, 5)
-
- this.setState({
- time
- })
- },
-
- end(time) {
- const data = {
- startTime: this.state.startTime,
- endTime: new Date()
- }
-
- document.title = 'Pling!'
-
- if (Notification.permission !== 'granted')
- Notification.requestPermission()
- else {
- const notification = new Notification('Pomodoro complete!', {
- icon: 'https://www.planetnatural.com/wp-content/uploads/2014/03/tomato-supplies.jpg',
- body: 'Time for a break!',
- })
- }
-
- fetch('/api/pomodoros', {
- method: 'POST',
- body: JSON.stringify(data),
- headers: {
- 'Accept': 'application/json',
- 'Content-Type': 'application/json'
- }
- })
- .then((response) => response.json())
- .then((json) => {
- console.log('succes')
- })
- },
-
- getInitialState(input) {
- return {
- time: length,
- totalTime: length,
- startTime: undefined
- }
- }
-})
diff --git a/client/components/Timer/template.marko b/client/components/Timer/template.marko
deleted file mode 100644
index b4e394a..0000000
--- a/client/components/Timer/template.marko
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
${time(data.time || 0)}
-
-
-
-
-
-
diff --git a/client/error.jsx b/client/error.jsx
new file mode 100644
index 0000000..1aff65f
--- /dev/null
+++ b/client/error.jsx
@@ -0,0 +1,5 @@
+export default function () {
+
+}
diff --git a/client/error.marko b/client/error.marko
deleted file mode 100644
index e183c9c..0000000
--- a/client/error.marko
+++ /dev/null
@@ -1,3 +0,0 @@
-
diff --git a/client/marko.json b/client/marko.json
deleted file mode 100644
index 30247b3..0000000
--- a/client/marko.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "tags-dir": [ "./components" ]
-}
diff --git a/client/master.jsx b/client/master.jsx
new file mode 100644
index 0000000..eac0c3a
--- /dev/null
+++ b/client/master.jsx
@@ -0,0 +1,25 @@
+import Layout from './components/Layout.jsx';
+
+export default ({ css, js }) => (
+ '' + (
+
+
+ Pomodoro
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+);
diff --git a/client/master.marko b/client/master.marko
deleted file mode 100644
index 95f6352..0000000
--- a/client/master.marko
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
- Pomodoro
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Pomodoro Time!
-
-
-
-
-
-
diff --git a/client/process.js b/client/process.js
deleted file mode 100644
index 52f3b4b..0000000
--- a/client/process.js
+++ /dev/null
@@ -1,7 +0,0 @@
-window.process = {
- browser: true,
- env: {},
- nextTick: (fnc) => {
- setTimeout(fnc)
- }
-}
diff --git a/client/routes.js b/client/routes.js
deleted file mode 100644
index 8144921..0000000
--- a/client/routes.js
+++ /dev/null
@@ -1,45 +0,0 @@
-export default {
- '': {
- name: '',
- //view: PageView,
- template: require('./pages/index.marko'),
- //subviews: {
- // newsletterForm: [ '.newsletter', require('./views/newsletter-form') ]
- //}
- widget: require('./pages/index')
- },
-
- 'samarbetspartners': {
- //view: 'Page'
- },
-
- 'om-oss': {
- name: 'om-oss',
- template: require('./pages/om-oss.marko'),
- //view: PageView,
- widget: require('./pages/om-oss')
- },
-
- 'nyhetsbrev': {
- name: 'nyhetsbrev',
- template: require('./pages/nyhetsbrev.marko'),
- //view: PageView,
- widget: require('./pages/nyhetsbrev'),
- //subviews: {
- // newsletterForm: [ '.newsletter-form', require('./components/newsletter-form/view') ]
- //},
- },
-
-
- 'kontakt': {
- name: 'kontakt',
- //view: PageView,
- template: require('./pages/kontakt.marko'),
- widget: require('./pages/kontakt'),
- //subviews: {
- // googleMap: [ '#map-canvas', require('./views/google-map') ],
- // contactForm: [ '.contact-form', require('./components/contact-form/view') ],
- // newsletterForm: [ '.nyhetsbrev', require('./views/newsletter-form') ]
- //}
- }
-};
diff --git a/client/util/split-time.js b/client/util/split-time.js
index 5ec196f..a77c992 100644
--- a/client/util/split-time.js
+++ b/client/util/split-time.js
@@ -1,17 +1,17 @@
-const divs = [ 60, 100, 10 ]
+const divs = [60, 100, 10];
export default function (time) {
- const arr = []
+ const arr = [];
for (let i = 0; i < divs.length; i++) {
- const nbr = divs.slice(i).reduce((a, b) => a * b)
+ const nbr = divs.slice(i).reduce((a, b) => a * b);
- const result = Math.floor(time / nbr)
+ const result = Math.floor(time / nbr);
- arr.push(result)
+ arr.push(result);
- time = time - result * nbr
- //this.timerElements[i].textContent = result
+ time = time - result * nbr;
+ // this.timerElements[i].textContent = result
}
- return arr
+ return arr;
}
diff --git a/client/util/time-filter.js b/client/util/time-filter.js
index eb6e67f..90883c1 100644
--- a/client/util/time-filter.js
+++ b/client/util/time-filter.js
@@ -1,8 +1,8 @@
-import splitTime from './split-time'
-import twoDigits from './two-digits'
+import splitTime from './split-time';
+import twoDigits from './two-digits';
export default function (time) {
- const arr = splitTime(time).map(twoDigits)
+ const arr = splitTime(time).map(twoDigits);
- return arr.join(':')
+ return arr.join(':');
}
diff --git a/client/util/two-digits.js b/client/util/two-digits.js
index b8500b6..87b7ffc 100644
--- a/client/util/two-digits.js
+++ b/client/util/two-digits.js
@@ -1,3 +1,3 @@
export default function twoDigits(val) {
- return val >= 10 ? val : '0' + val
+ return val >= 10 ? val : `0${val}`;
}
diff --git a/gulp b/gulp
index f69b449..349bb1f 160000
--- a/gulp
+++ b/gulp
@@ -1 +1 @@
-Subproject commit f69b4494ab2bc55edb09d503396f94bf8b457496
+Subproject commit 349bb1f3a91a4675b5ec3e8b907d8ae2daf39129
diff --git a/gulpconfig.js b/gulpconfig.js
new file mode 100644
index 0000000..d682633
--- /dev/null
+++ b/gulpconfig.js
@@ -0,0 +1,13 @@
+'use strict';
+
+// modules > native
+module.exports = {
+ rollup: {
+ entries: [
+ 'client/app.jsx',
+ ],
+ outputs: [
+ 'app.js',
+ ],
+ },
+};
diff --git a/gulpfile.js b/gulpfile.js
index 4c7951b..0f1e7d6 120000
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -1 +1 @@
-gulp/index.js
\ No newline at end of file
+gulp/gulpfile.js
\ No newline at end of file
diff --git a/package.json b/package.json
index 517975c..4151643 100644
--- a/package.json
+++ b/package.json
@@ -1,12 +1,12 @@
{
- "name": "budbilar",
+ "name": "pomodoro",
"version": "0.0.1",
"description": "När du vill få något budat till rätt pris.",
"main": "server/server.js",
"private": true,
"repository": {
"type": "git",
- "url": "git@gitlab.thecodebureau.com:axel/budbilar.git"
+ "url": "git@gitlab.bitmill.co:lohfu/pomodoro.git"
},
"scripts": {
"gulp": "gulp",
@@ -16,67 +16,30 @@
"start": "node server/server.js"
},
"dependencies": {
- "babel-preset-es2015-node6": "^0.3.0",
- "babel-register": "^6.14.0",
+ "babel-preset-es2015-node6": "^0.4.0",
+ "babel-register": "^6.18.0",
"body-parser": "^1.15.2",
"chalk": "^1.1.3",
"connect-redis": "^3.1.0",
"cookie-parser": "^1.4.3",
- "dollr": "0.0.9",
+ "dollr": "^0.1.1",
"express": "^4.14.0",
"express-service-errors": "github:thecodebureau/express-service-errors",
- "express-session": "^1.14.1",
- "lodash": "^4.15.0",
- "marko": "^3.10.1",
- "marko-widgets": "^6.3.4",
- "midwest": "0.0.2",
- "midwest-module-membership": "github:thebitmill/midwest-module-membership",
- "midwest-service-errors": "github:thebitmill/midwest-service-errors",
- "mongoose": "^4.6.0",
+ "express-session": "^1.14.2",
+ "hyperscript-jsx": "0.0.2",
+ "jsx-node": "^0.1.0",
+ "lodash": "^4.16.6",
+ "lowline": "^0.1.1",
+ "midwest": "^0.2.1",
+ "midwest-module-membership": "^0.1.0",
+ "midwest-service-errors": "^0.0.3",
+ "mongoose": "^4.6.6",
"mongopot": "github:lohfu/mongopot",
"morgan": "^1.7.0",
- "nodemailer": "^2.6.0",
+ "nodemailer": "^2.6.4",
"passport": "^0.3.2",
"passport-local": "^1.0.0",
- "require-dir": "^0.3.0"
- },
- "devDependencies": {
- "autoprefixer": "^6.4.1",
- "babel-plugin-add-module-exports": "^0.2.1",
- "babel-preset-es2015": "^6.14.0",
- "babel-preset-react": "^6.11.1",
- "browser-sync": "^2.16.0",
- "chalk": "^1.1.3",
- "csswring": "^5.1.0",
- "eslint": "^3.5.0",
- "eslint-config-airbnb": "^11.1.0",
- "eslint-config-airbnb-base": "^7.1.0",
- "eslint-plugin-import": "^1.15.0",
- "eslint-plugin-jsx-a11y": "^2.2.2",
- "eslint-plugin-react": "^6.2.2",
- "event-stream": "^3.3.4",
- "gulp": "github:gulpjs/gulp#4.0",
- "gulp-less": "^3.1.0",
- "gulp-postcss": "^6.2.0",
- "gulp-rename": "^1.2.2",
- "gulp-sourcemaps": "^1.6.0",
- "gulp-svgmin": "^1.2.2",
- "gulp-uglify": "^2.0.0",
- "gulp-util": "^3.0.7",
- "marko": "^3.10.1",
- "mkdirp": "^0.5.1",
- "nodemon": "^1.10.2",
- "postcss": "^5.2.0",
- "pretty-hrtime": "^1.0.2",
- "rimraf": "^2.5.4",
- "rollup": "^0.35.10",
- "rollup-plugin-babel": "^2.6.1",
- "rollup-plugin-commonjs": "^3.3.0",
- "rollup-plugin-marko": "0.0.2",
- "rollup-plugin-node-resolve": "^2.0.0",
- "rollup-plugin-replace": "^1.1.1",
- "through2": "^2.0.1",
- "vinyl-buffer": "^1.0.0",
- "vinyl-source-stream": "^1.1.0"
+ "preact": "^6.4.0",
+ "require-dir": "^0.3.1"
}
}
diff --git a/server/.eslintrc b/server/.eslintrc
new file mode 100644
index 0000000..ae582ee
--- /dev/null
+++ b/server/.eslintrc
@@ -0,0 +1,24 @@
+{
+ "extends": [
+ "airbnb-base",
+ "../.eslintrc"
+ ],
+
+ "parserOptions": {
+ "sourceType": "strict"
+ },
+
+ "env": {
+ "node": true
+ },
+
+ "rules": {
+ "global-require": 0
+ },
+
+ "globals": {
+ "ENV": true,
+ "LOGIN_USER": true,
+ "PWD": true
+ }
+}
diff --git a/server/config/dir.js b/server/config/dir.js
index 20c1347..1ad5a4b 100644
--- a/server/config/dir.js
+++ b/server/config/dir.js
@@ -1,7 +1,7 @@
-'use strict'
+'use strict';
-const p = require('path')
+const p = require('path');
module.exports = {
static: p.join(PWD, 'public'),
-}
+};
diff --git a/server/config/error-handler.js b/server/config/error-handler.js
index 938fbdf..0419b55 100644
--- a/server/config/error-handler.js
+++ b/server/config/error-handler.js
@@ -1,47 +1,47 @@
-'use strict'
+'use strict';
-const _ = require('lodash')
+const _ = require('lodash');
-const errorTemplate = require('../templates/error.marko')
+const errorTemplate = require('../../build/error.jsx');
const defaults = {
post: (req, res, next) => {
- res.template = errorTemplate
+ res.template = errorTemplate;
- next()
+ next();
},
mystify: {
- properties: ['errors', 'message', 'name', 'status', 'statusText']
+ properties: ['errors', 'message', 'name', 'status', 'statusText'],
},
log: {
// if database = true there has to be a mongoose model name ErrorModel
ignore: [],
- }
-}
+ },
+};
-const ErrorModel = require('midwest-service-errors/model')
+const ErrorModel = require('midwest-service-errors/model');
function store(error) {
ErrorModel.create(error, (err) => {
// TODO handle errors in error handler better
if (err) {
- console.error('ERROR WRITING TO DATABASE')
- console.error(err)
- console.log(err.errors)
- console.error('ORIGINAL ERROR')
- console.error(error)
+ console.error('ERROR WRITING TO DATABASE');
+ console.error(err);
+ console.error(err.errors);
+ console.error('ORIGINAL ERROR');
+ console.error(error);
}
- })
+ });
}
module.exports = _.merge(defaults, {
development: {
log: {
- store: store,
+ store,
console: true,
- }
+ },
},
testing: {
log: {
@@ -51,8 +51,8 @@ module.exports = _.merge(defaults, {
},
production: {
log: {
- store: store,
+ store,
console: false,
- }
+ },
},
-}[ENV])
+}[ENV]);
diff --git a/server/config/globals.js b/server/config/globals.js
index c6c45c0..4cfdf48 100644
--- a/server/config/globals.js
+++ b/server/config/globals.js
@@ -1,4 +1,4 @@
-'use strict'
+'use strict';
-global.LOGIN_USER = 'lohfu@lohfu.io'
-//global.LOGIN_USER = 'zarac@zarac.se'
+global.LOGIN_USER = 'lohfu@lohfu.io';
+// global.LOGIN_USER = 'zarac@zarac.se'
diff --git a/server/config/membership.js b/server/config/membership.js
index d9b236e..2c0f2f0 100644
--- a/server/config/membership.js
+++ b/server/config/membership.js
@@ -1,39 +1,40 @@
-'use strict'
+'use strict';
const config = {
- site: require('./site')
-}
+ site: require('./site'),
+};
module.exports = {
invite: {
- from: config.site.title + ' Robot <' + config.site.emails.robot + '>',
- subject: 'You have been invited to ' + config.site.title
+ from: `${config.site.title} Robot <${config.site.emails.robot}>`,
+ subject: `You have been invited to ${config.site.title}`,
},
timeouts: {
// 1 day
changePassword: 24 * 60 * 60 * 1000,
// verify email
- verifyEmail: 7 * 24 * 60 * 60 * 1000
+ verifyEmail: 7 * 24 * 60 * 60 * 1000,
},
paths: {
- register: '/register',
- login: '/login',
- forgotPassword: '/forgot-password',
- updatePassword: '/change-password'
+ register: '/admin/register',
+ login: '/admin/login',
+ forgotPassword: '/admin/forgot-password',
+ updatePassword: '/admin/change-password',
+ verifyEmail: '/admin/verify-email',
},
redirects: {
login: '/admin',
logout: '/',
- register: '/admin'
+ register: '/admin',
},
remember: {
// if expires is defined, it will be used. otherwise maxage
expires: new Date('2038-01-19T03:14:07.000Z'),
- //expires: Date.now() - 1,
+ // expires: Date.now() - 1,
maxAge: 30 * 24 * 60 * 60 * 1000,
},
@@ -46,22 +47,22 @@ module.exports = {
externalLoginFailed: 'External login failed.',
unverified: 'This account has not been verified.',
banned: 'User is banned.',
- blocked: 'User is blocked due to too many login attempts.'
+ blocked: 'User is blocked due to too many login attempts.',
},
register: {
missingProperties: 'Oh no missing stuff',
notAuthorized: 'The email is not authorized to create an account.',
- duplicateEmail: 'The email has already been registered.'
- }
+ duplicateEmail: 'The email has already been registered.',
+ },
},
passport: {
local: {
- usernameField: 'email'
+ usernameField: 'email',
},
- scope: [ 'email' ],
+ scope: ['email'],
//providers: {
// facebook: {
@@ -76,5 +77,5 @@ module.exports = {
// needs to be even
tokenLength: 64,
// needs to be even
- saltLength: 16
-}
+ saltLength: 16,
+};
diff --git a/server/config/mongo.js b/server/config/mongo.js
index 747a25b..2549856 100644
--- a/server/config/mongo.js
+++ b/server/config/mongo.js
@@ -1,11 +1,11 @@
-'use strict'
+'use strict';
const defaults = {
- uri: 'mongodb://pomodoro-supreme:lets-work-our-asses-off-poop-poop@mongo.bitmill.co/pomodoro'
-}
+ uri: 'mongodb://pomodoro-supreme:lets-work-our-asses-off-poop-poop@mongo.bitmill.co/pomodoro',
+};
module.exports = Object.assign(defaults, {
production: {
- //uri: 'mongodb://pomodoro-supreme:lets-work-our-asses-off-poop-poop@localhost/pomodoro'
- }
-}[ENV])
+ // uri: 'mongodb://pomodoro-supreme:lets-work-our-asses-off-poop-poop@localhost/pomodoro'
+ },
+}[ENV]);
diff --git a/server/config/port.js b/server/config/port.js
index dcb3848..3c517ed 100644
--- a/server/config/port.js
+++ b/server/config/port.js
@@ -1,10 +1,10 @@
-'use strict'
+'use strict';
-const basePort = 3050
+const basePort = 3050;
module.exports = {
development: basePort,
testing: basePort + 1,
staging: basePort + 2,
- production: basePort + 3
-}[ENV]
+ production: basePort + 3,
+}[ENV];
diff --git a/server/config/session.js b/server/config/session.js
index cb50cc2..7daf198 100644
--- a/server/config/session.js
+++ b/server/config/session.js
@@ -1,37 +1,38 @@
-'use strict'
+'use strict';
-const session = require('express-session')
+const chalk = require('chalk');
+const session = require('express-session');
-let redisStore
+let redisStore;
const config = {
- secret: 'asdf1h918798&(*&ijh21kj4hk123j45h2k34jh52k3g45)thisisacompletelyrandomgeneratedstring...whatastrangecoincidence...',
+ secret: 'sometimespoopfeelslikeheaveninawarmbun.:L:AKJSHFKJh12349087ashabbasbasbbasdbfas w',
resave: false,
- saveUninitialized: true
-}
+ saveUninitialized: true,
+};
const redisConfig = {
host: 'localhost',
- port: 6379
-}
+ port: 6379,
+};
if (ENV === 'production') {
- const RedisStore = require('connect-redis')(require('express-session'))
+ const RedisStore = require('connect-redis')(require('express-session'));
- redisStore = new RedisStore(redisConfig)
+ redisStore = new RedisStore(redisConfig);
- redisStore.on('connect', function () {
- console.info('Redis connected succcessfully')
- })
+ redisStore.on('connect', () => {
+ console.info(`[${chalk.cyan('INIT')}] Redis connected succcessfully`);
+ });
- redisStore.on('disconnect', function () {
- throw new Error('Unable to connect to redis. Has it been started?')
- })
+ redisStore.on('disconnect', () => {
+ throw new Error('Unable to connect to redis. Has it been started?');
+ });
- config.store = redisStore
+ config.store = redisStore;
} else {
- config.store = new session.MemoryStore()
+ config.store = new session.MemoryStore();
}
-module.exports = config
+module.exports = config;
diff --git a/server/config/shim.js b/server/config/shim.js
new file mode 100644
index 0000000..a6f1fc9
--- /dev/null
+++ b/server/config/shim.js
@@ -0,0 +1,59 @@
+'use strict';
+
+module.exports = {
+ 'https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-shim.min.js': [
+ 'chrome <= 12',
+ 'chrome mobile <= 12',
+ 'chrome mobile ios <= 12',
+ 'firefox <= 20',
+ 'firefox mobile <= 20',
+ 'ie <= 9',
+ 'ie mobile <= 9',
+ 'opera <= 12',
+ 'safari <= 5',
+ 'mobile safari <= 5',
+ 'samsung internet <= 1',
+ ],
+ 'https://cdnjs.cloudflare.com/ajax/libs/es6-shim/0.35.1/es6-shim.min.js': [
+ 'chrome <= 51',
+ 'chrome mobile <= 51',
+ 'chrome mobile ios <= 51',
+ 'edge <= 13',
+ 'edge mobile <= 13',
+ 'firefox <= 44',
+ 'firefox mobile <= 44',
+ 'ie <= 11',
+ 'ie mobile <= 11',
+ 'safari <= 9',
+ 'mobile safari <= 9',
+ 'samsung internet <= 2',
+ ],
+ 'https://unpkg.com/es7-shim@latest/dist/es7-shim.min.js': [
+ 'chrome <= 50',
+ 'chrome mobile <= 50',
+ 'chrome mobile ios <= 50',
+ 'edge <= 14',
+ 'edge mobile <= 14',
+ 'firefox <= 46',
+ 'firefox mobile <= 46',
+ 'ie <= 11',
+ 'ie mobile <= 11',
+ 'safari <= 10',
+ 'mobile safari <= 10',
+ 'samsung internet <= 3',
+ ],
+ 'https://cdnjs.cloudflare.com/ajax/libs/fetch/1.0.0/fetch.min.js': [
+ 'chrome <= 41',
+ 'chrome mobile <= 41',
+ 'chrome mobile ios <= 41',
+ 'edge <= 13',
+ 'edge mobile <= 13',
+ 'firefox <= 38',
+ 'firefox mobile <= 38',
+ 'ie <= 11',
+ 'ie mobile <= 11',
+ 'safari <= 9',
+ 'mobile safari <= 9',
+ 'samsung internet <= 3',
+ ],
+};
diff --git a/server/config/site.js b/server/config/site.js
index 83ac59d..d8393c6 100644
--- a/server/config/site.js
+++ b/server/config/site.js
@@ -1,51 +1,51 @@
-'use strict'
+'use strict';
-const _ = require('lodash')
+const _ = require('lodash');
-const domain = 'pomodoro.bitmill.co'
+const domain = 'pomodoro.bitmill.co';
const defaults = {
- domain: domain,
+ domain,
title: 'Pomodoro',
- name: 'pomodoro',
+ name: 'pomdoro',
protocol: 'http',
get host() {
- return this.port ? this.hostname + ':' + this.port : this.hostname
+ return this.port ? `${this.hostname}:${this.port}` : this.hostname;
},
get url() {
- return this.protocol + '://' + this.host + '/'
+ return `${this.protocol}://${this.host}/`;
},
emails: {
robot: 'no-reply@thecodebureau.com',
info: 'info@thecodebureau.com',
webmaster: 'webmaster@thecodebureau.com',
- order: 'info@thecodebureau.com'
- }
-}
+ order: 'info@thecodebureau.com',
+ },
+};
module.exports = _.merge(defaults, {
development: {
hostname: 'localhost',
- port: process.env.EXTERNAL_PORT || process.env.PORT || require('./port')
+ port: process.env.EXTERNAL_PORT || process.env.PORT || require('./port'),
},
testing: {
hostname: 'localhost',
- port: process.env.PORT || require('./port')
+ port: process.env.PORT || require('./port'),
},
staging: {
- hostname: 'staging.' + domain
+ hostname: 'staging.pomodoro.bitmill.co',
},
production: {
hostname: domain,
- protocol: 'https',
- emails: {
- robot: 'no-reply@bitmill.co',
- info: 'info@bitmill.co',
- webmaster: 'webmaster@bitmill.co',
- order: 'order@bitmill.co'
- }
- }
-}[ENV])
+ // protocol: 'https',
+ // emails: {
+ // robot: `no-reply@${domain}`,
+ // info: `info@${domain}`,
+ // webmaster: `webmaster@${domain}`,
+ // order: `order@${domain}`,
+ // },
+ },
+}[ENV]);
diff --git a/server/config/smtp.js b/server/config/smtp.js
index 44763e1..8dadf7c 100644
--- a/server/config/smtp.js
+++ b/server/config/smtp.js
@@ -1,15 +1,15 @@
-'use strict'
+'use strict';
-const _ = require('lodash')
+const _ = require('lodash');
const defaults = {
auth: {
user: 'SMTP_Injection',
// dev key
- pass: '2eec390c5b3f5d593c9f152179bf51e90b073784'
+ pass: '2eec390c5b3f5d593c9f152179bf51e90b073784',
},
host: 'smtp.sparkpostmail.com',
- port: 587
-}
+ port: 587,
+};
-module.exports = _.merge(defaults, {}[ENV])
+module.exports = _.merge(defaults, {}[ENV]);
diff --git a/server/pages.js b/server/pages.js
deleted file mode 100644
index c2197e3..0000000
--- a/server/pages.js
+++ /dev/null
@@ -1,13 +0,0 @@
-'use strict'
-
-const masterTemplate = require('../client/master.marko')
-
-const router = new (require('express')).Router()
-
-router.get('/', (req, res, next) => {
- res.template = masterTemplate
-
- next()
-})
-
-module.exports = router
diff --git a/server/render.jsx b/server/render.jsx
new file mode 100644
index 0000000..2a48ccd
--- /dev/null
+++ b/server/render.jsx
@@ -0,0 +1,31 @@
+module.exports = function (Component, Master) {
+ const locals = Object.assign({}, this.app.locals, this.locals);
+
+ let preamble = '';
+ let html;
+
+ if (typeof Master === 'function') {
+ preamble = '';
+
+ if (typeof Component === 'function') {
+ return this.send(preamble + (
+
+
+
+ ));
+ }
+
+ Component = Master;
+ }
+
+ if (typeof Component !== 'function') {
+ throw new Error('Not a Component');
+ } else if (Component.prototype && Component.prototype.render) {
+ const instance = new Component(locals);
+ html = instance.render(instance.props, instance.state);
+ } else {
+ html = Component(locals);
+ }
+
+ this.send(preamble ? preamble + html : html);
+};
diff --git a/server/routers/index.js b/server/routers/index.js
new file mode 100644
index 0000000..b5911d1
--- /dev/null
+++ b/server/routers/index.js
@@ -0,0 +1,13 @@
+'use strict';
+
+const masterTemplate = require('../../build/master.jsx');
+
+const router = new (require('express')).Router();
+
+router.get('/', (req, res, next) => {
+ res.template = masterTemplate;
+
+ next();
+});
+
+module.exports = router;
diff --git a/server/server.js b/server/server.js
index 47ccf8e..dc684b3 100644
--- a/server/server.js
+++ b/server/server.js
@@ -1,6 +1,5 @@
-'use strict'
+'use strict';
-require('babel-register')
/*
* The main file that sets up the Express instance and node
*
@@ -9,58 +8,55 @@ require('babel-register')
*/
// set up some globals (these are also set in Epiphany if not already set)
-global.ENV = process.env.NODE_ENV || 'development'
-global.PWD = process.env.NODE_PWD || process.cwd()
-
-// make node understand `*.marko` files
-require('marko/node-require').install()
+global.ENV = process.env.NODE_ENV || 'development';
+global.PWD = process.env.NODE_PWD || process.cwd();
// modules > native
-const p = require('path')
+const p = require('path');
+
+if (ENV === 'development') {
+ // output filename in console log and colour console.dir
+ require('midwest/util/console');
+ // needed so symlinked modules get access to main projects node_modules/
+ require('app-module-path').addPath(p.join(PWD, 'node_modules'));
+}
+
+// make node understand `*.jsx` files
+require('jsx-node').install({
+ replace: {
+ lowline: 'lodash',
+ preact: 'jsx-node',
+ },
+});
// modules > 3rd party
-const requireDir = require('require-dir')
-const _ = require('lodash')
-const express = require('express')
-const mongoose = require('mongoose')
-const passport = require('passport')
+const _ = require('lodash');
+const chalk = require('chalk');
+const express = require('express');
+const mongoose = require('mongoose');
+const passport = require('passport');
+const requireDir = require('require-dir');
// modules > express middlewares
-const bodyParser = require('body-parser')
-const session = require('express-session')
-const cookieParser = require('cookie-parser')
-
-// modules > 3rd party
-const chalk = require('chalk')
+const bodyParser = require('body-parser');
+const session = require('express-session');
+const cookieParser = require('cookie-parser');
// modules > midwest
-const colorizeStack = require('midwest/util/colorize-stack')
+const colorizeStack = require('midwest/util/colorize-stack');
-const config = requireDir('./config')
+const config = requireDir('./config', { camelcase: true });
// make error output stack pretty
process.on('uncaughtException', (err) => {
- console.error(chalk.red('UNCAUGHT EXCEPTION'))
+ console.error(chalk.red('UNCAUGHT EXCEPTION'));
if (err.stack) {
- console.error(colorizeStack(err.stack))
+ console.error(colorizeStack(err.stack));
} else {
- console.error(err)
+ console.error(err);
}
- process.exit(1)
-})
-
-// mongoose mpromise library is being deprecated
-mongoose.Promise = Promise
-
-// connect to mongodb
-mongoose.connect(config.mongo.uri, _.omit(config.mongo, 'uri'), (err) => {
- if (err) {
- console.error(err)
- process.exit()
- }
-
- console.info('[' + chalk.cyan('INIT') + '] Mongoose is connected.')
-})
+ process.exit(1);
+});
const prewares = [
express.static(config.dir.static, ENV === 'production' ? { maxAge: '1 year' } : null),
@@ -70,70 +66,86 @@ const prewares = [
session(config.session),
passport.initialize(),
passport.session(),
-]
+];
if (ENV === 'development') {
// only log requests to console in development mode
- prewares.unshift(require('morgan')('dev'))
- prewares.push(require('midwest-module-membership/passport/automatic-login'))
+ prewares.unshift(require('morgan')('dev'));
+ // automatically login global.LOGIN_USER
+ prewares.push(require('midwest-module-membership/passport/automatic-login'));
}
const postwares = [
require('midwest/middleware/ensure-found'),
// transform and log error
- require('midwest/middleware/error-handler'),
+ require('midwest/factories/error-handler')(config.errorHandler),
// respond
require('midwest/middleware/responder'),
-]
+];
-const server = express()
+const server = express();
// get IP & whatnot from nginx proxy
-server.set('trust proxy', true)
+server.set('trust proxy', true);
-server.locals.site = require('./config/site')
-
-if (ENV === 'production') {
- Object.assign(server.locals, {
- js: require(p.join(PWD, 'public/js.json')),
- css: require(p.join(PWD, 'public/css.json'))
- })
-}
+Object.assign(server.locals, {
+ site: require('./config/site'),
+});
// override default response render method for
-// more convenient use with marko
-server.response.render = function (template) {
- const locals = _.extend({}, server.locals, this.locals)
+// more convenient use with jsx
+server.response.render = require('./render.jsx');
- template.render(locals, this)
-}
+try {
+ server.locals.js = require(p.join(PWD, 'public/js.json'));
+} catch (e) {}
+
+try {
+ server.locals.css = require(p.join(PWD, 'public/css.json'));
+} catch (e) {}
// load all prewares
-server.use(...prewares)
+server.use(...prewares);
// routes > pages
-server.use(require('./pages'))
+server.use(require('./routers/index'));
// routes > authentication
-server.use('/auth', require('midwest-module-membership/passport/router'))
-
-// routes > api > membership
-server.use('/api/roles', require('midwest-module-membership/services/roles/router'))
-server.use('/api/permissions', require('midwest-module-membership/services/permissions/router'))
-server.use('/api/invites', require('midwest-module-membership/services/invites/router'))
-server.use('/api/users', require('midwest-module-membership/services/users/router'))
-
-// routes > api > errors
-server.use('/api/errors', require('midwest-service-errors/router'))
+server.use('/auth', require('midwest-module-membership/passport/router'));
// routes > api > pomodoro
-server.use('/api/pomodoros', require('./services/pomodoros/router'))
+server.use('/api/pomodoros', require('./services/pomodoros/router'));
+
+// routes > api > errors
+server.use('/api/errors', require('midwest-service-errors/router'));
+
+// routes > api > membership
+server.use('/api/roles', require('midwest-module-membership/services/roles/router'));
+server.use('/api/permissions', require('midwest-module-membership/services/permissions/router'));
+server.use('/api/invites', require('midwest-module-membership/services/invites/router'));
+server.use('/api/users', require('midwest-module-membership/services/users/router'));
// load all postwares
-server.use(...postwares)
+server.use(...postwares);
-server.listen(config.port, () => {
- console.info('[' + chalk.cyan('INIT') + '] HTTP Server listening on port ' + chalk.magenta('%s') + ' (' + chalk.yellow('%s') + ')', config.port, ENV)
-})
+// mpromise (built in mongoose promise library) is deprecated,
+// tell mongoose to use native Promises instead
+mongoose.Promise = Promise;
+// connect to mongodb
+mongoose.connect(config.mongo.uri, _.omit(config.mongo, 'uri'), (err) => {
+ if (err) {
+ console.error(err);
+ process.exit();
+ }
-module.exports = server
+ console.info(`[${chalk.cyan('INIT')}] Mongoose is connected.`);
+});
+
+// Only start Express server when it is the main module (ie not required by test)
+if (require.main === module) {
+ server.http = server.listen(config.port, () => {
+ console.info(`[${chalk.cyan('INIT')}] HTTP Server listening on port ${chalk.magenta(config.port)} (${chalk.yellow(server.get('env'))})`);
+ });
+}
+
+module.exports = server;
diff --git a/server/services/pomodoros/middleware.js b/server/services/pomodoros/middleware.js
index 915f72f..5ce1ac7 100644
--- a/server/services/pomodoros/middleware.js
+++ b/server/services/pomodoros/middleware.js
@@ -1,48 +1,48 @@
-'use strict'
+'use strict';
-const rest = require('midwest/middleware/rest')
-const formatQuery = require('midwest/middleware/format-query')
-const paginate = require('midwest/middleware/paginate')
+const rest = require('midwest/factories/rest');
+const formatQuery = require('midwest/factories/format-query');
+const paginate = require('midwest/factories/paginate');
-const Pomodoro = require('./model')
+const Pomodoro = require('./model');
function create(req, res, next) {
Pomodoro.create(Object.assign(req.body, {
user: req.user && req.user.id || '57b04f50a1eaaf354f3b96a6',
ip: req.ip,
- userAgent: req.headers['user-agent']
+ userAgent: req.headers['user-agent'],
}), (err, pomodoro) => {
- res.locals.pomodoro = pomodoro
+ res.locals.pomodoro = pomodoro;
- next(err)
- })
+ next(err);
+ });
}
function end(req, res, next) {
Pomodoro.findByIdAndUpdate(req.params.id, { endDate: new Date() }, (err, pomodoro) => {
- if (err) return next(err)
+ if (err) return next(err);
- res.locals.pomodoro = pomodoro
+ res.locals.pomodoro = pomodoro;
- next()
- })
+ next();
+ });
}
function getActive(req, res, next) {
Pomodoro.find({ user: req.user.id, endDate: { $eq: null } }, (err, pomodoros) => {
- res.locals.pomodoros = pomodoros
+ res.locals.pomodoros = pomodoros;
- return next(err)
- })
+ return next(err);
+ });
}
module.exports = Object.assign(rest(Pomodoro), {
create,
end,
- formatQuery: formatQuery([ 'limit', 'sort' ], {
- endDate: 'exists'
+ formatQuery: formatQuery(['limit', 'sort'], {
+ endDate: 'exists',
}),
getActive,
- paginate: paginate(Pomodoro, 50)
-})
+ paginate: paginate(Pomodoro, 50),
+});
diff --git a/server/services/pomodoros/model.js b/server/services/pomodoros/model.js
index e7a9339..a09adc5 100644
--- a/server/services/pomodoros/model.js
+++ b/server/services/pomodoros/model.js
@@ -1,31 +1,31 @@
-'use strict'
+'use strict';
-const mongoose = require('mongoose')
+const mongoose = require('mongoose');
const PomodoroSchema = new mongoose.Schema({
startTime: {
type: Date,
- required: true
+ required: true,
},
endTime: {
type: Date,
- required: true
+ required: true,
},
name: String,
location: String,
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
- required: true
+ required: true,
},
ip: {
type: String,
- required: true
+ required: true,
},
userAgent: {
type: String,
- required: true
+ required: true,
},
-})
+});
-module.exports = mongoose.model('Pomodoro', PomodoroSchema)
+module.exports = mongoose.model('Pomodoro', PomodoroSchema);
diff --git a/server/services/pomodoros/router.js b/server/services/pomodoros/router.js
index a96c300..35636e2 100644
--- a/server/services/pomodoros/router.js
+++ b/server/services/pomodoros/router.js
@@ -1,19 +1,19 @@
-'use strict'
+'use strict';
-const router = new (require('express')).Router()
+const router = new (require('express')).Router();
-const mw = require('./middleware')
+const mw = require('./middleware');
-const { isAuthenticated } = require('midwest-module-membership/passport/authorization-middleware')
+const { isAuthenticated } = require('midwest-module-membership/passport/authorization-middleware');
router.route('/')
.get(isAuthenticated, mw.formatQuery, mw.paginate, mw.query)
- .post(isAuthenticated, mw.create)
+ .post(isAuthenticated, mw.create);
router.route('/:id')
.get(isAuthenticated, mw.findById)
.patch(isAuthenticated, mw.update)
.put(isAuthenticated, mw.replace)
- .delete(isAuthenticated, mw.remove)
+ .delete(isAuthenticated, mw.remove);
-module.exports = router
+module.exports = router;
diff --git a/server/templates/error.marko b/server/templates/error.jsx
similarity index 100%
rename from server/templates/error.marko
rename to server/templates/error.jsx
diff --git a/server/templates/index.marko b/server/templates/index.jsx
similarity index 100%
rename from server/templates/index.marko
rename to server/templates/index.jsx