diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..a213078 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,37 @@ +{ + "env": { + "browser": true, + "commonjs": true, + "es6": true + }, + "extends": "eslint:recommended", + "parserOptions": { + "ecmaFeatures": { + "experimentalObjectRestSpread": true + }, + "sourceType": "module" + }, + "plugins": [ + ], + "rules": { + "indent": [ + "error", + 2, + { "SwitchCase": 1 } + ], + "linebreak-style": [ + "error", + "unix" + ], + "no-console": "off", + "no-unused-vars": "warn", + "quotes": [ + "error", + "single" + ], + "semi": [ + "error", + "always" + ] + } +} \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2a8d2fb --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +dist/ +node_modules/ +env.config.js diff --git a/package.json b/package.json new file mode 100644 index 0000000..f6fe7c8 --- /dev/null +++ b/package.json @@ -0,0 +1,41 @@ +{ + "name": "tools-demo", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "start": "webpack-dev-server", + "build": "webpack --config webpack.production.config.js" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "babel-core": "^6.24.0", + "babel-loader": "^6.4.1", + "babel-preset-es2015": "^6.24.0", + "compression-webpack-plugin": "^0.3.2", + "css-loader": "^0.27.2", + "eslint": "^4.3.0", + "eslint-plugin-react": "^7.1.0", + "extract-loader": "^0.1.0", + "extract-text-webpack-plugin": "^2.1.0", + "favicons-webpack-plugin": "0.0.7", + "file-loader": "^0.10.1", + "html-loader": "^0.4.5", + "html-webpack-plugin": "^2.28.0", + "image-webpack-loader": "^3.2.0", + "node-sass": "^4.5.0", + "raw-loader": "^0.5.1", + "sass-loader": "^6.0.3", + "style-ext-html-webpack-plugin": "^3.3.0", + "style-loader": "^0.13.2", + "webpack": "^2.5.1", + "webpack-dev-server": "^2.4.1" + }, + "dependencies": { + "jquery": "^3.1.1", + "lodash": "^4.17.4", + "pusher-js": "^4.1.0" + } +} diff --git a/src/index.html b/src/index.html new file mode 100644 index 0000000..a4019b0 --- /dev/null +++ b/src/index.html @@ -0,0 +1,20 @@ + + + + 9to5 : Tools + + + + + + +
+
Action A
+
Action B
+
Action C
+
+
+

+  
+ + \ No newline at end of file diff --git a/src/js/constants.js b/src/js/constants.js new file mode 100644 index 0000000..f2ffef5 --- /dev/null +++ b/src/js/constants.js @@ -0,0 +1,4 @@ +export const PUSHER_KEY = process.env.PUSHER_KEY; + +export const SERVER_URL = process.env.SERVER_URL; +export const SERVER_AUTH_URL = SERVER_URL + '/pusher/auth'; \ No newline at end of file diff --git a/src/js/index.js b/src/js/index.js new file mode 100644 index 0000000..9336470 --- /dev/null +++ b/src/js/index.js @@ -0,0 +1,62 @@ +import $ from 'jquery'; +import Pusher from 'pusher-js'; +import { PUSHER_KEY, SERVER_AUTH_URL } from './constants'; + +const pusher = new Pusher(PUSHER_KEY, { + cluster: 'us2', + encrypted: true, + authEndpoint: SERVER_AUTH_URL +}); +const channel = pusher.subscribe('private-tools-demo'); +channel.bind('pusher:subscription_succeeded', function() { + console.log('connected'); +}); + +try { + var userId = localStorage.getItem('userId'); + if (!userId) { + userId = Math.floor(Math.random() * 100000); + localStorage.setItem('userId', userId); + } +} catch (e) { + userId = Math.floor(Math.random() * 100000); +} + +$(document).ready(() => { + $('.tools').click(function(e) { + var offset = $(this).offset(); + var relativeX = (e.pageX - offset.left); + var relativeY = (e.pageY - offset.top); + const payload = { + user: userId, + action: { + type: 'canvas-click', + data: { + x: relativeX, + y: relativeY + } + } + }; + channel.trigger('client-tool-action', payload); + }); + + $('.btn').click(function(e) { + const payload = { + user: userId, + action: { + type: 'btn-click', + data: $(this).text() + } + }; + channel.trigger('client-tool-action', payload); + e.preventDefault(); + e.stopPropagation(); + return false; + }); + + + channel.bind('client-tool-action', function(data) { + console.log(data); + $('.console pre').text(JSON.stringify(data, null, 2)); + }); +}); \ No newline at end of file diff --git a/src/styles/main.scss b/src/styles/main.scss new file mode 100644 index 0000000..58ab5fa --- /dev/null +++ b/src/styles/main.scss @@ -0,0 +1,44 @@ +$red: #FF2120; +$blue: #271DFF; + +html, body { + margin: 0; + font-family: Futura; + width: 100%; + height: 100%; + overflow: hidden; +} + +.tools, .console { + width: 100%; + height: 50%; + overflow-y: scroll; +} + +.console { + border-top: 1px solid #ccc; + + pre { + margin: 16px; + padding: 8px; + background-color: #eee; + } +} + +.btn { + cursor: pointer; + display: inline-block; + margin: 8px; + border: 4px solid black; + padding: 8px 16px; + + &:hover { + color: $blue; + border-color: $blue; + } + + &:active { + color: $red; + border-color: $red; + } +} \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..af21e72 --- /dev/null +++ b/webpack.config.js @@ -0,0 +1,69 @@ +const ExtractTextPlugin = require('extract-text-webpack-plugin'); +const StyleExtHtmlWebpackPlugin = require('style-ext-html-webpack-plugin'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const FaviconsWebpackPlugin = require('favicons-webpack-plugin'); +const CompressionPlugin = require('compression-webpack-plugin'); +const webpack = require('webpack'); +const path = require('path'); +const config = require('./env.config.js').development; + +module.exports = { + devtool: '#cheap-module-eval-source-map', + entry: [ + 'webpack-dev-server/client?http://0.0.0.0:8080', + './src/js/index.js', + './src/styles/main.scss' + ], + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, + resolve: { + extensions: ['.js', '.jsx'], + modules: ['node_modules'] + }, + module: { + rules: [ + { + test: /\.js?$/, + exclude: /node_modules/, + use: 'babel-loader?presets[]=es2015' + }, + { + test: /\.scss$/, + exclude: /node_modules/, + use: ExtractTextPlugin.extract({ + fallback: 'style-loader', + use: ['css-loader', 'sass-loader'] + }) + } + ] + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env': { + 'NODE_ENV': JSON.stringify('development'), + 'PUSHER_KEY': config.PUSHER_KEY, + 'SERVER_URL': config.SERVER_URL + } + }), + new webpack.HotModuleReplacementPlugin(), + new HtmlWebpackPlugin({ template: './src/index.html' }), + new ExtractTextPlugin('styles.css'), + // new StyleExtHtmlWebpackPlugin(), + // new webpack.optimize.UglifyJsPlugin({ output: { ascii_only: true } }) + ], + devServer: { + contentBase: './dist', + watchOptions: { + aggregateTimeout: 100, + poll: 300 + }, + historyApiFallback: { + index: 'index.html' + }, + hot: true, + host: '0.0.0.0', + port: 8080 + } +}; \ No newline at end of file diff --git a/webpack.production.config.js b/webpack.production.config.js new file mode 100644 index 0000000..a37614d --- /dev/null +++ b/webpack.production.config.js @@ -0,0 +1,55 @@ +const ExtractTextPlugin = require('extract-text-webpack-plugin'); +const StyleExtHtmlWebpackPlugin = require('style-ext-html-webpack-plugin'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const FaviconsWebpackPlugin = require('favicons-webpack-plugin'); +const CompressionPlugin = require('compression-webpack-plugin'); +const webpack = require('webpack'); +const path = require('path'); +const config = require('./env.config.js').production; + +module.exports = { + devtool: '#cheap-module-eval-source-map', + entry: [ + './src/js/index.js', + './src/styles/main.scss' + ], + output: { + filename: 'bundle.js', + path: path.resolve(__dirname, 'dist') + }, + resolve: { + extensions: ['.js'], + modules: ['node_modules'] + }, + module: { + rules: [ + { + test: /\.js?$/, + exclude: /node_modules/, + use: 'babel-loader?presets[]=es2015' + }, + { + test: /\.scss$/, + exclude: /node_modules/, + use: ExtractTextPlugin.extract({ + fallback: 'style-loader', + use: ['css-loader', 'sass-loader'] + }) + } + ] + }, + plugins: [ + new webpack.DefinePlugin({ + 'process.env': { + 'NODE_ENV': JSON.stringify('production'), + 'PUSHER_KEY': config.PUSHER_KEY, + 'SERVER_URL': config.SERVER_URL + } + }), + new webpack.HotModuleReplacementPlugin(), + new HtmlWebpackPlugin({ template: './src/index.html' }), + new ExtractTextPlugin('styles.css'), + // new StyleExtHtmlWebpackPlugin(), + // new webpack.optimize.UglifyJsPlugin({ output: { ascii_only: true } }) + ], +}; \ No newline at end of file