diff --git a/src/config.json b/src/config.json index 511510749233da02e7452d8e86f14f17544617da..0c6dc1dfe4b5839abe92f447489133637279cd4f 100644 --- a/src/config.json +++ b/src/config.json @@ -90,8 +90,6 @@ "user.firstname", "email" ], - "searchKeys": [ - "email" - ] + "searchKeys": [] } } diff --git a/src/events/viewEvent.js b/src/events/viewEvent.js index a7758e91d99cedf8265a30e35859ea1d78069a70..3d73d3a5431eea9d485e77e7d27eff50b4468b97 100644 --- a/src/events/viewEvent.js +++ b/src/events/viewEvent.js @@ -40,10 +40,18 @@ styler.add('eventView', viewLayout); class ParticipantsTable { constructor({ attrs: { where } }) { - this.ctrl = new DatalistController('eventsignups', { - embedded: { user: 1 }, - where, - }, signupConfig.tableKeys); + this.ctrl = new DatalistController( + 'eventsignups', { + embedded: { user: 1 }, + where, + }, + [ + 'email', + 'user.firstname', + 'user.lastname', + ], + false, + ); } getItemData(data) { diff --git a/src/listcontroller.js b/src/listcontroller.js index bc759b307e92a02d5522e68b65014274b5bb75de..1d871958e6b962ce77e83a49e3d59d2bfb16c5f2 100644 --- a/src/listcontroller.js +++ b/src/listcontroller.js @@ -2,10 +2,16 @@ import Stream from 'mithril/stream'; import { ResourceHandler } from './auth'; export default class DatalistController { - constructor(resource, query = {}, searchKeys = false) { - this.handler = new ResourceHandler(resource, searchKeys); + constructor(resource, query = {}, searchKeys = false, onlineSearch = true) { + this.onlineSearch = onlineSearch; + if (onlineSearch) { + this.handler = new ResourceHandler(resource, searchKeys); + } else { + this.handler = new ResourceHandler(resource, false); + this.clientSearchKeys = searchKeys ||Â []; + } this.query = query || {}; - this.items = []; + this.search = null; // state pointer that is counted up every time the table is refreshed so // we can tell infinite scroll that the data-version has changed. this.stateCounter = Stream(0); @@ -27,25 +33,66 @@ export default class DatalistController { getPageData(pageNum) { // for some reason this is called before the object is instantiated. // check this and return nothing - const query = {}; - Object.keys(this.query).forEach((key) => { query[key] = this.query[key]; }); + const query = Object.assign({}, this.query); query.max_results = 10; query.page = pageNum; return new Promise((resolve, reject) => { this.handler.get(query).then((data) => { - resolve(data._items); + // If onlineSearch is false, we filter the page-results at the client + // because the API would not understand the search pattern, e.g. for + // embedded keys like user.firstname + if (!this.onlineSearch && this.clientSearchKeys.length > 0 && this.search) { + const response = []; + // We go through all response items and will add them to response if + // they match the query. + data._items.forEach((item) => { + // Try every search Key seperately, such that any match with any + // key is sufficient + this.clientSearchKeys.some((key) => { + if (key.match(/.*\..*/)) { + // traverse the key, this is a key pointing to a sub-object + let intermediateObject = Object.assign({}, item); + key.split('.').forEach((subKey) => { + intermediateObject = intermediateObject[subKey]; + }); + if (intermediateObject.includes(this.search)) { + response.push(item); + // return true to end the search of this object, it is already + // matched + return true; + } + } else if (item[key] && item[key].includes(this.search)) { + response.push(item); + // return true to end the search of this object, it is already + // matched + return true; + } + return false; + }); + }); + resolve(response); + } else { + resolve(data._items); + } }); }); } setSearch(search) { - this.query.search = search; - this.refresh(); + if (this.onlineSearch) { + this.search = search; + this.query.search = search; + this.refresh(); + } else if (this.clientSearchKeys.length > 0) { + this.search = search; + this.refresh(); + } } setQuery(query) { this.query = query; + this.query.search = this.search; this.refresh(); } }