├── .eslintrc ├── .gitignore ├── README.md ├── bower.json ├── gulpfile.js ├── main.js ├── package.json ├── src ├── .eslintrc ├── html │ └── main.html ├── js │ ├── actions │ │ └── CommentActions.es6 │ ├── components │ │ ├── App.es6 │ │ └── site │ │ │ ├── CommentSite.es6 │ │ │ └── IndexSite.es6 │ ├── main.es6 │ ├── mixins │ │ └── DBMixin.es6 │ └── stores │ │ └── CommentStore.es6 └── less │ └── main.less └── webpack.config.js /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true 5 | }, 6 | "rules": { 7 | /** 8 | * Strict mode 9 | */ 10 | // babel inserts "use strict"; for us 11 | // http://eslint.org/docs/rules/strict 12 | "strict": [2, "global"], 13 | 14 | /** 15 | * Variables 16 | */ 17 | "no-shadow": 2, // http://eslint.org/docs/rules/no-shadow 18 | "no-shadow-restricted-names": 2, // http://eslint.org/docs/rules/no-shadow-restricted-names 19 | "no-unused-vars": [2, { // http://eslint.org/docs/rules/no-unused-vars 20 | "vars": "local", 21 | "args": "after-used" 22 | }], 23 | "no-use-before-define": 2, // http://eslint.org/docs/rules/no-use-before-define 24 | 25 | /** 26 | * Possible errors 27 | */ 28 | "comma-dangle": [2, "never"], // http://eslint.org/docs/rules/comma-dangle 29 | "no-cond-assign": [2, "always"], // http://eslint.org/docs/rules/no-cond-assign 30 | "no-console": 1, // http://eslint.org/docs/rules/no-console 31 | "no-debugger": 1, // http://eslint.org/docs/rules/no-debugger 32 | "no-alert": 1, // http://eslint.org/docs/rules/no-alert 33 | "no-constant-condition": 1, // http://eslint.org/docs/rules/no-constant-condition 34 | "no-dupe-keys": 2, // http://eslint.org/docs/rules/no-dupe-keys 35 | "no-duplicate-case": 2, // http://eslint.org/docs/rules/no-duplicate-case 36 | "no-empty": 2, // http://eslint.org/docs/rules/no-empty 37 | "no-ex-assign": 2, // http://eslint.org/docs/rules/no-ex-assign 38 | "no-extra-boolean-cast": 0, // http://eslint.org/docs/rules/no-extra-boolean-cast 39 | "no-extra-semi": 2, // http://eslint.org/docs/rules/no-extra-semi 40 | "no-func-assign": 2, // http://eslint.org/docs/rules/no-func-assign 41 | "no-inner-declarations": 2, // http://eslint.org/docs/rules/no-inner-declarations 42 | "no-invalid-regexp": 2, // http://eslint.org/docs/rules/no-invalid-regexp 43 | "no-irregular-whitespace": 2, // http://eslint.org/docs/rules/no-irregular-whitespace 44 | "no-obj-calls": 2, // http://eslint.org/docs/rules/no-obj-calls 45 | "no-reserved-keys": 2, // http://eslint.org/docs/rules/no-reserved-keys 46 | "no-sparse-arrays": 2, // http://eslint.org/docs/rules/no-sparse-arrays 47 | "no-unreachable": 2, // http://eslint.org/docs/rules/no-unreachable 48 | "use-isnan": 2, // http://eslint.org/docs/rules/use-isnan 49 | "block-scoped-var": 2, // http://eslint.org/docs/rules/block-scoped-var 50 | 51 | /** 52 | * Best practices 53 | */ 54 | "consistent-return": 2, // http://eslint.org/docs/rules/consistent-return 55 | "curly": [2, "multi-line"], // http://eslint.org/docs/rules/curly 56 | "default-case": 2, // http://eslint.org/docs/rules/default-case 57 | "dot-notation": [2, { // http://eslint.org/docs/rules/dot-notation 58 | "allowKeywords": true 59 | }], 60 | "eqeqeq": 2, // http://eslint.org/docs/rules/eqeqeq 61 | "guard-for-in": 2, // http://eslint.org/docs/rules/guard-for-in 62 | "no-caller": 2, // http://eslint.org/docs/rules/no-caller 63 | "no-else-return": 2, // http://eslint.org/docs/rules/no-else-return 64 | "no-eq-null": 2, // http://eslint.org/docs/rules/no-eq-null 65 | "no-eval": 2, // http://eslint.org/docs/rules/no-eval 66 | "no-extend-native": 2, // http://eslint.org/docs/rules/no-extend-native 67 | "no-extra-bind": 2, // http://eslint.org/docs/rules/no-extra-bind 68 | "no-fallthrough": 2, // http://eslint.org/docs/rules/no-fallthrough 69 | "no-floating-decimal": 2, // http://eslint.org/docs/rules/no-floating-decimal 70 | "no-implied-eval": 2, // http://eslint.org/docs/rules/no-implied-eval 71 | "no-lone-blocks": 2, // http://eslint.org/docs/rules/no-lone-blocks 72 | "no-loop-func": 2, // http://eslint.org/docs/rules/no-loop-func 73 | "no-multi-str": 2, // http://eslint.org/docs/rules/no-multi-str 74 | "no-native-reassign": 2, // http://eslint.org/docs/rules/no-native-reassign 75 | "no-new": 2, // http://eslint.org/docs/rules/no-new 76 | "no-new-func": 2, // http://eslint.org/docs/rules/no-new-func 77 | "no-new-wrappers": 2, // http://eslint.org/docs/rules/no-new-wrappers 78 | "no-octal": 2, // http://eslint.org/docs/rules/no-octal 79 | "no-octal-escape": 2, // http://eslint.org/docs/rules/no-octal-escape 80 | "no-param-reassign": 2, // http://eslint.org/docs/rules/no-param-reassign 81 | "no-proto": 2, // http://eslint.org/docs/rules/no-proto 82 | "no-redeclare": 2, // http://eslint.org/docs/rules/no-redeclare 83 | "no-return-assign": 2, // http://eslint.org/docs/rules/no-return-assign 84 | "no-script-url": 2, // http://eslint.org/docs/rules/no-script-url 85 | "no-self-compare": 2, // http://eslint.org/docs/rules/no-self-compare 86 | "no-sequences": 2, // http://eslint.org/docs/rules/no-sequences 87 | "no-throw-literal": 2, // http://eslint.org/docs/rules/no-throw-literal 88 | "no-with": 2, // http://eslint.org/docs/rules/no-with 89 | "radix": 2, // http://eslint.org/docs/rules/radix 90 | "vars-on-top": 2, // http://eslint.org/docs/rules/vars-on-top 91 | "wrap-iife": [2, "any"], // http://eslint.org/docs/rules/wrap-iife 92 | "yoda": 2, // http://eslint.org/docs/rules/yoda 93 | 94 | /** 95 | * Style 96 | */ 97 | "indent": [2, 2], // http://eslint.org/docs/rules/ 98 | "brace-style": [2, // http://eslint.org/docs/rules/brace-style 99 | "1tbs", { 100 | "allowSingleLine": true 101 | }], 102 | "quotes": [ 103 | 2, "single", "avoid-escape" // http://eslint.org/docs/rules/quotes 104 | ], 105 | "camelcase": [2, { // http://eslint.org/docs/rules/camelcase 106 | "properties": "never" 107 | }], 108 | "comma-spacing": [2, { // http://eslint.org/docs/rules/comma-spacing 109 | "before": false, 110 | "after": true 111 | }], 112 | "comma-style": [2, "last"], // http://eslint.org/docs/rules/comma-style 113 | "eol-last": 2, // http://eslint.org/docs/rules/eol-last 114 | "func-names": 0, // http://eslint.org/docs/rules/func-names 115 | "key-spacing": [2, { // http://eslint.org/docs/rules/key-spacing 116 | "beforeColon": false, 117 | "afterColon": true 118 | }], 119 | "max-len": [1, 80, 4], 120 | "new-cap": [2, { // http://eslint.org/docs/rules/new-cap 121 | "newIsCap": true 122 | }], 123 | "no-multiple-empty-lines": [2, { // http://eslint.org/docs/rules/no-multiple-empty-lines 124 | "max": 2 125 | }], 126 | "no-nested-ternary": 2, // http://eslint.org/docs/rules/no-nested-ternary 127 | "no-new-object": 2, // http://eslint.org/docs/rules/no-new-object 128 | "no-spaced-func": 2, // http://eslint.org/docs/rules/no-spaced-func 129 | "no-trailing-spaces": 2, // http://eslint.org/docs/rules/no-trailing-spaces 130 | "no-wrap-func": 2, // http://eslint.org/docs/rules/no-wrap-func 131 | "no-underscore-dangle": 0, // http://eslint.org/docs/rules/no-underscore-dangle 132 | "one-var": [2, "never"], // http://eslint.org/docs/rules/one-var 133 | "padded-blocks": [2, "never"], // http://eslint.org/docs/rules/padded-blocks 134 | "semi": [2, "always"], // http://eslint.org/docs/rules/semi 135 | "semi-spacing": [2, { // http://eslint.org/docs/rules/semi-spacing 136 | "before": false, 137 | "after": true 138 | }], 139 | "space-after-keywords": 2, // http://eslint.org/docs/rules/space-after-keywords 140 | "space-before-blocks": 2, // http://eslint.org/docs/rules/space-before-blocks 141 | "space-before-function-paren": [2, "never"], // http://eslint.org/docs/rules/space-before-function-paren 142 | "space-infix-ops": 2, // http://eslint.org/docs/rules/space-infix-ops 143 | "space-return-throw-case": 2, // http://eslint.org/docs/rules/space-return-throw-case 144 | "spaced-line-comment": 2, // http://eslint.org/docs/rules/spaced-line-comment 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | node_modules/ 3 | bower_components/ 4 | npm-debug.log 5 | db.json 6 | *.app 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Electron, Semantic-UI Example 2 | Start developing Electron application easily with the included tooling. 3 | 4 | Using gulp, webpack, semantic-ui, react, reflux, lowdb, less, babel(es6), eslint 5 | 6 | # Install 7 | ``` 8 | git clone git@github.com:ironhee/electron-semantic-ui-example.git 9 | ``` 10 | # Setup 11 | 12 | 1. Install [NVM](https://github.com/creationix/nvm) 13 | ``` 14 | curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.25.4/install.sh | bash 15 | ``` 16 | 17 | 2. Install node 0.11.13 ([Electron native-node-module-compatibility](http://electron.atom.io/docs/v0.27.0/tutorial/using-native-node-modules/#native-node-module-compatibility)) 18 | ``` 19 | nvm install 0.11.13 20 | nvm use 0.11.13 21 | ``` 22 | 23 | 4. Install [Bower](https://github.com/bower/bower) 24 | ``` 25 | npm install -g bower 26 | ``` 27 | 28 | 3. Install Packages 29 | ``` 30 | npm install 31 | bower install 32 | ``` 33 | 34 | 4. Install [Gulp](https://github.com/gulpjs/gulp) 35 | ``` 36 | npm install -g gulp 37 | ``` 38 | 39 | 5. Build Source 40 | ``` 41 | gulp build 42 | ``` 43 | 44 | # Develop 45 | Electron watch: ```npm run dev``` 46 | 47 | Source watch ```gulp watch``` 48 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electron-semantic-ui-example", 3 | "version": "0.0.0", 4 | "authors": [ 5 | "ironhee " 6 | ], 7 | "license": "MIT", 8 | "ignore": [ 9 | "**/.*", 10 | "node_modules", 11 | "bower_components", 12 | "test", 13 | "tests" 14 | ], 15 | "dependencies": { 16 | "semantic-ui": "~1.12.3" 17 | }, 18 | "overrides": { 19 | "semantic-ui": { 20 | "main": [] 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var gulp = require('gulp'); 4 | var runSequence = require('run-sequence'); 5 | var gutil = require('gulp-util'); 6 | var mainBowerFiles = require('main-bower-files'); 7 | var concat = require('gulp-concat'); 8 | var rename = require('gulp-rename'); 9 | var less = require('gulp-less'); 10 | var filter = require('gulp-filter'); 11 | var clean = require('gulp-clean'); 12 | var shell = require('gulp-shell'); 13 | var sourcemaps = require('gulp-sourcemaps'); 14 | var webpack = require('webpack'); 15 | var webpackConfig = require('./webpack.config'); 16 | 17 | 18 | function webpackLogger(callback) { 19 | return function(err, stats) { 20 | if (err) throw new gutil.PluginError('webpack', err); 21 | gutil.log('[webpack] Build success:'.yellow, stats.toString({ 22 | hash: false, 23 | version: false, 24 | cached: false, 25 | colors: true 26 | })); 27 | if (callback) { 28 | callback(); 29 | } 30 | }; 31 | } 32 | 33 | 34 | gulp.task('default', ['watch']); 35 | 36 | gulp.task('watch', function() { 37 | runSequence( 38 | 'build', 39 | [ 40 | 'watch-src', 41 | 'watch-vendor' 42 | ] 43 | ); 44 | }); 45 | 46 | gulp.task('build', function(callback) { 47 | runSequence( 48 | 'clean:dist', 49 | 'build-src', 50 | 'build-vendor', 51 | callback 52 | ); 53 | }); 54 | 55 | gulp.task('build-src', [ 56 | 'build-src:js', 57 | 'build-src:css', 58 | 'build-src:html' 59 | ]); 60 | 61 | gulp.task('build-vendor', [ 62 | 'build-vendor:js', 63 | 'build-vendor:css', 64 | 'build-vendor:semantic-ui' 65 | ]); 66 | 67 | gulp.task('watch-src', [ 68 | 'watch-src:js', 69 | 'watch-src:css', 70 | 'watch-src:html' 71 | ]); 72 | 73 | gulp.task('watch-vendor', function() { 74 | gulp.watch('bower.json' ['build-vendor']); 75 | }); 76 | 77 | gulp.task('watch-src:js', function() { 78 | webpack(webpackConfig).watch({}, webpackLogger()); 79 | }); 80 | 81 | gulp.task('watch-src:css', function() { 82 | gulp.watch('./src/less/**/*', ['build-src:css']); 83 | }); 84 | 85 | gulp.task('watch-src:html', function() { 86 | gulp.watch('./src/html/**/*', ['build-src:html']); 87 | }); 88 | 89 | gulp.task('build-src:js', function(callback) { 90 | webpack(webpackConfig).run(webpackLogger(callback)); 91 | }); 92 | 93 | gulp.task('build-src:css', function() { 94 | return gulp.src('src/less/main.less') 95 | .pipe(sourcemaps.init()) 96 | .pipe(less()) 97 | .pipe(rename('main.css')) 98 | .pipe(sourcemaps.write('./')) 99 | .pipe(gulp.dest('dist')); 100 | }); 101 | 102 | gulp.task('build-src:html', function() { 103 | return gulp.src('src/html/main.html') 104 | .pipe(gulp.dest('dist')); 105 | }); 106 | 107 | gulp.task('build-vendor:js', function() { 108 | return gulp.src(mainBowerFiles()) 109 | .pipe(filter(['**/*.js'])) 110 | .pipe(sourcemaps.init()) 111 | .pipe(concat('vendor.js')) 112 | .pipe(sourcemaps.write('./')) 113 | .pipe(gulp.dest('dist')); 114 | }); 115 | 116 | gulp.task('build-vendor:css', function() { 117 | return gulp.src(mainBowerFiles()) 118 | .pipe(filter(['**/*.css'])) 119 | .pipe(sourcemaps.init()) 120 | .pipe(concat('vendor.css')) 121 | .pipe(sourcemaps.write('./')) 122 | .pipe(gulp.dest('dist')); 123 | }); 124 | 125 | gulp.task('build-vendor:semantic-ui', function() { 126 | return gulp.src('bower_components/semantic-ui/dist/**/*') 127 | .pipe(gulp.dest('dist/semantic-ui')); 128 | }); 129 | 130 | gulp.task('clean:dist', function() { 131 | return gulp.src('dist') 132 | .pipe(clean()); 133 | }); 134 | 135 | gulp.task('build-electron', function(callback) { 136 | runSequence( 137 | 'build', 138 | 'build-electron:clean', 139 | 'build-electron:src', 140 | callback 141 | ); 142 | }); 143 | 144 | gulp.task('build-electron:clean', function() { 145 | return gulp.src('Electron.app') 146 | .pipe(clean()); 147 | }); 148 | 149 | gulp.task('build-electron:src', shell.task([ 150 | 'cp -a node_modules/electron-prebuilt/dist/Electron.app ./', 151 | 'mkdir Electron.app/Contents/Resources/app', 152 | 'cp main.js Electron.app/Contents/Resources/app/', 153 | 'cp package.json Electron.app/Contents/Resources/app/', 154 | 'cp -a dist Electron.app/Contents/Resources/app/' 155 | ])); 156 | -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | var app = require('app'); // Module to control application life. 3 | var BrowserWindow = require('browser-window'); // Module to create native browser window. 4 | 5 | // Report crashes to our server. 6 | require('crash-reporter').start(); 7 | 8 | // Keep a global reference of the window object, if you don't, the window will 9 | // be closed automatically when the javascript object is GCed. 10 | var mainWindow = null; 11 | 12 | // Quit when all windows are closed. 13 | app.on('window-all-closed', function() { 14 | if (process.platform != 'darwin') 15 | app.quit(); 16 | }); 17 | 18 | // This method will be called when Electron has done everything 19 | // initialization and ready for creating browser windows. 20 | app.on('ready', function() { 21 | // Create the browser window. 22 | mainWindow = new BrowserWindow({width: 800, height: 600}); 23 | 24 | // and load the index.html of the app. 25 | mainWindow.loadUrl('file://' + __dirname + '/dist/main.html'); 26 | 27 | if (process.argv.indexOf('--dev') >= 0) { 28 | // Open the devtools. 29 | mainWindow.openDevTools(); 30 | } 31 | 32 | // Emitted when the window is closed. 33 | mainWindow.on('closed', function() { 34 | // Dereference the window object, usually you would store windows 35 | // in an array if your app supports multi windows, this is the time 36 | // when you should delete the corresponding element. 37 | mainWindow = null; 38 | }); 39 | }); 40 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "electron-semantic-ui-example", 3 | "version": "0.0.0", 4 | "description": "electron-semantic-ui-example", 5 | "main": "main.js", 6 | "scripts": { 7 | "dev": "node_modules/electron-prebuilt/cli.js ./ --dev" 8 | }, 9 | "author": "ironhee ", 10 | "license": "MIT", 11 | "devDependencies": { 12 | "babel-core": "^5.5.8", 13 | "babel-eslint": "^3.1.15", 14 | "babel-loader": "^5.1.4", 15 | "electron-prebuilt": "^0.28.1", 16 | "eslint": "^0.23.0", 17 | "eslint-plugin-react": "^2.5.2", 18 | "gulp": "^3.9.0", 19 | "gulp-clean": "^0.3.1", 20 | "gulp-concat": "^2.5.2", 21 | "gulp-filter": "^2.0.2", 22 | "gulp-less": "^3.0.3", 23 | "gulp-rename": "^1.2.2", 24 | "gulp-shell": "^0.4.2", 25 | "gulp-sourcemaps": "^1.5.2", 26 | "gulp-util": "^3.0.5", 27 | "json-loader": "^0.5.2", 28 | "main-bower-files": "^2.8.0", 29 | "node-libs-browser": "^0.5.2", 30 | "run-sequence": "^1.1.0", 31 | "webpack": "^1.9.11" 32 | }, 33 | "dependencies": { 34 | "jquery": "^2.1.4", 35 | "lowdb": "^0.10.0", 36 | "q": "^1.4.1", 37 | "react": "^0.13.3", 38 | "react-router": "^0.13.3", 39 | "reflux": "^0.2.8", 40 | "underscore": "^1.8.3", 41 | "underscore-db": "^0.9.0" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "plugins": [ 4 | "react" 5 | ], 6 | "env": { 7 | "browser": true, 8 | "node": true 9 | }, 10 | "ecmaFeatures": { 11 | "arrowFunctions": true, 12 | "blockBindings": true, 13 | "classes": true, 14 | "defaultParams": true, 15 | "destructuring": true, 16 | "forOf": true, 17 | "generators": false, 18 | "modules": true, 19 | "objectLiteralComputedProperties": true, 20 | "objectLiteralDuplicateProperties": false, 21 | "objectLiteralShorthandMethods": true, 22 | "objectLiteralShorthandProperties": true, 23 | "spread": true, 24 | "superInFunctions": true, 25 | "templateStrings": true, 26 | "jsx": true 27 | }, 28 | "rules": { 29 | /** 30 | * Strict mode 31 | */ 32 | // babel inserts "use strict"; for us 33 | // http://eslint.org/docs/rules/strict 34 | "strict": [2, "never"], 35 | 36 | /** 37 | * ES6 38 | */ 39 | "no-var": 2, // http://eslint.org/docs/rules/no-var 40 | 41 | /** 42 | * JSX style 43 | */ 44 | "react/display-name": 0, 45 | "react/jsx-boolean-value": 2, 46 | "react/jsx-quotes": [2, "double"], 47 | "react/jsx-no-undef": 2, 48 | "react/jsx-sort-props": 0, 49 | "react/jsx-sort-prop-types": 0, 50 | "react/jsx-uses-react": 2, 51 | "react/jsx-uses-vars": 2, 52 | "react/no-did-mount-set-state": [2, "allow-in-func"], 53 | "react/no-did-update-set-state": 2, 54 | "react/no-multi-comp": 2, 55 | "react/no-unknown-property": 2, 56 | "react/prop-types": 2, 57 | "react/react-in-jsx-scope": 2, 58 | "react/self-closing-comp": 2, 59 | "react/wrap-multilines": 2, 60 | "react/sort-comp": [2, { 61 | "order": [ 62 | "displayName", 63 | "mixins", 64 | "statics", 65 | "propTypes", 66 | "getDefaultProps", 67 | "getInitialState", 68 | "componentWillMount", 69 | "componentDidMount", 70 | "componentWillReceiveProps", 71 | "shouldComponentUpdate", 72 | "componentWillUpdate", 73 | "componentWillUnmount", 74 | "/^on.+$/", 75 | "/^get.+$/", 76 | "/^render.+$/", 77 | "render" 78 | ] 79 | }] 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/html/main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello World! 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/js/actions/CommentActions.es6: -------------------------------------------------------------------------------- 1 | import Reflux from 'reflux'; 2 | 3 | 4 | export default Reflux.createActions({ 5 | 6 | create: { 7 | asyncResult: true 8 | }, 9 | 10 | update: { 11 | asyncResult: true 12 | }, 13 | 14 | remove: { 15 | asyncResult: true 16 | } 17 | 18 | }); 19 | -------------------------------------------------------------------------------- /src/js/components/App.es6: -------------------------------------------------------------------------------- 1 | import $ from 'jquery'; 2 | import React from 'react'; 3 | import { Link, RouteHandler } from 'react-router'; 4 | 5 | 6 | export default React.createClass({ 7 | 8 | displayName: 'App', 9 | 10 | componentDidMount() { 11 | this.adjustHeightForBeauty(); 12 | }, 13 | 14 | render() { 15 | return ( 16 |
17 |
18 | 19 | Home 20 | 21 | 22 | Comment 23 | 24 |
25 |
26 | 27 |
28 |
29 | ); 30 | }, 31 | 32 | adjustHeightForBeauty() { 33 | let mainSectionHeight = $(window).height(); 34 | $(React.findDOMNode(this.refs.main)).css('min-height', mainSectionHeight); 35 | } 36 | 37 | }); 38 | -------------------------------------------------------------------------------- /src/js/components/site/CommentSite.es6: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Reflux from 'reflux'; 3 | import _ from 'underscore'; 4 | import CommentStore from 'stores/CommentStore'; 5 | import CommentActions from 'actions/CommentActions'; 6 | 7 | 8 | function getStoreState() { 9 | return { 10 | comments: CommentStore.value() || [] 11 | }; 12 | } 13 | 14 | 15 | export default React.createClass({ 16 | 17 | displayName: 'CommentSite', 18 | 19 | mixins: [ 20 | Reflux.listenTo(CommentStore, 'onStoreChange') 21 | ], 22 | 23 | getInitialState() { 24 | return getStoreState(); 25 | }, 26 | 27 | onStoreChange() { 28 | this.setState(getStoreState()); 29 | }, 30 | 31 | onCreateComment() { 32 | let comment = React.findDOMNode(this.refs.newComment); 33 | CommentActions.create(comment.value); 34 | comment.value = ''; 35 | comment.focus(); 36 | return false; 37 | }, 38 | 39 | onRemoveComment(commentID) { 40 | CommentActions.remove(commentID); 41 | }, 42 | 43 | render() { 44 | return ( 45 |
46 |

Comments

47 | { _.map(this.state.comments, (comment) => ( 48 |
49 | 50 | 51 | 52 |
53 | { comment.user.name } 54 |
55 | 56 | { comment.createdAt } 57 | 58 |
59 |
60 | { comment.content } 61 |
62 | 71 |
72 |
73 | )) } 74 |
75 |
76 | 77 |
78 |
80 | Add Reply 81 |
82 |
83 |
84 | ); 85 | } 86 | 87 | }); 88 | -------------------------------------------------------------------------------- /src/js/components/site/IndexSite.es6: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | 4 | export default React.createClass({ 5 | 6 | displayName: 'IndexSite', 7 | 8 | render() { 9 | return ( 10 |
11 |

Hello world

12 |
13 | ); 14 | } 15 | 16 | }); 17 | -------------------------------------------------------------------------------- /src/js/main.es6: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Router, { HashLocation, Route } from 'react-router'; 3 | import App from 'components/App'; 4 | import IndexSite from 'components/site/IndexSite'; 5 | import CommentSite from 'components/site/CommentSite'; 6 | 7 | 8 | let routes = ( 9 | 10 | 11 | 12 | 13 | ); 14 | 15 | 16 | Router.run(routes, HashLocation, (Root) => { 17 | React.render(, document.body); 18 | }); 19 | -------------------------------------------------------------------------------- /src/js/mixins/DBMixin.es6: -------------------------------------------------------------------------------- 1 | import underscoreDB from 'underscore-db'; 2 | import low from 'lowdb'; 3 | import _ from 'underscore'; 4 | 5 | 6 | let db = low(); 7 | db._.mixin(underscoreDB); 8 | 9 | 10 | export default function DBMixin(type) { 11 | return _.extend({}, db(type)); 12 | } 13 | -------------------------------------------------------------------------------- /src/js/stores/CommentStore.es6: -------------------------------------------------------------------------------- 1 | import Reflux from 'reflux'; 2 | import { Promise } from 'q'; 3 | import DBMixin from 'mixins/DBMixin'; 4 | import CommentActions from 'actions/CommentActions'; 5 | 6 | 7 | export default Reflux.createStore({ 8 | 9 | mixins: [new DBMixin('comment')], 10 | 11 | listenables: [CommentActions], 12 | 13 | onRemove(commentID) { 14 | CommentActions.remove.promise( 15 | new Promise((resolve) => { 16 | this.removeById(commentID); 17 | resolve(); 18 | this.trigger(); 19 | }) 20 | ); 21 | }, 22 | 23 | onCreate(content) { 24 | CommentActions.create.promise( 25 | new Promise((resolve) => { 26 | let comment = this.insert({ 27 | content, 28 | createdAt: new Date(), 29 | user: { 30 | name: 'Foo', 31 | avatar: 'http://semantic-ui.com/images/avatar/small/matt.jpg' 32 | } 33 | }); 34 | resolve(comment); 35 | this.trigger(comment); 36 | }) 37 | ); 38 | }, 39 | 40 | onUpdate(commentID, content) { 41 | CommentActions.update.promise( 42 | new Promise((resolve) => { 43 | let comment = this.updateById(commentID, { 44 | content 45 | }); 46 | resolve(comment); 47 | this.trigger(comment); 48 | }) 49 | ); 50 | } 51 | 52 | }); 53 | -------------------------------------------------------------------------------- /src/less/main.less: -------------------------------------------------------------------------------- 1 | .site > .menu { 2 | border-radius: 0 !important; 3 | } 4 | 5 | .main.container { 6 | max-width: 800px; 7 | background-color: #FFFFFF; 8 | margin: 0em auto; 9 | box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, 0.05); 10 | border-left: 1px solid #DDDDDD; 11 | border-right: 1px solid #DDDDDD; 12 | border-bottom: 1px solid #DDDDDD; 13 | padding: 2em 2em 7em; 14 | z-index: 1; 15 | } 16 | 17 | .comments { 18 | max-width: 100% !important; 19 | margin: 0 auto !important; 20 | } 21 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | 4 | var _ = require('underscore'); 5 | var pkg = require('./package.json'); 6 | 7 | 8 | module.exports = { 9 | devtool: 'eval', 10 | resolve: { 11 | modulesDirectories: ['src/js'], 12 | extensions: ['', '.es6', '.js'] 13 | }, 14 | entry: { 15 | 'main': './src/js/main.es6' 16 | }, 17 | output: { 18 | path: 'dist/', 19 | filename: '[name].js', 20 | libraryTarget: 'commonjs2' 21 | }, 22 | target: 'atom', 23 | externals: _.keys(pkg.dependencies), 24 | module: { 25 | loaders: [ 26 | { test: /\.es6$/, loader: 'babel-loader' }, 27 | { test: /\.jsx$/, loader: 'babel-loader' }, 28 | { test: /\.json$/, loader: 'json-loader' } 29 | ] 30 | } 31 | }; 32 | --------------------------------------------------------------------------------