├── app
├── .gitkeep
└── helpers
│ ├── dispatch.js
│ └── get-state.js
├── addon
├── .gitkeep
├── helpers
│ ├── get-state.js
│ └── dispatch.js
└── _private
│ └── closure-action.js
├── vendor
└── .gitkeep
├── tests
├── unit
│ └── .gitkeep
├── integration
│ ├── .gitkeep
│ └── components
│ │ └── helper-test.js
├── dummy
│ ├── app
│ │ ├── helpers
│ │ │ └── .gitkeep
│ │ ├── models
│ │ │ └── .gitkeep
│ │ ├── routes
│ │ │ └── .gitkeep
│ │ ├── components
│ │ │ ├── .gitkeep
│ │ │ ├── x-child.js
│ │ │ ├── x-parent.js
│ │ │ └── heart-progress.js
│ │ ├── controllers
│ │ │ └── .gitkeep
│ │ ├── templates
│ │ │ ├── components
│ │ │ │ └── .gitkeep
│ │ │ └── application.hbs
│ │ ├── resolver.js
│ │ ├── enhancers
│ │ │ └── index.js
│ │ ├── reducers
│ │ │ ├── low.js
│ │ │ ├── high.js
│ │ │ ├── name.js
│ │ │ ├── index.js
│ │ │ └── progress.js
│ │ ├── router.js
│ │ ├── app.js
│ │ ├── index.html
│ │ └── styles
│ │ │ └── app.css
│ ├── public
│ │ ├── robots.txt
│ │ ├── ember.png
│ │ ├── redux.png
│ │ └── crossdomain.xml
│ └── config
│ │ └── environment.js
├── test-helper.js
├── helpers
│ ├── destroy-app.js
│ ├── resolver.js
│ ├── start-app.js
│ └── module-for-acceptance.js
├── .jshintrc
└── index.html
├── .watchmanconfig
├── .bowerrc
├── blueprints
├── .jshintrc
└── ember-redux-helpers
│ └── index.js
├── index.js
├── config
├── environment.js
└── ember-try.js
├── .npmignore
├── testem.js
├── bower.json
├── .ember-cli
├── .gitignore
├── .jshintrc
├── .editorconfig
├── .travis.yml
├── ember-cli-build.js
├── LICENSE.md
├── package.json
└── README.md
/app/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/addon/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/vendor/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/unit/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/integration/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/helpers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/models/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/routes/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/controllers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/components/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.watchmanconfig:
--------------------------------------------------------------------------------
1 | {
2 | "ignore_dirs": ["tmp", "dist"]
3 | }
4 |
--------------------------------------------------------------------------------
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "bower_components",
3 | "analytics": false
4 | }
5 |
--------------------------------------------------------------------------------
/tests/dummy/public/robots.txt:
--------------------------------------------------------------------------------
1 | # http://www.robotstxt.org
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/app/helpers/dispatch.js:
--------------------------------------------------------------------------------
1 | export { default, dispatch } from 'ember-redux-helpers/helpers/dispatch';
2 |
--------------------------------------------------------------------------------
/app/helpers/get-state.js:
--------------------------------------------------------------------------------
1 | export { default, getState } from 'ember-redux-helpers/helpers/get-state';
2 |
--------------------------------------------------------------------------------
/blueprints/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "predef": [
3 | "console"
4 | ],
5 | "strict": false
6 | }
7 |
--------------------------------------------------------------------------------
/tests/dummy/app/resolver.js:
--------------------------------------------------------------------------------
1 | import Resolver from 'ember-resolver';
2 |
3 | export default Resolver;
4 |
--------------------------------------------------------------------------------
/tests/dummy/app/enhancers/index.js:
--------------------------------------------------------------------------------
1 | export default window.devToolsExtension ? window.devToolsExtension() : f => f;
2 |
--------------------------------------------------------------------------------
/tests/dummy/public/ember.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jkusa/ember-redux-helpers/HEAD/tests/dummy/public/ember.png
--------------------------------------------------------------------------------
/tests/dummy/public/redux.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jkusa/ember-redux-helpers/HEAD/tests/dummy/public/redux.png
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /* jshint node: true */
2 | 'use strict';
3 |
4 | module.exports = {
5 | name: 'ember-redux-helpers'
6 | };
7 |
--------------------------------------------------------------------------------
/config/environment.js:
--------------------------------------------------------------------------------
1 | /*jshint node:true*/
2 | 'use strict';
3 |
4 | module.exports = function(/* environment, appConfig */) {
5 | return { };
6 | };
7 |
--------------------------------------------------------------------------------
/tests/test-helper.js:
--------------------------------------------------------------------------------
1 | import resolver from './helpers/resolver';
2 | import {
3 | setResolver
4 | } from 'ember-qunit';
5 |
6 | setResolver(resolver);
7 |
--------------------------------------------------------------------------------
/tests/helpers/destroy-app.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default function destroyApp(application) {
4 | Ember.run(application, 'destroy');
5 | }
6 |
--------------------------------------------------------------------------------
/tests/dummy/app/reducers/low.js:
--------------------------------------------------------------------------------
1 | export default ((state=0, action) => { // jshint ignore:line
2 | if(action.type === 'UP') {
3 | return state + 1;
4 | }
5 | return state;
6 | });
7 |
--------------------------------------------------------------------------------
/tests/dummy/app/reducers/high.js:
--------------------------------------------------------------------------------
1 | export default ((state=9, action) => { // jshint ignore:line
2 | if(action.type === 'DOWN') {
3 | return state - 1;
4 | }
5 | return state;
6 | });
7 |
--------------------------------------------------------------------------------
/tests/dummy/app/reducers/name.js:
--------------------------------------------------------------------------------
1 | export default ((state='Tomster', action) => { // jshint ignore:line
2 | if(action.type === 'UPDATE_NAME') {
3 | return action.name;
4 | }
5 | return state;
6 | });
7 |
--------------------------------------------------------------------------------
/tests/dummy/app/reducers/index.js:
--------------------------------------------------------------------------------
1 | import low from 'dummy/reducers/low';
2 | import high from 'dummy/reducers/high';
3 | import name from 'dummy/reducers/name';
4 | import progress from 'dummy/reducers/progress';
5 |
6 | export default { low, high, name, progress };
7 |
--------------------------------------------------------------------------------
/tests/dummy/app/router.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import config from './config/environment';
3 |
4 | const Router = Ember.Router.extend({
5 | location: config.locationType
6 | });
7 |
8 | Router.map(function() {
9 | });
10 |
11 | export default Router;
12 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | /bower_components
2 | /config/ember-try.js
3 | /dist
4 | /tests
5 | /tmp
6 | **/.gitkeep
7 | .bowerrc
8 | .editorconfig
9 | .ember-cli
10 | .gitignore
11 | .jshintrc
12 | .watchmanconfig
13 | .travis.yml
14 | bower.json
15 | ember-cli-build.js
16 | testem.js
17 |
--------------------------------------------------------------------------------
/testem.js:
--------------------------------------------------------------------------------
1 | /*jshint node:true*/
2 | module.exports = {
3 | "framework": "qunit",
4 | "test_page": "tests/index.html?hidepassed",
5 | "disable_watching": true,
6 | "launch_in_ci": [
7 | "PhantomJS"
8 | ],
9 | "launch_in_dev": [
10 | "PhantomJS",
11 | "Chrome"
12 | ]
13 | };
14 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ember-redux-helpers",
3 | "dependencies": {
4 | "ember": "~2.5.0",
5 | "ember-cli-shims": "0.1.1",
6 | "ember-cli-test-loader": "0.2.2",
7 | "ember-qunit-notifications": "0.1.0",
8 | "font-awesome": "~4.5.0",
9 | "highlightjs": "^9.4.0"
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/x-child.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import hbs from 'htmlbars-inline-precompile';
3 |
4 | export default Ember.Component.extend({
5 | layout: hbs`
6 | {{high}}
7 |
8 | `
9 | });
10 |
--------------------------------------------------------------------------------
/.ember-cli:
--------------------------------------------------------------------------------
1 | {
2 | /**
3 | Ember CLI sends analytics information by default. The data is completely
4 | anonymous, but there are times when you might want to disable this behavior.
5 |
6 | Setting `disableAnalytics` to true will prevent any data from being sent.
7 | */
8 | "disableAnalytics": false
9 | }
10 |
--------------------------------------------------------------------------------
/tests/helpers/resolver.js:
--------------------------------------------------------------------------------
1 | import Resolver from '../../resolver';
2 | import config from '../../config/environment';
3 |
4 | const resolver = Resolver.create();
5 |
6 | resolver.namespace = {
7 | modulePrefix: config.modulePrefix,
8 | podModulePrefix: config.podModulePrefix
9 | };
10 |
11 | export default resolver;
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 |
7 | # dependencies
8 | /node_modules
9 | /bower_components
10 |
11 | # misc
12 | /.sass-cache
13 | /connect.lock
14 | /coverage/*
15 | /libpeerconnection.log
16 | npm-debug.log
17 | testem.log
18 |
--------------------------------------------------------------------------------
/tests/dummy/app/reducers/progress.js:
--------------------------------------------------------------------------------
1 | export default ((state=80, action) => { // jshint ignore:line
2 | if(action.type === 'MORE') {
3 | if(state < 100) {
4 | state = state + 10;
5 | }
6 | }
7 |
8 | if(action.type === 'LESS') {
9 | if(state > 0) {
10 | state = state - 10;
11 | }
12 | }
13 |
14 | return state;
15 | });
16 |
--------------------------------------------------------------------------------
/addon/helpers/get-state.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | export default Ember.Helper.extend({
4 |
5 | redux: Ember.inject.service('redux'),
6 |
7 | init() {
8 | this._super(...arguments);
9 | this.get('redux').subscribe(() => {
10 | this.recompute();
11 | });
12 | },
13 |
14 | compute(params) {
15 | let state = this.get('redux').getState();
16 | return Ember.get(state, params[0]);
17 | }
18 | });
19 |
--------------------------------------------------------------------------------
/addon/_private/closure-action.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 |
3 | let ClosureActionModule;
4 |
5 | if ('ember-htmlbars/keywords/closure-action' in Ember.__loader.registry) {
6 | ClosureActionModule = Ember.__loader.require('ember-htmlbars/keywords/closure-action');
7 | } else {
8 | ClosureActionModule = Ember.__loader.require('ember-routing-htmlbars/keywords/closure-action');
9 | }
10 |
11 | export default ClosureActionModule.ACTION;
12 |
--------------------------------------------------------------------------------
/tests/dummy/app/app.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import Resolver from './resolver';
3 | import loadInitializers from 'ember-load-initializers';
4 | import config from './config/environment';
5 |
6 | let App;
7 |
8 | Ember.MODEL_FACTORY_INJECTIONS = true;
9 |
10 | App = Ember.Application.extend({
11 | modulePrefix: config.modulePrefix,
12 | podModulePrefix: config.podModulePrefix,
13 | Resolver
14 | });
15 |
16 | loadInitializers(App, config.modulePrefix);
17 |
18 | export default App;
19 |
--------------------------------------------------------------------------------
/blueprints/ember-redux-helpers/index.js:
--------------------------------------------------------------------------------
1 | /*jshint node:true*/
2 | module.exports = {
3 |
4 | description: 'Set up additional packages for Ember apps',
5 |
6 | normalizeEntityName: function() {},
7 |
8 | afterInstall: function(options) {
9 | return this.addPackagesToProject([
10 | { name: 'ember-browserify', target: '^1.1.9' },
11 | { name: 'ember-redux', target: '^1.4.0' },
12 | { name: 'redux', target: '^3.4.0' },
13 | { name: 'redux-thunk', target: '^2.0.1' }
14 | ]);
15 | }
16 | };
17 |
--------------------------------------------------------------------------------
/tests/helpers/start-app.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import Application from '../../app';
3 | import config from '../../config/environment';
4 |
5 | export default function startApp(attrs) {
6 | let application;
7 |
8 | let attributes = Ember.merge({}, config.APP);
9 | attributes = Ember.merge(attributes, attrs); // use defaults, but you can override;
10 |
11 | Ember.run(() => {
12 | application = Application.create(attributes);
13 | application.setupForTesting();
14 | application.injectTestHelpers();
15 | });
16 |
17 | return application;
18 | }
19 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/x-parent.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import hbs from 'htmlbars-inline-precompile';
3 |
4 | export default Ember.Component.extend({
5 | layout: hbs`
6 | {{get-state "low"}}
7 |
8 | {{x-child
9 | high=(get-state "high")
10 | down=(dispatch "DOWN")
11 | }}
12 | {{get-state "name"}}
13 |
14 | `
15 | });
16 |
--------------------------------------------------------------------------------
/addon/helpers/dispatch.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import ACTION from '../_private/closure-action';
3 |
4 | export default Ember.Helper.extend({
5 |
6 | redux: Ember.inject.service('redux'),
7 |
8 | compute([type, ...params], hash) {
9 | let redux = this.get('redux');
10 |
11 | let action = (...invocationArgs) => {
12 | Ember.run.join(() => {
13 | redux.dispatch(
14 | Object.assign({}, hash, {
15 | type,
16 | invocationArgs
17 | })
18 | );
19 | });
20 | };
21 |
22 | action[ACTION] = true;
23 | return action;
24 | }
25 | });
26 |
--------------------------------------------------------------------------------
/tests/helpers/module-for-acceptance.js:
--------------------------------------------------------------------------------
1 | import { module } from 'qunit';
2 | import startApp from '../helpers/start-app';
3 | import destroyApp from '../helpers/destroy-app';
4 |
5 | export default function(name, options = {}) {
6 | module(name, {
7 | beforeEach() {
8 | this.application = startApp();
9 |
10 | if (options.beforeEach) {
11 | options.beforeEach.apply(this, arguments);
12 | }
13 | },
14 |
15 | afterEach() {
16 | if (options.afterEach) {
17 | options.afterEach.apply(this, arguments);
18 | }
19 |
20 | destroyApp(this.application);
21 | }
22 | });
23 | }
24 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "predef": [
3 | "document",
4 | "window",
5 | "-Promise"
6 | ],
7 | "browser": true,
8 | "boss": true,
9 | "curly": true,
10 | "debug": false,
11 | "devel": true,
12 | "eqeqeq": true,
13 | "evil": true,
14 | "forin": false,
15 | "immed": false,
16 | "laxbreak": false,
17 | "newcap": true,
18 | "noarg": true,
19 | "noempty": false,
20 | "nonew": false,
21 | "nomen": false,
22 | "onevar": false,
23 | "plusplus": false,
24 | "regexp": false,
25 | "undef": true,
26 | "sub": true,
27 | "strict": false,
28 | "white": false,
29 | "eqnull": true,
30 | "esnext": true,
31 | "unused": true
32 | }
33 |
--------------------------------------------------------------------------------
/tests/dummy/public/crossdomain.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
15 |
16 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # editorconfig.org
4 |
5 | root = true
6 |
7 |
8 | [*]
9 | end_of_line = lf
10 | charset = utf-8
11 | trim_trailing_whitespace = true
12 | insert_final_newline = true
13 | indent_style = space
14 | indent_size = 2
15 |
16 | [*.js]
17 | indent_style = space
18 | indent_size = 2
19 |
20 | [*.hbs]
21 | insert_final_newline = false
22 | indent_style = space
23 | indent_size = 2
24 |
25 | [*.css]
26 | indent_style = space
27 | indent_size = 2
28 |
29 | [*.html]
30 | indent_style = space
31 | indent_size = 2
32 |
33 | [*.{diff,md}]
34 | trim_trailing_whitespace = false
35 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | ---
2 | language: node_js
3 | node_js:
4 | - "0.12"
5 |
6 | sudo: false
7 |
8 | cache:
9 | directories:
10 | - node_modules
11 |
12 | env:
13 | - EMBER_TRY_SCENARIO=default
14 | - EMBER_TRY_SCENARIO=ember-1.13
15 | - EMBER_TRY_SCENARIO=ember-release
16 | - EMBER_TRY_SCENARIO=ember-beta
17 | - EMBER_TRY_SCENARIO=ember-canary
18 |
19 | matrix:
20 | fast_finish: true
21 | allow_failures:
22 | - env: EMBER_TRY_SCENARIO=ember-canary
23 |
24 | before_install:
25 | - export PATH=/usr/local/phantomjs-2.0.0/bin:$PATH
26 | - "npm config set spin false"
27 | - "npm install -g npm@^2"
28 |
29 | install:
30 | - npm install -g bower
31 | - npm install
32 | - bower install
33 |
34 | script:
35 | - ember try $EMBER_TRY_SCENARIO test
36 |
--------------------------------------------------------------------------------
/ember-cli-build.js:
--------------------------------------------------------------------------------
1 | /*jshint node:true*/
2 | /* global require, module */
3 | var EmberAddon = require('ember-cli/lib/broccoli/ember-addon');
4 |
5 | module.exports = function(defaults) {
6 | var app = new EmberAddon(defaults, {
7 | babel: {
8 | includePolyfill: true
9 | }
10 | });
11 |
12 | /*
13 | This build file specifies the options for the dummy test app of this
14 | addon, located in `/tests/dummy`
15 | This build file does *not* influence how the addon or the app using it
16 | behave. You most likely want to be modifying `./index.js` or app's build file
17 | */
18 | app.import('bower_components/highlightjs/styles/github.css');
19 | app.import('bower_components/highlightjs/highlight.pack.js');
20 | return app.toTree();
21 | };
22 |
--------------------------------------------------------------------------------
/tests/dummy/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dummy
7 |
8 |
9 |
10 | {{content-for "head"}}
11 |
12 |
13 |
14 |
15 | {{content-for "head-footer"}}
16 |
17 |
18 | {{content-for "body"}}
19 |
20 |
21 |
22 |
23 |
24 | {{content-for "body-footer"}}
25 |
26 |
27 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6 |
7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8 |
9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 |
--------------------------------------------------------------------------------
/tests/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "predef": [
3 | "document",
4 | "window",
5 | "location",
6 | "setTimeout",
7 | "$",
8 | "-Promise",
9 | "define",
10 | "console",
11 | "visit",
12 | "exists",
13 | "fillIn",
14 | "click",
15 | "keyEvent",
16 | "triggerEvent",
17 | "find",
18 | "findWithAssert",
19 | "wait",
20 | "DS",
21 | "andThen",
22 | "currentURL",
23 | "currentPath",
24 | "currentRouteName",
25 | "ProgressBar"
26 | ],
27 | "node": false,
28 | "browser": false,
29 | "boss": true,
30 | "curly": true,
31 | "debug": false,
32 | "devel": false,
33 | "eqeqeq": true,
34 | "evil": true,
35 | "forin": false,
36 | "immed": false,
37 | "laxbreak": false,
38 | "newcap": true,
39 | "noarg": true,
40 | "noempty": false,
41 | "nonew": false,
42 | "nomen": false,
43 | "onevar": false,
44 | "plusplus": false,
45 | "regexp": false,
46 | "undef": true,
47 | "sub": true,
48 | "strict": false,
49 | "white": false,
50 | "eqnull": true,
51 | "esnext": true,
52 | "unused": true
53 | }
54 |
--------------------------------------------------------------------------------
/tests/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Dummy Tests
7 |
8 |
9 |
10 | {{content-for "head"}}
11 | {{content-for "test-head"}}
12 |
13 |
14 |
15 |
16 |
17 | {{content-for "head-footer"}}
18 | {{content-for "test-head-footer"}}
19 |
20 |
21 | {{content-for "body"}}
22 | {{content-for "test-body"}}
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | {{content-for "body-footer"}}
32 | {{content-for "test-body-footer"}}
33 |
34 |
35 |
--------------------------------------------------------------------------------
/config/ember-try.js:
--------------------------------------------------------------------------------
1 | /*jshint node:true*/
2 | module.exports = {
3 | scenarios: [
4 | {
5 | name: 'default',
6 | bower: {
7 | dependencies: { }
8 | }
9 | },
10 | {
11 | name: 'ember-1.13',
12 | bower: {
13 | dependencies: {
14 | 'ember': '~1.13.0'
15 | },
16 | resolutions: {
17 | 'ember': '~1.13.0'
18 | }
19 | }
20 | },
21 | {
22 | name: 'ember-release',
23 | bower: {
24 | dependencies: {
25 | 'ember': 'components/ember#release'
26 | },
27 | resolutions: {
28 | 'ember': 'release'
29 | }
30 | }
31 | },
32 | {
33 | name: 'ember-beta',
34 | bower: {
35 | dependencies: {
36 | 'ember': 'components/ember#beta'
37 | },
38 | resolutions: {
39 | 'ember': 'beta'
40 | }
41 | }
42 | },
43 | {
44 | name: 'ember-canary',
45 | bower: {
46 | dependencies: {
47 | 'ember': 'components/ember#canary'
48 | },
49 | resolutions: {
50 | 'ember': 'canary'
51 | }
52 | }
53 | }
54 | ]
55 | };
56 |
--------------------------------------------------------------------------------
/tests/dummy/config/environment.js:
--------------------------------------------------------------------------------
1 | /* jshint node: true */
2 |
3 | module.exports = function(environment) {
4 | var ENV = {
5 | modulePrefix: 'dummy',
6 | environment: environment,
7 | baseURL: '/',
8 | locationType: 'auto',
9 | EmberENV: {
10 | FEATURES: {
11 | // Here you can enable experimental features on an ember canary build
12 | // e.g. 'with-controller': true
13 | }
14 | },
15 |
16 | APP: {
17 | // Here you can pass flags/options to your application instance
18 | // when it is created
19 | }
20 | };
21 |
22 | if (environment === 'development') {
23 | // ENV.APP.LOG_RESOLVER = true;
24 | // ENV.APP.LOG_ACTIVE_GENERATION = true;
25 | // ENV.APP.LOG_TRANSITIONS = true;
26 | // ENV.APP.LOG_TRANSITIONS_INTERNAL = true;
27 | // ENV.APP.LOG_VIEW_LOOKUPS = true;
28 | }
29 |
30 | if (environment === 'test') {
31 | // Testem prefers this...
32 | ENV.baseURL = '/';
33 | ENV.locationType = 'none';
34 |
35 | // keep test console output quieter
36 | ENV.APP.LOG_ACTIVE_GENERATION = false;
37 | ENV.APP.LOG_VIEW_LOOKUPS = false;
38 |
39 | ENV.APP.rootElement = '#ember-testing';
40 | }
41 |
42 | if (environment === 'production') {
43 | ENV.locationType = 'hash';
44 | ENV.baseURL = '/ember-redux-helpers/';
45 |
46 | }
47 |
48 | return ENV;
49 | };
50 |
--------------------------------------------------------------------------------
/tests/dummy/app/components/heart-progress.js:
--------------------------------------------------------------------------------
1 | import Ember from 'ember';
2 | import hbs from 'htmlbars-inline-precompile';
3 |
4 | const { computed, get, set } = Ember;
5 |
6 | export default Ember.Component.extend({
7 | layout: hbs`
8 |
9 | {{yield}}
10 |
11 |
17 | `,
18 |
19 | classNames: ['heart-progress'],
20 |
21 | didInsertElement() {
22 | this._super(...arguments);
23 | let heart = new ProgressBar.Path(`#${this.elementId} #heart-path`);
24 | set(this, 'heart', heart);
25 |
26 | heart.set(get(this, 'value'));
27 | },
28 |
29 | didUpdateAttrs() {
30 | let heart = get(this, 'heart');
31 | if(heart) {
32 | heart.set(get(this, 'value'));
33 | }
34 | },
35 |
36 | value: computed('progress', function() {
37 | let progress = get(this, 'progress');
38 | if(progress) {
39 | return progress/100;
40 | }
41 | return 0;
42 | })
43 | });
44 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ember-redux-helpers",
3 | "version": "0.1.1",
4 | "description": "A set of Ember Template Helpers for Redux.JS",
5 | "directories": {
6 | "doc": "doc",
7 | "test": "tests"
8 | },
9 | "scripts": {
10 | "build": "ember build",
11 | "start": "ember server",
12 | "test": "ember try:testall"
13 | },
14 | "repository": "https://github.com/jkusa/ember-redux-helpers.git",
15 | "engines": {
16 | "node": ">= 0.10.0"
17 | },
18 | "author": "Jon Kilroy ",
19 | "license": "MIT",
20 | "devDependencies": {
21 | "broccoli-asset-rev": "^2.4.2",
22 | "ember-ajax": "0.7.1",
23 | "ember-browserify": "^1.1.9",
24 | "ember-cli": "2.5.1",
25 | "ember-cli-app-version": "^1.0.0",
26 | "ember-cli-dependency-checker": "^1.2.0",
27 | "ember-cli-font-awesome": "1.5.0",
28 | "ember-cli-github-pages": "0.1.0",
29 | "ember-cli-htmlbars": "^1.0.3",
30 | "ember-cli-htmlbars-inline-precompile": "^0.3.1",
31 | "ember-cli-inject-live-reload": "^1.4.0",
32 | "ember-cli-jshint": "^1.0.0",
33 | "ember-cli-qunit": "^1.4.0",
34 | "ember-cli-release": "0.2.8",
35 | "ember-cli-sri": "^2.1.0",
36 | "ember-cli-uglify": "^1.2.0",
37 | "ember-data": "^2.5.0",
38 | "ember-disable-prototype-extensions": "^1.1.0",
39 | "ember-export-application-global": "^1.0.5",
40 | "ember-load-initializers": "^0.5.1",
41 | "ember-progress-bar": "0.0.3",
42 | "ember-redux": "^1.4.0",
43 | "ember-resolver": "^2.0.3",
44 | "ember-try": "^0.2.2",
45 | "loader.js": "^4.0.1",
46 | "progressbar.js": "^1.0.1",
47 | "redux": "^3.4.0",
48 | "redux-thunk": "^2.0.1"
49 | },
50 | "keywords": [
51 | "ember-addon",
52 | "ember-cli",
53 | "ember",
54 | "redux"
55 | ],
56 | "dependencies": {
57 | "ember-cli-babel": "^5.1.6"
58 | },
59 | "ember-addon": {
60 | "configPath": "tests/dummy/config",
61 | "demoURL": "http://jkusa.github.io/ember-redux-helpers"
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ember-redux-helpers
2 |
3 | [](https://travis-ci.org/jkusa/ember-redux-helpers)
4 |
5 | A set of [Ember](http://emberjs.com) Template Helpers for [Redux.JS](http://redux.js.org)
6 |
7 | ## Demo Page
8 |
9 | http://jkusa.github.io/ember-redux-helpers/
10 |
11 | ## Usage
12 |
13 | ### `{{get-state "state.path"}}`
14 |
15 | Helper to fetch and subscribe to state properties in the redux store
16 |
17 | ```hbs
18 | {!-- component.hbs --}}
19 | {{progress-bar
20 | progress=(get-state 'progress')
21 | }}
22 | ```
23 |
24 | Use object paths just like you would with [Ember.get](http://emberjs.com/api/#method_get)
25 |
26 | ```hbs
27 | {{!-- component.hbs --}}
28 | {{todo-item
29 | todo=(get-state 'todos.firstObject')
30 | }}
31 | ```
32 |
33 | ### `{{dispatch "TYPE" key=value key=value}}`
34 |
35 | Closure action helper to dispatch directly to the redux store
36 |
37 | ```hs
38 | {{!-- component.hbs --}}
39 |
42 | ```
43 |
44 | ```js
45 | //reducer.js
46 | export default (state=0, action) => {
47 |
48 | if(action.type === 'ADD') {
49 | state += action.value;
50 | }
51 |
52 | return state;
53 | };
54 | ```
55 |
56 | Arguments provided while invoking the action can be referenced via the __invocationArgs__ property array
57 |
58 | ```hbs
59 | {{!-- component.hbs --}}
60 |
61 | ```
62 |
63 | ```js
64 | //reducer.js
65 | export default (state={}, action) => {
66 |
67 | if (action.type === 'UPDATE') {
68 |
69 | let { field, invocationArgs } = action;
70 | state = Object.assign(state, {
71 | //invocaionArgs contains the event obj
72 | [field]: invocationArgs[0].target.value
73 | });
74 |
75 | }
76 |
77 | return state;
78 | };
79 | ```
80 |
81 | ## Compatibility
82 |
83 | This addon will work on Ember versions `1.13.x` and up only, due to use of the new `Helper` implementation.
84 |
85 | ## Thanks
86 |
87 | Thanks to @toranb and @rwjblue who inspired this addon.
88 |
--------------------------------------------------------------------------------
/tests/integration/components/helper-test.js:
--------------------------------------------------------------------------------
1 | import { moduleForComponent, test } from 'ember-qunit';
2 | import hbs from 'htmlbars-inline-precompile';
3 |
4 | moduleForComponent('x-parent', 'integration: redux helpers test', {
5 | integration: true,
6 | setup() {
7 | this.inject.service('redux');
8 | }
9 | });
10 |
11 | test('dispatch and get-state can be used to interact with the redux store', function(assert) {
12 | assert.expect(8);
13 |
14 | this.render(hbs`{{x-parent}}`);
15 |
16 | let $parent = this.$('.low-state'),
17 | $child = this.$('.high-state'),
18 | $name = this.$('.name-state');
19 |
20 | /* == Test initial state == */
21 |
22 | assert.equal($parent.text(),
23 | 0,
24 | 'parent rendered the correct initial low state from redux');
25 |
26 | assert.equal($child.text(),
27 | 9,
28 | 'child received the correct initial high state from redux as a prop');
29 |
30 | assert.equal($name.text(),
31 | 'Tomster',
32 | 'parent rendered the correct initial name state from redux');
33 |
34 | /* == Test Dispatch and Rerender == */
35 |
36 | this.$('.btn-up').trigger('click');
37 | assert.equal($parent.text(),
38 | 1,
39 | 'dispatch action was correctly called and parent rerendered');
40 |
41 | this.$('.btn-down').trigger('click');
42 | assert.equal($child.text(),
43 | 8,
44 | 'dispatch closure action was correctly called and childed rerendered');
45 |
46 | /* == Test Dispatch and Rerender Again == */
47 |
48 | this.$('.btn-up').trigger('click');
49 | assert.equal($parent.text(),
50 | 2,
51 | 'dispatch action was correctly called and parent rerendered');
52 |
53 | this.$('.btn-down').trigger('click');
54 | assert.equal($child.text(),
55 | 7,
56 | 'dispatch closure action was correctly called and childed rerendered');
57 |
58 | /* == Test Dispatch with Parameter == */
59 |
60 | this.$('.btn-name').trigger('click');
61 | assert.equal($name.text(),
62 | 'Zoey',
63 | 'dispatch action with parameter was correctly called and parent rerendered');
64 | });
65 |
--------------------------------------------------------------------------------
/tests/dummy/app/templates/application.hbs:
--------------------------------------------------------------------------------
1 |
33 |
34 |
35 |
36 | \{{get-state "state.path"}}
37 |
38 | helper to fetch and subscribe to state properties in the redux store
39 |
40 |
41 |
42 | \{{!-- component.hbs --}}
43 | \{{progress-bar
44 | progress=(get-state 'progress')
45 | }}
46 |
47 |
48 |
49 | Use object paths just like you would with
Ember.get
50 |
51 |
52 |
53 | \{{!-- component.hbs --}}
54 | \{{todo-item
55 | todo=(get-state 'todos.firstObject')
56 | }}
57 |
58 |
59 |
60 |
61 |
62 | \{{dispatch "TYPE" prop=value prop=value}}
63 |
64 | closure action helper to dispatch directly to the redux store
65 |
66 |
67 |
68 | \{{!-- component.hbs --}}
69 | <button
70 | onclick=\{{dispatch 'ADD' value=value}}>
71 | Click to Add
72 | </button>
73 |
74 |
75 | //reducer.js
76 | export default (state=0, action) => {
77 |
78 | if(action.type === 'ADD') {
79 | state += action.value;
80 | }
81 |
82 | return state;
83 | };
84 |
85 |
86 |
87 | arguments provided while invoking the action can be referenced via the invocationArgs array property
88 |
89 |
90 |
91 | \{{!-- component.hbs --}}
92 | <input
93 | onchange=(dispatch 'UPDATE' field='title')
94 | >
95 |
96 |
97 | //reducer.js
98 | export default (state={}, action) => {
99 |
100 | if (action.type === 'UPDATE') {
101 |
102 | let { field, invocationArgs } = action;
103 | state = Object.assign(state, {
104 | //invocaionArgs contains the event obj
105 | [field]: invocationArgs[0].target.value
106 | });
107 |
108 | }
109 |
110 | return state;
111 | };
112 |
113 |
114 |
115 |
116 |
117 |
124 |
125 |
--------------------------------------------------------------------------------
/tests/dummy/app/styles/app.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0 auto;
3 | padding: 15px;
4 | width: 400px;
5 | font-family: HelveticaNeue-Light,"Helvetica Neue Light","Helvetica Neue",Helvetica,Arial,"Lucida Grande",sans-serif;
6 | font-weight: 300;
7 | color: #4B4B4D;
8 | background-color: #FFFDFD;
9 | }
10 |
11 | a {
12 | text-decoration: inherit;
13 | color: inherit;
14 | cursor: pointer;
15 | border: dotted #555;
16 | border-width: 0 0 1px 0;
17 | }
18 |
19 | button {
20 | cursor: pointer;
21 | }
22 |
23 | button:focus {
24 | outline: 0;
25 | }
26 |
27 | h1 {
28 | margin: 5px 0 0;
29 | }
30 |
31 | h2 {
32 | font-size: 18px;
33 | text-align: center;
34 | font-weight: 100;
35 | margin-top: 0;
36 | }
37 |
38 | svg {
39 | display: block;
40 | margin: auto;
41 | height: 100%;
42 | }
43 |
44 | .progress,
45 | code {
46 | font-size: 12px;
47 | font-family: Menlo,Monaco,Consolas,"Courier New",monospace;
48 | }
49 |
50 | header {
51 | width: 100%;
52 | text-align: center;
53 | }
54 |
55 | pre {
56 | margin: 0;
57 | }
58 |
59 | section {
60 | margin: 20px;
61 | border: 1px solid #CCC;
62 | border-radius: 5px;
63 | }
64 |
65 | footer {
66 | margin: 20px
67 | }
68 |
69 | em {
70 | color: #0086b3;
71 | }
72 |
73 | section h3 {
74 | border-bottom: 1px solid #CCC;
75 | margin: 0;
76 | padding: 10px;
77 | font-size: 16px;
78 | text-align: center;
79 | }
80 |
81 | .description {
82 | padding: 10px;
83 | border-bottom: 1px solid #CCC;
84 | border-top: 1px solid #CCC;
85 | text-align: center;
86 | }
87 |
88 | .example {
89 | padding: 10px;
90 | }
91 |
92 | .example code {
93 | font-size: 12px;
94 | }
95 |
96 | .install-cmd {
97 | margin: 20px 0;
98 | display: block;
99 | }
100 |
101 | .progress-btn-group {
102 | justify-content: space-around;
103 | display: flex;
104 | }
105 |
106 | .btn code {
107 | margin: 3px;
108 | font-size: 10px;
109 | }
110 |
111 | .plus {
112 | font-size: 30px;
113 | }
114 |
115 | .btn.dispatch {
116 | z-index: 1;
117 | margin: 9px 0;
118 | border-radius: 3px;
119 | border: 1px solid #E34C32;
120 | background: transparent;
121 | color: #E34C32;
122 | font-weight: 600;
123 | }
124 |
125 | .btn.dispatch .hljs {
126 | background-color: transparent;
127 | }
128 |
129 | .btn.dispatch:hover {
130 | background-color: rgba(0,0,0,0.01);
131 | border-color: #4B4B4D;
132 | }
133 |
134 | .heart-progress {
135 | height: 350px;
136 | position: relative;
137 | }
138 |
139 | .inner-container {
140 | top: -15px;
141 | width: 100%;
142 | height: 100%;
143 | flex-direction: column;
144 | margin: auto auto;
145 | position: absolute;
146 | display: flex;
147 | justify-content: center;
148 | align-items: center;
149 | }
150 |
151 | .logos {
152 | display: flex;
153 | align-items: center;
154 | margin: 10px;
155 | }
156 |
157 | .redux {
158 | padding: 0 8px;
159 | }
160 |
161 | .progress {
162 | display: flex;
163 | align-items: center;
164 | }
165 |
166 | .progress .hljs {
167 | background-color: transparent;
168 | }
169 |
170 | .profile-link {
171 | text-align: center;
172 | }
173 |
174 | a.ember-link,
175 | .profile-link a {
176 | border: none;
177 | }
178 |
179 | .gh-link {
180 | text-align: center;
181 | margin: 20px 0;
182 | }
183 |
184 | .gh-link a {
185 | display: inline-block;
186 | border: 1px solid #4B4B4D;
187 | padding: 3px 5px;
188 | -webkit-border-radius: 3px;
189 | -moz-border-radius: 3px;
190 | border-radius: 3px;
191 | }
192 |
193 | .gh-link a:hover {
194 | background-color: #4B4B4D;
195 | color: #FFFDFD;
196 | }
197 |
198 | .gh-link span {
199 | display: inline-block;
200 | font-size: inherit;
201 | }
202 |
203 | .gh-link span:before {
204 | font: normal normal normal 14px/1 FontAwesome;
205 | content: "\f09b";
206 | font-size: 26px;
207 | vertical-align: sub;
208 | }
209 |
210 | .todo-link {
211 | font-weight: 600;
212 | text-align: center;
213 | margin: 10px 50px;
214 | }
215 |
--------------------------------------------------------------------------------