+

Filter deprecations by version range

- To: - {{#x-select data-test-select-to=true value=selectedTo action=(action (mut to)) as |xs|}} - {{#each toVersions as |version|}} - {{#xs.option value=version}} - {{version}} - {{/xs.option}} - {{/each}} - {{/x-select}} + + From: + {{#x-select data-test-select-from=true value=selectedFrom action=(action (mut from)) as |xs|}} + {{#each fromVersions as |version|}} + {{#xs.option value=version}} + {{version}} + {{/xs.option}} + {{/each}} + {{/x-select}} + - Number of deprecations: {{filteredDeprecations.length}} + + To: + {{#x-select data-test-select-to=true value=selectedTo action=(action (mut to)) as |xs|}} + {{#each toVersions as |version|}} + {{#xs.option value=version}} + {{version}} + {{/xs.option}} + {{/each}} + {{/x-select}} + {{#each filteredDeprecations as |deprecation|}} {{deprecation-article From a62268c62a292e5cfdbecb41089c010958e9ba89 Mon Sep 17 00:00:00 2001 From: Chris Freeman Date: Thu, 27 Sep 2018 15:14:33 -0500 Subject: [PATCH 8/8] comments and cleanup --- app/controllers/filters.js | 37 +++++++++++++------ app/routes/filters.js | 8 ++++ .../acceptance/filtering-by-versions-test.js | 2 +- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/app/controllers/filters.js b/app/controllers/filters.js index 9d87f0c9..c70a223a 100644 --- a/app/controllers/filters.js +++ b/app/controllers/filters.js @@ -8,6 +8,8 @@ export default Controller.extend({ from: null, to: null, + // The model is initially an array of arrays, one for each project/version pair + // (e.g. `ember-data-2.x`), so we need to flatten it to make filtering easier flattenedDeprecations: computed('model.[]', function() { return this.model.reduce((acc, elem) => { let rawArray = elem.toArray(); @@ -15,6 +17,8 @@ export default Controller.extend({ }, []); }), + // Create a deduped list of semver-coerced versions from all the deprecations that were loaded. + // We'll use this as the basis for our filter dropdowns versions: computed('flattenedDeprecations.@each.since', function() { let versionsList = this.flattenedDeprecations.reduce((acc, elem) => { let coerced = semver.coerce(elem.since); @@ -30,40 +34,49 @@ export default Controller.extend({ return versionsList.sort(); }), + // `fromVersions` is the list of versions that the `from` dropdown uses. It's restricted so that + // you can't select a `from` version that is higher than your `to` version. fromVersions: computed('versions.[]', 'to', function() { return this.to ? this.versions.filter(version => semver.lt(version, this.to)) : this.versions; }), + // `toVersions` is the list of versions that the `to` dropdown uses. It's restricted so that + // you can't select a `to` version that is lower than your `from` version. toVersions: computed('versions.[]', 'from', function() { return this.from ? this.versions.filter(version => semver.gt(version, this.from)) : this.versions; }), + // This will usually just mirror the `from` query param, but in case that param is empty, + // this lets us just use the lowest possible version as a default selectedFrom: computed('from', function() { - if (!this.from) { - return this.get('versions.firstObject'); - } - - return this.from; + return this.from || this.get('versions.firstObject'); }), + // This will usually just mirror the `to` query param, but in case that param is empty, + // this lets us just use the highest possible version as a default selectedTo: computed('to', function() { - if(!this.to) { - return this.get('versions.lastObject'); - } - - return this.to; + return this.to || this.get('versions.lastObject'); }), - filteredDeprecations: computed('flattenedDeprecations', 'from', 'to', function() { let deprecations = this.flattenedDeprecations; return deprecations.filter(deprecation => { - return (deprecation.since >= this.selectedFrom) && (deprecation.since <= this.selectedTo); + let coerced = semver.coerce(deprecation.since); + let version = coerced && coerced.version; + + // In case we're not able to get an actual semver version (like, if the version is a bunch + // of words or something) we just return false immediately rather than trying to pass it + // into the `semver` functions. + if (!version) { + return false; + } + + return semver.gte(version, this.selectedFrom) && semver.lte(version, this.selectedTo); }); }), }); diff --git a/app/routes/filters.js b/app/routes/filters.js index 25b77d4f..fa02c28c 100644 --- a/app/routes/filters.js +++ b/app/routes/filters.js @@ -4,6 +4,12 @@ import { all } from 'rsvp'; export default Route.extend({ model() { + // Since we currently load the deprecation files in project/version buckets + // (e.g. ember-data-2.x), we need to instead get ahold of all of the deprecations at once + // so we can do more fine-grained filtering. + + // Read the `contentFolders` config used to serve all the markdown files as static JSON assets + // and transform them in `store.query` param objects let contentFolders = config.contentFolders.map(folder => { let [ path, version ] = folder.split('/'); @@ -13,6 +19,8 @@ export default Route.extend({ }; }); + // Fire off queries for all the different project/version combinations. + // These will be flattened and filtered in the controller. let queryObjectPromises = contentFolders.map(version => { return this.store.query('content', version); }); diff --git a/tests/acceptance/filtering-by-versions-test.js b/tests/acceptance/filtering-by-versions-test.js index 53bc5072..f5bc440c 100644 --- a/tests/acceptance/filtering-by-versions-test.js +++ b/tests/acceptance/filtering-by-versions-test.js @@ -1,5 +1,5 @@ import { module, test } from 'qunit'; -import { visit, currentURL, findAll, pauseTest } from '@ember/test-helpers'; +import { visit, currentURL, findAll } from '@ember/test-helpers'; import { setupApplicationTest } from 'ember-qunit'; import { select } from 'deprecation-app/tests/helpers/x-select';