From f630c04f0a90294291eaf49f697f986c25cc946e Mon Sep 17 00:00:00 2001 From: Joel Chen Date: Mon, 19 Jun 2017 18:45:07 -0700 Subject: [PATCH 1/2] archetype-react-component: [major] clappify --- .../README.md | 255 +----------------- .../config/webpack/partial/test-base.js | 14 +- .../package.json | 9 +- .../.travis.yml | 31 --- .../CHANGELOG.md | 21 -- .../CONTRIBUTING.md | 71 ----- .../DEVELOPMENT.md | 74 ++--- .../README.md | 86 +----- .../archetype-clap.js | 114 ++++++++ .../archetype-gulpfile.js | 97 ------- .../clap.js | 3 + .../gulpfile.js | 3 - .../package.json | 9 +- 13 files changed, 178 insertions(+), 609 deletions(-) delete mode 100644 packages/electrode-archetype-react-component/.travis.yml delete mode 100644 packages/electrode-archetype-react-component/CHANGELOG.md delete mode 100644 packages/electrode-archetype-react-component/CONTRIBUTING.md create mode 100644 packages/electrode-archetype-react-component/archetype-clap.js delete mode 100644 packages/electrode-archetype-react-component/archetype-gulpfile.js create mode 100644 packages/electrode-archetype-react-component/clap.js delete mode 100644 packages/electrode-archetype-react-component/gulpfile.js diff --git a/packages/electrode-archetype-react-component-dev/README.md b/packages/electrode-archetype-react-component-dev/README.md index 531f0dbfa..519f5b10c 100644 --- a/packages/electrode-archetype-react-component-dev/README.md +++ b/packages/electrode-archetype-react-component-dev/README.md @@ -1,262 +1,9 @@ -# Archetype: Electrode React Component +# Archetype: Electrode React Component Dev [![NPM version][npm-image]][npm-url] [![Dependency Status][daviddm-image]][daviddm-url] [![devDependency Status][daviddm-dev-image]][daviddm-dev-url] [![npm downloads][npm-downloads-image]][npm-downloads-url] A Walmart Labs flavored react component archetype. -## Creating A New Component - -First, install [yeoman](http://yeoman.io/) to help quickly create an empty component: - -```bash -$ npm install -g yo -``` - -Now, `yo` can scaffold the project for you. - -```bash -$ yo electrode-component -``` - -You should see something similar to the below session: - -```sh -$ yo electrode-component - -Welcome to the Electrode Component generator - -Were going to set up a new Electrode Component, ready for development with -gulp, webpack, demo, electrode component archetype, live-reload - -? What is your Package/GitHub project name? (e.g., 'wysiwyg-component') product-card -? What is the ClassName for your component? ProductCard -? What will be the npm package name? product-card -? What will be the GitHub organization username (e.g., 'walmartlabs')? electrodeio -? What is your name? (for copyright notice, etc.) arpan nanavati -? What is your GitHub Username? ananavati -? What is the name of the GitHub repo this will be published at? product-card -? Would you like to create a new directory for your project? Yes - - create .babelrc - create .gitignore - create .npmignore - create .editorconfig - create gulpfile.js - create package.json - create README.md - create src/components/product-card.jsx - create src/styles/product-card.styl - create src/index.js - create demo/demo.jsx - create demo/demo.css - create demo/index.jsx - create demo/examples/product-card.example - create test/client/.eslintrc - create test/client/components/product-card.spec.jsx - -Your new Electrode Component is ready! - -Your component is in '/src' and your demo files are in '/demo/*' - -Type 'cd product-card' then 'gulp demo' to run the development build and demo tasks. -``` - -## Configuring an existing project / manual setup - -If you prefer to create your component manually or if you have an existing component that you want to migrate to using this archetype, follow the instructions below: - -###### run the following in your project - -```bash -$ npm install --save-dev electrode-gulp-helper electrode-archetype-react-component electrode-archetype-react-component-dev -``` - - -###### Add a `.babelrc` to your project - -The `.babelrc` needs to extend -[the archetype's babel configuration](config/babel/.babelrc) in order to apply the presents (ES2015, React) and the plugins like i18n. If your project needs additional Babel settings (like using stage 0 features) you can add them to this file. See the [Babel docs](https://babeljs.io/docs/usage/babelrc/) for more information. - -```json -{ - "extends": "./node_modules/electrode-archetype-react-component/config/babel/.babelrc" -} -``` - -###### Add a `gulpfile.js` to your project - -The `gulpfile.js` needs to extend -[the archetype's gulp tasks](/arhcetype-gulpfile.js) in order to apply the shared tasks on your new/existing electrode component. Add this following lines of code to the newly created `gulpfile.js` - -```javascript -"use strict"; - -const exec = require("electrode-gulp-helper").exec; - -const tasks = { - "demo": ["generate", "server-dev"], - "demo-iso": ["dev-iso"], - "generate": ["generate-metadata", "generate-documentation"], - "generate-documentation": () => exec(`electrode-docgen --package ./package.json --src ./src --markdown components.md`), - "generate-metadata": () => exec(`electrode-docgen --package ./package.json --src ./src --metadata components.json`), - "prepublish": ["npm:prepublish"], - "preversion": ["check-cov"] -} - -require("electrode-archetype-react-component")(tasks); -``` - - -## Managing Dependencies - -The archetypes are split into two parts: `` and `-dev`. Both archetypes need to be in each component and should be included in the `package.json`'s `devDependencies`. - ---- - -## Project Structure - -This archetype assumes an architecture as follows: - -``` -demo/ - demo.jsx - demo.css -src - components/ - *.jsx - styles/ - *.css - index.js -test - client/ - spec/ - components/ - *.jsx? - *.jsx? - main.js - test.html -.babelrc -package.json -``` - -## CSS Modules - -By default, this archetype assumes you are using CSS-Modules + CSS-Next, you need -to opt-in to stylus support by adding a `*.styl` to your *project's* `demo/demo.styl` & `src/styles/*.styl` - -## Gotchas - -For the `demo-iso` task to work, `demo/demo.jsx` has some limitations: - -* `demo/demo.jsx` can't use `react-router` -* `demo/demo.jsx` can't import files that rely on webpack loaders e.g. `.styl` files. - -This is because the server rendering uses node for both routing and import statements. -Specifically for routing, `react-router` instances create a history that relies on DOM availability. -This will break server render with an error like this: -`Unhandled rejection Invariant Violation: Browser history needs a DOM` - -## Demo server config - -If you would like to augment or override the demo server config you can add `archetype-demo-server.config.js` file to the root of the project. This file will be merged with the default config and passed into the `electrode-server` instance. Add any hapi plugins or settings here. - -```js -// Sample archetype-demo-server.config.js -module.exports = { - "plugins": { - "my-electrode-plugin": {} - } -}; -``` - -## Tasks exposed via npm scripts & gulp as part of the electrode-archetype-react-component - -```bash -$ gulp help -[13:02:10] Using gulpfile ~/walmart-oss/test-generator-electrode-component/product-card/gulpfile.js -[13:02:10] Starting 'help'... - -Usage - gulp [TASK] [OPTIONS...] - -Available tasks - archetype:check .............. tasks: ["archetype:lint","archetype:test-dev-pkg","clean-test-init"] - archetype:lint --------------- tasks: ["archetype:lint-server"] - archetype:lint-server - archetype:test-dev-pkg - babel-src-step - build ........................ tasks: ["build-lib","build-dist"] - build-dist ------------------- tasks: ["clean-dist","build-dist-min","build-dist-dev"] - build-dist-dev - build-dist-min ............... Build minified dist files for production - deps: ["~production-env"] - build-lib -------------------- deps: ["~production-env"] - build-lib:clean-tmp - build-lib:copy-flow - build-lib:flatten-l10n - check ........................ tasks: ["check-dep","lint","test-cov"] - check-ci --------------------- tasks: ["check-dep","lint","test-ci"] - check-cov .................... tasks: ["lint","test-cov"] - check-dep - check-dev -------------------- tasks: ["lint","test-dev"] - clean ........................ tasks: ["clean-lib","clean-dist"] - clean-dist - clean-lib - clean-test-init - cov-frontend - cov-frontend-50 - cov-frontend-70 - cov-frontend-85 - cov-frontend-95 - default ---------------------- Invokes 'gulp help' - demo ......................... tasks: ["generate","server-dev"] - demo-iso --------------------- tasks: ["dev-iso"] - dev .......................... Start server in development mode - tasks: ["~webpack-dev",["server-dev","server-test"]] - dev-iso ---------------------- Start ISO server in development mode - tasks: ["~webpack-dev",["iso-render-server-start","server-dev-iso"]] - generate ..................... tasks: ["generate-metadata","generate-documentation"] - generate-documentation - generate-metadata - help ------------------------- Display this help text. - hot .......................... Start server in hot/auto-watch mode - tasks: ["~webpack-dev",["server-hot","server-test"]] - iso-render-server-start ------ tasks: ["~webpack-dev","iso-render-server-start-watch"] - iso-render-server-start-watch - lint ......................... tasks: ["lint-react-demo","lint-react-src","lint-react-test","lint-scripts"] - lint-react-demo - lint-react-src - lint-react-test - lint-scripts - npm:prepublish --------------- tasks: ["build-lib","build-dist-dev","build-dist-min"] - prepublish ................... tasks: ["npm:prepublish"] - preversion ------------------- tasks: ["check-cov"] - server-dev - server-dev-iso - server-hot - server-test - test-ci ...................... tasks: ["test-frontend-ci"] - test-cov --------------------- tasks: ["test-frontend-cov"] - test-dev ..................... tasks: ["test-frontend-dev"] - test-frontend - test-frontend-ci - test-frontend-cov - test-frontend-dev - test-frontend-dev-watch - test-watch ------------------- tasks: ["test-frontend-dev-watch"] - -``` - -## Check the archetype configs: - -If you are enhancing / refactoring this archetype and have locally checked it out, -please see [`CONTRIBUTING.md`](./CONTRIBUTING.md) for our guidelines. - -The main check we provide for the archetype itself is: - -```sh -$ gulp check -``` [npm-image]: https://badge.fury.io/js/electrode-archetype-react-component-dev.svg [npm-url]: https://npmjs.org/package/electrode-archetype-react-component-dev diff --git a/packages/electrode-archetype-react-component-dev/config/webpack/partial/test-base.js b/packages/electrode-archetype-react-component-dev/config/webpack/partial/test-base.js index 962955830..368019676 100644 --- a/packages/electrode-archetype-react-component-dev/config/webpack/partial/test-base.js +++ b/packages/electrode-archetype-react-component-dev/config/webpack/partial/test-base.js @@ -12,16 +12,12 @@ var prodCfg = require("../webpack.config"); * https://github.com/sinonjs/sinon/pull/600#issuecomment-162529457 */ /* - * Added fix for "gulp check" on Windows + * Added fix for "clap check" on Windows */ if (process.platform === "win32") { - prodCfg.module.noParse = [ - /node_modules\\sinon\\/ - ]; + prodCfg.module.noParse = [/node_modules\\sinon\\/]; } else { - prodCfg.module.noParse = [ - /node_modules\/sinon\// - ]; + prodCfg.module.noParse = [/node_modules\/sinon\//]; } module.exports = { @@ -34,5 +30,5 @@ module.exports = { "react/addons": true, // important!! https://github.com/airbnb/enzyme/issues/302 "react/lib/ExecutionEnvironment": true, "react/lib/ReactContext": true - }, -} + } +}; diff --git a/packages/electrode-archetype-react-component-dev/package.json b/packages/electrode-archetype-react-component-dev/package.json index 8d89e3e93..a4c40849c 100644 --- a/packages/electrode-archetype-react-component-dev/package.json +++ b/packages/electrode-archetype-react-component-dev/package.json @@ -11,9 +11,6 @@ "url": "https://github.com/electrode-io/electrode/issues" }, "license": "Apache-2.0", - "config": { - "archetype": "node_modules/electrode-archetype-react-component" - }, "scripts": {}, "dependencies": { "autoprefixer-stylus": "0.13.0", @@ -34,13 +31,13 @@ "bunyan": "^1.5.1", "chai": "^3.2.0", "chai-shallowly": "^0.9.10", + "chalk": "^1.1.3", "component-playground": "^1.0.1", "config": "^1.19.0", "css-loader": "^0.26.1", "electrode-check-dependencies": "^1.0.2", "electrode-demo-index": "^1.0.0", "electrode-docgen": "^1.0.0", - "electrode-gulp-helper": "^1.0.0", "enzyme": "^2.3.0", "eslint": "^3.18.0", "eslint-config-walmart": "^1.1.0", @@ -100,7 +97,9 @@ "url-loader": "^0.5.6", "webpack": "^2.3.1", "webpack-config-composer": "^1.0.2", - "webpack-dev-server": "^2.4.2" + "webpack-dev-server": "^2.4.2", + "xclap": "^0.2.0", + "xsh": "^0.3.2" }, "engines": { "node": ">= 4 <= 8", diff --git a/packages/electrode-archetype-react-component/.travis.yml b/packages/electrode-archetype-react-component/.travis.yml deleted file mode 100644 index fdc8f3e72..000000000 --- a/packages/electrode-archetype-react-component/.travis.yml +++ /dev/null @@ -1,31 +0,0 @@ -language: node_js - -node_js: - - v6 - -brances: - only: - - master - -before_install: - - npm install -g gulp yo generator-electrode - - currentfolder=${PWD##*/} - - if [ "$currentfolder" != 'electrode-archetype-react-component' ]; then cd .. && eval "mv $currentfolder electrode-archetype-react-component" && cd electrode-archetype-react-component; fi - - npm install - - cd dev ; npm install ; cd .. - -before_script: - - export DISPLAY=:99.0 - - sh -e /etc/init.d/xvfb start - -script: - # run the archetype check task. - - gulp archetype:check - - # create a new component using electrode:component yeoman generator to run the components unit-tests. - - yo electrode:component --projectName=product-card --packageName=product-card --packageGitHubOrg=walmartlabs --developerName="Arpan Nanavati" --ghUser=ananavati --ghRepo=product-card --createDirectory=Y --quotes='"' - - cd product-card/packages/product-card - - # run ci tests and generate a bundle. - - gulp check-ci - - gulp build diff --git a/packages/electrode-archetype-react-component/CHANGELOG.md b/packages/electrode-archetype-react-component/CHANGELOG.md deleted file mode 100644 index b0fe6347a..000000000 --- a/packages/electrode-archetype-react-component/CHANGELOG.md +++ /dev/null @@ -1,21 +0,0 @@ -# Change Log -All notable changes to this project will be documented in this file. -This project adheres to [Semantic Versioning](http://semver.org/). - -#################################################################################################### - Archetype-Next - -## x.x.x (xxxx-xx-xx) - -#### User Facing Changes - -#### Internal Changes - -#################################################################################################### - -## 0.0.1 - -- Initial release - - [configs for `webpack`, `karma`, `eslint`, `babel`](config) - - [tasks](README.md#tasks) - - docs for [README.md](README.md), [CHANGELOG.md](CHANGELOG.md), [CONTRIBUTING.md](CONTRIBUTING.md) diff --git a/packages/electrode-archetype-react-component/CONTRIBUTING.md b/packages/electrode-archetype-react-component/CONTRIBUTING.md deleted file mode 100644 index c6a2a27d0..000000000 --- a/packages/electrode-archetype-react-component/CONTRIBUTING.md +++ /dev/null @@ -1,71 +0,0 @@ -Contributing -============ - -Thanks for helping out! - -## Dependencies - -We have a three-way dependency scheme: - -* `package.json:dependencies`: Production dependencies for the archetype - installed in a project. -* `dev/package.json:dependencies`: Development dependencies for the archetype - installed in a project. -* `package.json:devDependencies`: The development dependencies used _internally_ - for the this archetype during development (self tests, checks, etc.) that - are **not** part of the overall archeype outside workflow. - -## Checks, Tests - -Ideally, we have CI do all this for us. For _now_, before opening a PR you must -do all of the following steps: - -Check the archetype configs: - -```sh -$ gulp check -``` - -Check a fresh init'ed project: - -```sh -$ npm install -g yo -$ cd /TEMP/DIR -$ yo electrode-component -(answer prompts) - -$ cd NEW_PROJ -$ gulp check-cov -``` - -## Documentation - -To generate the usage snippet in the `README.md`, run: - -```sh -$ gulp help -``` - -in any project where this archetype is installed and paste in the output. - -# Release - -For tagged official releases _only_, make sure to: - -1. Update appropriate `CHANGELOG.md` notes -2. Bump `package.json` version -3. Generate a new `ARCHETYPE-dev` `package.json` -4. Add to git, tag, and publish - -```sh -$ vim CHANGELOG.md # Version notes -$ vim package.json # Bump version -$ gulp prepublish # Generate `dev/package.json` -$ gulp check # Last check! -$ git add package.json dev CHANGELOG.md -$ git commit -m "Version bump" -$ git tag -a "vNUMBER" -m "Version NUMBER" -$ git push && git push --tags -$ npm publish # Publish main project -$ cd dev && npm publish # Publish dev project -``` diff --git a/packages/electrode-archetype-react-component/DEVELOPMENT.md b/packages/electrode-archetype-react-component/DEVELOPMENT.md index 4539435a0..722ab7416 100644 --- a/packages/electrode-archetype-react-component/DEVELOPMENT.md +++ b/packages/electrode-archetype-react-component/DEVELOPMENT.md @@ -1,7 +1,7 @@ Development =========== -We use `gulp` and `npm` to control all aspects of development and +We use `clap` and `npm` to control all aspects of development and publishing. @@ -11,7 +11,7 @@ Build for production use (NPM, bower, etc) and create `dist` UMD bundles (min'ed, non-min'ed) ``` -$ gulp build +$ clap build ``` Note that `dist/` files are only updated and committed on **tagged releases**. @@ -26,18 +26,18 @@ Run the `demo` application with watched rebuilds either doing: ### Basic Watched Builds -```sh -$ gulp dev # dev test/app server -$ gulp open-dev # (OR) dev servers _and a browser window opens!_ +```bash +$ clap dev # dev test/app server +$ clap open-dev # (OR) dev servers _and a browser window opens!_ ``` ### Watched Builds + Hot Reloading Same as above, but with hot reloading of React components. -```sh -$ gulp hot # hot test/app server -$ gulp open-hot # (OR) hot servers _and a browser window opens!_ +```bash +$ clap hot # hot test/app server +$ clap open-hot # (OR) hot servers _and a browser window opens!_ ``` From there, using either `dev` or `hot`, you can see: @@ -70,32 +70,32 @@ Testing is an important part of the development process at Walmart. The technolo During development, you are expected to be running either: -```sh -$ gulp dev +```bash +$ clap dev ``` to build the lib and test files. With these running, you can run the faster -```sh -$ gulp check-dev +```bash +$ clap check-dev ``` Command. It is comprised of: -```sh -$ gulp lint -$ gulp test-dev +```bash +$ clap lint +$ clap test-dev ``` Note that the tests here are not instrumented for code coverage and are thus more development / debugging friendly. ### Hot Test Running -Assuming you have one terminal with `gulp hot` you can have your tests run hot as well: +Assuming you have one terminal with `clap hot` you can have your tests run hot as well: -```sh -$ gulp test-watch # if you already have hot running on a tab. -$ gulp concurrent-test-watch # If you want to run in only 1 terminal window. +```bash +$ clap test-watch # if you already have hot running on a tab. +$ clap concurrent-test-watch # If you want to run in only 1 terminal window. ``` **NOTE: ** This feature is relatively new and occasionally your tests will run _before_ the new @@ -106,20 +106,20 @@ webpack build is completed. This is okay, just try saving a file to reload all o CI doesn't have source / test file watchers, so has to _build_ the test files via the commands: -```sh -$ gulp check # PhantomJS only -$ gulp check-cov # (OR) PhantomJS w/ coverage -$ gulp check-ci # (OR) PhantomJS,Firefox + coverage - available on Travis. +```bash +$ clap check # PhantomJS only +$ clap check-cov # (OR) PhantomJS w/ coverage +$ clap check-ci # (OR) PhantomJS,Firefox + coverage - available on Travis. ``` Which is currently comprised of: -```sh -$ gulp lint # AND ... +```bash +$ clap lint # AND ... -$ gulp test # PhantomJS only -$ gulp test-cov # (OR) PhantomJS w/ coverage -$ gulp test-ci # (OR) PhantomJS,Firefox + coverage +$ clap test # PhantomJS only +$ clap test-cov # (OR) PhantomJS w/ coverage +$ clap test-ci # (OR) PhantomJS,Firefox + coverage ``` Note that `(test|check)-(cov|ci)` run code coverage and thus the @@ -129,13 +129,13 @@ test code may be harder to debug because it is instrumented. The client tests rely on webpack dev server to create and serve the bundle of the app/test code at: http://127.0.0.1:3001/assets/main.js which is done -with the task `gulp server-test` (part of `npm dev`). +with the task `clap server-test` (part of `npm dev`). ### Code Coverage Code coverage is generated via the commands: -```sh -$ gulp check-cov # part of `gulp check` task +```bash +$ clap check-cov # part of `clap check` task ``` Code coverage reports are outputted to: @@ -153,17 +153,17 @@ Test results are output to test.html which can view by opening Run either of the below commands before opening the link. -```sh -gulp server-test -gulp dev # (OR) (which includes `server-test`) -gulp hot # (OR) (which includes `server-test`) +```bash +clap server-test +clap dev # (OR) (which includes `server-test`) +clap hot # (OR) (which includes `server-test`) ``` ## Releases **IMPORTANT - NPM**: To correctly run `preversion` your first step is to make sure that you have a very modern `npm` binary: -```sh +```bash $ npm install -g npm ``` @@ -171,7 +171,7 @@ Built files in `dist/` should **not** be committed during development or PRs. Instead we _only_ build and commit them for published, tagged releases. So the basic workflow is: -```sh +```bash # Make sure you have a clean, up-to-date `master` $ git pull $ git status # (should be no changes) diff --git a/packages/electrode-archetype-react-component/README.md b/packages/electrode-archetype-react-component/README.md index 81b9c6dcf..5733b63b4 100644 --- a/packages/electrode-archetype-react-component/README.md +++ b/packages/electrode-archetype-react-component/README.md @@ -26,7 +26,7 @@ $ yo electrode-component Welcome to the Electrode Component generator Were going to set up a new Electrode Component, ready for development with -gulp, webpack, demo, electrode component archetype, live-reload +react, webpack, demo, electrode component archetype, live-reload ? What is your Package/GitHub project name? (e.g., 'wysiwyg-component') product-card ? What is the ClassName for your component? ProductCard @@ -42,7 +42,7 @@ gulp, webpack, demo, electrode component archetype, live-reload create .gitignore create .npmignore create .editorconfig - create gulpfile.js + create clap.js create package.json create README.md create src/components/product-card.jsx @@ -62,7 +62,7 @@ If you prefer to create your component manually or if you have an existing compo ###### run the following in your project ```bash -$ npm install --save-dev electrode-gulp-helper electrode-archetype-react-component electrode-archetype-react-component-dev +$ npm install --save-dev electrode-archetype-react-component electrode-archetype-react-component-dev ``` @@ -77,22 +77,23 @@ The `.babelrc` needs to extend } ``` -###### Add a `gulpfile.js` to your project +###### Add a `clap.js` to your project -The `gulpfile.js` needs to extend -[the archetype's gulp tasks](/arhcetype-gulpfile.js) in order to apply the shared tasks on your new/existing electrode component. Add this following lines of code to the newly created `gulpfile.js` +The `clap.js` needs to extend +[the archetype's clap tasks](/arhcetype-clap.js) in order to apply the shared tasks on your new/existing electrode component. Add this following lines of code to the newly created `clap.js` -```javascript +```js "use strict"; -const exec = require("electrode-gulp-helper").exec; +const xclap = require("xclap"); const tasks = { "prepublish": ["npm:prepublish"], "preversion": ["check-cov"] } +xclap.load("myprj", tasks); -require("electrode-archetype-react-component")(tasks); +require("electrode-archetype-react-component")(xclap); ``` @@ -106,7 +107,7 @@ The archetypes are split into two parts: `` and `-dev`. Bo This archetype assumes an architecture as follows: -``` +```text archetype config.js src @@ -169,69 +170,6 @@ Add following styling to `src/styles/your-component.css` } ``` -## Tasks exposed via npm scripts & gulp as part of the electrode-archetype-react-component - -```bash -$ gulp help -[13:02:10] Using gulpfile ~/walmart-oss/test-generator-electrode-component/product-card/gulpfile.js -[13:02:10] Starting 'help'... - -Usage - gulp [TASK] [OPTIONS...] - -Available tasks - archetype:check .............. tasks: ["archetype:lint","archetype:test-dev-pkg","clean-test-init"] - archetype:lint --------------- tasks: ["archetype:lint-server"] - archetype:lint-server - archetype:test-dev-pkg - babel-src-step - build ........................ tasks: ["build-lib","build-dist"] - build-dist ------------------- tasks: ["clean-dist","build-dist-min","build-dist-dev"] - build-dist-dev - build-dist-min ............... Build minified dist files for production - deps: ["~production-env"] - build-lib -------------------- deps: ["~production-env"] - build-lib:clean-tmp - build-lib:copy-flow - build-lib:flatten-l10n - check ........................ tasks: ["check-dep","lint","test-cov"] - check-ci --------------------- tasks: ["check-dep","lint","test-ci"] - check-cov .................... tasks: ["lint","test-cov"] - check-dep - check-dev -------------------- tasks: ["lint","test-dev"] - clean ........................ tasks: ["clean-lib","clean-dist"] - clean-dist - clean-lib - clean-test-init - cov-frontend - cov-frontend-50 - cov-frontend-70 - cov-frontend-85 - cov-frontend-95 - default ---------------------- Invokes 'gulp help' - help ------------------------- Display this help text. - iso-render-server-start ------ tasks: ["~webpack-dev","iso-render-server-start-watch"] - iso-render-server-start-watch - lint ......................... tasks: ["lint-react-src","lint-react-test","lint-scripts"] - lint-react-src - lint-react-test - lint-scripts - npm:prepublish --------------- tasks: ["build-lib","build-dist-dev","build-dist-min"] - prepublish ................... tasks: ["npm:prepublish"] - preversion ------------------- tasks: ["check-cov"] - server-test - test-ci ...................... tasks: ["test-frontend-ci"] - test-cov --------------------- tasks: ["test-frontend-cov"] - test-dev ..................... tasks: ["test-frontend-dev"] - test-frontend - test-frontend-ci - test-frontend-cov - test-frontend-dev - test-frontend-dev-watch - test-watch ------------------- tasks: ["test-frontend-dev-watch"] - -``` - ## Check the archetype configs: If you are enhancing / refactoring this archetype and have locally checked it out, @@ -240,7 +178,7 @@ please see [`CONTRIBUTING.md`](./CONTRIBUTING.md) for our guidelines. The main check we provide for the archetype itself is: ```sh -$ gulp archetype:check +$ clap archetype:check ``` Built with :heart: by [Team Electrode](https://github.com/orgs/electrode-io/people) @WalmartLabs. diff --git a/packages/electrode-archetype-react-component/archetype-clap.js b/packages/electrode-archetype-react-component/archetype-clap.js new file mode 100644 index 000000000..4dc30bfa9 --- /dev/null +++ b/packages/electrode-archetype-react-component/archetype-clap.js @@ -0,0 +1,114 @@ +"use strict"; + +const Path = require("path"); +const archetype = require("./config/archetype"); +const devRequire = archetype.devRequire; +const xsh = devRequire("xsh"); +const $$ = xsh.$; +const exec = xsh.exec; +const mkCmd = xsh.mkCmd; +const chalk = devRequire("chalk"); + +if (process.argv[1].indexOf("gulp") >= 0) { + const cmd = chalk.magenta(`clap ${process.argv.slice(2).join(" ")}`); + console.log(`\nPlease use ${chalk.magenta("clap")} to run archetype commands.`); + console.log(`\nie: ${cmd}`); + const icmd = chalk.magenta(`'npm i -g xclap-cli'`); + console.log(`\nIf you haven't done so, please run ${icmd}\n`); + process.exit(1); +} + +function setupPath() { + const nmBin = "node_modules/.bin"; + xsh.envPath.addToFront(Path.resolve(nmBin)); + xsh.envPath.addToFront(Path.join(archetype.devPath, nmBin)); + xsh.envPath.addToFront(Path.join(__dirname, nmBin)); +} + +function setProductionEnv() { + process.env.NODE_ENV = "production"; +} + +function checkFrontendCov(minimum) { + if (typeof minimum === "string") { + minimum += "."; + } else { + minimum = ""; + } + + return exec(`istanbul check-coverage 'coverage/client/*/coverage.json'`, + `--config=${archetype.devPath}/config/istanbul/.istanbul.${minimum}yml`); +} + +const tasks = { + // env setup common tasks + "~production-env": () => setProductionEnv(), + + // code build/compile tasks + "build": ["clean-dist", "build-lib", "build-dist"], + "build-dist": ["build-dist-min", "build-lib:clean-tmp"], + "build-dist-min": { + dep: ["~production-env"], + desc: "Build minified dist files for production", + task: `webpack --config ${archetype.devPath}/config/webpack/webpack.config.js --colors` + }, + "build-lib": { + dep: ["~production-env"], + task: ["clean-lib", "babel-src-step", "build-lib:flatten-l10n", "build-lib:copy-flow", "build-lib:clean-tmp"] + }, + "babel-src-step": `babel src -d lib`, + "build-lib:clean-tmp": () => $$.rm("-rf", "./tmp"), + "build-lib:copy-flow": `node ${archetype.devPath}/scripts/copy-as-flow-declaration.js`, + "build-lib:flatten-l10n": `node ${archetype.devPath}/scripts/l10n/flatten-messages.js`, + + "archetype:check": ["archetype:test-dev-pkg", "clean-test-init", "archetype:test-init-pkg", "clean-test-init"], + "archetype:test-dev-pkg": `pjv -f dev/package.json`, + "archetype:test-init-pkg": "pjv -f test-init/package.json", + + "check": ["check-dep", "lint", "test-cov", "build-lib:clean-tmp"], + "check-ci": ["check-dep", "lint", "test-ci", "build-lib:clean-tmp"], + "check-cov": ["lint", "test-cov"], + "check-dep": `ecd -f package.json --cf ${archetype.devPath}/config/dependencies/check.json -w`, + "check-dev": ["lint", "test-dev"], + + "clean": ["clean-lib", "clean-dist"], + "clean-dist": () => $$.rm("-rf", "dist"), + "clean-lib": () => $$.rm("-rf", "lib"), + "clean-test-init": () => $$.rm("-rf", "test-init"), + + "cov-frontend": () => checkFrontendCov(), + "cov-frontend-50": () => checkFrontendCov("50"), + "cov-frontend-70": () => checkFrontendCov("70"), + "cov-frontend-85": () => checkFrontendCov("85"), + "cov-frontend-95": () => checkFrontendCov("95"), + + "lint": ["lint-react-src", "lint-react-test", "lint-scripts"], + "lint-react-src": mkCmd(`eslint --ext .js,.jsx`, + `-c ${archetype.devPath}/config/eslint/.eslintrc-react src --color`), + "lint-react-test": mkCmd(`eslint --ext .js,.jsx`, + `-c ${archetype.devPath}/config/eslint/.eslintrc-react-test test/client --color`), + "lint-scripts": `eslint --ext .js -c ${archetype.devPath}/config/eslint/.eslintrc-base scripts --color`, + + "npm:prepublish": ["build-lib", "build-dist-min"], + + "server-test": mkCmd(`webpack-dev-server --port 3001`, + `--config ${archetype.devPath}/config/webpack/webpack.config.test.js --colors`), + + "test-ci": ["test-frontend-ci"], + "test-cov": ["test-frontend-cov"], + "test-dev": ["test-frontend-dev"], + "test-watch": ["test-frontend-dev-watch"], + "concurrent-test-watch": ["hot", "test-frontend-dev-watch"], + "test-frontend": `karma start ${archetype.devPath}/config/karma/karma.conf.js --colors`, + "test-frontend-ci": `karma start --browsers PhantomJS,Firefox ${archetype.devPath}/config/karma/karma.conf.coverage.js --colors`, + "test-frontend-cov": `karma start ${archetype.devPath}/config/karma/karma.conf.coverage.js --colors`, + "test-frontend-dev": `karma start ${archetype.devPath}/config/karma/karma.conf.dev.js --colors`, + "test-frontend-dev-watch": mkCmd(`karma start ${archetype.devPath}/config/karma/karma.conf.watch.js`, + ` --colors --browsers Chrome --no-single-run --auto-watch`) +}; + +module.exports = function (xclap) { + setupPath(); + xclap = xclap || devRequire("xclap"); + xclap.load("electrode", tasks); +}; diff --git a/packages/electrode-archetype-react-component/archetype-gulpfile.js b/packages/electrode-archetype-react-component/archetype-gulpfile.js deleted file mode 100644 index 5bb152c91..000000000 --- a/packages/electrode-archetype-react-component/archetype-gulpfile.js +++ /dev/null @@ -1,97 +0,0 @@ -"use strict"; - -const $$ = require("shelljs"); -const Path = require("path"); -const archetype = require("./config/archetype"); -const gulpHelper = archetype.devRequire("electrode-gulp-helper"); -const exec = gulpHelper.exec; - -function setupPath() { - const nmBin = "node_modules/.bin"; - gulpHelper.envPath.addToFront(Path.resolve(nmBin)); - gulpHelper.envPath.addToFront(Path.join(archetype.devPath, nmBin)); - gulpHelper.envPath.addToFront(Path.join(__dirname, nmBin)); -} - -function setProductionEnv() { - process.env.NODE_ENV = "production"; -} - -function checkFrontendCov(minimum) { - if (typeof minimum === "string") { - minimum += "."; - } else { - minimum = ""; - } - - return exec(`istanbul check-coverage 'coverage/client/*/coverage.json' --config=${archetype.devPath}/config/istanbul/.istanbul.${minimum}yml`); -} - -const tasks = { - // env setup common tasks - "~production-env": () => setProductionEnv(), - - // code build/compile tasks - "build": ["clean-dist", "build-lib", "build-dist"], - "build-dist": ["build-dist-min", "build-lib:clean-tmp"], - "build-dist-min": { - dep: ["~production-env"], - desc: "Build minified dist files for production", - task: () => exec(`webpack --config ${archetype.devPath}/config/webpack/webpack.config.js --colors`) - }, - "build-lib": { - dep: ["~production-env"], - task: ["clean-lib", "babel-src-step", "build-lib:flatten-l10n", "build-lib:copy-flow", "build-lib:clean-tmp"] - }, - "babel-src-step": () => exec(`babel src -d lib`), - "build-lib:clean-tmp": () => $$.rm("-rf", "./tmp"), - "build-lib:copy-flow": () => exec(`node ${archetype.devPath}/scripts/copy-as-flow-declaration.js`), - "build-lib:flatten-l10n": () => exec(`node ${archetype.devPath}/scripts/l10n/flatten-messages.js`), - - "archetype:check": ["archetype:test-dev-pkg", "clean-test-init", "archetype:test-init", "archetype:test-init-pkg", "clean-test-init"], - "archetype:test-dev-pkg": () => exec(`pjv -f dev/package.json`), - "archetype:test-init": () => exec(`yo electrode-component --projectName=test-init --packageName=test-init --packageGitHubOrg=walmartlabs --developerName="Arpan Nanavati" --ghUser=ananavati --ghRepo=test-init --createDirectory=Y`), - "archetype:test-init-pkg": "pjv -f test-init/package.json", - - "check": ["check-dep", "lint", "test-cov", "build-lib:clean-tmp"], - "check-ci": ["check-dep", "lint", "test-ci", "build-lib:clean-tmp"], - "check-cov": ["lint", "test-cov"], - "check-dep": () => exec(`ecd -f package.json --cf ${archetype.devPath}/config/dependencies/check.json -w`), - "check-dev": ["lint", "test-dev"], - - "clean": ["clean-lib", "clean-dist"], - "clean-dist": () => $$.rm("-rf", "dist"), - "clean-lib": () => $$.rm("-rf", "lib"), - "clean-test-init": () => $$.rm("-rf", "test-init"), - - "cov-frontend": () => checkFrontendCov(), - "cov-frontend-50": () => checkFrontendCov("50"), - "cov-frontend-70": () => checkFrontendCov("70"), - "cov-frontend-85": () => checkFrontendCov("85"), - "cov-frontend-95": () => checkFrontendCov("95"), - - "lint": ["lint-react-src", "lint-react-test", "lint-scripts"], - "lint-react-src": () => exec(`eslint --ext .js,.jsx -c ${archetype.devPath}/config/eslint/.eslintrc-react src --color`), - "lint-react-test": () => exec(`eslint --ext .js,.jsx -c ${archetype.devPath}/config/eslint/.eslintrc-react-test test/client --color`), - "lint-scripts": () => exec(`eslint --ext .js -c ${archetype.devPath}/config/eslint/.eslintrc-base scripts --color`), - - "npm:prepublish": ["build-lib", "build-dist-min"], - - "server-test": () => exec(`webpack-dev-server --port 3001 --config ${archetype.devPath}/config/webpack/webpack.config.test.js --colors`), - - "test-ci": ["test-frontend-ci"], - "test-cov": ["test-frontend-cov"], - "test-dev": ["test-frontend-dev"], - "test-watch": ["test-frontend-dev-watch"], - "concurrent-test-watch": ["hot", "test-frontend-dev-watch"], - "test-frontend": () => exec(`karma start ${archetype.devPath}/config/karma/karma.conf.js --colors`), - "test-frontend-ci": () => exec(`karma start --browsers PhantomJS,Firefox ${archetype.devPath}/config/karma/karma.conf.coverage.js --colors`), - "test-frontend-cov": () => exec(`karma start ${archetype.devPath}/config/karma/karma.conf.coverage.js --colors`), - "test-frontend-dev": () => exec(`karma start ${archetype.devPath}/config/karma/karma.conf.dev.js --colors`), - "test-frontend-dev-watch": () => exec(`karma start ${archetype.devPath}/config/karma/karma.conf.watch.js --colors --browsers Chrome --no-single-run --auto-watch`) -}; - -module.exports = function (componentTasks, gulp) { - setupPath(); - gulpHelper.loadTasks(Object.assign(tasks, componentTasks), gulp || require("gulp")); -}; diff --git a/packages/electrode-archetype-react-component/clap.js b/packages/electrode-archetype-react-component/clap.js new file mode 100644 index 000000000..2c488e36e --- /dev/null +++ b/packages/electrode-archetype-react-component/clap.js @@ -0,0 +1,3 @@ +"use strict"; + +require("./archetype-clap")(); diff --git a/packages/electrode-archetype-react-component/gulpfile.js b/packages/electrode-archetype-react-component/gulpfile.js deleted file mode 100644 index 8d84db6f8..000000000 --- a/packages/electrode-archetype-react-component/gulpfile.js +++ /dev/null @@ -1,3 +0,0 @@ -"use strict"; - -require("./archetype-gulpfile")(); diff --git a/packages/electrode-archetype-react-component/package.json b/packages/electrode-archetype-react-component/package.json index 470f02a6c..b1b65a547 100644 --- a/packages/electrode-archetype-react-component/package.json +++ b/packages/electrode-archetype-react-component/package.json @@ -16,21 +16,16 @@ "url": "https://github.com/ananavati" }, "license": "Apache-2.0", - "config": { - "archetype": "node_modules/electrode-archetype-react-component" - }, - "main": "archetype-gulpfile.js", + "main": "archetype-clap.js", "scripts": {}, "devDependencies": { - "electrode-gulp-helper": "^1.0.4", "eslint": "^3.18.0", "eslint-config-walmart": "^1.1.0", "eslint-plugin-filenames": "^1.1.0", - "gulp": "^3.9.1", "opener": "^1.4.1", "optional-require": "^1.0.0", "package-json-validator": "^0.6.1", - "shelljs": "^0.7.0" + "xclap": "^0.2.0" }, "engines": { "node": ">= 4 <= 8", From 8447d88460cb1864ae9ed64cc70140eee9dc98e9 Mon Sep 17 00:00:00 2001 From: Joel Chen Date: Mon, 19 Jun 2017 20:11:18 -0700 Subject: [PATCH 2/2] samples demo component --- samples/demo-component/.gitignore | 506 +++++++++++++++++ samples/demo-component/README.md | 1 + samples/demo-component/demo-app/.editorconfig | 11 + .../demo-component/demo-app/.gitattributes | 1 + samples/demo-component/demo-app/.gitignore | 157 ++++++ samples/demo-component/demo-app/.travis.yml | 5 + samples/demo-component/demo-app/.yo-rc.json | 5 + samples/demo-component/demo-app/LICENSE | 2 + samples/demo-component/demo-app/README.md | 27 + .../demo-app/archetype/config/index.js | 5 + .../config/webpack/webpack.config.dev.js | 16 + .../config/webpack/webpack.config.js | 16 + samples/demo-component/demo-app/clap.js | 1 + .../demo-component/demo-app/config/default.js | 50 ++ .../demo-app/config/development.json | 2 + .../demo-app/config/production.js | 23 + .../demo-app/config/production.json | 2 + samples/demo-component/demo-app/package.json | 59 ++ .../demo-app/src/client/.babelrc | 3 + .../demo-app/src/client/actions/index.jsx | 0 .../demo-app/src/client/app.jsx | 28 + .../demo-app/src/client/components/home.jsx | 23 + .../demo-app/src/client/images/electrode.png | Bin 0 -> 5402 bytes .../demo-app/src/client/reducers/index.jsx | 14 + .../demo-app/src/client/routes.jsx | 7 + .../demo-app/src/client/styles/base.css | 14 + .../demo-app/src/server/.babelrc | 3 + .../demo-app/src/server/index.js | 16 + .../demo-app/src/server/views/index-view.jsx | 39 ++ .../demo-app/test/client/.babelrc | 3 + .../demo-app/test/client/.eslintrc | 5 + .../test/client/components/home.spec.jsx | 34 ++ .../demo-app/test/server/.babelrc | 3 + .../demo-app/test/server/.eslintrc | 5 + samples/demo-component/lerna.json | 7 + samples/demo-component/package.json | 26 + .../packages/demo-component/.babelrc | 3 + .../packages/demo-component/.editorconfig | 14 + .../packages/demo-component/.gitignore | 514 ++++++++++++++++++ .../packages/demo-component/.npmignore | 28 + .../packages/demo-component/README.md | 66 +++ .../packages/demo-component/clap.js | 23 + .../demo-component/images/jchip-128.jpg | Bin 0 -> 3881 bytes .../demo-component/images/nature-600-337.jpg | Bin 0 -> 42149 bytes .../packages/demo-component/package.json | 42 ++ .../src/components/AppBarExampleIconMenu.jsx | 26 + .../BottomNavigationExampleSimple.jsx | 55 ++ .../src/components/CardExampleWithAvatar.jsx | 30 + .../src/components/demo-component.jsx | 27 + .../packages/demo-component/src/index.js | 1 + .../src/lang/default-messages.js | 20 + .../packages/demo-component/src/lang/en.json | 4 + .../tenants/electrodeio/default-messages.js | 11 + .../src/styles/demo-component.css | 14 + .../demo-component/test/client/.eslintrc | 5 + .../client/components/demo-component.spec.jsx | 20 + .../helpers/intl-enzyme-test-helper.js | 45 ++ 57 files changed, 2067 insertions(+) create mode 100644 samples/demo-component/.gitignore create mode 100644 samples/demo-component/README.md create mode 100644 samples/demo-component/demo-app/.editorconfig create mode 100644 samples/demo-component/demo-app/.gitattributes create mode 100644 samples/demo-component/demo-app/.gitignore create mode 100644 samples/demo-component/demo-app/.travis.yml create mode 100644 samples/demo-component/demo-app/.yo-rc.json create mode 100644 samples/demo-component/demo-app/LICENSE create mode 100644 samples/demo-component/demo-app/README.md create mode 100644 samples/demo-component/demo-app/archetype/config/index.js create mode 100644 samples/demo-component/demo-app/archetype/config/webpack/webpack.config.dev.js create mode 100644 samples/demo-component/demo-app/archetype/config/webpack/webpack.config.js create mode 100644 samples/demo-component/demo-app/clap.js create mode 100644 samples/demo-component/demo-app/config/default.js create mode 100644 samples/demo-component/demo-app/config/development.json create mode 100644 samples/demo-component/demo-app/config/production.js create mode 100644 samples/demo-component/demo-app/config/production.json create mode 100644 samples/demo-component/demo-app/package.json create mode 100644 samples/demo-component/demo-app/src/client/.babelrc create mode 100644 samples/demo-component/demo-app/src/client/actions/index.jsx create mode 100644 samples/demo-component/demo-app/src/client/app.jsx create mode 100644 samples/demo-component/demo-app/src/client/components/home.jsx create mode 100644 samples/demo-component/demo-app/src/client/images/electrode.png create mode 100644 samples/demo-component/demo-app/src/client/reducers/index.jsx create mode 100644 samples/demo-component/demo-app/src/client/routes.jsx create mode 100644 samples/demo-component/demo-app/src/client/styles/base.css create mode 100644 samples/demo-component/demo-app/src/server/.babelrc create mode 100644 samples/demo-component/demo-app/src/server/index.js create mode 100644 samples/demo-component/demo-app/src/server/views/index-view.jsx create mode 100644 samples/demo-component/demo-app/test/client/.babelrc create mode 100644 samples/demo-component/demo-app/test/client/.eslintrc create mode 100644 samples/demo-component/demo-app/test/client/components/home.spec.jsx create mode 100644 samples/demo-component/demo-app/test/server/.babelrc create mode 100644 samples/demo-component/demo-app/test/server/.eslintrc create mode 100644 samples/demo-component/lerna.json create mode 100644 samples/demo-component/package.json create mode 100644 samples/demo-component/packages/demo-component/.babelrc create mode 100644 samples/demo-component/packages/demo-component/.editorconfig create mode 100644 samples/demo-component/packages/demo-component/.gitignore create mode 100644 samples/demo-component/packages/demo-component/.npmignore create mode 100644 samples/demo-component/packages/demo-component/README.md create mode 100644 samples/demo-component/packages/demo-component/clap.js create mode 100644 samples/demo-component/packages/demo-component/images/jchip-128.jpg create mode 100644 samples/demo-component/packages/demo-component/images/nature-600-337.jpg create mode 100644 samples/demo-component/packages/demo-component/package.json create mode 100644 samples/demo-component/packages/demo-component/src/components/AppBarExampleIconMenu.jsx create mode 100644 samples/demo-component/packages/demo-component/src/components/BottomNavigationExampleSimple.jsx create mode 100644 samples/demo-component/packages/demo-component/src/components/CardExampleWithAvatar.jsx create mode 100644 samples/demo-component/packages/demo-component/src/components/demo-component.jsx create mode 100644 samples/demo-component/packages/demo-component/src/index.js create mode 100644 samples/demo-component/packages/demo-component/src/lang/default-messages.js create mode 100644 samples/demo-component/packages/demo-component/src/lang/en.json create mode 100644 samples/demo-component/packages/demo-component/src/lang/tenants/electrodeio/default-messages.js create mode 100644 samples/demo-component/packages/demo-component/src/styles/demo-component.css create mode 100644 samples/demo-component/packages/demo-component/test/client/.eslintrc create mode 100644 samples/demo-component/packages/demo-component/test/client/components/demo-component.spec.jsx create mode 100644 samples/demo-component/packages/demo-component/test/client/components/helpers/intl-enzyme-test-helper.js diff --git a/samples/demo-component/.gitignore b/samples/demo-component/.gitignore new file mode 100644 index 000000000..558690804 --- /dev/null +++ b/samples/demo-component/.gitignore @@ -0,0 +1,506 @@ + +# Created by https://www.gitignore.io/api/osx,windows,linux,xcode,objective-c,swift,android,java,jetbrains,eclipse,sublimetext,node,vim,netbeans,emacs,vagrant,textmate,otto,gradle + +### OSX ### +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + + +### Windows ### +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + + +### Xcode ### +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata + +## Other +*.xccheckout +*.moved-aside +*.xcuserstate + + +### Objective-C ### +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata + +## Other +*.xccheckout +*.moved-aside +*.xcuserstate +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md + +fastlane/report.xml +fastlane/screenshots + +### Objective-C Patch ### +*.xcscmblueprint + + +### Swift ### +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata + +## Other +*.xccheckout +*.moved-aside +*.xcuserstate +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +.build/ + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md + +fastlane/report.xml +fastlane/screenshots + + +### Android ### +# Built application files +*.apk +*.ap_ + +# Files for the Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +### Android Patch ### +gen-external-apklibs + + +### Java ### +*.class + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + + +### JetBrains ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm + +*.iml + +## Directory-based project format: +.idea/ +# if you remove the above rule, at least ignore the following: + +# User-specific stuff: +# .idea/workspace.xml +# .idea/tasks.xml +# .idea/dictionaries +# .idea/shelf + +# Sensitive or high-churn files: +# .idea/dataSources.ids +# .idea/dataSources.xml +# .idea/sqlDataSources.xml +# .idea/dynamic.xml +# .idea/uiDesigner.xml + +# Gradle: +# .idea/gradle.xml +# .idea/libraries + +# Mongo Explorer plugin: +# .idea/mongoSettings.xml + +## File-based project format: +*.ipr +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + + +### Eclipse ### +*.pydevproject +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath + +# Eclipse Core +.project + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# Java annotation processor (APT) +.factorypath + +# PDT-specific +.buildpath + +# sbteclipse plugin +.target + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + + +### SublimeText ### +# cache files for sublime text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# workspace files are user-specific +*.sublime-workspace + +# project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using SublimeText +# *.sublime-project + +# sftp configuration file +sftp-config.json + + +### Node ### +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directory +# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git +node_modules + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history + + +### Vim ### +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +*.un~ +Session.vim +.netrwhist +*~ + + +### NetBeans ### +nbproject/private/ +build/ +nbbuild/ +dist/ +nbdist/ +nbactions.xml +.nb-gradle/ + + +### Emacs ### +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ + + +### Vagrant ### +.vagrant/ + + +### TextMate ### +*.tmproj +*.tmproject +tmtags + + +### Otto ### +.otto/ + + +### Gradle ### +.gradle +build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Cache of project +.gradletasknamecache + +############################################################################### + +### Automation ### +reports +screenshots +sauce_connect*.txt +*.dmp + +### Electrode Projects ### +dist +tmp diff --git a/samples/demo-component/README.md b/samples/demo-component/README.md new file mode 100644 index 000000000..9f93defe7 --- /dev/null +++ b/samples/demo-component/README.md @@ -0,0 +1 @@ +# Electrode Demo Component diff --git a/samples/demo-component/demo-app/.editorconfig b/samples/demo-component/demo-app/.editorconfig new file mode 100644 index 000000000..beffa3084 --- /dev/null +++ b/samples/demo-component/demo-app/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/samples/demo-component/demo-app/.gitattributes b/samples/demo-component/demo-app/.gitattributes new file mode 100644 index 000000000..176a458f9 --- /dev/null +++ b/samples/demo-component/demo-app/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/samples/demo-component/demo-app/.gitignore b/samples/demo-component/demo-app/.gitignore new file mode 100644 index 000000000..ad8ad8cf1 --- /dev/null +++ b/samples/demo-component/demo-app/.gitignore @@ -0,0 +1,157 @@ + + +# Created by https://www.gitignore.io/api/gitbook,node,webstorm,bower,osx + +### GitBook ### +# Node rules: +## Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +## Dependency directory +## Commenting this out is preferred by some people, see +## https://docs.npmjs.com/misc/faq#should-i-check-my-node_modules-folder-into-git +node_modules + +# Book build output +_book + +# eBook build output +*.epub +*.mobi +*.pdf + + +### Node ### +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directory +# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git +node_modules + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history + + +### WebStorm ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm + +*.iml + +## Directory-based project format: +.idea/ +# if you remove the above rule, at least ignore the following: + +# User-specific stuff: +# .idea/workspace.xml +# .idea/tasks.xml +# .idea/dictionaries +# .idea/shelf + +# Sensitive or high-churn files: +# .idea/dataSources.ids +# .idea/dataSources.xml +# .idea/sqlDataSources.xml +# .idea/dynamic.xml +# .idea/uiDesigner.xml + +# Gradle: +# .idea/gradle.xml +# .idea/libraries + +# Mongo Explorer plugin: +# .idea/mongoSettings.xml + +## File-based project format: +*.ipr +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + + +### Bower ### +bower_components +.bower-cache +.bower-registry +.bower-tmp + + +### OSX ### +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# others +.hg +.project +.tmp + +# Build +dist +Procfile +config/assets.json +npm-shrinkwrap.json + +.isomorphic-loader-config.json diff --git a/samples/demo-component/demo-app/.travis.yml b/samples/demo-component/demo-app/.travis.yml new file mode 100644 index 000000000..348670299 --- /dev/null +++ b/samples/demo-component/demo-app/.travis.yml @@ -0,0 +1,5 @@ +language: node_js +node_js: + - 8 + - 6 + - 4 diff --git a/samples/demo-component/demo-app/.yo-rc.json b/samples/demo-component/demo-app/.yo-rc.json new file mode 100644 index 000000000..47ef9f9a8 --- /dev/null +++ b/samples/demo-component/demo-app/.yo-rc.json @@ -0,0 +1,5 @@ +{ + "generator-electrode": { + "serverType": "HapiJS" + } +} diff --git a/samples/demo-component/demo-app/LICENSE b/samples/demo-component/demo-app/LICENSE new file mode 100644 index 000000000..b5da1eba4 --- /dev/null +++ b/samples/demo-component/demo-app/LICENSE @@ -0,0 +1,2 @@ +Copyright (c) 2017 Electrode (https://github.com/electrode-io) +All rights reserved. diff --git a/samples/demo-component/demo-app/README.md b/samples/demo-component/demo-app/README.md new file mode 100644 index 000000000..375175c6f --- /dev/null +++ b/samples/demo-component/demo-app/README.md @@ -0,0 +1,27 @@ +# demo-app [![NPM version][npm-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Dependency Status][daviddm-image]][daviddm-url] +> The demo App + +## Installation + +```sh +$ npm install --save demo-app +``` + +## Usage + +```js +var demoApp = require('demo-app'); + +demoApp('Rainbow'); +``` +## License + + © [electrode](https://github.com/electrode) + + +[npm-image]: https://badge.fury.io/js/demo-app.svg +[npm-url]: https://npmjs.org/package/demo-app +[travis-image]: https://travis-ci.org//demo-app.svg?branch=master +[travis-url]: https://travis-ci.org//demo-app +[daviddm-image]: https://david-dm.org//demo-app.svg?theme=shields.io +[daviddm-url]: https://david-dm.org//demo-app diff --git a/samples/demo-component/demo-app/archetype/config/index.js b/samples/demo-component/demo-app/archetype/config/index.js new file mode 100644 index 000000000..4b6ea0427 --- /dev/null +++ b/samples/demo-component/demo-app/archetype/config/index.js @@ -0,0 +1,5 @@ +module.exports = { + webpack: { + cssModuleStylusSupport: true + } +}; diff --git a/samples/demo-component/demo-app/archetype/config/webpack/webpack.config.dev.js b/samples/demo-component/demo-app/archetype/config/webpack/webpack.config.dev.js new file mode 100644 index 000000000..63464f57f --- /dev/null +++ b/samples/demo-component/demo-app/archetype/config/webpack/webpack.config.dev.js @@ -0,0 +1,16 @@ +console.log("oops"); +const Path = require("path"); + +const repoPackagesDir = Path.join(__dirname, "../../../../packages"); + +module.exports = { + resolve: { + alias: { + "demo-component": Path.join(repoPackagesDir, "demo-component/src") + }, + modules: [ + Path.join(repoPackagesDir, "demo-component"), + Path.join(repoPackagesDir, "demo-component/node_modules") + ] + } +}; diff --git a/samples/demo-component/demo-app/archetype/config/webpack/webpack.config.js b/samples/demo-component/demo-app/archetype/config/webpack/webpack.config.js new file mode 100644 index 000000000..63464f57f --- /dev/null +++ b/samples/demo-component/demo-app/archetype/config/webpack/webpack.config.js @@ -0,0 +1,16 @@ +console.log("oops"); +const Path = require("path"); + +const repoPackagesDir = Path.join(__dirname, "../../../../packages"); + +module.exports = { + resolve: { + alias: { + "demo-component": Path.join(repoPackagesDir, "demo-component/src") + }, + modules: [ + Path.join(repoPackagesDir, "demo-component"), + Path.join(repoPackagesDir, "demo-component/node_modules") + ] + } +}; diff --git a/samples/demo-component/demo-app/clap.js b/samples/demo-component/demo-app/clap.js new file mode 100644 index 000000000..a2ee8ceb2 --- /dev/null +++ b/samples/demo-component/demo-app/clap.js @@ -0,0 +1 @@ +require("electrode-archetype-react-app")(); diff --git a/samples/demo-component/demo-app/config/default.js b/samples/demo-component/demo-app/config/default.js new file mode 100644 index 000000000..a4f498908 --- /dev/null +++ b/samples/demo-component/demo-app/config/default.js @@ -0,0 +1,50 @@ +"use strict"; + +const defaultListenPort = 3000; + +const portFromEnv = () => { + const x = parseInt(process.env.PORT, 10); + /* istanbul ignore next */ + return (x !== null && !isNaN(x)) ? x : defaultListenPort; +}; + +module.exports = { + "plugins": { + "inert": { + "enable": true + }, + "electrodeStaticPaths": { + "enable": true, + "options": { + "pathPrefix": "dist" + } + }, + "webapp": { + "module": "electrode-react-webapp/lib/hapi", + "options": { + "pageTitle": "demo-app", + "serverSideRendering": false, + "paths": { + "/{args*}": { + "content": { + "module": "./{{env.APP_SRC_DIR}}/server/views/index-view" + } + } + } + } + } + }, + "connections": { + "default": { + "host": process.env.HOST, + "address": process.env.HOST_IP || "0.0.0.0", + "port": portFromEnv(), + "routes": { + "cors": true + }, + "state": { + "ignoreErrors":true + } + } + } +}; diff --git a/samples/demo-component/demo-app/config/development.json b/samples/demo-component/demo-app/config/development.json new file mode 100644 index 000000000..2c63c0851 --- /dev/null +++ b/samples/demo-component/demo-app/config/development.json @@ -0,0 +1,2 @@ +{ +} diff --git a/samples/demo-component/demo-app/config/production.js b/samples/demo-component/demo-app/config/production.js new file mode 100644 index 000000000..668d4ad20 --- /dev/null +++ b/samples/demo-component/demo-app/config/production.js @@ -0,0 +1,23 @@ +// +// This file is here to allow enabling the plugins inert and electrodeStaticPaths, overriding the +// settings in production.json, in order to serve the static JS and CSS bundle files from +// the dist directory so you can test your app server locally in production mode. +// +// When running in a real production environment where your static files are most likely served +// by a dedicated CDN server, you might want to turn these plugins off. +// + +const serveStaticFiles = () => { + return process.env.STATIC_FILES_OFF !== "true"; +}; + +module.exports = { + "plugins": { + "inert": { + "enable": serveStaticFiles() + }, + "electrodeStaticPaths": { + "enable": serveStaticFiles() + } + } +}; diff --git a/samples/demo-component/demo-app/config/production.json b/samples/demo-component/demo-app/config/production.json new file mode 100644 index 000000000..2c63c0851 --- /dev/null +++ b/samples/demo-component/demo-app/config/production.json @@ -0,0 +1,2 @@ +{ +} diff --git a/samples/demo-component/demo-app/package.json b/samples/demo-component/demo-app/package.json new file mode 100644 index 000000000..1f5196178 --- /dev/null +++ b/samples/demo-component/demo-app/package.json @@ -0,0 +1,59 @@ +{ + "name": "demo-app", + "version": "0.0.1", + "description": "The demo App", + "homepage": "https://github.com/electrode/electrode-io", + "author": { + "name": "electrode", + "email": "electrode@electrode.com", + "url": "https://github.com/electrode" + }, + "contributors": [], + "files": [ + "server", + "client", + "test" + ], + "main": "server/index.js", + "keywords": [ + "e", + "l", + "c", + "t", + "r", + "o", + "d" + ], + "repository": { + "type": "git", + "url": "https://github.com/demo-app" + }, + "engines": { + "node": "^4.x.x || ^6.x.x || ^7.x.x", + "npm": ">= 3.x.x" + }, + "scripts": { + "prestart": "clap build", + "start": "if test \"$NODE_ENV\" = \"production\"; then npm run prod; else clap dev; fi", + "test": "clap check", + "coverage": "clap check", + "prod": "echo 'Starting standalone server in PROD mode'; NODE_ENV=production node ./lib/server/", + "heroku-postbuild": "clap build" + }, + "dependencies": { + "bluebird": "^3.4.6", + "electrode-archetype-react-app": "../../../packages/electrode-archetype-react-app", + "electrode-confippet": "^1.0.0", + "electrode-react-webapp": "^1.1.0", + "electrode-redux-router-engine": "^1.2.2", + "electrode-server": "^1.0.0", + "electrode-static-paths": "^1.0.0", + "lodash": "^4.10.1" + }, + "devDependencies": { + "electrode-archetype-react-app-dev": "../../../packages/electrode-archetype-react-app-dev", + "json-stringify-safe": "^5.0.1", + "safe-json-stringify": "^1.0.4" + }, + "private": true +} diff --git a/samples/demo-component/demo-app/src/client/.babelrc b/samples/demo-component/demo-app/src/client/.babelrc new file mode 100644 index 000000000..e4c602292 --- /dev/null +++ b/samples/demo-component/demo-app/src/client/.babelrc @@ -0,0 +1,3 @@ +{ + "extends": "electrode-archetype-react-app-dev/config/babel/babelrc-client" +} diff --git a/samples/demo-component/demo-app/src/client/actions/index.jsx b/samples/demo-component/demo-app/src/client/actions/index.jsx new file mode 100644 index 000000000..e69de29bb diff --git a/samples/demo-component/demo-app/src/client/app.jsx b/samples/demo-component/demo-app/src/client/app.jsx new file mode 100644 index 000000000..bba71e8e4 --- /dev/null +++ b/samples/demo-component/demo-app/src/client/app.jsx @@ -0,0 +1,28 @@ +// +// This is the client side entry point for the React app. +// + +import React from "react"; +import {render} from "react-dom"; +import {routes} from "./routes"; +import {Router, browserHistory} from "react-router"; +import {createStore} from "redux"; +import {Provider} from "react-redux"; +/* */ +import "./styles/base.css"; +import rootReducer from "./reducers"; + +// Add the client app start up code to a function as window.webappStart. +// The webapp's full HTML will check and call it once the js-content +// DOM is created. +/**/ +window.webappStart = () => { + const initialState = window.__PRELOADED_STATE__; + const store = createStore(rootReducer, initialState); + render( + + {routes} + , + document.querySelector(".js-content") + ); +}; diff --git a/samples/demo-component/demo-app/src/client/components/home.jsx b/samples/demo-component/demo-app/src/client/components/home.jsx new file mode 100644 index 000000000..f7eb69081 --- /dev/null +++ b/samples/demo-component/demo-app/src/client/components/home.jsx @@ -0,0 +1,23 @@ +import React from "react"; +import { connect } from "react-redux"; +import { IntlProvider } from "react-intl"; + +import { DemoComponent } from "demo-component"; +import electrodePng from "../images/electrode.png"; + +const locale = "en"; + +export class Home extends React.Component { + render() { + return ( + +
+

Electrode Component Demo App

+ +
+
+ ); + } +} + +export default connect(state => state)(Home); diff --git a/samples/demo-component/demo-app/src/client/images/electrode.png b/samples/demo-component/demo-app/src/client/images/electrode.png new file mode 100644 index 0000000000000000000000000000000000000000..3df8cf54adba6827af33a2f4da268127540557d0 GIT binary patch literal 5402 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 Z)L9hArXurB { + return store || {}; +}; + +const checkBox = (store) => { + return store || {}; +}; + +export default combineReducers({ + number, + checkBox +}); diff --git a/samples/demo-component/demo-app/src/client/routes.jsx b/samples/demo-component/demo-app/src/client/routes.jsx new file mode 100644 index 000000000..16995ebb7 --- /dev/null +++ b/samples/demo-component/demo-app/src/client/routes.jsx @@ -0,0 +1,7 @@ +import React from "react"; +import {Route} from "react-router"; +import Home from "./components/home"; + +export const routes = ( + +); diff --git a/samples/demo-component/demo-app/src/client/styles/base.css b/samples/demo-component/demo-app/src/client/styles/base.css new file mode 100644 index 000000000..25ebc7ce1 --- /dev/null +++ b/samples/demo-component/demo-app/src/client/styles/base.css @@ -0,0 +1,14 @@ +:root { + --black: #000; + --white: #fff; +} + +body { + font: 12px Helvetica, Arial, sans-serif; +} + +a.button { + -webkit-border-radius: 5px; + -moz-border-radius: 5px; + border-radius: 5px; +} diff --git a/samples/demo-component/demo-app/src/server/.babelrc b/samples/demo-component/demo-app/src/server/.babelrc new file mode 100644 index 000000000..ebb946309 --- /dev/null +++ b/samples/demo-component/demo-app/src/server/.babelrc @@ -0,0 +1,3 @@ +{ + "extends": "electrode-archetype-react-app-dev/config/babel/babelrc-server" +} diff --git a/samples/demo-component/demo-app/src/server/index.js b/samples/demo-component/demo-app/src/server/index.js new file mode 100644 index 000000000..8413721a7 --- /dev/null +++ b/samples/demo-component/demo-app/src/server/index.js @@ -0,0 +1,16 @@ +"use strict"; + +process.on("SIGINT", () => { + process.exit(0); +}); + +const electrodeConfippet = require("electrode-confippet"); +const staticPathsDecor = require("electrode-static-paths"); +const support = require("electrode-archetype-react-app/support"); + +support.load() + .then(() => { + const config = electrodeConfippet.config; + + require("electrode-server")(config, [staticPathsDecor()]); // eslint-disable-line + }); diff --git a/samples/demo-component/demo-app/src/server/views/index-view.jsx b/samples/demo-component/demo-app/src/server/views/index-view.jsx new file mode 100644 index 000000000..65e83205a --- /dev/null +++ b/samples/demo-component/demo-app/src/server/views/index-view.jsx @@ -0,0 +1,39 @@ +// +// This is the server side entry point for the React app. +// + +import ReduxRouterEngine from "electrode-redux-router-engine"; +import {routes} from "../../client/routes"; +import {createStore} from "redux"; +import rootReducer from "../../client/reducers"; + +const Promise = require("bluebird"); + +function createReduxStore(req, match) { // eslint-disable-line + const initialState = { + checkBox: {checked: false}, + number: {value: 999} + }; + + const store = createStore(rootReducer, initialState); + return Promise.resolve(store); +} + +// +// This function is exported as the content for the webapp plugin. +// +// See config/default.json under plugins.webapp on specifying the content. +// +// When the Web server hits the routes handler installed by the webapp plugin, it +// will call this function to retrieve the content for SSR if it's enabled. +// +// + +module.exports = (req) => { + const app = req.server && req.server.app || req.app; + if (!app.routesEngine) { + app.routesEngine = new ReduxRouterEngine({routes, createReduxStore}); + } + + return app.routesEngine.render(req); +}; diff --git a/samples/demo-component/demo-app/test/client/.babelrc b/samples/demo-component/demo-app/test/client/.babelrc new file mode 100644 index 000000000..e4c602292 --- /dev/null +++ b/samples/demo-component/demo-app/test/client/.babelrc @@ -0,0 +1,3 @@ +{ + "extends": "electrode-archetype-react-app-dev/config/babel/babelrc-client" +} diff --git a/samples/demo-component/demo-app/test/client/.eslintrc b/samples/demo-component/demo-app/test/client/.eslintrc new file mode 100644 index 000000000..5045798f4 --- /dev/null +++ b/samples/demo-component/demo-app/test/client/.eslintrc @@ -0,0 +1,5 @@ +--- +extends: + - "../../node_modules/electrode-archetype-react-app-dev/config/eslint/.eslintrc-react-test" + + diff --git a/samples/demo-component/demo-app/test/client/components/home.spec.jsx b/samples/demo-component/demo-app/test/client/components/home.spec.jsx new file mode 100644 index 000000000..e72b18565 --- /dev/null +++ b/samples/demo-component/demo-app/test/client/components/home.spec.jsx @@ -0,0 +1,34 @@ +import React from "react"; +import ReactDOM from "react-dom"; +import Home from "client/components/home"; +import {createStore} from "redux"; +import rootReducer from "client/reducers"; + +describe("Home", () => { + let component; + let container; + + beforeEach(() => { + container = document.createElement("div"); + }); + + afterEach(() => { + ReactDOM.unmountComponentAtNode(container); + }); + + it("has expected content with deep render", () => { + const initialState = { + checkBox: {checked: false}, + number: {value: 999} + }; + + const store = createStore(rootReducer, initialState); + + component = ReactDOM.render( + , + container + ); + + expect(component).to.not.be.false; + }); +}); diff --git a/samples/demo-component/demo-app/test/server/.babelrc b/samples/demo-component/demo-app/test/server/.babelrc new file mode 100644 index 000000000..ebb946309 --- /dev/null +++ b/samples/demo-component/demo-app/test/server/.babelrc @@ -0,0 +1,3 @@ +{ + "extends": "electrode-archetype-react-app-dev/config/babel/babelrc-server" +} diff --git a/samples/demo-component/demo-app/test/server/.eslintrc b/samples/demo-component/demo-app/test/server/.eslintrc new file mode 100644 index 000000000..4c5e1c6ba --- /dev/null +++ b/samples/demo-component/demo-app/test/server/.eslintrc @@ -0,0 +1,5 @@ +--- +extends: + - "../../node_modules/electrode-archetype-react-app-dev/config/eslint/.eslintrc-mocha-test" + + diff --git a/samples/demo-component/lerna.json b/samples/demo-component/lerna.json new file mode 100644 index 000000000..88e3762d5 --- /dev/null +++ b/samples/demo-component/lerna.json @@ -0,0 +1,7 @@ +{ + "lerna": "2.0.0-rc.1", + "packages": [ + "packages/*" + ], + "version": "locked" +} diff --git a/samples/demo-component/package.json b/samples/demo-component/package.json new file mode 100644 index 000000000..bd5394631 --- /dev/null +++ b/samples/demo-component/package.json @@ -0,0 +1,26 @@ +{ + "name": "demo-component", + "version": "1.0.0", + "description": "Electrode Demo Component repo", + "author": { + "name": "Joel Chen", + "url": "https://github.com/jchip" + }, + "repository": { + "type": "git", + "url": "https://github.com/electrode-io/electrode.git" + }, + "bugs": { + "url": "https://github.com/electrode-io/electrode/issues" + }, + "homepage": "https://github.com/electrode-io/electrode", + "scripts": { + "bootstrap": "lerna bootstrap", + "test": "npm run bootstrap && lerna run test" + }, + "dependency": {}, + "devDependencies": { + "lerna": "^2.0.0-rc.1", + "lodash": "^4.10.1" + } +} diff --git a/samples/demo-component/packages/demo-component/.babelrc b/samples/demo-component/packages/demo-component/.babelrc new file mode 100644 index 000000000..0c48bf401 --- /dev/null +++ b/samples/demo-component/packages/demo-component/.babelrc @@ -0,0 +1,3 @@ +{ + "extends": "./node_modules/electrode-archetype-react-component/config/babel/.babelrc" +} diff --git a/samples/demo-component/packages/demo-component/.editorconfig b/samples/demo-component/packages/demo-component/.editorconfig new file mode 100644 index 000000000..1f38c5e77 --- /dev/null +++ b/samples/demo-component/packages/demo-component/.editorconfig @@ -0,0 +1,14 @@ +# This file is for unifying the coding style for different editors and IDEs +# editorconfig.org + +root = true + +[*] +indent_style = space +indent_size = 2 +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/samples/demo-component/packages/demo-component/.gitignore b/samples/demo-component/packages/demo-component/.gitignore new file mode 100644 index 000000000..0918b45e5 --- /dev/null +++ b/samples/demo-component/packages/demo-component/.gitignore @@ -0,0 +1,514 @@ + +# Created by https://www.gitignore.io/api/osx,windows,linux,xcode,objective-c,swift,android,java,jetbrains,eclipse,sublimetext,node,vim,netbeans,emacs,vagrant,textmate,otto,gradle + +### OSX ### +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + + +### Windows ### +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msm +*.msp + +# Windows shortcuts +*.lnk + + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + + +### Xcode ### +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata + +## Other +*.xccheckout +*.moved-aside +*.xcuserstate + + +### Objective-C ### +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata + +## Other +*.xccheckout +*.moved-aside +*.xcuserstate +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md + +fastlane/report.xml +fastlane/screenshots + +### Objective-C Patch ### +*.xcscmblueprint + + +### Swift ### +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated +build/ +DerivedData + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata + +## Other +*.xccheckout +*.moved-aside +*.xcuserstate +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa + +# Swift Package Manager +# +# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. +# Packages/ +.build/ + +# CocoaPods +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md + +fastlane/report.xml +fastlane/screenshots + + +### Android ### +# Built application files +*.apk +*.ap_ + +# Files for the Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Android Studio captures folder +captures/ + +### Android Patch ### +gen-external-apklibs + + +### Java ### +*.class + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + + +### JetBrains ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm + +*.iml + +## Directory-based project format: +.idea/ +# if you remove the above rule, at least ignore the following: + +# User-specific stuff: +# .idea/workspace.xml +# .idea/tasks.xml +# .idea/dictionaries +# .idea/shelf + +# Sensitive or high-churn files: +# .idea/dataSources.ids +# .idea/dataSources.xml +# .idea/sqlDataSources.xml +# .idea/dynamic.xml +# .idea/uiDesigner.xml + +# Gradle: +# .idea/gradle.xml +# .idea/libraries + +# Mongo Explorer plugin: +# .idea/mongoSettings.xml + +## File-based project format: +*.ipr +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + + +### Eclipse ### +*.pydevproject +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath + +# Eclipse Core +.project + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# Java annotation processor (APT) +.factorypath + +# PDT-specific +.buildpath + +# sbteclipse plugin +.target + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + + +### SublimeText ### +# cache files for sublime text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# workspace files are user-specific +*.sublime-workspace + +# project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using SublimeText +# *.sublime-project + +# sftp configuration file +sftp-config.json + + +### Node ### +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directory +# https://docs.npmjs.com/misc/faq#should-i-check-my-node-modules-folder-into-git +node_modules + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history + + +### Vim ### +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +*.un~ +Session.vim +.netrwhist +*~ + + +### NetBeans ### +nbproject/private/ +build/ +nbbuild/ +dist/ +nbdist/ +nbactions.xml +.nb-gradle/ + + +### Emacs ### +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ + + +### Vagrant ### +.vagrant/ + + +### TextMate ### +*.tmproj +*.tmproject +tmtags + + +### Otto ### +.otto/ + + +### Gradle ### +.gradle +build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Cache of project +.gradletasknamecache + +############################################################################### + +### Automation ### +reports +screenshots +sauce_connect*.txt +*.dmp + +### Walmart Projects ### +lib +dist +tmp + +############################################################################### +#########################_WALMART_STANDARD_GITIGNORE_########################## +############################################################################### +# All changes made above this line are subject to overwrites as the standard # +# .gitignore evolves. Please add any project specific ignores below. # +############################################################################### diff --git a/samples/demo-component/packages/demo-component/.npmignore b/samples/demo-component/packages/demo-component/.npmignore new file mode 100644 index 000000000..7c0ac811c --- /dev/null +++ b/samples/demo-component/packages/demo-component/.npmignore @@ -0,0 +1,28 @@ +# Cruft +*.sublime-workspace +.DS_Store +.AppleDouble +.LSOverride +Icon +._* +.Spotlight-V100 +.Trashes +Thumbs.db +ehthumbs.db +Desktop.ini +$RECYCLE.BIN/ +.tmp +npm-debug.log* + +# Code / build +coverage +node_modules +bower_components +test +karma* +webpack* +.eslint* +.editor* +.travis* + +.idea/ diff --git a/samples/demo-component/packages/demo-component/README.md b/samples/demo-component/packages/demo-component/README.md new file mode 100644 index 000000000..76398d7ba --- /dev/null +++ b/samples/demo-component/packages/demo-component/README.md @@ -0,0 +1,66 @@ +# Electrode Demo Component + +__COMPONENT DESCRIPTION GOES HERE__ + + +## Demo & Examples + +Live demo: [electrode.github.io/demo-component](http://electrode.github.io/demo-component/) + +To build the package locally, run: + +``` +npm install + +``` + +To run the package demo locally, run the `demo-app` : + +``` +npm install +clap dev + +``` + +Then open [`localhost:8000`](http://localhost:8000) in a browser. + + +## Installation + +The easiest way to use demo-component is to install it from NPM and include it in your own React build process (using [Browserify](http://browserify.org), [Webpack](http://webpack.github.io/), etc). + +You can also use the standalone build by including `dist/demo-component.js` in your page. If you use this, make sure you have already included React, and it is available as a global variable. + +``` +npm install demo-component --save +``` + + +## Usage + +__EXPLAIN USAGE HERE__ + +``` +var DemoComponent = require('demo-component'); + +Example +``` + +### Properties + +* __DOCUMENT PROPERTIES HERE__ + +### Notes + +__ADDITIONAL USAGE NOTES__ + + +## Development (`src`, `lib` and the build process) + +**NOTE:** The source code for the component is in `src`. A transpiled CommonJS version (generated with Babel) is available in `lib` for use with node.js, browserify and webpack. A UMD bundle is also built to `dist`, which can be included without the need for any build system. + +## License + +__PUT LICENSE HERE__ + +Copyright (c) 2017 electrode. diff --git a/samples/demo-component/packages/demo-component/clap.js b/samples/demo-component/packages/demo-component/clap.js new file mode 100644 index 000000000..3ecc67cc0 --- /dev/null +++ b/samples/demo-component/packages/demo-component/clap.js @@ -0,0 +1,23 @@ +"use strict"; + + + +/** + * There is a full range of clap tasks defined in the above archetype + * but below is a concise list of most often used clap tasks at the + * component level + * + * Full list of clap tasks: + * https://github.com/electrode-io/electrode-archetype-react-component/blob/master/archetype-clap.js#L38-L134 + * + */ + +const xclap = require("xclap"); +const tasks = { + + "prepublish": ["npm:prepublish"] +}; + +xclap.load("myprj", tasks); + +require("electrode-archetype-react-component")(xclap); diff --git a/samples/demo-component/packages/demo-component/images/jchip-128.jpg b/samples/demo-component/packages/demo-component/images/jchip-128.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ad7291fa29ee082dd0f9b07adf8bed8dac944ee4 GIT binary patch literal 3881 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 literal 0 HcmV?d00001 diff --git a/samples/demo-component/packages/demo-component/images/nature-600-337.jpg b/samples/demo-component/packages/demo-component/images/nature-600-337.jpg new file mode 100644 index 0000000000000000000000000000000000000000..60fb163704d5ac92c06a72f5f2bd0b66aba9fd4d GIT binary patch literal 42149 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 P4I!e607@vLga`lG!gPU3 literal 0 HcmV?d00001 diff --git a/samples/demo-component/packages/demo-component/package.json b/samples/demo-component/packages/demo-component/package.json new file mode 100644 index 000000000..217c1d98b --- /dev/null +++ b/samples/demo-component/packages/demo-component/package.json @@ -0,0 +1,42 @@ +{ + "name": "demo-component", + "version": "1.0.0", + "description": "Electrode Demo Component", + "main": "lib/index.js", + "author": { + "name": "Joel Chen", + "url": "https://github.com/jchip" + }, + "repository": { + "type": "git", + "url": "https://github.com/electrode-io/electrode.git" + }, + "bugs": { + "url": "https://github.com/electrode-io/electrode/issues" + }, + "homepage": "https://github.com/electrode-io/electrode", + "dependencies": { + "material-ui": "^0.18.3", + "react-tap-event-plugin": "^2.0.1" + }, + "devDependencies": { + "electrode-archetype-react-component": "../../../../packages/electrode-archetype-react-component", + "electrode-archetype-react-component-dev": "../../../../packages/electrode-archetype-react-component-dev", + "xclap": "^0.2.0" + }, + "engines": { + "node": ">= 4", + "npm": ">= 3" + }, + "scripts": { + "prepublish": "clap prepublish", + "start": "clap demo", + "test": "clap check" + }, + "keywords": [ + "react", + "electrode", + "electrode-component", + "react-component" + ] +} diff --git a/samples/demo-component/packages/demo-component/src/components/AppBarExampleIconMenu.jsx b/samples/demo-component/packages/demo-component/src/components/AppBarExampleIconMenu.jsx new file mode 100644 index 000000000..4651f60ca --- /dev/null +++ b/samples/demo-component/packages/demo-component/src/components/AppBarExampleIconMenu.jsx @@ -0,0 +1,26 @@ +import React from "react"; +import AppBar from "material-ui/AppBar"; +import IconButton from "material-ui/IconButton"; +import IconMenu from "material-ui/IconMenu"; +import MenuItem from "material-ui/MenuItem"; +import MoreVertIcon from "material-ui/svg-icons/navigation/more-vert"; +import NavigationClose from "material-ui/svg-icons/navigation/close"; + +const AppBarExampleIconMenu = () => + } + iconElementRight={ + } + targetOrigin={{ horizontal: "right", vertical: "top" }} + anchorOrigin={{ horizontal: "right", vertical: "top" }} + > + + + + + } + />; + +export default AppBarExampleIconMenu; diff --git a/samples/demo-component/packages/demo-component/src/components/BottomNavigationExampleSimple.jsx b/samples/demo-component/packages/demo-component/src/components/BottomNavigationExampleSimple.jsx new file mode 100644 index 000000000..192d1c6cc --- /dev/null +++ b/samples/demo-component/packages/demo-component/src/components/BottomNavigationExampleSimple.jsx @@ -0,0 +1,55 @@ +import React, { Component } from "react"; +import FontIcon from "material-ui/FontIcon"; +import { BottomNavigation, BottomNavigationItem } from "material-ui/BottomNavigation"; +import Paper from "material-ui/Paper"; +import IconLocationOn from "material-ui/svg-icons/communication/location-on"; + +const recentsIcon = restore; +const favoritesIcon = favorite; +const nearbyIcon = ; + +/* eslint-disable no-magic-numbers */ + +/** + * A simple example of `BottomNavigation`, with three labels and icons + * provided. The selected `BottomNavigationItem` is determined by application + * state (for instance, by the URL). + */ +class BottomNavigationExampleSimple extends Component { + constructor() { + super(); + this.state = { + selectedIndex: 0 + }; + } + + select(index) { + return this.setState({ selectedIndex: index }); + } + + render() { + return ( + + + this.select(0)} + /> + this.select(1)} + /> + this.select(2)} + /> + + + ); + } +} + +export default BottomNavigationExampleSimple; diff --git a/samples/demo-component/packages/demo-component/src/components/CardExampleWithAvatar.jsx b/samples/demo-component/packages/demo-component/src/components/CardExampleWithAvatar.jsx new file mode 100644 index 000000000..26a9196b0 --- /dev/null +++ b/samples/demo-component/packages/demo-component/src/components/CardExampleWithAvatar.jsx @@ -0,0 +1,30 @@ +import React from "react"; +import { Card, CardActions, CardHeader, CardMedia, CardTitle, CardText } from "material-ui/Card"; +import FlatButton from "material-ui/FlatButton"; +import natureJpg from "../../images/nature-600-337.jpg"; +import avatarJpg from "../../images/jchip-128.jpg"; +import { FormattedMessage } from "react-intl"; +import messages from "../lang/default-messages"; + +const CardExampleWithAvatar = () => + + + }> + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Donec mattis pretium massa. Aliquam erat volutpat. Nulla facilisi. + Donec vulputate interdum sollicitudin. Nunc lacinia auctor quam sed pellentesque. + Aliquam dui mauris, mattis quis lacus id, pellentesque lobortis odio.

+ + + + + + + + ; + +export default CardExampleWithAvatar; diff --git a/samples/demo-component/packages/demo-component/src/components/demo-component.jsx b/samples/demo-component/packages/demo-component/src/components/demo-component.jsx new file mode 100644 index 000000000..7249626f9 --- /dev/null +++ b/samples/demo-component/packages/demo-component/src/components/demo-component.jsx @@ -0,0 +1,27 @@ +import React from "react"; +import MuiThemeProvider from "material-ui/styles/MuiThemeProvider"; +import AppBarExampleIconMenu from "./AppBarExampleIconMenu"; +import BottomNavigationExampleSimple from "./BottomNavigationExampleSimple"; +import CardExampleWithAvatar from "./CardExampleWithAvatar"; + +import styles from "../../src/styles/demo-component.css"; // eslint-disable-line + +export default class DemoComponent extends React.Component { + render() { + return ( + +

+ + + +
+ + ); + } +} + +DemoComponent.displayName = "DemoComponent"; + +DemoComponent.propTypes = {}; + +DemoComponent.defaultProps = {}; diff --git a/samples/demo-component/packages/demo-component/src/index.js b/samples/demo-component/packages/demo-component/src/index.js new file mode 100644 index 000000000..d3a3954bb --- /dev/null +++ b/samples/demo-component/packages/demo-component/src/index.js @@ -0,0 +1 @@ +export { default as DemoComponent } from "./components/demo-component"; diff --git a/samples/demo-component/packages/demo-component/src/lang/default-messages.js b/samples/demo-component/packages/demo-component/src/lang/default-messages.js new file mode 100644 index 000000000..a27eb6158 --- /dev/null +++ b/samples/demo-component/packages/demo-component/src/lang/default-messages.js @@ -0,0 +1,20 @@ +import { defineMessages } from "react-intl"; + +const $tenant = process.env.ELECTRODE_TENANT; +let tenantMessages; + +try { + tenantMessages = require(`./tenants/${$tenant}/default-messages`); //eslint-disable-line +} catch (err) { + tenantMessages = {}; +} + +const messages = defineMessages({ + editMe: { + description: "Edit this description", + defaultMessage: "Edit me!", + id: "DemoComponent.defaultTenant.editMe" + } +}); + +module.exports = Object.assign({}, messages, tenantMessages); diff --git a/samples/demo-component/packages/demo-component/src/lang/en.json b/samples/demo-component/packages/demo-component/src/lang/en.json new file mode 100644 index 000000000..3b0d6b0e9 --- /dev/null +++ b/samples/demo-component/packages/demo-component/src/lang/en.json @@ -0,0 +1,4 @@ +{ + "DemoComponent.walmart.editMe": "Edit Me! Walmart English", + "DemoComponent.samsclub.editMe": "Edit Me! samsclub English" +} diff --git a/samples/demo-component/packages/demo-component/src/lang/tenants/electrodeio/default-messages.js b/samples/demo-component/packages/demo-component/src/lang/tenants/electrodeio/default-messages.js new file mode 100644 index 000000000..e7569e982 --- /dev/null +++ b/samples/demo-component/packages/demo-component/src/lang/tenants/electrodeio/default-messages.js @@ -0,0 +1,11 @@ +import {defineMessages} from "react-intl"; + +const messages = defineMessages({ + editMe: { + description: "Edit this description", + defaultMessage: "Edit me!", + id: "DemoComponent.electrodeio.editMe" + } +}); + +module.exports = messages; diff --git a/samples/demo-component/packages/demo-component/src/styles/demo-component.css b/samples/demo-component/packages/demo-component/src/styles/demo-component.css new file mode 100644 index 000000000..0a7614565 --- /dev/null +++ b/samples/demo-component/packages/demo-component/src/styles/demo-component.css @@ -0,0 +1,14 @@ +:root { + --black: #000; + --white: #fff; +} + +.baseStyle { + background-color: var(--black); + color: var(--white); +} + +.someStyle { + composes: baseStyle; + font-size: 18px; +} diff --git a/samples/demo-component/packages/demo-component/test/client/.eslintrc b/samples/demo-component/packages/demo-component/test/client/.eslintrc new file mode 100644 index 000000000..6f336fde6 --- /dev/null +++ b/samples/demo-component/packages/demo-component/test/client/.eslintrc @@ -0,0 +1,5 @@ +--- +extends: + - "../../node_modules/electrode-archetype-react-component-dev/config/eslint/.eslintrc-react-test" + + diff --git a/samples/demo-component/packages/demo-component/test/client/components/demo-component.spec.jsx b/samples/demo-component/packages/demo-component/test/client/components/demo-component.spec.jsx new file mode 100644 index 000000000..90842e487 --- /dev/null +++ b/samples/demo-component/packages/demo-component/test/client/components/demo-component.spec.jsx @@ -0,0 +1,20 @@ +/** + * Client tests + */ +import React from "react"; +import { shallow } from "enzyme"; + +import DemoComponent from "src/components/demo-component"; + +describe("components/demo-component", () => { + + describe("Mounting", () => { + + it("should render into the document", () => { + const component = shallow(); + expect(component).to.not.be.null; + }); + + }); + +}); diff --git a/samples/demo-component/packages/demo-component/test/client/components/helpers/intl-enzyme-test-helper.js b/samples/demo-component/packages/demo-component/test/client/components/helpers/intl-enzyme-test-helper.js new file mode 100644 index 000000000..b24a3e7a2 --- /dev/null +++ b/samples/demo-component/packages/demo-component/test/client/components/helpers/intl-enzyme-test-helper.js @@ -0,0 +1,45 @@ +/** + * Components using the react-intl module require access to the intl context. + * This is not available when mounting single components in Enzyme. + * These helper functions aim to address that and wrap a valid, + * English-locale intl context around them. + */ + +import React from "react"; +import { IntlProvider, intlShape } from "react-intl"; +import { mount, shallow } from "enzyme"; + +// You can pass your messages to the IntlProvider. Optional: remove if unneeded. +const messages = require("src/lang/en.json"); // en.json + +// Create the IntlProvider to retrieve context for wrapping around. +const intlProvider = new IntlProvider({ locale: "en", messages }, {}); +const { intl } = intlProvider.getChildContext(); + +/* + When using React-Intl `injectIntl` on components, props.intl is required. +*/ +const nodeWithIntlProp = (node) => { + return React.cloneElement(node, { intl }); +}; + +const shallowWithIntl = (node) => { + return shallow( + nodeWithIntlProp(node), + { + context: {intl} + } + ); +}; + +const mountWithIntl = (node) => { + return mount( + nodeWithIntlProp(node), + { + context: {intl}, + childContextTypes: { intl: intlShape } + } + ); +}; + +export { nodeWithIntlProp, shallowWithIntl, mountWithIntl };