Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add present object to params and use sendEvent #3

Merged
merged 8 commits into from
Apr 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,20 @@ language: node_js
node_js:
- "6"

sudo: false
sudo: required

cache:
directories:
- $HOME/.npm
- $HOME/.cache # includes bowers cache

addons:
apt:
sources:
- google-chrome
packages:
- google-chrome-stable

env:
# we recommend testing LTS's and latest stable release (bonus points to beta/canary)
- EMBER_TRY_SCENARIO=ember-lts-2.4
Expand All @@ -25,6 +32,8 @@ matrix:
- env: EMBER_TRY_SCENARIO=ember-canary

before_install:
- 'export DISPLAY=:99.0'
- sh -e /etc/init.d/xvfb start
- npm config set spin false
- npm install -g bower phantomjs-prebuilt
- bower --version
Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Changelog
=========

## 0.0.0

- Hold Your Horses,
- Pack Your Parachutes,
- We're Coming,
- But we haven't released anything yet.
34 changes: 15 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,27 +1,23 @@
# ember-parachute
# Ember Parachute

This README outlines the details of collaborating on this Ember addon.
[![Build Status](https://travis-ci.org/offirgolan/ember-parachute.svg)](https://travis-ci.org/offirgolan/ember-parachute)
[![npm version](https://badge.fury.io/js/ember-parachute.svg)](http://badge.fury.io/js/ember-parachute)

## Installation

* `git clone <repository-url>` this repository
* `cd ember-parachute`
* `npm install`
* `bower install`
<div style="text-align:center">
<img src="http://i.imgur.com/COd11eL.png" />
</div>

## Running

* `ember serve`
* Visit your app at [http://localhost:4200](http://localhost:4200).
## Installation

## Running Tests
```
ember install ember-parachute
```

* `npm test` (Runs `ember try:each` to test your addon against multiple Ember versions)
* `ember test`
* `ember test --server`
## Helpful Links

## Building
- ### [Changelog](CHANGELOG.md)

* `ember build`
## Looking for help?
If it is a bug [please open an issue on GitHub](http://github.com/offirgolan/ember-parachute/issues).

For more information on using ember-cli, visit [https://ember-cli.com/](https://ember-cli.com/).
## Usage
46 changes: 29 additions & 17 deletions addon/-private/query-params-builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,31 @@ const {
get,
Mixin,
assign,
computed
assert,
isEmpty,
computed,
} = Ember;

const {
keys
} = Object;

export default class QueryParamsBuilder {
constructor(options = {}) {
this.options = this._normalizeOptions(options);
constructor(queryParams = {}) {
assert('[ember-parachute] You cannot pass an empty object to the query params builder.', queryParams && !isEmpty(keys(queryParams)));

this._queryParams = queryParams;
this.queryParams = this._normalizeQueryParams(queryParams);
this.Mixin = this._generateMixin();
}

extend(options = {}) {
return new QueryParamsBuilder(assign({}, this.options, options));
extend() {
return new QueryParamsBuilder(assign({}, this._queryParams, ...arguments));
}

_normalizeOptions(options) {
return keys(options).reduce((o, key) => {
_normalizeQueryParams(queryParams) {
return keys(queryParams).reduce((o, key) => {
let queryParam = queryParams[key];
let defaults = {
key,
name: key,
Expand All @@ -34,36 +40,42 @@ export default class QueryParamsBuilder {
}
};

o[key] = assign(defaults, options[key]);
assert(`[ember-parachute] The query paramater ${key} must specify an object.`, queryParam && typeof queryParam === 'object');

o[key] = assign(defaults, queryParam);

return o;
}, {});
}

_generateMixin() {
let options = this.options;
let queryParams = keys(options).reduce((qps, key) => {
qps[key] = options[key].name || key;
let queryParams = this.queryParams;

// Create the `key` to `name` mapping used by Ember to register the QPs
let queryParamsMap = keys(queryParams).reduce((qps, key) => {
qps[key] = queryParams[key].name || key;
return qps;
}, {});

let defaultValues = keys(options).reduce((defaults, key) => {
defaults[key] = options[key].defaultValue;
// Get all the default values for each QP `key` to be set onto the controller
let defaultValues = keys(queryParams).reduce((defaults, key) => {
defaults[key] = queryParams[key].defaultValue;
return defaults;
}, {});

let allQueryParams = computed(...keys(options), function() {
return keys(options).reduce((qps, key) => {
qps[key] = options[key].value(this);
// Create a CP that is a collection of all QPs and their value
let allQueryParams = computed(...keys(queryParams), function() {
return keys(queryParams).reduce((qps, key) => {
qps[key] = queryParams[key].value(this);
return qps;
}, {});
}).readOnly();

return Mixin.create(defaultValues, {
[HAS_PARACHUTE]: true,
[QP_BUILDER]: this,
queryParams,
allQueryParams,
queryParams: queryParamsMap,
queryParamsDidChange() {}
});
}
Expand Down
15 changes: 11 additions & 4 deletions addon/-private/transforms.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
import Ember from 'ember';

const {
isPresent,
makeArray
} = Ember;

export default {
String(value) {
return `${value}`;
Expand All @@ -11,11 +18,11 @@ export default {
return Number(value);
},

Array(value = []) {
return value.join(',');
Array(value) {
return makeArray(value).join(',');
},

Object(value = {}) {
return value;
Object(value) {
return isPresent(value) ? value : {};
}
};
73 changes: 33 additions & 40 deletions addon/services/qp.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Ember from 'ember';
import normalizeNamedParams from '../utils/normalized-named-params';
import { HAS_PARACHUTE, QP_BUILDER } from '../-private/symbols';

const {
Expand All @@ -8,7 +9,9 @@ const {
isEmpty,
isPresent,
tryInvoke,
getOwner
getOwner,
sendEvent,
A: emberArray
} = Ember;

const {
Expand All @@ -32,9 +35,9 @@ export default Ember.Service.extend({
* @param {Object} removed
* @return
*/
update(routeName, controller, changed, totalPresent, removed) {
update(routeName, controller, changed = {}, present = {}, removed = {}) {
if (this._hasParachute(controller)) {
this._scheduleChangeEvent(routeName, assign({}, changed, removed));
this._scheduleChangeEvent(routeName, assign({}, changed, removed), present);
}
},

Expand All @@ -47,10 +50,10 @@ export default Ember.Service.extend({
* @return {Object}
*/
queryParamsFor(routeName) {
let { controller, queryParams } = this.cacheFor(routeName);
let { controller, queryParamsArray } = this.cacheFor(routeName);

return queryParams.reduce((qps, data) => {
qps[data.key] = data.value(controller);
return queryParamsArray.reduce((qps, qp) => {
qps[qp.key] = qp.value(controller);
return qps;
}, {});
},
Expand All @@ -64,11 +67,11 @@ export default Ember.Service.extend({
* @param {...string} params
*/
resetParams(routeName, ...params) {
let { controller, queryParams } = this.cacheFor(routeName);
let { controller, queryParamsArray } = this.cacheFor(routeName);

let defaults = queryParams.reduce((defaults, data) => {
if (isEmpty(params) || params.includes(data.key)) {
defaults[data.key] = data.defaultValue;
let defaults = queryParamsArray.reduce((defaults, qp) => {
if (isEmpty(params) || params.includes(qp.key)) {
defaults[qp.key] = qp.defaultValue;
}
return defaults;
}, {});
Expand All @@ -88,9 +91,10 @@ export default Ember.Service.extend({
setDefaultValue(routeName, param, defaultValue) {
let { controller } = this.cacheFor(routeName);
let qpBuilder = controller.get(QP_BUILDER);
let queryParam = qpBuilder.queryParams[param];

assert(`[ember-parachute] The query paramater '${param}' does not exist.`, qpBuilder.options[param]);
qpBuilder.options[param].defaultValue = defaultValue;
assert(`[ember-parachute] The query paramater '${param}' does not exist.`, queryParam);
queryParam.defaultValue = defaultValue;
},

/**
Expand All @@ -115,10 +119,10 @@ export default Ember.Service.extend({

cache[routeName] = {
controller,
qpMap: qpBuilder.options,
queryParams: keys(qpBuilder.options).map((key) => {
return qpBuilder.options[key];
})
queryParams: qpBuilder.queryParams,
queryParamsArray: emberArray(keys(qpBuilder.queryParams).map((key) => {
return qpBuilder.queryParams[key];
}))
}
}

Expand All @@ -131,38 +135,27 @@ export default Ember.Service.extend({
* @method _scheduleChangeEvent
* @private
* @param {String} routeName
* @param {Object} changed
* @param {Object} removed
* @param {Object} changes
* @param {Object} present
* @return
*/
_scheduleChangeEvent(routeName, changes) {
_scheduleChangeEvent(routeName, changes = {}, present = {}) {
Ember.run.schedule('afterRender', () => {
let { controller, queryParams } = this.cacheFor(routeName);
let { controller, queryParamsArray } = this.cacheFor(routeName);
let changedKeys = keys(changes);

/*
Convert the changes hash to use `key` instead of `name`
to keep a common convention.

ex) { key: 'sortDirection', name: 'sort_direction' }
We use `key` everywhere but the changes object uses `name`.
*/
let changed = queryParams.reduce((changed, data) => {
if (changedKeys.includes(data.name)) {
changed[data.key] = changes[data.name];
}

return changed;
}, {});

tryInvoke(controller, 'queryParamsDidChange', [{
let objToPass = {
routeName,
changed,
changed: normalizeNamedParams(changes, queryParamsArray),
present: normalizeNamedParams(present, queryParamsArray),
queryParams: this.queryParamsFor(routeName),
shouldRefresh: queryParams.any((data) => {
return changedKeys.includes(data.name) && data.refresh;
shouldRefresh: queryParamsArray.any((qp) => {
return changedKeys.includes(qp.name) && qp.refresh;
})
}]);
};

tryInvoke(controller, 'queryParamsDidChange', [ objToPass ]);
sendEvent(controller, 'queryParamsDidChange', [ objToPass ]);
});
},

Expand Down
21 changes: 21 additions & 0 deletions addon/utils/normalized-named-params.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* Convert the a QP object to use `key` instead of `name`
* to keep a common convention.
*
* ex) { key: 'sortDirection', name: 'sort_direction' }
* We want yo use `key` since `name` is just a sort of display value.
*
* @method normalizeNamedParams
* @public
* @param {Object} o
* @param {Array} qp
* @return {Object}
*/
export default function normalizeNamedParams(o, qp) {
return qp.reduce((ko, data) => {
if (o[data.name]) {
ko[data.key] = o[data.name];
}
return ko;
}, {});
}
23 changes: 23 additions & 0 deletions config/changelog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// jshint node:true

// For details on each option run `ember help release`
module.exports = {

// angular style guide: https://github.com/angular/angular.js/blob/v1.4.8/CONTRIBUTING.md#commit
// jquery style guide: https://contribute.jquery.org/commits-and-pull-requests/#commit-guidelines
// ember style guide: https://github.com/emberjs/ember.js/blob/master/CONTRIBUTING.md#commit-tagging
style: 'angular', // 'ember' 'jquery'

head: 'master',
base: '-last', // a branch or tag name, `-last` defaults to the version in package.json

hooks: {
/*
parser: function(commit) { return commit; }
filter: function(commit) { return true; },
groupSort: function(commits) { return { commits: commits }; },
format: function(commit) { return commit.title; },
*/
}

};
Loading