-
Notifications
You must be signed in to change notification settings - Fork 2k
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’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
UI: Faceted search on the jobs list page #5236
Changes from 1 commit
8ed8a85
3d87c47
3b235a1
5aef4d9
3b8187f
b20dc67
0d8dd50
a207fdd
2fdec7e
b769365
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -19,7 +19,7 @@ const qpDeserialize = str => { | |||
} | ||||
}; | ||||
|
||||
const selectionFromQP = qpKey => | ||||
const qpSelection = qpKey => | ||||
computed(qpKey, function() { | ||||
return qpDeserialize(this.get(qpKey)); | ||||
}); | ||||
|
@@ -51,21 +51,21 @@ export default Controller.extend(Sortable, Searchable, { | |||
fuzzySearchProps: computed(() => ['name']), | ||||
fuzzySearchEnabled: true, | ||||
|
||||
facetOptionsType: computed(() => [ | ||||
optionsType: computed(() => [ | ||||
{ key: 'batch', label: 'Batch' }, | ||||
{ key: 'parameterized', label: 'Parameterized' }, | ||||
{ key: 'periodic', label: 'Periodic' }, | ||||
{ key: 'service', label: 'Service' }, | ||||
{ key: 'system', label: 'System' }, | ||||
]), | ||||
|
||||
facetOptionsStatus: computed(() => [ | ||||
optionsStatus: computed(() => [ | ||||
{ key: 'pending', label: 'Pending' }, | ||||
{ key: 'running', label: 'Running' }, | ||||
{ key: 'dead', label: 'Dead' }, | ||||
]), | ||||
|
||||
facetOptionsDatacenter: computed('visibleJobs.[]', function() { | ||||
optionsDatacenter: computed('visibleJobs.[]', function() { | ||||
const flatten = (acc, val) => acc.concat(val); | ||||
const allDatacenters = new Set( | ||||
this.get('visibleJobs') | ||||
|
@@ -78,14 +78,14 @@ export default Controller.extend(Sortable, Searchable, { | |||
scheduleOnce('actions', () => { | ||||
this.set( | ||||
'qpDatacenter', | ||||
qpSerialize(intersection(availableDatacenters, this.get('facetSelectionDatacenter'))) | ||||
qpSerialize(intersection(availableDatacenters, this.get('selectionDatacenter'))) | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That'd work fine, but it wouldn't save me a dependency since I'm already using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah cool, I think it's just here: nomad/ui/app/models/allocation.js Line 73 in c12bdcd
You could remove lodash there also? I suppose it depends what side of the fence you are on, but it would save a dependency, no biggie either way. |
||||
); | ||||
}); | ||||
|
||||
return availableDatacenters.sort().map(dc => ({ key: dc, label: dc })); | ||||
}), | ||||
|
||||
facetOptionsPrefix: computed('visibleJobs.[]', function() { | ||||
optionsPrefix: computed('visibleJobs.[]', function() { | ||||
// A prefix is defined as the start of a job name up to the first - or . | ||||
// ex: mktg-analytics -> mktg, ds.supermodel.classifier -> ds | ||||
const hasPrefix = /.[-._]/; | ||||
|
@@ -114,7 +114,7 @@ export default Controller.extend(Sortable, Searchable, { | |||
scheduleOnce('actions', () => { | ||||
this.set( | ||||
'qpPrefix', | ||||
qpSerialize(intersection(availablePrefixes, this.get('facetSelectionPrefix'))) | ||||
qpSerialize(intersection(availablePrefixes, this.get('selectionPrefix'))) | ||||
); | ||||
}); | ||||
|
||||
|
@@ -130,10 +130,10 @@ export default Controller.extend(Sortable, Searchable, { | |||
qpDatacenter: '', | ||||
qpPrefix: '', | ||||
|
||||
facetSelectionType: selectionFromQP('qpType'), | ||||
facetSelectionStatus: selectionFromQP('qpStatus'), | ||||
facetSelectionDatacenter: selectionFromQP('qpDatacenter'), | ||||
facetSelectionPrefix: selectionFromQP('qpPrefix'), | ||||
selectionType: qpSelection('qpType'), | ||||
selectionStatus: qpSelection('qpStatus'), | ||||
selectionDatacenter: qpSelection('qpDatacenter'), | ||||
selectionPrefix: qpSelection('qpPrefix'), | ||||
|
||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should all these go up at the top of the class definition with your other variables? |
||||
/** | ||||
Filtered jobs are those that match the selected namespace and aren't children | ||||
|
@@ -153,21 +153,21 @@ export default Controller.extend(Sortable, Searchable, { | |||
|
||||
filteredJobs: computed( | ||||
'visibleJobs.[]', | ||||
'facetSelectionType', | ||||
'facetSelectionStatus', | ||||
'facetSelectionDatacenter', | ||||
'facetSelectionPrefix', | ||||
'selectionType', | ||||
'selectionStatus', | ||||
'selectionDatacenter', | ||||
'selectionPrefix', | ||||
function() { | ||||
const { | ||||
facetSelectionType: types, | ||||
facetSelectionStatus: statuses, | ||||
facetSelectionDatacenter: datacenters, | ||||
facetSelectionPrefix: prefixes, | ||||
selectionType: types, | ||||
selectionStatus: statuses, | ||||
selectionDatacenter: datacenters, | ||||
selectionPrefix: prefixes, | ||||
} = this.getProperties( | ||||
'facetSelectionType', | ||||
'facetSelectionStatus', | ||||
'facetSelectionDatacenter', | ||||
'facetSelectionPrefix' | ||||
'selectionType', | ||||
'selectionStatus', | ||||
'selectionDatacenter', | ||||
'selectionPrefix' | ||||
); | ||||
|
||||
// A job must match ALL filter facets, but it can match ANY selection within a facet | ||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hehe I see what you mean here by unattractive! So my URL right now has:
Generally I've seen these things done with
status[]=thing
, I'm not sure how ember treats that though, I did notice something the other day related to this, I'll try and dig it out again in a bit incase it helps.I'm not entirely sure that
"
should be in URLs, and also that,
shouldn't - probably worth having a look to see what is 'usual' here. Do you need the"
's? Are you expecting to havetrue
and"true"
at the same time?Anyway, if you take a look lemme know what you find out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here's the thing I was looking at the other day which is ever so slightly related to this
https://github.com/tildeio/route-recognizer/blob/0940966757104ea5297717102b1ae3dc260ee8ee/lib/route-recognizer.ts#L564-L574
Looks like ember is aware of the
key[]=value
thing, just be careful as I'm not sure it encodes keys properly when you do that. I don't think that would effect you here anyway.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was honestly expecting Ember to use the
status[]=&status[]=
style when I bound an array to a query param, but that's not what happened. Instead it basically does what I'm doing now: JSON stringifying.As for encoding characters, it's curious that you are seeing
"
and,
in the URL, what browser are you using? In Chrome, they were automatically encoded. Not sure if that's a property of Ember or Chrome.Yes-ish. Ideally I would change
qpSerialize
to justarr.join(',')
, but commas (and basically everything) is a legal job name and datacenter character. So there are other possible encoding schemes thanJSON.stringify
, but it's not worth spinning my wheels on that.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh weird were you not getting
"
s? I was in Chrome. I did find it strange that it seemed to be encoding one but not the other. I'm gonna check this branch out again in a bit and double check. It was definitely showing me actual"
s when I did this first pass.Yeah for sure, this is why I was thinking a
filter[status][]=url%20encoded%2Cjob-name&filter[status][]=another%22url%20encoded%2Cjob-name
seemed to make more sense to me? I'm not entirely sure what ember does though, so I'm not sure how easily it is to make ember produce/consume that - I might have a bit more of a dig in a bit myself later.So my question would be, what's the reason for doing it here if ember does the same? I don't have enough practical info on what ember does here though.
I think I'd still be tempted to use URL encoding to encode strings for the URL - but there's also an argument to say 'use the framework', and if it uses a javascript encoder to encode the entire data blob into a single string parameter and then URL encode it then maybe there is a reason for that I'm not aware of/haven't thought of. It might just be 'because it's more straightforward'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Definitely getting
"
s in Chrome