From 035ea922ae7da14d2db8a9e36e379177eca7b086 Mon Sep 17 00:00:00 2001 From: Seyi Adebajo Date: Sun, 18 Mar 2018 21:43:31 -0700 Subject: [PATCH] creates container component for search sources. refactors search controller --- .../search/containers/search-sources.ts | 68 ++++++++++ wherehows-web/app/controllers/search.js | 122 +++++++----------- .../search/containers/search-sources.hbs | 5 + wherehows-web/app/templates/search.hbs | 11 +- .../search/containers/search-sources-test.js | 78 +++++++++++ 5 files changed, 202 insertions(+), 82 deletions(-) create mode 100644 wherehows-web/app/components/search/containers/search-sources.ts create mode 100644 wherehows-web/app/templates/components/search/containers/search-sources.hbs create mode 100644 wherehows-web/tests/integration/components/search/containers/search-sources-test.js diff --git a/wherehows-web/app/components/search/containers/search-sources.ts b/wherehows-web/app/components/search/containers/search-sources.ts new file mode 100644 index 0000000000..9b898a14d4 --- /dev/null +++ b/wherehows-web/app/components/search/containers/search-sources.ts @@ -0,0 +1,68 @@ +import Component from '@ember/component'; +import { get, computed } from '@ember/object'; +import { capitalize } from '@ember/string'; +import { task } from 'ember-concurrency'; +import { DatasetPlatform } from 'wherehows-web/constants'; +import { IDataPlatform } from 'wherehows-web/typings/api/list/platforms'; +import { readPlatforms } from 'wherehows-web/utils/api/list/platforms'; +import { arrayMap } from 'wherehows-web/utils/array'; + +/** + * Describes the interface of the object passed as radio option for source + * @interface ISearchSourceOption + */ +interface ISearchSourceOption { + name: 'source'; + value: DatasetPlatform; + label: string; + group: string; +} + +export default class SearchSourcesContainer extends Component { + didInsertElement(this: SearchSourcesContainer) { + get(this, 'getPlatformsTask').perform(); + } + + /** + * The current source to narrow search results to + * @type {DatasetPlatform} + */ + currentSource: DatasetPlatform; + + /** + * Lists data platforms available to restrict search results by source + * @type {Array} + * @private + */ + _sources: Array = []; + + /** + * Gets the available platforms and extracts a list of dataset sources + * @type {(Task>, (a?: any) => TaskInstance>>>)} + */ + getPlatformsTask = task(function*(this: SearchSourcesContainer): IterableIterator>> { + const platforms: Array = yield readPlatforms(); + const getDatasetPlatform = ({ name }: IDataPlatform): DatasetPlatform => name; + const dataPlatforms = arrayMap(getDatasetPlatform)(platforms); + + get(this, '_sources').setObjects(dataPlatforms); + }); + + /** + * Creates a list of options with radio props for the data platforms that can be selected as a search filter + * @type {(ComputedProperty>} + */ + sources = computed('currentSource', '_sources.[]', function( + this: SearchSourcesContainer + ): Array { + const allSource = 'all'; + const sourceAsOption = (source: DatasetPlatform): ISearchSourceOption => ({ + name: 'source', + value: source, + label: capitalize(source), + group: String(get(this, 'currentSource')).toLowerCase() + }); + + return arrayMap(sourceAsOption)([allSource, ...get(this, '_sources')]); + }); +} diff --git a/wherehows-web/app/controllers/search.js b/wherehows-web/app/controllers/search.js index 2686b02406..adca970588 100644 --- a/wherehows-web/app/controllers/search.js +++ b/wherehows-web/app/controllers/search.js @@ -1,55 +1,10 @@ import Controller from '@ember/controller'; import { computed, set, get } from '@ember/object'; import { capitalize } from '@ember/string'; +import { action } from 'ember-decorators/object'; -const sources = ['all', 'dali', 'espresso', 'hive', 'hdfs', 'kafka', 'oracle', 'teradata', 'voldemort']; - -export default Controller.extend({ - queryParams: ['keyword', 'category', 'source', 'page'], - keyword: '', - category: 'datasets', - source: 'all', - page: 1, - header: 'Refine By', - - sources: computed('source', function() { - return sources.map(source => ({ - name: 'source', - value: source, - label: capitalize(source), - group: String(get(this, 'source')).toLowerCase() - })); - }), - - isMetric: false, - - datasetTitle: computed('model.source', function() { - var model = this.get('model'); - if (model && model.source) { - if (model.source.toLocaleLowerCase() != 'all') { - return model.source; - } - } - return 'Datasets'; - }), - isDatasets: computed('model.category', function() { - var model = this.get('model'); - if (model && model.category) { - if (model.category.toLocaleLowerCase() === 'datasets') { - return true; - } - } - return false; - }), - isComments: computed('model.category', function() { - var model = this.get('model'); - if (model && model.category) { - if (model.category.toLocaleLowerCase() === 'comments') { - return true; - } - } - return false; - }), +// gradual refactor into es class, hence extends EmberObject instance +export default class Search extends Controller.extend({ isMetrics: computed('model.category', function() { var model = this.get('model'); if (model && model.category) { @@ -59,24 +14,7 @@ export default Controller.extend({ } return false; }), - isFlows: computed('model.category', function() { - var model = this.get('model'); - if (model && model.category) { - if (model.category.toLocaleLowerCase() === 'flows') { - return true; - } - } - return false; - }), - isJobs: computed('model.category', function() { - var model = this.get('model'); - if (model && model.category) { - if (model.category.toLocaleLowerCase() === 'jobs') { - return true; - } - } - return false; - }), + previousPage: computed('model.page', function() { var model = this.get('model'); if (model && model.page) { @@ -130,19 +68,47 @@ export default Controller.extend({ } else { return false; } - }), + }) +}) { + queryParams = ['keyword', 'category', 'source', 'page']; - actions: { - sourceDidChange(groupName, value) { - set(this, groupName, value); - }, + /** + * Search keyword to look for + * @type {string} + */ + keyword = ''; - startDateDidChange(date = null) { - set(this, 'startDate', date); - }, + /** + * The category to narrow/ filter search results + * @type {string} + */ + category = 'datasets'; - endDateDidChange(date = null) { - set(this, 'endDate', date); - } + /** + * Dataset Platform to restrict search results to + * @type {'all'|DatasetPlatform} + */ + source = 'all'; + + /** + * The current search page + * @type {number} + */ + page = 1; + + /** + * Header text for search sidebar + * @type {string} + */ + header = 'Refine By'; + + /** + * Handles the response to changing the source platform to search through + * @param _groupName is radioGroup name i.e. binding to Search.source + * @param value + */ + @action + sourceDidChange(_groupName, value) { + set(this, 'source', value); } -}); +} diff --git a/wherehows-web/app/templates/components/search/containers/search-sources.hbs b/wherehows-web/app/templates/components/search/containers/search-sources.hbs new file mode 100644 index 0000000000..4b20f49048 --- /dev/null +++ b/wherehows-web/app/templates/components/search/containers/search-sources.hbs @@ -0,0 +1,5 @@ +{{#if getPlatformsTask.isRunning}} + {{pendulum-ellipsis-animation}} +{{else}} + {{yield (hash radioSources=sources)}} +{{/if}} diff --git a/wherehows-web/app/templates/search.hbs b/wherehows-web/app/templates/search.hbs index be9476842f..1daa0e96f8 100644 --- a/wherehows-web/app/templates/search.hbs +++ b/wherehows-web/app/templates/search.hbs @@ -1,10 +1,13 @@
{{#search/filter-rail header=header as |rail|}} - {{rail.radioGroup - radioOptions=sources - title="Source" - changed=(action "sourceDidChange")}} + + {{#search/containers/search-sources currentSource=source as |searchSource|}} + {{rail.radioGroup + radioOptions=searchSource.radioSources + title="Source" + changed=(action "sourceDidChange")}} + {{/search/containers/search-sources}} {{!--Api for date range not currently available--}} {{!--rail.dateRange diff --git a/wherehows-web/tests/integration/components/search/containers/search-sources-test.js b/wherehows-web/tests/integration/components/search/containers/search-sources-test.js new file mode 100644 index 0000000000..5b6c181e8f --- /dev/null +++ b/wherehows-web/tests/integration/components/search/containers/search-sources-test.js @@ -0,0 +1,78 @@ +import { moduleForComponent, test } from 'ember-qunit'; +import hbs from 'htmlbars-inline-precompile'; +import sinon from 'sinon'; +import { waitUntil, find } from 'ember-native-dom-helpers'; + +const platformsResponse = { + platforms: [ + { + name: 'platform1' + }, + { + name: 'platform2' + } + ] +}; + +moduleForComponent('search/containers/search-sources', 'Integration | Component | search/containers/search sources', { + integration: true, + + beforeEach() { + this.server = sinon.createFakeServer(); + this.server.respondImmediately = true; + }, + + afterEach() { + this.server.restore(); + } +}); + +test('it renders', async function(assert) { + this.server.respondWith('GET', /\/api\/v2\/list\/platforms/, [ + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify(platformsResponse) + ]); + + this.render(hbs` + {{#search/containers/search-sources}} +
Yielded Content
+ {{/search/containers/search-sources}} + `); + + await waitUntil(() => find('.inner-content')); + + assert.equal( + this.$() + .text() + .trim(), + 'Yielded Content', + 'inner content is rendered' + ); +}); + +test('Platform sources yielded', async function(assert) { + this.server.respondWith('GET', /\/api\/v2\/list\/platforms/, [ + 200, + { 'Content-Type': 'application/json' }, + JSON.stringify(platformsResponse) + ]); + + this.render(hbs` + {{#search/containers/search-sources as |container|}} + + {{#each container.radioSources as |source|}} + {{source.value}} + {{/each}} + + {{/search/containers/search-sources}} + `); + + await waitUntil(() => find('.inner-content')); + + const text = document.querySelector('.inner-content').textContent.trim(); + assert.ok( + ['all', 'platform1', 'platform2'].reduce((acc, curr) => acc && text.includes(curr), true), + 'it yields platform sources and `all`' + ); +});