Skip to content

Commit

Permalink
temp: filtering DSL test
Browse files Browse the repository at this point in the history
  • Loading branch information
ChaiWithJai committed Oct 26, 2022
1 parent c2ce152 commit fb70217
Show file tree
Hide file tree
Showing 6 changed files with 708 additions and 67 deletions.
6 changes: 6 additions & 0 deletions ui/app/adapters/job.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,10 @@ export default class JobAdapter extends WatchableNamespaceIDs {
},
});
}

handleResponse(_status, headers) {
const result = super.handleResponse(...arguments);
result.meta = { nextToken: headers['x-nomad-nexttoken'] };
return result;
}
}
83 changes: 52 additions & 31 deletions ui/app/controllers/jobs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,43 +25,56 @@ export default class IndexController extends Controller.extend(
isForbidden = false;

queryParams = [
{
pageSize: 'pageSize',
},
{
currentPage: 'page',
},
{
searchTerm: 'search',
},
'pageSize',
'nextToken',
'status',
'type',
'searchTerm',
'datacenter',
'prefix',
{
sortProperty: 'sort',
},
{
sortDescending: 'desc',
},
{
qpType: 'type',
},
{
qpStatus: 'status',
},
{
qpDatacenter: 'dc',
},
{
qpPrefix: 'prefix',
},
{
qpNamespace: 'namespace',
},
];

currentPage = 1;

sortProperty = 'modifyIndex';
sortDescending = true;
@tracked pageSize = this.userSettings.pageSize;
@tracked nextToken = null;
@tracked previousTokens = [];

get shouldDisableNext() {
return !this.model.jobs.meta?.nextToken;
}

get shouldDisablePrev() {
return !this.previousTokens.length;
}

@action
onNext(nextToken) {
this.previousTokens = [...this.previousTokens, this.nextToken];
this.nextToken = nextToken;
}

@action
onPrev(lastToken) {
this.previousTokens.pop();
this.previousTokens = [...this.previousTokens];
this.nextToken = lastToken;
}

@action
refresh() {
this.nextToken = null;
this.previousTokens = [];
}

@action
setPageSize(newPageSize) {
Expand All @@ -80,15 +93,15 @@ export default class IndexController extends Controller.extend(

fuzzySearchEnabled = true;

qpType = '';
qpStatus = '';
qpDatacenter = '';
qpPrefix = '';
@tracked type = '';
@tracked status = '';
@tracked datacenter = '';
@tracked prefix = '';

@selection('qpType') selectionType;
@selection('qpStatus') selectionStatus;
@selection('qpDatacenter') selectionDatacenter;
@selection('qpPrefix') selectionPrefix;
@selection('type') selectionType;
@selection('status') selectionStatus;
@selection('datacenter') selectionDatacenter;
@selection('prefix') selectionPrefix;

@computed
get optionsType() {
Expand Down Expand Up @@ -260,7 +273,15 @@ export default class IndexController extends Controller.extend(

isShowingDeploymentDetails = false;

@action
setFacetQueryParam(queryParam, selection) {
this._resetTokens();
this.set(queryParam, serialize(selection));
}

@action
_resetTokens() {
this.nextToken = null;
this.previousTokens = [];
}
}
112 changes: 108 additions & 4 deletions ui/app/routes/jobs/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,118 @@ export default class IndexRoute extends Route.extend(
pageSize: {
refreshModel: true,
},
nextToken: {
refreshModel: true,
},
status: {
refreshModel: true,
},
type: {
refreshModel: true,
},
searchTerm: {
refreshModel: true,
},
datacenter: {
refreshModel: true,
},
prefix: {
refreshModel: true,
},
};

model(params) {
model({
searchTerm,
type,
qpNamespace,
pageSize,
status,
nextToken,
datacenter,
}) {
const parseJSON = (qp) => (qp ? JSON.parse(qp) : null);
const iterateOverList = (list, type) => {
const dictionary = {
type: ['Type', '=='],
status: ['Status', '=='],
datacenter: ['Datacenters', 'contains'],
};
const [selector, matcher] = dictionary[type];
if (!list) return null;
return list.reduce((accum, val, idx) => {
if (idx !== list.length - 1) {
accum += `${selector} ${matcher} "${val}" or `;
} else {
accum += `${selector} ${matcher} "${val}")`;
}
return accum;
}, '(');
};
/*
We use our own DSL for filter expressions. This function takes our query parameters and builds a query that matches our DSL.
Documentation can be found here: https://www.nomadproject.io/api-docs#filtering
*/
const generateFilterExpression = () => {
const searchFilter = searchTerm ? `Name contains "${searchTerm}"` : null;
const typeFilter = iterateOverList(parseJSON(type), 'type');
const datacenterFilter = iterateOverList(
parseJSON(datacenter),
'datacenter'
);
const statusFilter = iterateOverList(parseJSON(status), 'status');

let filterExp;
if (searchTerm) {
if (!type && !status && !datacenter) {
return searchFilter;
}
filterExp = `(${searchFilter})`;
if (type) {
filterExp = `${filterExp} and ${typeFilter}`;
}
if (datacenter) {
filterExp = `${filterExp} and ${datacenterFilter}`;
}
if (status) {
filterExp = `${filterExp} and ${statusFilter}`;
}
return filterExp;
}

if (type || status || datacenter) {
const lookup = {
[type]: typeFilter,
[status]: statusFilter,
[datacenter]: datacenterFilter,
};

filterExp = [type, status, datacenter].reduce((result, filter) => {
const expression = lookup[filter];
if (!!filter && result !== '') {
result = result.concat(` and ${expression}`);
} else if (filter) {
result = expression;
}
return result;
}, '');
debugger;
return filterExp;
}

return null;
};

const hasFilters = !!generateFilterExpression();

return RSVP.hash({
jobs: this.store
.query('job', {
namespace: params.qpNamespace,
per_page: params.pageSize,
filter: `ParentID is empty`,
namespace: qpNamespace,
per_page: pageSize,
filter: hasFilters
? `ParentID is empty and ${generateFilterExpression()}`
: `ParentID is empty`,
next_token: nextToken,
})
.catch(notifyForbidden(this)),
namespaces: this.store.findAll('namespace'),
Expand All @@ -43,6 +146,7 @@ export default class IndexRoute extends Route.extend(
namespace: controller.qpNamespace,
per_page: controller.pageSize,
filter: `ParentID is empty`,
next_token: controller.nextToken,
})
);
}
Expand Down
60 changes: 31 additions & 29 deletions ui/app/templates/jobs/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -51,28 +51,28 @@
@label="Type"
@options={{this.optionsType}}
@selection={{this.selectionType}}
@onSelect={{action this.setFacetQueryParam "qpType"}}
@onSelect={{action this.setFacetQueryParam "type"}}
/>
<MultiSelectDropdown
data-test-status-facet
@label="Status"
@options={{this.optionsStatus}}
@selection={{this.selectionStatus}}
@onSelect={{action this.setFacetQueryParam "qpStatus"}}
@onSelect={{action this.setFacetQueryParam "status"}}
/>
<MultiSelectDropdown
data-test-datacenter-facet
@label="Datacenter"
@options={{this.optionsDatacenter}}
@selection={{this.selectionDatacenter}}
@onSelect={{action this.setFacetQueryParam "qpDatacenter"}}
@onSelect={{action this.setFacetQueryParam "datacenter"}}
/>
<MultiSelectDropdown
data-test-prefix-facet
@label="Prefix"
@options={{this.optionsPrefix}}
@selection={{this.selectionPrefix}}
@onSelect={{action this.setFacetQueryParam "qpPrefix"}}
@onSelect={{action this.setFacetQueryParam "prefix"}}
/>
</div>
</div>
Expand Down Expand Up @@ -107,7 +107,6 @@
<ListPagination
@source={{this.sortedJobs}}
@size={{this.pageSize}}
@page={{this.currentPage}}
as |p|
>
<ListTable
Expand Down Expand Up @@ -146,31 +145,34 @@
<JobRow @data-test-job-row={{row.model.plainId}} @job={{row.model}} />
</t.body>
</ListTable>
<div class="table-foot">
<div class="table-foot with-padding">
<PageSizeSelect @onChange={{action this.setPageSize}} />
<nav class="pagination">
<div class="pagination-numbers">
{{p.startsAt}}
{{p.endsAt}}
of
{{this.sortedJobs.length}}
{{#if this.searchTerm}}
<em>
(
{{dec this.sortedJobs.length this.filteredJobs.length}}
hidden by search term)
</em>
{{/if}}
</div>
<p.prev @class="pagination-previous">
{{x-icon "chevron-left"}}
</p.prev>
<p.next @class="pagination-next">
{{x-icon "chevron-right"}}
</p.next>
<ul class="pagination-list"></ul>
</nav>
<div>
<button
type="button"
class="button"
{{on "click" this.refresh}}
>
{{x-icon "refresh-default" class="is-text"}}
Refresh
</button>
<button
type="button"
class="button is-text is-borderless"
disabled={{this.shouldDisablePrev}}
{{on "click" (fn this.onPrev this.lastToken)}}
>
{{x-icon "chevron-left" class="is-large"}}
</button>
<button
type="button"
class="button is-text is-borderless"
disabled={{this.shouldDisableNext}}
{{on "click" (fn this.onNext this.model.jobs.meta.nextToken)}}
>
{{x-icon "chevron-right" class="is-large"}}
</button>
</div>
</div>
</ListPagination>
{{else}}
Expand Down
2 changes: 1 addition & 1 deletion ui/app/templates/jobs/loading.hbs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<section class="section has-text-centered"><LoadingSpinner /></section>
<section class="section has-text-centered" data-test-jobs-loading><LoadingSpinner /></section>
Loading

0 comments on commit fb70217

Please sign in to comment.