Introduce encode/decode for array query params

This commit is contained in:
Michael Lange 2019-01-23 13:56:32 -08:00 committed by Preetha Appan
parent 40b1857632
commit 5ae2f38c4e
No known key found for this signature in database
GPG key ID: 9F7C19990A50EAFC
2 changed files with 64 additions and 16 deletions

View file

@ -2,9 +2,28 @@ import { inject as service } from '@ember/service';
import { alias } from '@ember/object/computed';
import Controller, { inject as controller } from '@ember/controller';
import { computed } from '@ember/object';
import { scheduleOnce } from '@ember/runloop';
import intersection from 'lodash.intersection';
import Sortable from 'nomad-ui/mixins/sortable';
import Searchable from 'nomad-ui/mixins/searchable';
// An unattractive but robust way to encode query params
const qpSerialize = arr => (arr.length ? JSON.stringify(arr) : '');
const qpDeserialize = str => {
try {
return JSON.parse(str)
.compact()
.without('');
} catch (e) {
return [];
}
};
const selectionFromQP = qpKey =>
computed(qpKey, function() {
return qpDeserialize(this.get(qpKey));
});
export default Controller.extend(Sortable, Searchable, {
system: service(),
jobsController: controller('jobs'),
@ -16,6 +35,10 @@ export default Controller.extend(Sortable, Searchable, {
searchTerm: 'search',
sortProperty: 'sort',
sortDescending: 'desc',
qpType: 'type',
qpStatus: 'status',
qpDatacenter: 'dc',
qpPrefix: 'prefix',
},
currentPage: 1,
@ -50,10 +73,16 @@ export default Controller.extend(Sortable, Searchable, {
.reduce(flatten, [])
);
return Array.from(allDatacenters)
.compact()
.sort()
.map(dc => ({ key: dc, label: dc }));
// Remove any invalid datacenters from the query param/selection
const availableDatacenters = Array.from(allDatacenters).compact();
scheduleOnce('actions', () => {
this.set(
'qpDatacenter',
qpSerialize(intersection(availableDatacenters, this.get('facetSelectionDatacenter')))
);
});
return availableDatacenters.sort().map(dc => ({ key: dc, label: dc }));
}),
facetOptionsPrefix: computed('visibleJobs.[]', function() {
@ -77,10 +106,20 @@ export default Controller.extend(Sortable, Searchable, {
count: nameHistogram[key],
}));
// Only consider prefixes that match more than one name, then convert to an
// options array, including the counts in the label
return nameTable
.filter(name => name.count > 1)
// Only consider prefixes that match more than one name
const prefixes = nameTable.filter(name => name.count > 1);
// Remove any invalid prefixes from the query param/selection
const availablePrefixes = prefixes.mapBy('prefix');
scheduleOnce('actions', () => {
this.set(
'qpPrefix',
qpSerialize(intersection(availablePrefixes, this.get('facetSelectionPrefix')))
);
});
// Sort, format, and include the count in the label
return prefixes
.sortBy('prefix')
.reverse()
.map(name => ({
@ -89,10 +128,15 @@ export default Controller.extend(Sortable, Searchable, {
}));
}),
facetSelectionType: computed(() => []),
facetSelectionStatus: computed(() => []),
facetSelectionDatacenter: computed(() => []),
facetSelectionPrefix: computed(() => []),
qpType: '',
qpStatus: '',
qpDatacenter: '',
qpPrefix: '',
facetSelectionType: selectionFromQP('qpType'),
facetSelectionStatus: selectionFromQP('qpStatus'),
facetSelectionDatacenter: selectionFromQP('qpDatacenter'),
facetSelectionPrefix: selectionFromQP('qpPrefix'),
/**
Filtered jobs are those that match the selected namespace and aren't children
@ -150,6 +194,10 @@ export default Controller.extend(Sortable, Searchable, {
isShowingDeploymentDetails: false,
setFacetQueryParam(queryParam, selection) {
this.set(queryParam, qpSerialize(selection));
},
actions: {
gotoJob(job) {
this.transitionToRoute('jobs.job', job.get('plainId'));

View file

@ -18,22 +18,22 @@
label="Type"
options=facetOptionsType
selection=facetSelectionType
onSelect=(action (mut facetSelectionType))}}
onSelect=(action setFacetQueryParam "qpType")}}
{{multi-select-dropdown
label="Status"
options=facetOptionsStatus
selection=facetSelectionStatus
onSelect=(action (mut facetSelectionStatus))}}
onSelect=(action setFacetQueryParam "qpStatus")}}
{{multi-select-dropdown
label="Datacenter"
options=facetOptionsDatacenter
selection=facetSelectionDatacenter
onSelect=(action (mut facetSelectionDatacenter))}}
onSelect=(action setFacetQueryParam "qpDatacenter")}}
{{multi-select-dropdown
label="Prefix"
options=facetOptionsPrefix
selection=facetSelectionPrefix
onSelect=(action (mut facetSelectionPrefix))}}
onSelect=(action setFacetQueryParam "qpPrefix")}}
</div>
</div>
<div class="column is-minimum is-centered">