creates container component for search sources. refactors search controller

This commit is contained in:
Seyi Adebajo 2018-03-18 21:43:31 -07:00
parent a0e8eef9a7
commit 035ea922ae
5 changed files with 202 additions and 82 deletions

View File

@ -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<DatasetPlatform>}
* @private
*/
_sources: Array<DatasetPlatform> = [];
/**
* Gets the available platforms and extracts a list of dataset sources
* @type {(Task<Promise<Array<IDataPlatform>>, (a?: any) => TaskInstance<Promise<Array<IDataPlatform>>>>)}
*/
getPlatformsTask = task(function*(this: SearchSourcesContainer): IterableIterator<Promise<Array<IDataPlatform>>> {
const platforms: Array<IDataPlatform> = 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<Array<ISearchSourceOption>>}
*/
sources = computed('currentSource', '_sources.[]', function(
this: SearchSourcesContainer
): Array<ISearchSourceOption> {
const allSource = <DatasetPlatform>'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')]);
});
}

View File

@ -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);
}
}
});

View File

@ -0,0 +1,5 @@
{{#if getPlatformsTask.isRunning}}
{{pendulum-ellipsis-animation}}
{{else}}
{{yield (hash radioSources=sources)}}
{{/if}}

View File

@ -1,10 +1,13 @@
<div class="row">
<div class="col-md-3 wh-sidebar">
{{#search/filter-rail header=header as |rail|}}
{{#search/containers/search-sources currentSource=source as |searchSource|}}
{{rail.radioGroup
radioOptions=sources
radioOptions=searchSource.radioSources
title="Source"
changed=(action "sourceDidChange")}}
{{/search/containers/search-sources}}
{{!--Api for date range not currently available--}}
{{!--rail.dateRange

View File

@ -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}}
<div class="inner-content">Yielded Content</div>
{{/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|}}
<span class="inner-content">
{{#each container.radioSources as |source|}}
{{source.value}}
{{/each}}
</span>
{{/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`'
);
});