diff --git a/.eslintignore b/.eslintignore
index f517d4c..77c5fb7 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,6 +1,10 @@
-blueprints/**/files/**
+bin
+blueprints
coverage/**
node_modules/**
dist/**
*.spec.js
src/index.html
+config
+build
+server
diff --git a/.eslintrc b/.eslintrc
index 4a6fe9c..f5c335c 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -1,8 +1,7 @@
{
- "parser" : "babel-eslint",
+ "parser": "babel-eslint",
"extends" : [
- "standard",
- "standard-react"
+ "airbnb"
],
"env" : {
"browser" : true
@@ -15,7 +14,5 @@
"__BASENAME__" : false
},
"rules": {
- "semi" : [2, "never"],
- "max-len": [2, 120, 2]
}
}
diff --git a/README.md b/README.md
index c5ca6cd..6f889c5 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,9 @@
+# Climb Social Displayer
+
+A standalone application which demonstrates different Climb Social views and helps users embed them in their own web pages.
+
+---
+
# React Redux Starter Kit
[](https://gitter.im/davezuko/react-redux-starter-kit?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
diff --git a/bin/compile.js b/bin/compile.js
index 76126d4..838b050 100644
--- a/bin/compile.js
+++ b/bin/compile.js
@@ -1,24 +1,24 @@
-import fs from 'fs-extra'
-import _debug from 'debug'
-import webpackCompiler from '../build/webpack-compiler'
-import webpackConfig from '../build/webpack.config'
-import config from '../config'
+import fs from 'fs-extra';
+import _debug from 'debug';
+import webpackCompiler from '../build/webpack-compiler';
+import webpackConfig from '../build/webpack.config';
+import config from '../config';
-const debug = _debug('app:bin:compile')
+const debug = _debug('app:bin:compile');
const paths = config.utils_paths
;(async function () {
try {
- debug('Run compiler')
- const stats = await webpackCompiler(webpackConfig)
+ debug('Run compiler');
+ const stats = await webpackCompiler(webpackConfig);
if (stats.warnings.length && config.compiler_fail_on_warning) {
- debug('Config set to fail on warning, exiting with status code "1".')
- process.exit(1)
+ debug('Config set to fail on warning, exiting with status code "1".');
+ process.exit(1);
}
- debug('Copy static assets to dist folder.')
- fs.copySync(paths.client('static'), paths.dist())
+ debug('Copy static assets to dist folder.');
+ fs.copySync(paths.client('static'), paths.dist());
} catch (e) {
- debug('Compiler encountered an error.', e)
- process.exit(1)
+ debug('Compiler encountered an error.', e);
+ process.exit(1);
}
-})()
+})();
diff --git a/bin/server.js b/bin/server.js
index 07f2dae..5460853 100644
--- a/bin/server.js
+++ b/bin/server.js
@@ -1,11 +1,11 @@
-import config from '../config'
-import server from '../server/main'
-import _debug from 'debug'
+import config from '../config';
+import server from '../server/main';
+import _debug from 'debug';
-const debug = _debug('app:bin:server')
-const port = config.server_port
-const host = config.server_host
+const debug = _debug('app:bin:server');
+const port = config.server_port;
+const host = config.server_host;
-server.listen(port)
-debug(`Server is now running at http://${host}:${port}.`)
-debug(`Server accessible via localhost:${port} if you are using the project defaults.`)
+server.listen(port);
+debug(`Server is now running at http://${host}:${port}.`);
+debug(`Server accessible via localhost:${port} if you are using the project defaults.`);
diff --git a/blueprints/blueprint/index.js b/blueprints/blueprint/index.js
index d0660e1..86d5025 100644
--- a/blueprints/blueprint/index.js
+++ b/blueprints/blueprint/index.js
@@ -1,13 +1,13 @@
module.exports = {
- description () {
- return 'generates a blueprint and definition'
+ description() {
+ return 'generates a blueprint and definition';
},
- beforeInstall () {
- console.log('Before installation hook!')
+ beforeInstall() {
+ console.log('Before installation hook!');
},
- afterInstall () {
- console.log('After installation hook!')
- }
-}
+ afterInstall() {
+ console.log('After installation hook!');
+ },
+};
diff --git a/blueprints/duck/index.js b/blueprints/duck/index.js
index 033ff45..560b28a 100644
--- a/blueprints/duck/index.js
+++ b/blueprints/duck/index.js
@@ -1,5 +1,5 @@
module.exports = {
- description () {
- return 'generates a redux duck'
- }
-}
+ description() {
+ return 'generates a redux duck';
+ },
+};
diff --git a/blueprints/dumb/index.js b/blueprints/dumb/index.js
index b0c217a..63792ac 100644
--- a/blueprints/dumb/index.js
+++ b/blueprints/dumb/index.js
@@ -1,5 +1,5 @@
module.exports = {
- description () {
- return 'generates a dumb (pure) component'
- }
-}
+ description() {
+ return 'generates a dumb (pure) component';
+ },
+};
diff --git a/blueprints/form/index.js b/blueprints/form/index.js
index a6a8d19..f3ba55a 100644
--- a/blueprints/form/index.js
+++ b/blueprints/form/index.js
@@ -1,5 +1,5 @@
module.exports = {
- description () {
- return 'generates a connected redux-form form component'
- }
-}
+ description() {
+ return 'generates a connected redux-form form component';
+ },
+};
diff --git a/blueprints/layout/index.js b/blueprints/layout/index.js
index 31630e8..f9a7e0d 100644
--- a/blueprints/layout/index.js
+++ b/blueprints/layout/index.js
@@ -1,5 +1,5 @@
module.exports = {
- description () {
- return 'generates a functional layout component'
- }
-}
+ description() {
+ return 'generates a functional layout component';
+ },
+};
diff --git a/blueprints/smart/index.js b/blueprints/smart/index.js
index 1a1402f..78aed7e 100644
--- a/blueprints/smart/index.js
+++ b/blueprints/smart/index.js
@@ -1,13 +1,13 @@
module.exports = {
- description () {
- return 'generates a smart (container) component'
+ description() {
+ return 'generates a smart (container) component';
},
- fileMapTokens () {
+ fileMapTokens() {
return {
__smart__: (options) => {
- return options.settings.getSetting('smartPath')
- }
- }
- }
-}
+ return options.settings.getSetting('smartPath');
+ },
+ };
+ },
+};
diff --git a/blueprints/view/index.js b/blueprints/view/index.js
index 5316a09..00b4110 100644
--- a/blueprints/view/index.js
+++ b/blueprints/view/index.js
@@ -1,5 +1,5 @@
module.exports = {
- description () {
- return 'generates a view component'
- }
-}
+ description() {
+ return 'generates a view component';
+ },
+};
diff --git a/build/karma.conf.js b/build/karma.conf.js
index 29c0f03..978fb41 100644
--- a/build/karma.conf.js
+++ b/build/karma.conf.js
@@ -1,10 +1,10 @@
-import { argv } from 'yargs'
-import config from '../config'
-import webpackConfig from './webpack.config'
-import _debug from 'debug'
+import { argv } from 'yargs';
+import config from '../config';
+import webpackConfig from './webpack.config';
+import _debug from 'debug';
-const debug = _debug('app:karma')
-debug('Create configuration.')
+const debug = _debug('app:karma');
+debug('Create configuration.');
const karmaConfig = {
basePath: '../', // project root in relation to bin/karma.js
@@ -14,14 +14,14 @@ const karmaConfig = {
pattern: `./${config.dir_test}/test-bundler.js`,
watched: false,
served: true,
- included: true
- }
+ included: true,
+ },
],
singleRun: !argv.watch,
frameworks: ['mocha'],
reporters: ['mocha'],
preprocessors: {
- [`${config.dir_test}/test-bundler.js`]: ['webpack']
+ [`${config.dir_test}/test-bundler.js`]: ['webpack'],
},
browsers: ['PhantomJS'],
webpack: {
@@ -30,20 +30,20 @@ const karmaConfig = {
...webpackConfig.resolve,
alias: {
...webpackConfig.resolve.alias,
- sinon: 'sinon/pkg/sinon.js'
- }
+ sinon: 'sinon/pkg/sinon.js',
+ },
},
plugins: webpackConfig.plugins,
module: {
noParse: [
- /\/sinon\.js/
+ /\/sinon\.js/,
],
loaders: webpackConfig.module.loaders.concat([
{
test: /sinon(\\|\/)pkg(\\|\/)sinon\.js/,
- loader: 'imports?define=>false,require=>false'
- }
- ])
+ loader: 'imports?define=>false,require=>false',
+ },
+ ]),
},
// Enzyme fix, see:
// https://github.com/airbnb/enzyme/issues/47
@@ -51,27 +51,27 @@ const karmaConfig = {
...webpackConfig.externals,
'react/addons': true,
'react/lib/ExecutionEnvironment': true,
- 'react/lib/ReactContext': 'window'
+ 'react/lib/ReactContext': 'window',
},
- sassLoader: webpackConfig.sassLoader
+ sassLoader: webpackConfig.sassLoader,
},
webpackMiddleware: {
- noInfo: true
+ noInfo: true,
},
coverageReporter: {
- reporters: config.coverage_reporters
- }
-}
+ reporters: config.coverage_reporters,
+ },
+};
if (config.globals.__COVERAGE__) {
- karmaConfig.reporters.push('coverage')
+ karmaConfig.reporters.push('coverage');
karmaConfig.webpack.module.preLoaders = [{
test: /\.(js|jsx)$/,
include: new RegExp(config.dir_client),
loader: 'isparta',
- exclude: /node_modules/
- }]
+ exclude: /node_modules/,
+ }];
}
// cannot use `export default` because of Karma.
-module.exports = (cfg) => cfg.set(karmaConfig)
+module.exports = (cfg) => cfg.set(karmaConfig);
diff --git a/build/webpack-compiler.js b/build/webpack-compiler.js
index 5e150f0..36d8c8a 100644
--- a/build/webpack-compiler.js
+++ b/build/webpack-compiler.js
@@ -1,35 +1,35 @@
-import webpack from 'webpack'
-import _debug from 'debug'
-import config from '../config'
+import webpack from 'webpack';
+import _debug from 'debug';
+import config from '../config';
-const debug = _debug('app:build:webpack-compiler')
-const DEFAULT_STATS_FORMAT = config.compiler_stats
+const debug = _debug('app:build:webpack-compiler');
+const DEFAULT_STATS_FORMAT = config.compiler_stats;
-export default function webpackCompiler (webpackConfig, statsFormat = DEFAULT_STATS_FORMAT) {
+export default function webpackCompiler(webpackConfig, statsFormat = DEFAULT_STATS_FORMAT) {
return new Promise((resolve, reject) => {
- const compiler = webpack(webpackConfig)
+ const compiler = webpack(webpackConfig);
compiler.run((err, stats) => {
- const jsonStats = stats.toJson()
+ const jsonStats = stats.toJson();
- debug('Webpack compile completed.')
- debug(stats.toString(statsFormat))
+ debug('Webpack compile completed.');
+ debug(stats.toString(statsFormat));
if (err) {
- debug('Webpack compiler encountered a fatal error.', err)
- return reject(err)
+ debug('Webpack compiler encountered a fatal error.', err);
+ return reject(err);
} else if (jsonStats.errors.length > 0) {
- debug('Webpack compiler encountered errors.')
- debug(jsonStats.errors.join('\n'))
- return reject(new Error('Webpack compiler encountered errors'))
+ debug('Webpack compiler encountered errors.');
+ debug(jsonStats.errors.join('\n'));
+ return reject(new Error('Webpack compiler encountered errors'));
} else if (jsonStats.warnings.length > 0) {
- debug('Webpack compiler encountered warnings.')
- debug(jsonStats.warnings.join('\n'))
+ debug('Webpack compiler encountered warnings.');
+ debug(jsonStats.warnings.join('\n'));
} else {
- debug('No errors or warnings encountered.')
+ debug('No errors or warnings encountered.');
}
- resolve(jsonStats)
- })
- })
+ resolve(jsonStats);
+ });
+ });
}
diff --git a/build/webpack.config.js b/build/webpack.config.js
index 7962f66..111671e 100644
--- a/build/webpack.config.js
+++ b/build/webpack.config.js
@@ -1,36 +1,36 @@
-import webpack from 'webpack'
-import cssnano from 'cssnano'
-import HtmlWebpackPlugin from 'html-webpack-plugin'
-import ExtractTextPlugin from 'extract-text-webpack-plugin'
-import config from '../config'
-import _debug from 'debug'
+import webpack from 'webpack';
+import cssnano from 'cssnano';
+import HtmlWebpackPlugin from 'html-webpack-plugin';
+import ExtractTextPlugin from 'extract-text-webpack-plugin';
+import config from '../config';
+import _debug from 'debug';
-const debug = _debug('app:webpack:config')
-const paths = config.utils_paths
-const {__DEV__, __PROD__, __TEST__} = config.globals
+const debug = _debug('app:webpack:config');
+const paths = config.utils_paths;
+const { __DEV__, __PROD__, __TEST__ } = config.globals;
-debug('Create configuration.')
+debug('Create configuration.');
const webpackConfig = {
name: 'client',
target: 'web',
devtool: config.compiler_devtool,
resolve: {
root: paths.client(),
- extensions: ['', '.js', '.jsx', '.json']
+ extensions: ['', '.js', '.jsx', '.json'],
},
- module: {}
-}
+ module: {},
+};
// ------------------------------------
// Entry Points
// ------------------------------------
-const APP_ENTRY_PATH = paths.client('main.js')
+const APP_ENTRY_PATH = paths.client('main.js');
webpackConfig.entry = {
app: __DEV__
? [APP_ENTRY_PATH, `webpack-hot-middleware/client?path=${config.compiler_public_path}__webpack_hmr`]
: [APP_ENTRY_PATH],
- vendor: config.compiler_vendor
-}
+ vendor: config.compiler_vendor,
+};
// ------------------------------------
// Bundle Output
@@ -38,8 +38,8 @@ webpackConfig.entry = {
webpackConfig.output = {
filename: `[name].[${config.compiler_hash_type}].js`,
path: paths.dist(),
- publicPath: config.compiler_public_path
-}
+ publicPath: config.compiler_public_path,
+};
// ------------------------------------
// Plugins
@@ -53,19 +53,19 @@ webpackConfig.plugins = [
filename: 'index.html',
inject: 'body',
minify: {
- collapseWhitespace: true
- }
- })
-]
+ collapseWhitespace: true,
+ },
+ }),
+];
if (__DEV__) {
- debug('Enable plugins for live development (HMR, NoErrors).')
+ debug('Enable plugins for live development (HMR, NoErrors).');
webpackConfig.plugins.push(
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
- )
+ );
} else if (__PROD__) {
- debug('Enable plugins for production (OccurenceOrder, Dedupe & UglifyJS).')
+ debug('Enable plugins for production (OccurenceOrder, Dedupe & UglifyJS).');
webpackConfig.plugins.push(
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.optimize.DedupePlugin(),
@@ -73,19 +73,19 @@ if (__DEV__) {
compress: {
unused: true,
dead_code: true,
- warnings: false
- }
+ warnings: false,
+ },
})
- )
+ );
}
// Don't split bundles during testing, since we only want import one bundle
if (!__TEST__) {
webpackConfig.plugins.push(
new webpack.optimize.CommonsChunkPlugin({
- names: ['vendor']
+ names: ['vendor'],
})
- )
+ );
}
// ------------------------------------
@@ -128,38 +128,38 @@ webpackConfig.module.loaders = [{
presets: ['es2015', 'react', 'stage-0'],
env: {
production: {
- presets: ['react-optimize']
- }
- }
- }
+ presets: ['react-optimize'],
+ },
+ },
+ },
},
{
test: /\.json$/,
- loader: 'json'
-}]
+ loader: 'json',
+}];
// ------------------------------------
// Style Loaders
// ------------------------------------
// We use cssnano with the postcss loader, so we tell
// css-loader not to duplicate minimization.
-const BASE_CSS_LOADER = 'css?sourceMap&-minimize'
+const BASE_CSS_LOADER = 'css?sourceMap&-minimize';
// Add any packge names here whose styles need to be treated as CSS modules.
// These paths will be combined into a single regex.
const PATHS_TO_TREAT_AS_CSS_MODULES = [
// 'react-toolbox', (example)
-]
+];
// If config has CSS modules enabled, treat this project's styles as CSS modules.
if (config.compiler_css_modules) {
PATHS_TO_TREAT_AS_CSS_MODULES.push(
paths.client().replace(/[\^\$\.\*\+\-\?\=\!\:\|\\\/\(\)\[\]\{\}\,]/g, '\\$&') // eslint-disable-line
- )
+ );
}
-const isUsingCSSModules = !!PATHS_TO_TREAT_AS_CSS_MODULES.length
-const cssModulesRegex = new RegExp(`(${PATHS_TO_TREAT_AS_CSS_MODULES.join('|')})`)
+const isUsingCSSModules = !!PATHS_TO_TREAT_AS_CSS_MODULES.length;
+const cssModulesRegex = new RegExp(`(${PATHS_TO_TREAT_AS_CSS_MODULES.join('|')})`);
// Loaders for styles that need to be treated as CSS modules.
if (isUsingCSSModules) {
@@ -167,8 +167,8 @@ if (isUsingCSSModules) {
BASE_CSS_LOADER,
'modules',
'importLoaders=1',
- 'localIdentName=[name]__[local]___[hash:base64:5]'
- ].join('&')
+ 'localIdentName=[name]__[local]___[hash:base64:5]',
+ ].join('&');
webpackConfig.module.loaders.push({
test: /\.scss$/,
@@ -177,9 +177,9 @@ if (isUsingCSSModules) {
'style',
cssModulesLoader,
'postcss',
- 'sass?sourceMap'
- ]
- })
+ 'sass?sourceMap',
+ ],
+ });
webpackConfig.module.loaders.push({
test: /\.css$/,
@@ -187,13 +187,13 @@ if (isUsingCSSModules) {
loaders: [
'style',
cssModulesLoader,
- 'postcss'
- ]
- })
+ 'postcss',
+ ],
+ });
}
// Loaders for files that should not be treated as CSS modules.
-const excludeCSSModules = isUsingCSSModules ? cssModulesRegex : false
+const excludeCSSModules = isUsingCSSModules ? cssModulesRegex : false;
webpackConfig.module.loaders.push({
test: /\.scss$/,
exclude: excludeCSSModules,
@@ -201,43 +201,43 @@ webpackConfig.module.loaders.push({
'style',
BASE_CSS_LOADER,
'postcss',
- 'sass?sourceMap'
- ]
-})
+ 'sass?sourceMap',
+ ],
+});
webpackConfig.module.loaders.push({
test: /\.css$/,
exclude: excludeCSSModules,
loaders: [
'style',
BASE_CSS_LOADER,
- 'postcss'
- ]
-})
+ 'postcss',
+ ],
+});
// ------------------------------------
// Style Configuration
// ------------------------------------
webpackConfig.sassLoader = {
- includePaths: paths.client('styles')
-}
+ includePaths: paths.client('styles'),
+};
webpackConfig.postcss = [
cssnano({
autoprefixer: {
add: true,
remove: true,
- browsers: ['last 2 versions']
+ browsers: ['last 2 versions'],
},
discardComments: {
- removeAll: true
+ removeAll: true,
},
discardUnused: false,
mergeIdents: false,
reduceIdents: false,
safe: true,
- sourcemap: true
- })
-]
+ sourcemap: true,
+ }),
+];
// File loaders
/* eslint-disable */
@@ -259,20 +259,20 @@ webpackConfig.module.loaders.push(
// need to use the extractTextPlugin to fix this issue:
// http://stackoverflow.com/questions/34133808/webpack-ots-parsing-error-loading-fonts/34133809#34133809
if (!__DEV__) {
- debug('Apply ExtractTextPlugin to CSS loaders.')
+ debug('Apply ExtractTextPlugin to CSS loaders.');
webpackConfig.module.loaders.filter((loader) =>
loader.loaders && loader.loaders.find((name) => /css/.test(name.split('?')[0]))
).forEach((loader) => {
- const [first, ...rest] = loader.loaders
- loader.loader = ExtractTextPlugin.extract(first, rest.join('!'))
- Reflect.deleteProperty(loader, 'loaders')
- })
+ const [first, ...rest] = loader.loaders;
+ loader.loader = ExtractTextPlugin.extract(first, rest.join('!'));
+ Reflect.deleteProperty(loader, 'loaders');
+ });
webpackConfig.plugins.push(
new ExtractTextPlugin('[name].[contenthash].css', {
- allChunks: true
+ allChunks: true,
})
- )
+ );
}
-export default webpackConfig
+export default webpackConfig;
diff --git a/config/environments.js b/config/environments.js
index 9bef69f..2379af4 100644
--- a/config/environments.js
+++ b/config/environments.js
@@ -14,9 +14,9 @@ export default {
enabled: false,
options: {
host: 'http://localhost:8000',
- match: /^\/api\/.*/
- }
- }
+ match: /^\/api\/.*/,
+ },
+ },
}),
// ======================================================
@@ -30,7 +30,7 @@ export default {
compiler_stats: {
chunks: true,
chunkModules: true,
- colors: true
- }
- })
-}
+ colors: true,
+ },
+ }),
+};
diff --git a/config/index.js b/config/index.js
index 70fe44d..536a80d 100644
--- a/config/index.js
+++ b/config/index.js
@@ -1,12 +1,12 @@
/* eslint key-spacing:0 spaced-comment:0 */
-import path from 'path'
-import _debug from 'debug'
-import { argv } from 'yargs'
-import ip from 'ip'
+import path from 'path';
+import _debug from 'debug';
+import { argv } from 'yargs';
+import ip from 'ip';
-const localip = ip.address()
-const debug = _debug('app:config')
-debug('Creating default configuration.')
+const localip = ip.address();
+const debug = _debug('app:config');
+debug('Creating default configuration.');
// ========================================================
// Default Configuration
@@ -41,7 +41,7 @@ const config = {
compiler_stats : {
chunks : false,
chunkModules : false,
- colors : true
+ colors : true,
},
compiler_vendor : [
'history',
@@ -49,7 +49,7 @@ const config = {
'react-redux',
'react-router',
'react-router-redux',
- 'redux'
+ 'redux',
],
// ----------------------------------
@@ -57,9 +57,9 @@ const config = {
// ----------------------------------
coverage_reporters : [
{ type : 'text-summary' },
- { type : 'lcov', dir : 'coverage' }
- ]
-}
+ { type : 'lcov', dir : 'coverage' },
+ ],
+};
/************************************************
-------------------------------------------------
@@ -76,7 +76,7 @@ Edit at Your Own Risk
// N.B.: globals added here must _also_ be added to .eslintrc
config.globals = {
'process.env' : {
- 'NODE_ENV' : JSON.stringify(config.env)
+ 'NODE_ENV' : JSON.stringify(config.env),
},
'NODE_ENV' : config.env,
'__DEV__' : config.env === 'development',
@@ -84,49 +84,49 @@ config.globals = {
'__TEST__' : config.env === 'test',
'__DEBUG__' : config.env === 'development' && !argv.no_debug,
'__COVERAGE__' : !argv.watch && config.env === 'test',
- '__BASENAME__' : JSON.stringify(process.env.BASENAME || '')
-}
+ '__BASENAME__' : JSON.stringify(process.env.BASENAME || ''),
+};
// ------------------------------------
// Validate Vendor Dependencies
// ------------------------------------
-const pkg = require('../package.json')
+const pkg = require('../package.json');
config.compiler_vendor = config.compiler_vendor
.filter((dep) => {
- if (pkg.dependencies[dep]) return true
+ if (pkg.dependencies[dep]) return true;
debug(
`Package "${dep}" was not found as an npm dependency in package.json; ` +
`it won't be included in the webpack vendor bundle.
Consider removing it from vendor_dependencies in ~/config/index.js`
- )
- })
+ );
+ });
// ------------------------------------
// Utilities
// ------------------------------------
-const resolve = path.resolve
+const resolve = path.resolve;
const base = (...args) =>
- Reflect.apply(resolve, null, [config.path_base, ...args])
+ Reflect.apply(resolve, null, [config.path_base, ...args]);
config.utils_paths = {
base : base,
client : base.bind(null, config.dir_client),
- dist : base.bind(null, config.dir_dist)
-}
+ dist : base.bind(null, config.dir_dist),
+};
// ========================================================
// Environment Configuration
// ========================================================
-debug(`Looking for environment overrides for NODE_ENV "${config.env}".`)
-const environments = require('./environments').default
-const overrides = environments[config.env]
+debug(`Looking for environment overrides for NODE_ENV "${config.env}".`);
+const environments = require('./environments').default;
+const overrides = environments[config.env];
if (overrides) {
- debug('Found overrides, applying to default configuration.')
- Object.assign(config, overrides(config))
+ debug('Found overrides, applying to default configuration.');
+ Object.assign(config, overrides(config));
} else {
- debug('No environment overrides found, defaults will be used.')
+ debug('No environment overrides found, defaults will be used.');
}
-export default config
+export default config;
diff --git a/package.json b/package.json
index a6f8c13..c1c62f5 100644
--- a/package.json
+++ b/package.json
@@ -107,12 +107,16 @@
"node-sass": "^3.7.0",
"normalize.css": "^4.1.1",
"postcss-loader": "^0.9.0",
+ "query-string": "^4.1.0",
"react": "^15.0.0",
+ "react-climb-social": "^2.0.0-alpha.4",
"react-dom": "^15.0.0",
"react-redux": "^4.0.0",
"react-router": "^2.2.0",
"react-router-redux": "^4.0.0",
"redux": "^3.0.0",
+ "redux-actions": "^0.9.1",
+ "redux-debounced": "^0.2.0",
"redux-thunk": "^2.0.0",
"rimraf": "^2.5.1",
"sass-loader": "^3.0.0",
@@ -122,7 +126,7 @@
"yargs": "^4.0.0"
},
"devDependencies": {
- "babel-eslint": "^6.0.0-beta.6",
+ "babel-eslint": "^6.0.4",
"chai": "^3.4.1",
"chai-as-promised": "^5.1.0",
"chai-enzyme": "^0.4.0",
@@ -130,9 +134,12 @@
"codecov": "^1.0.1",
"enzyme": "^2.0.0",
"eslint": "^2.4.0",
+ "eslint-config-airbnb": "^9.0.1",
"eslint-config-standard": "^5.1.0",
"eslint-config-standard-react": "^2.2.0",
"eslint-plugin-babel": "^3.0.0",
+ "eslint-plugin-import": "^1.8.0",
+ "eslint-plugin-jsx-a11y": "^1.2.0",
"eslint-plugin-promise": "^1.0.8",
"eslint-plugin-react": "^5.0.0",
"eslint-plugin-standard": "^1.3.1",
diff --git a/server/lib/apply-express-middleware.js b/server/lib/apply-express-middleware.js
index 4c8ba2d..0f15764 100644
--- a/server/lib/apply-express-middleware.js
+++ b/server/lib/apply-express-middleware.js
@@ -1,14 +1,14 @@
// Based on: https://github.com/dayAlone/koa-webpack-hot-middleware/blob/master/index.js
-export default function applyExpressMiddleware (fn, req, res) {
- const originalEnd = res.end
+export default function applyExpressMiddleware(fn, req, res) {
+ const originalEnd = res.end;
return new Promise((resolve) => {
res.end = function () {
- originalEnd.apply(this, arguments)
- resolve(false)
- }
+ originalEnd.apply(this, arguments);
+ resolve(false);
+ };
fn(req, res, function () {
- resolve(true)
- })
- })
+ resolve(true);
+ });
+ });
}
diff --git a/server/main.js b/server/main.js
index 15e39bc..865c5f6 100644
--- a/server/main.js
+++ b/server/main.js
@@ -1,48 +1,48 @@
-import Koa from 'koa'
-import convert from 'koa-convert'
-import webpack from 'webpack'
-import webpackConfig from '../build/webpack.config'
-import historyApiFallback from 'koa-connect-history-api-fallback'
-import serve from 'koa-static'
-import proxy from 'koa-proxy'
-import _debug from 'debug'
-import config from '../config'
-import webpackDevMiddleware from './middleware/webpack-dev'
-import webpackHMRMiddleware from './middleware/webpack-hmr'
-
-const debug = _debug('app:server')
-const paths = config.utils_paths
-const app = new Koa()
+import Koa from 'koa';
+import convert from 'koa-convert';
+import webpack from 'webpack';
+import webpackConfig from '../build/webpack.config';
+import historyApiFallback from 'koa-connect-history-api-fallback';
+import serve from 'koa-static';
+import proxy from 'koa-proxy';
+import _debug from 'debug';
+import config from '../config';
+import webpackDevMiddleware from './middleware/webpack-dev';
+import webpackHMRMiddleware from './middleware/webpack-hmr';
+
+const debug = _debug('app:server');
+const paths = config.utils_paths;
+const app = new Koa();
// Enable koa-proxy if it has been enabled in the config.
if (config.proxy && config.proxy.enabled) {
- app.use(convert(proxy(config.proxy.options)))
+ app.use(convert(proxy(config.proxy.options)));
}
// This rewrites all routes requests to the root /index.html file
// (ignoring file requests). If you want to implement isomorphic
// rendering, you'll want to remove this middleware.
app.use(convert(historyApiFallback({
- verbose: false
-})))
+ verbose: false,
+})));
// ------------------------------------
// Apply Webpack HMR Middleware
// ------------------------------------
if (config.env === 'development') {
- const compiler = webpack(webpackConfig)
+ const compiler = webpack(webpackConfig);
// Enable webpack-dev and webpack-hot middleware
- const { publicPath } = webpackConfig.output
+ const { publicPath } = webpackConfig.output;
- app.use(webpackDevMiddleware(compiler, publicPath))
- app.use(webpackHMRMiddleware(compiler))
+ app.use(webpackDevMiddleware(compiler, publicPath));
+ app.use(webpackHMRMiddleware(compiler));
// Serve static assets from ~/src/static since Webpack is unaware of
// these files. This middleware doesn't need to be enabled outside
// of development since this directory will be copied into ~/dist
// when the application is compiled.
- app.use(convert(serve(paths.client('static'))))
+ app.use(convert(serve(paths.client('static'))));
} else {
debug(
'Server is being run outside of live development mode, meaning it will ' +
@@ -50,12 +50,12 @@ if (config.env === 'development') {
'do not need an application server for this and can instead use a web ' +
'server such as nginx to serve your static files. See the "deployment" ' +
'section in the README for more information on deployment strategies.'
- )
+ );
// Serving ~/dist by default. Ideally these files should be served by
// the web server and not the app server, but this helps to demo the
// server in production.
- app.use(convert(serve(paths.dist())))
+ app.use(convert(serve(paths.dist())));
}
-export default app
+export default app;
diff --git a/server/middleware/webpack-dev.js b/server/middleware/webpack-dev.js
index 8187ba6..21be1c7 100644
--- a/server/middleware/webpack-dev.js
+++ b/server/middleware/webpack-dev.js
@@ -1,13 +1,13 @@
-import WebpackDevMiddleware from 'webpack-dev-middleware'
-import applyExpressMiddleware from '../lib/apply-express-middleware'
-import _debug from 'debug'
-import config from '../../config'
+import WebpackDevMiddleware from 'webpack-dev-middleware';
+import applyExpressMiddleware from '../lib/apply-express-middleware';
+import _debug from 'debug';
+import config from '../../config';
-const paths = config.utils_paths
-const debug = _debug('app:server:webpack-dev')
+const paths = config.utils_paths;
+const debug = _debug('app:server:webpack-dev');
export default function (compiler, publicPath) {
- debug('Enable webpack dev middleware.')
+ debug('Enable webpack dev middleware.');
const middleware = WebpackDevMiddleware(compiler, {
publicPath,
@@ -16,19 +16,19 @@ export default function (compiler, publicPath) {
quiet: config.compiler_quiet,
noInfo: config.compiler_quiet,
lazy: false,
- stats: config.compiler_stats
- })
+ stats: config.compiler_stats,
+ });
- return async function koaWebpackDevMiddleware (ctx, next) {
+ return async function koaWebpackDevMiddleware(ctx, next) {
let hasNext = await applyExpressMiddleware(middleware, ctx.req, {
end: (content) => (ctx.body = content),
setHeader: function () {
- ctx.set.apply(ctx, arguments)
- }
- })
+ ctx.set.apply(ctx, arguments);
+ },
+ });
if (hasNext) {
- await next()
+ await next();
}
- }
+ };
}
diff --git a/server/middleware/webpack-hmr.js b/server/middleware/webpack-hmr.js
index ddaff4d..738de93 100644
--- a/server/middleware/webpack-hmr.js
+++ b/server/middleware/webpack-hmr.js
@@ -1,18 +1,18 @@
-import WebpackHotMiddleware from 'webpack-hot-middleware'
-import applyExpressMiddleware from '../lib/apply-express-middleware'
-import _debug from 'debug'
+import WebpackHotMiddleware from 'webpack-hot-middleware';
+import applyExpressMiddleware from '../lib/apply-express-middleware';
+import _debug from 'debug';
-const debug = _debug('app:server:webpack-hmr')
+const debug = _debug('app:server:webpack-hmr');
export default function (compiler, opts) {
- debug('Enable Webpack Hot Module Replacement (HMR).')
+ debug('Enable Webpack Hot Module Replacement (HMR).');
- const middleware = WebpackHotMiddleware(compiler, opts)
- return async function koaWebpackHMR (ctx, next) {
- let hasNext = await applyExpressMiddleware(middleware, ctx.req, ctx.res)
+ const middleware = WebpackHotMiddleware(compiler, opts);
+ return async function koaWebpackHMR(ctx, next) {
+ let hasNext = await applyExpressMiddleware(middleware, ctx.req, ctx.res);
if (hasNext && next) {
- await next()
+ await next();
}
- }
+ };
}
diff --git a/src/components/Counter/index.js b/src/components/Counter/index.js
deleted file mode 100644
index ef982b9..0000000
--- a/src/components/Counter/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import Counter from './Counter'
-
-export default Counter
diff --git a/src/components/DisplayPicker/DisplayPicker.js b/src/components/DisplayPicker/DisplayPicker.js
new file mode 100644
index 0000000..ddb4cc6
--- /dev/null
+++ b/src/components/DisplayPicker/DisplayPicker.js
@@ -0,0 +1,38 @@
+import React, { PropTypes } from 'react';
+import Navigation from './DisplayPickerNavigation';
+import Stage from './DisplayPickerStage';
+import EmbedCode from './DisplayPickerEmbedCode';
+
+import FastInput from 'components/FastInput';
+
+const DisplayPicker = ({ collectionId, setCollection, selected }) => (
+
+
+
+
+
+
+
+
+
+);
+
+
+DisplayPicker.propTypes = {
+ collectionId: PropTypes.string,
+ options: PropTypes.arrayOf(PropTypes.object).isRequired,
+ selected: PropTypes.object.isRequired,
+ setDisplay: PropTypes.func.isRequired,
+ setCollection: PropTypes.func.isRequired,
+};
+
+export default DisplayPicker;
diff --git a/src/components/DisplayPicker/DisplayPickerEmbedCode.js b/src/components/DisplayPicker/DisplayPickerEmbedCode.js
new file mode 100644
index 0000000..3850057
--- /dev/null
+++ b/src/components/DisplayPicker/DisplayPickerEmbedCode.js
@@ -0,0 +1,9 @@
+import React from 'react';
+
+const DisplayPickerEmbedCode = () => (
+
+);
+
+export default DisplayPickerEmbedCode;
diff --git a/src/components/DisplayPicker/DisplayPickerNavigation.js b/src/components/DisplayPicker/DisplayPickerNavigation.js
new file mode 100644
index 0000000..1d5bf44
--- /dev/null
+++ b/src/components/DisplayPicker/DisplayPickerNavigation.js
@@ -0,0 +1,32 @@
+import React, { PropTypes } from 'react';
+import PushButton from 'components/PushButton';
+
+export class DisplayPickerNavigation extends React.Component {
+ static propTypes = {
+ options: PropTypes.arrayOf(PropTypes.object).isRequired,
+ selected: PropTypes.object.isRequired,
+ setDisplay: PropTypes.func.isRequired,
+ };
+
+ static defaultProps = {
+ options: [],
+ };
+
+ render() {
+ const { options, selected, setDisplay } = this.props;
+
+ return (
+
+ {options.map(option =>
+ setDisplay(option)}
+ isActive={selected.key === option.key}
+ >{option.name}
+ )}
+
+ );
+ }
+}
+
+export default DisplayPickerNavigation;
diff --git a/src/components/DisplayPicker/DisplayPickerStage.js b/src/components/DisplayPicker/DisplayPickerStage.js
new file mode 100644
index 0000000..d8a3c0b
--- /dev/null
+++ b/src/components/DisplayPicker/DisplayPickerStage.js
@@ -0,0 +1,20 @@
+import React, { PropTypes } from 'react';
+import { ClimbView } from 'react-climb-social';
+
+
+const DisplayPickerStage = ({ collectionId, layout }) => (
+
+);
+
+DisplayPickerStage.propTypes = {
+ name: PropTypes.string,
+ layout: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
+ collectionId: PropTypes.string,
+};
+
+export default DisplayPickerStage;
diff --git a/src/components/DisplayPicker/index.js b/src/components/DisplayPicker/index.js
new file mode 100644
index 0000000..40cca88
--- /dev/null
+++ b/src/components/DisplayPicker/index.js
@@ -0,0 +1,2 @@
+import DisplayPicker from './DisplayPicker';
+export default DisplayPicker;
diff --git a/src/components/FastInput/FastInput.js b/src/components/FastInput/FastInput.js
new file mode 100644
index 0000000..9d993be
--- /dev/null
+++ b/src/components/FastInput/FastInput.js
@@ -0,0 +1,39 @@
+import React, { PropTypes } from 'react';
+
+export class FastInput extends React.Component {
+
+ static propTypes = {
+ type: PropTypes.oneOf(['text']).isRequired,
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+ onChange: PropTypes.func.isRequired,
+ };
+
+ static defaultProps = {
+ type: 'text',
+ };
+
+ constructor(props) {
+ super(props);
+ this.state = { value: props.value };
+ }
+
+ handleChange(value) {
+ this.setState({ value }, () => this.props.onChange(value));
+ }
+
+ render() {
+ const { type } = this.props;
+ const { value } = this.state;
+
+ return (
+ this.handleChange(target.value)}
+ />
+ );
+ }
+}
+
+export default FastInput;
+
diff --git a/src/components/FastInput/index.js b/src/components/FastInput/index.js
new file mode 100644
index 0000000..76101ee
--- /dev/null
+++ b/src/components/FastInput/index.js
@@ -0,0 +1,2 @@
+import FastInput from './FastInput';
+export default FastInput;
diff --git a/src/components/Header/Header.js b/src/components/Header/Header.js
index 0acbe91..116d6d6 100644
--- a/src/components/Header/Header.js
+++ b/src/components/Header/Header.js
@@ -1,18 +1,10 @@
-import React from 'react'
-import { IndexLink, Link } from 'react-router'
-import classes from './Header.scss'
-
-export const Header = () => (
-
-
React Redux Starter Kit
-
- Home
-
- {' · '}
-
- Counter
-
-
-)
-
-export default Header
+import React from 'react';
+// import classes from './Header.scss';
+
+export const Header = () => (
+
+
Climb Social
+
+);
+
+export default Header;
diff --git a/src/components/Header/index.js b/src/components/Header/index.js
index 7cd29d7..a9ce105 100644
--- a/src/components/Header/index.js
+++ b/src/components/Header/index.js
@@ -1,3 +1,3 @@
-import Header from './Header'
+import Header from './Header';
-export default Header
+export default Header;
diff --git a/src/components/PushButton/PushButton.js b/src/components/PushButton/PushButton.js
new file mode 100644
index 0000000..2507585
--- /dev/null
+++ b/src/components/PushButton/PushButton.js
@@ -0,0 +1,26 @@
+import React, { PropTypes } from 'react';
+
+export class PushButton extends React.Component {
+ static propTypes = {
+ children: PropTypes.node.isRequired,
+ isActive: PropTypes.bool,
+ onClick: PropTypes.func,
+ };
+
+ static defaultProps = {
+ isActive: false,
+ };
+
+ render() {
+ const { isActive, ...others } = this.props;
+
+ return (
+
+ );
+ }
+}
+
+export default PushButton;
diff --git a/src/components/PushButton/index.js b/src/components/PushButton/index.js
new file mode 100644
index 0000000..c12f72a
--- /dev/null
+++ b/src/components/PushButton/index.js
@@ -0,0 +1,2 @@
+import PushButton from './PushButton';
+export default PushButton;
diff --git a/src/components/Counter/Counter.js b/src/components/_Counter/Counter.js
similarity index 61%
rename from src/components/Counter/Counter.js
rename to src/components/_Counter/Counter.js
index 13eb168..4367fc5 100644
--- a/src/components/Counter/Counter.js
+++ b/src/components/_Counter/Counter.js
@@ -1,5 +1,5 @@
-import React from 'react'
-import classes from './Counter.scss'
+import React from 'react';
+import classes from './Counter.scss';
export const Counter = (props) => (
@@ -10,20 +10,20 @@ export const Counter = (props) => (
{props.counter}
-
-)
+);
Counter.propTypes = {
counter: React.PropTypes.number.isRequired,
doubleAsync: React.PropTypes.func.isRequired,
- increment: React.PropTypes.func.isRequired
-}
+ increment: React.PropTypes.func.isRequired,
+};
-export default Counter
+export default Counter;
diff --git a/src/components/Counter/Counter.scss b/src/components/_Counter/Counter.scss
similarity index 100%
rename from src/components/Counter/Counter.scss
rename to src/components/_Counter/Counter.scss
diff --git a/src/components/_Counter/index.js b/src/components/_Counter/index.js
new file mode 100644
index 0000000..97f7f53
--- /dev/null
+++ b/src/components/_Counter/index.js
@@ -0,0 +1,3 @@
+import Counter from './Counter';
+
+export default Counter;
diff --git a/src/components/_Header/Header.js b/src/components/_Header/Header.js
new file mode 100644
index 0000000..9a7fd2e
--- /dev/null
+++ b/src/components/_Header/Header.js
@@ -0,0 +1,18 @@
+import React from 'react';
+import { IndexLink, Link } from 'react-router';
+import classes from './Header.scss';
+
+export const Header = () => (
+
+
React Redux Starter Kit
+
+ Home
+
+ {' · '}
+
+ Counter
+
+
+);
+
+export default Header;
diff --git a/src/components/_Header/Header.scss b/src/components/_Header/Header.scss
new file mode 100644
index 0000000..1dcd731
--- /dev/null
+++ b/src/components/_Header/Header.scss
@@ -0,0 +1,4 @@
+.activeRoute {
+ font-weight: bold;
+ text-decoration: underline;
+}
diff --git a/src/components/_Header/index.js b/src/components/_Header/index.js
new file mode 100644
index 0000000..a9ce105
--- /dev/null
+++ b/src/components/_Header/index.js
@@ -0,0 +1,3 @@
+import Header from './Header';
+
+export default Header;
diff --git a/src/containers/AppContainer.js b/src/containers/AppContainer.js
index f658a9e..f573716 100644
--- a/src/containers/AppContainer.js
+++ b/src/containers/AppContainer.js
@@ -1,26 +1,20 @@
-import React, { PropTypes } from 'react'
-import { Router } from 'react-router'
-import { Provider } from 'react-redux'
+import React, { PropTypes } from 'react';
+import { Router } from 'react-router';
+import { Provider } from 'react-redux';
-class AppContainer extends React.Component {
- static propTypes = {
- history: PropTypes.object.isRequired,
- routes: PropTypes.object.isRequired,
- routerKey: PropTypes.number,
- store: PropTypes.object.isRequired
- }
+const AppContainer = ({ history, routes, routerKey, store }) => (
+
+
+
+
+
+);
- render () {
- const { history, routes, routerKey, store } = this.props
+AppContainer.propTypes = {
+ history: PropTypes.object.isRequired,
+ routes: PropTypes.object.isRequired,
+ routerKey: PropTypes.number,
+ store: PropTypes.object.isRequired,
+};
- return (
-
-
-
-
-
- )
- }
-}
-
-export default AppContainer
+export default AppContainer;
diff --git a/src/index.html b/src/index.html
index 08a85d6..69e0975 100644
--- a/src/index.html
+++ b/src/index.html
@@ -1,7 +1,7 @@
- React Redux Starter Kit
+ Climb Social Displayer
diff --git a/src/layouts/CoreLayout/CoreLayout.js b/src/layouts/CoreLayout/CoreLayout.js
index 58286e8..c26bf98 100644
--- a/src/layouts/CoreLayout/CoreLayout.js
+++ b/src/layouts/CoreLayout/CoreLayout.js
@@ -1,19 +1,19 @@
-import React from 'react'
-import Header from '../../components/Header'
-import classes from './CoreLayout.scss'
-import '../../styles/core.scss'
+import React from 'react';
+import Header from '../../components/Header';
+import classes from './CoreLayout.scss';
+import '../../styles/core.scss';
export const CoreLayout = ({ children }) => (
-
+
-)
+);
CoreLayout.propTypes = {
- children: React.PropTypes.element.isRequired
-}
+ children: React.PropTypes.element.isRequired,
+};
-export default CoreLayout
+export default CoreLayout;
diff --git a/src/layouts/CoreLayout/index.js b/src/layouts/CoreLayout/index.js
index 7fe88c1..bff4621 100644
--- a/src/layouts/CoreLayout/index.js
+++ b/src/layouts/CoreLayout/index.js
@@ -1,3 +1,3 @@
-import CoreLayout from './CoreLayout'
+import CoreLayout from './CoreLayout';
-export default CoreLayout
+export default CoreLayout;
diff --git a/src/main.js b/src/main.js
index 6d396ec..e501f38 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,17 +1,17 @@
-import React from 'react'
-import ReactDOM from 'react-dom'
-import createBrowserHistory from 'history/lib/createBrowserHistory'
-import { useRouterHistory } from 'react-router'
-import { syncHistoryWithStore } from 'react-router-redux'
-import createStore from './store/createStore'
-import AppContainer from './containers/AppContainer'
+import React from 'react';
+import ReactDOM from 'react-dom';
+import createBrowserHistory from 'history/lib/createBrowserHistory';
+import { useRouterHistory } from 'react-router';
+import { syncHistoryWithStore } from 'react-router-redux';
+import createStore from './store/createStore';
+import AppContainer from './containers/AppContainer';
// ========================================================
// Browser History Setup
// ========================================================
const browserHistory = useRouterHistory(createBrowserHistory)({
- basename: __BASENAME__
-})
+ basename: __BASENAME__,
+});
// ========================================================
// Store and History Instantiation
@@ -20,28 +20,28 @@ const browserHistory = useRouterHistory(createBrowserHistory)({
// react-router-redux reducer under the routerKey "router" in src/routes/index.js,
// so we need to provide a custom `selectLocationState` to inform
// react-router-redux of its location.
-const initialState = window.___INITIAL_STATE__
-const store = createStore(initialState, browserHistory)
+const initialState = window.___INITIAL_STATE__;
+const store = createStore(initialState, browserHistory);
const history = syncHistoryWithStore(browserHistory, store, {
- selectLocationState: (state) => state.router
-})
+ selectLocationState: (state) => state.router,
+});
// ========================================================
// Developer Tools Setup
// ========================================================
if (__DEBUG__) {
if (window.devToolsExtension) {
- window.devToolsExtension.open()
+ window.devToolsExtension.open();
}
}
// ========================================================
// Render Setup
// ========================================================
-const MOUNT_NODE = document.getElementById('root')
+const MOUNT_NODE = document.getElementById('root');
let render = (routerKey = null) => {
- const routes = require('./routes/index').default(store)
+ const routes = require('./routes/index').default(store);
ReactDOM.render(
{
routerKey={routerKey}
/>,
MOUNT_NODE
- )
-}
+ );
+};
// Enable HMR and catch runtime errors in RedBox
// This code is excluded from production bundle
if (__DEV__ && module.hot) {
- const renderApp = render
+ const renderApp = render;
const renderError = (error) => {
- const RedBox = require('redbox-react')
+ const RedBox = require('redbox-react');
- ReactDOM.render(, MOUNT_NODE)
- }
+ ReactDOM.render(, MOUNT_NODE);
+ };
render = () => {
try {
- renderApp(Math.random())
+ renderApp(Math.random());
} catch (error) {
- renderError(error)
+ renderError(error);
}
- }
- module.hot.accept(['./routes/index'], () => render())
+ };
+ module.hot.accept(['./routes/index'], () => render());
}
// ========================================================
// Go!
// ========================================================
-render()
+render();
diff --git a/src/routes/Home/components/HomeView.js b/src/routes/Home/components/HomeView.js
index f1f6b96..221ca67 100644
--- a/src/routes/Home/components/HomeView.js
+++ b/src/routes/Home/components/HomeView.js
@@ -1,15 +1,19 @@
-import React from 'react'
-import DuckImage from '../assets/Duck.jpg'
-import classes from './HomeView.scss'
+import React from 'react';
+// import classes from './HomeView.scss';
+
+import DisplayPickerContainer from '../containers/DisplayPickerContainer';
export const HomeView = () => (
-
Welcome!
-

+
Publish this Collection
+
Pick a style. Get your embed code.
+
+
+
+
-)
+);
-export default HomeView
+export default HomeView;
diff --git a/src/routes/Home/components/HomeView.scss b/src/routes/Home/components/HomeView.scss
index 10de960..e69de29 100644
--- a/src/routes/Home/components/HomeView.scss
+++ b/src/routes/Home/components/HomeView.scss
@@ -1,5 +0,0 @@
-.duck {
- display: block;
- width: 120px;
- margin: 1.5rem auto;
-}
diff --git a/src/routes/Home/containers/DisplayPickerContainer.js b/src/routes/Home/containers/DisplayPickerContainer.js
new file mode 100644
index 0000000..17d2e22
--- /dev/null
+++ b/src/routes/Home/containers/DisplayPickerContainer.js
@@ -0,0 +1,20 @@
+import { connect } from 'react-redux';
+import { bindActionCreators } from 'redux';
+import { actions as displayActions } from '../modules/display';
+
+import DisplayPicker from 'components/DisplayPicker';
+
+
+const mapStateToProps = (state) => ({
+ collectionId: state.display.collectionId,
+ options: state.display.options,
+ selected: state.display.selected,
+});
+
+const mapDispatchToProps = (dispatch) =>
+ bindActionCreators(displayActions, dispatch);
+
+export default connect(
+ mapStateToProps,
+ mapDispatchToProps
+)(DisplayPicker);
diff --git a/src/routes/Home/index.js b/src/routes/Home/index.js
index 984f23f..ccd9db6 100644
--- a/src/routes/Home/index.js
+++ b/src/routes/Home/index.js
@@ -1,6 +1,5 @@
-import HomeView from './components/HomeView'
+import HomeView from './components/HomeView';
-// Sync route definition
export default {
- component: HomeView
-}
+ component: HomeView,
+};
diff --git a/src/routes/Home/modules/display.js b/src/routes/Home/modules/display.js
new file mode 100644
index 0000000..5b447ca
--- /dev/null
+++ b/src/routes/Home/modules/display.js
@@ -0,0 +1,51 @@
+import { createAction, handleActions } from 'redux-actions';
+import queryString from 'query-string';
+
+const displayOptions = [
+ {
+ key: 'list',
+ name: 'List',
+ },
+ {
+ key: 'grid',
+ name: 'Grid',
+ layout: 'square',
+ },
+];
+
+// Constants
+export const COLLECTION_ID_SET = 'COLLECTION_ID_SET';
+export const DISPLAY_SET = 'DISPLAY_SET';
+
+// Action Creators
+export const setCollection = (payload) => ({
+ type: COLLECTION_ID_SET,
+ payload,
+ meta: {
+ debounce: {
+ time: 300,
+ },
+ },
+});
+
+export const setDisplay = createAction(DISPLAY_SET);
+
+export const actions = {
+ setCollection,
+ setDisplay,
+};
+
+
+// Reducer
+const { collection } = queryString.parse(window.location.search);
+
+export const initialState = {
+ collectionId: collection,
+ options: displayOptions,
+ selected: displayOptions[0],
+};
+
+export default handleActions({
+ [COLLECTION_ID_SET]: (state, { payload }) => ({ ...state, collectionId: payload }),
+ [DISPLAY_SET]: (state, { payload }) => ({ ...state, selected: payload }),
+}, initialState);
diff --git a/src/routes/Counter/containers/CounterContainer.js b/src/routes/_Counter/containers/CounterContainer.js
similarity index 86%
rename from src/routes/Counter/containers/CounterContainer.js
rename to src/routes/_Counter/containers/CounterContainer.js
index d0fe41a..c0352b0 100644
--- a/src/routes/Counter/containers/CounterContainer.js
+++ b/src/routes/_Counter/containers/CounterContainer.js
@@ -1,12 +1,12 @@
-import { connect } from 'react-redux'
-import { increment, doubleAsync } from '../modules/counter'
+import { connect } from 'react-redux';
+import { increment, doubleAsync } from '../modules/counter';
/* This is a container component. Notice it does not contain any JSX,
nor does it import React. This component is **only** responsible for
wiring in the actions and state necessary to render a presentational
component - in this case, the counter: */
-import Counter from 'components/Counter'
+import Counter from 'components/Counter';
/* Object of action creators (can also be function that returns object).
Keys will be passed as props to presentational components. Here we are
@@ -14,12 +14,12 @@ import Counter from 'components/Counter'
const mapActionCreators = {
increment: () => increment(1),
- doubleAsync
-}
+ doubleAsync,
+};
const mapStateToProps = (state) => ({
- counter: state.counter
-})
+ counter: state.counter,
+});
/* Note: mapStateToProps is where you should use `reselect` to create selectors, ie:
@@ -35,4 +35,4 @@ const mapStateToProps = (state) => ({
Selectors are composable. They can be used as input to other selectors.
https://github.com/reactjs/reselect */
-export default connect(mapStateToProps, mapActionCreators)(Counter)
+export default connect(mapStateToProps, mapActionCreators)(Counter);
diff --git a/src/routes/Counter/index.js b/src/routes/_Counter/index.js
similarity index 68%
rename from src/routes/Counter/index.js
rename to src/routes/_Counter/index.js
index bfb6c71..e8fcb2d 100644
--- a/src/routes/Counter/index.js
+++ b/src/routes/_Counter/index.js
@@ -1,24 +1,24 @@
-import { injectReducer } from '../../store/reducers'
+import { injectReducer } from '../../store/reducers';
export default (store) => ({
path: 'counter',
/* Async getComponent is only invoked when route matches */
- getComponent (nextState, cb) {
+ getComponent(nextState, cb) {
/* Webpack - use 'require.ensure' to create a split point
and embed an async module loader (jsonp) when bundling */
require.ensure([], (require) => {
/* Webpack - use require callback to define
dependencies for bundling */
- const Counter = require('./containers/CounterContainer').default
- const reducer = require('./modules/counter').default
+ const Counter = require('./containers/CounterContainer').default;
+ const reducer = require('./modules/counter').default;
/* Add the reducer to the store on key 'counter' */
- injectReducer(store, { key: 'counter', reducer })
+ injectReducer(store, { key: 'counter', reducer });
/* Return getComponent */
- cb(null, Counter)
+ cb(null, Counter);
/* Webpack named bundle */
- }, 'counter')
- }
-})
+ }, 'counter');
+ },
+});
diff --git a/src/routes/Counter/modules/counter.js b/src/routes/_Counter/modules/counter.js
similarity index 64%
rename from src/routes/Counter/modules/counter.js
rename to src/routes/_Counter/modules/counter.js
index 8283ced..7b23279 100644
--- a/src/routes/Counter/modules/counter.js
+++ b/src/routes/_Counter/modules/counter.js
@@ -1,16 +1,16 @@
// ------------------------------------
// Constants
// ------------------------------------
-export const COUNTER_INCREMENT = 'COUNTER_INCREMENT'
+export const COUNTER_INCREMENT = 'COUNTER_INCREMENT';
// ------------------------------------
// Actions
// ------------------------------------
-export function increment (value = 1) {
+export function increment(value = 1) {
return {
type: COUNTER_INCREMENT,
- payload: value
- }
+ payload: value,
+ };
}
/* This is a thunk, meaning it is a function that immediately
@@ -21,35 +21,33 @@ export function increment (value = 1) {
you'd probably want to dispatch an action of COUNTER_DOUBLE and let the
reducer take care of this logic. */
-export const doubleAsync = () => {
- return (dispatch, getState) => {
- return new Promise((resolve) => {
+export const doubleAsync = () =>
+ (dispatch, getState) =>
+ new Promise((resolve) => {
setTimeout(() => {
- dispatch(increment(getState().counter))
- resolve()
- }, 200)
- })
- }
-}
+ dispatch(increment(getState().counter));
+ resolve();
+ }, 200);
+ });
export const actions = {
increment,
- doubleAsync
-}
+ doubleAsync,
+};
// ------------------------------------
// Action Handlers
// ------------------------------------
const ACTION_HANDLERS = {
- [COUNTER_INCREMENT]: (state, action) => state + action.payload
-}
+ [COUNTER_INCREMENT]: (state, action) => state + action.payload,
+};
// ------------------------------------
// Reducer
// ------------------------------------
-const initialState = 0
-export default function counterReducer (state = initialState, action) {
- const handler = ACTION_HANDLERS[action.type]
+const initialState = 0;
+export default function counterReducer(state = initialState, action) {
+ const handler = ACTION_HANDLERS[action.type];
- return handler ? handler(state, action) : state
+ return handler ? handler(state, action) : state;
}
diff --git a/src/routes/Home/assets/Duck.jpg b/src/routes/_Home/assets/Duck.jpg
similarity index 100%
rename from src/routes/Home/assets/Duck.jpg
rename to src/routes/_Home/assets/Duck.jpg
diff --git a/src/routes/_Home/components/HomeView.js b/src/routes/_Home/components/HomeView.js
new file mode 100644
index 0000000..77ed4df
--- /dev/null
+++ b/src/routes/_Home/components/HomeView.js
@@ -0,0 +1,16 @@
+import React from 'react';
+import DuckImage from '../assets/Duck.jpg';
+import classes from './HomeView.scss';
+
+export const HomeView = () => (
+
+
Welcome!
+

+
+);
+
+export default HomeView;
diff --git a/src/routes/_Home/components/HomeView.scss b/src/routes/_Home/components/HomeView.scss
new file mode 100644
index 0000000..10de960
--- /dev/null
+++ b/src/routes/_Home/components/HomeView.scss
@@ -0,0 +1,5 @@
+.duck {
+ display: block;
+ width: 120px;
+ margin: 1.5rem auto;
+}
diff --git a/src/routes/_Home/index.js b/src/routes/_Home/index.js
new file mode 100644
index 0000000..d937c77
--- /dev/null
+++ b/src/routes/_Home/index.js
@@ -0,0 +1,6 @@
+import HomeView from './components/HomeView';
+
+// Sync route definition
+export default {
+ component: HomeView,
+};
diff --git a/src/routes/_index.js b/src/routes/_index.js
new file mode 100644
index 0000000..9227ab9
--- /dev/null
+++ b/src/routes/_index.js
@@ -0,0 +1,36 @@
+// We only need to import the modules necessary for initial render
+import CoreLayout from '../layouts/CoreLayout/CoreLayout';
+import Home from './Home';
+import CounterRoute from './Counter';
+
+/* Note: Instead of using JSX, we recommend using react-router
+ PlainRoute objects to build route definitions. */
+
+export const createRoutes = (store) => ({
+ path: '/',
+ component: CoreLayout,
+ indexRoute: Home,
+ childRoutes: [
+ new CounterRoute(store),
+ ],
+});
+
+/* Note: childRoutes can be chunked or otherwise loaded programmatically
+ using getChildRoutes with the following signature:
+
+ getChildRoutes (location, cb) {
+ require.ensure([], (require) => {
+ cb(null, [
+ // Remove imports!
+ require('./Counter').default(store)
+ ])
+ })
+ }
+
+ However, this is not necessary for code-splitting! It simply provides
+ an API for async route definitions. Your code splitting should occur
+ inside the route `getComponent` function, since it is only invoked
+ when the route exists and matches.
+*/
+
+export default createRoutes;
diff --git a/src/routes/index.js b/src/routes/index.js
index 7b36956..3d7c753 100644
--- a/src/routes/index.js
+++ b/src/routes/index.js
@@ -1,36 +1,10 @@
-// We only need to import the modules necessary for initial render
-import CoreLayout from '../layouts/CoreLayout/CoreLayout'
-import Home from './Home'
-import CounterRoute from './Counter'
+import CoreLayout from '../layouts/CoreLayout/CoreLayout';
+import Home from './Home';
-/* Note: Instead of using JSX, we recommend using react-router
- PlainRoute objects to build route definitions. */
-
-export const createRoutes = (store) => ({
+export const createRoutes = (/* store */) => ({
path: '/',
component: CoreLayout,
indexRoute: Home,
- childRoutes: [
- CounterRoute(store)
- ]
-})
-
-/* Note: childRoutes can be chunked or otherwise loaded programmatically
- using getChildRoutes with the following signature:
-
- getChildRoutes (location, cb) {
- require.ensure([], (require) => {
- cb(null, [
- // Remove imports!
- require('./Counter').default(store)
- ])
- })
- }
-
- However, this is not necessary for code-splitting! It simply provides
- an API for async route definitions. Your code splitting should occur
- inside the route `getComponent` function, since it is only invoked
- when the route exists and matches.
-*/
+});
-export default createRoutes
+export default createRoutes;
diff --git a/src/store/createStore.js b/src/store/createStore.js
index 698fb31..c4f4319 100644
--- a/src/store/createStore.js
+++ b/src/store/createStore.js
@@ -1,22 +1,23 @@
-import { applyMiddleware, compose, createStore } from 'redux'
-import { routerMiddleware } from 'react-router-redux'
-import thunk from 'redux-thunk'
-import makeRootReducer from './reducers'
+import { applyMiddleware, compose, createStore } from 'redux';
+import { routerMiddleware } from 'react-router-redux';
+import createDebounce from 'redux-debounced';
+import thunk from 'redux-thunk';
+import makeRootReducer from './reducers';
export default (initialState = {}, history) => {
// ======================================================
// Middleware Configuration
// ======================================================
- const middleware = [thunk, routerMiddleware(history)]
+ const middleware = [thunk, routerMiddleware(history), createDebounce()];
// ======================================================
// Store Enhancers
// ======================================================
- const enhancers = []
+ const enhancers = [];
if (__DEBUG__) {
- const devToolsExtension = window.devToolsExtension
+ const devToolsExtension = window.devToolsExtension;
if (typeof devToolsExtension === 'function') {
- enhancers.push(devToolsExtension())
+ enhancers.push(devToolsExtension());
}
}
@@ -30,15 +31,15 @@ export default (initialState = {}, history) => {
applyMiddleware(...middleware),
...enhancers
)
- )
- store.asyncReducers = {}
+ );
+ store.asyncReducers = {};
if (module.hot) {
module.hot.accept('./reducers', () => {
- const reducers = require('./reducers').default
- store.replaceReducer(reducers)
- })
+ const reducers = require('./reducers').default;
+ store.replaceReducer(reducers);
+ });
}
- return store
-}
+ return store;
+};
diff --git a/src/store/reducers.js b/src/store/reducers.js
index 3162282..0bd9a0b 100644
--- a/src/store/reducers.js
+++ b/src/store/reducers.js
@@ -1,17 +1,20 @@
-import { combineReducers } from 'redux'
-import { routerReducer as router } from 'react-router-redux'
+import { combineReducers } from 'redux';
+import { routerReducer as router } from 'react-router-redux';
-export const makeRootReducer = (asyncReducers) => {
- return combineReducers({
+// Sync routes
+import display from '../routes/Home/modules/display';
+
+export const makeRootReducer = (asyncReducers) =>
+ combineReducers({
// Add sync reducers here
+ display,
router,
- ...asyncReducers
- })
-}
+ ...asyncReducers,
+ });
export const injectReducer = (store, { key, reducer }) => {
- store.asyncReducers[key] = reducer
- store.replaceReducer(makeRootReducer(store.asyncReducers))
-}
+ store.asyncReducers[key] = reducer;
+ store.replaceReducer(makeRootReducer(store.asyncReducers));
+};
-export default makeRootReducer
+export default makeRootReducer;
diff --git a/tests/components/DisplayPicker.spec.js b/tests/components/DisplayPicker.spec.js
new file mode 100644
index 0000000..f3b00e3
--- /dev/null
+++ b/tests/components/DisplayPicker.spec.js
@@ -0,0 +1,8 @@
+import React from 'react'
+import DisplayPicker from 'components/DisplayPicker/DisplayPicker'
+
+describe('(Component) DisplayPicker', () => {
+ it('should exist', () => {
+
+ })
+})
diff --git a/tests/components/FastInput.spec.js b/tests/components/FastInput.spec.js
new file mode 100644
index 0000000..fd97d30
--- /dev/null
+++ b/tests/components/FastInput.spec.js
@@ -0,0 +1,8 @@
+import React from 'react'
+import FastInput from 'components/FastInput/FastInput'
+
+describe('(Component) FastInput', () => {
+ it('should exist', () => {
+
+ })
+})
diff --git a/tests/components/PushButton.spec.js b/tests/components/PushButton.spec.js
new file mode 100644
index 0000000..c187467
--- /dev/null
+++ b/tests/components/PushButton.spec.js
@@ -0,0 +1,8 @@
+import React from 'react'
+import PushButton from 'components/PushButton/PushButton'
+
+describe('(Component) PushButton', () => {
+ it('should exist', () => {
+
+ })
+})
diff --git a/tests/containers/DisplayPickerContainer.spec.js b/tests/containers/DisplayPickerContainer.spec.js
new file mode 100644
index 0000000..4608642
--- /dev/null
+++ b/tests/containers/DisplayPickerContainer.spec.js
@@ -0,0 +1,5 @@
+describe('(Component) DisplayPickerContainer', () => {
+ it('exists', () => {
+
+ })
+})
diff --git a/tests/routes/Home/modules/display.spec.js b/tests/routes/Home/modules/display.spec.js
new file mode 100644
index 0000000..b6757eb
--- /dev/null
+++ b/tests/routes/Home/modules/display.spec.js
@@ -0,0 +1,9 @@
+import reducer, { initialState } from 'redux/modules/display'
+
+describe('(Redux) display', () => {
+ describe('(Reducer)', () => {
+ it('sets up initial state', () => {
+ expect(reducer(undefined, {})).to.eql(initialState)
+ })
+ })
+})
diff --git a/tests/test-bundler.js b/tests/test-bundler.js
index 507082a..a15a524 100644
--- a/tests/test-bundler.js
+++ b/tests/test-bundler.js
@@ -1,20 +1,20 @@
// ---------------------------------------
// Test Environment Setup
// ---------------------------------------
-import sinon from 'sinon'
-import chai from 'chai'
-import sinonChai from 'sinon-chai'
-import chaiAsPromised from 'chai-as-promised'
-import chaiEnzyme from 'chai-enzyme'
+import sinon from 'sinon';
+import chai from 'chai';
+import sinonChai from 'sinon-chai';
+import chaiAsPromised from 'chai-as-promised';
+import chaiEnzyme from 'chai-enzyme';
-chai.use(sinonChai)
-chai.use(chaiAsPromised)
-chai.use(chaiEnzyme())
+chai.use(sinonChai);
+chai.use(chaiAsPromised);
+chai.use(chaiEnzyme());
-global.chai = chai
-global.sinon = sinon
-global.expect = chai.expect
-global.should = chai.should()
+global.chai = chai;
+global.sinon = sinon;
+global.expect = chai.expect;
+global.should = chai.should();
// ---------------------------------------
// Require Tests
@@ -24,17 +24,17 @@ global.should = chai.should()
// for some reason an array literal without a trailing `;` causes
// some build environments to fail.
const __karmaWebpackManifest__ = new Array() // eslint-disable-line
-const inManifest = (path) => ~__karmaWebpackManifest__.indexOf(path)
+const inManifest = (path) => ~__karmaWebpackManifest__.indexOf(path);
// require all `tests/**/*.spec.js`
-const testsContext = require.context('./', true, /\.spec\.js$/)
+const testsContext = require.context('./', true, /\.spec\.js$/);
// only run tests that have changed after the first pass.
const testsToRun = testsContext.keys().filter(inManifest)
-;(testsToRun.length ? testsToRun : testsContext.keys()).forEach(testsContext)
+;(testsToRun.length ? testsToRun : testsContext.keys()).forEach(testsContext);
// require all `src/**/*.js` except for `main.js` (for isparta coverage reporting)
if (__COVERAGE__) {
- const componentsContext = require.context('../src/', true, /^((?!main).)*\.js$/)
- componentsContext.keys().forEach(componentsContext)
+ const componentsContext = require.context('../src/', true, /^((?!main).)*\.js$/);
+ componentsContext.keys().forEach(componentsContext);
}