Tarea #164 Filtros con superpoderes

This commit is contained in:
Daniel Herrero 2018-03-13 14:30:25 +01:00
parent 6b1ad875cb
commit 176ce860ca
6 changed files with 90 additions and 57 deletions

View File

@ -5,7 +5,7 @@
"validations" : true, "validations" : true,
"routes": [ "routes": [
{ {
"url": "/clients", "url": "/clients?q",
"state": "clients", "state": "clients",
"component": "vn-client-index", "component": "vn-client-index",
"acl": ["employee"] "acl": ["employee"]

View File

@ -1,4 +1,4 @@
<mg-ajax path="/client/api/Clients/filter" options="mgIndex"></mg-ajax> <mg-ajax path="/client/api/Clients/filter" options="vnIndexNonAuto"></mg-ajax>
<div margin-medium> <div margin-medium>
<div class="vn-list"> <div class="vn-list">
<vn-card> <vn-card>

View File

@ -11,7 +11,7 @@
"component": "ui-view" "component": "ui-view"
}, },
{ {
"url": "/list", "url": "/list?q",
"state": "item.index", "state": "item.index",
"component": "vn-item-list" "component": "vn-item-list"
}, },

View File

@ -1,4 +1,4 @@
<mg-ajax path="/item/api/Items/filter" options="mgIndex"></mg-ajax> <mg-ajax path="/item/api/Items/filter" options="vnIndexNonAuto"></mg-ajax>
<div margin-medium> <div margin-medium>
<div class="vn-list"> <div class="vn-list">
<vn-card> <vn-card>

View File

@ -1,7 +1,7 @@
import ngModule from '../../module'; import ngModule from '../../module';
export default class Controller { export default class Controller {
constructor($element, $scope, $document, $compile, vnPopover, $timeout) { constructor($element, $scope, $document, $compile, vnPopover, $timeout, $state, $transitions) {
this.element = $element[0]; this.element = $element[0];
this.$scope = $scope; this.$scope = $scope;
this.$document = $document; this.$document = $document;
@ -9,46 +9,52 @@ export default class Controller {
this.vnPopover = vnPopover; this.vnPopover = vnPopover;
this.$timeout = $timeout; this.$timeout = $timeout;
this.stringSearch = ''; this.stringSearch = '';
this.$state = $state;
this.deregisterCallback = $transitions.onStart({},
transition => this.changeState(transition));
} }
clearFilter() { clearFilter() {
this.index.filter = { this.index.filter = {
page: 1, page: 1,
size: 20 size: 20
}; };
} }
/**
* String search to JSON filter setFilter(filterObject) {
*/ this.clearFilter();
getFiltersFromSearch() { Object.assign(this.index.filter, filterObject);
let toFind = this.stringSearch; }
let find;
if (this.stringSearch) { getFiltersFromString(stringSearch) {
let result = {};
if (stringSearch) {
// find pattern key:value or key:(extra value) and returns array // find pattern key:value or key:(extra value) and returns array
find = toFind.match(/((([\w_]+):([\w_]+))|([\w_]+):\(([\w_ ]+)\))/gi); let findPattern = stringSearch.match(/((([\w_]+):([\w_]+))|([\w_]+):\(([\w_ ]+)\))/gi);
// remove pattern key:value or key:(extra value) from string and returns string let remnantString = (stringSearch.replace(/((([\w_]+):([\w_]+))|([\w_]+):\(([\w_ ]+)\))/gi, '')).trim();
this.index.filter.search = (toFind.replace(/((([\w_]+):([\w_]+))|([\w_]+):\(([\w_ ]+)\))/gi, '')).trim(); if (findPattern) {
if (find) for (let i = 0; i < findPattern.length; i++) {
for (let i = 0; i < find.length; i++) { let aux = findPattern[i].split(':');
let aux = find[i].split(':');
let property = aux[0]; let property = aux[0];
let value = aux[1].replace(/\(|\)/g, ''); let value = aux[1].replace(/\(|\)/g, '');
this.index.filter[property] = value.trim(); result[property] = value.trim();
} }
}
if (remnantString) {
result.search = remnantString;
}
} }
return result;
} }
/**
* JSON filter to string search createStringFromObject(filterObject) {
*
* @param {Object} filter The filter
*/
createFilterSearch(filter) {
let search = []; let search = [];
let keys = Object.keys(filter); let keys = Object.keys(filterObject);
if (keys.length) { if (keys.length) {
keys.forEach(k => { keys.forEach(k => {
let ignore = (this.ignoreKeys && this.ignoreKeys instanceof Array && this.ignoreKeys.indexOf(k) !== -1); let ignore = (this.ignoreKeys && this.ignoreKeys instanceof Array && this.ignoreKeys.indexOf(k) !== -1);
if (!ignore) { if (!ignore) {
let value = filter[k]; let value = filterObject[k];
if (typeof value === 'string' && value.indexOf(' ') !== -1) { if (typeof value === 'string' && value.indexOf(' ') !== -1) {
search.push(`${k}:(${value})`); search.push(`${k}:(${value})`);
@ -57,42 +63,59 @@ export default class Controller {
} }
} }
}); });
if (filterObject.search)
search.unshift(filterObject.search);
} }
if (this.index.filter.search) { return (search.length) ? search.join(' ') : '';
search.push(this.index.filter.search);
}
delete this.index.filter.search;
this.stringSearch = (search.length) ? search.join(' ') : '';
} }
changeState(transition) {
return !(transition._targetState._identifier.name === this.$state.current.name);
}
pushFiltersToState(filters) {
let history = window.history || {pushState: () => {
console.error('Error in history.pushState(): Browser incompatibility error');
}};
let aux = window.location.hash.split('?q=');
if (Object.keys(filters).length)
history.pushState({}, null, `${aux[0]}?q=${encodeURIComponent(JSON.stringify(filters))}`);
else
history.pushState({}, null, aux[0]);
}
onpenFilters(event) { onpenFilters(event) {
let filter = {};
if (this.stringSearch) { if (this.stringSearch) {
this.getFiltersFromSearch(); filter = this.getFiltersFromString(this.stringSearch);
} }
this.child = this.vnPopover.showComponent(this.popover, this.$scope, this.element); this.child = this.vnPopover.showComponent(this.popover, this.$scope, this.element);
// XXX: ¿Existe una forma más adecuada de acceder al controlador de un componente? // XXX: ¿Existe una forma más adecuada de acceder al controlador de un componente?
var childCtrl = angular.element(this.child).isolateScope().$ctrl; var childCtrl = angular.element(this.child).isolateScope().$ctrl;
childCtrl.filter = Object.assign({}, this.index.filter); childCtrl.filter = Object.assign({}, filter);
childCtrl.onSubmit = filter => this.onChildSubmit(filter); childCtrl.onSubmit = filter => this.onChildSubmit(filter);
if (this.data) if (this.data)
childCtrl.data = Object.assign({}, this.data); childCtrl.data = Object.assign({}, this.data);
event.preventDefault(); event.preventDefault();
} }
onChildSubmit(filter) { onChildSubmit(filter) {
this.createFilterSearch(filter); this.stringSearch = this.createStringFromObject(filter);
this.index.filter = { this.clearFilter();
page: 1,
size: 20
};
this.$timeout(() => { this.$timeout(() => {
this.onSubmit(); this.onSubmit();
}); });
} }
onSubmit() { onSubmit() {
let filter = {};
if (this.stringSearch) { if (this.stringSearch) {
this.getFiltersFromSearch(); filter = this.getFiltersFromString(this.stringSearch);
} }
this.setFilter(filter);
if (this.onSearch) if (this.onSearch)
this.onSearch(); this.onSearch();
@ -103,12 +126,25 @@ export default class Controller {
angular.element(this.child).remove(); angular.element(this.child).remove();
} }
delete this.child; delete this.child;
this.pushFiltersToState(filter);
} }
$onDestroy() { $onDestroy() {
this.clearFilter(); this.clearFilter();
this.deregisterCallback();
}
$onInit() {
if (this.$state.params.q) {
let filter = JSON.parse(decodeURIComponent(this.$state.params.q));
this.stringSearch = this.createStringFromObject(filter);
}
this.$timeout(() => {
this.onSubmit();
});
} }
} }
Controller.$inject = ['$element', '$scope', '$document', '$compile', 'vnPopover', '$timeout']; Controller.$inject = ['$element', '$scope', '$document', '$compile', 'vnPopover', '$timeout', '$state', '$transitions'];
ngModule.component('vnSearchbar', { ngModule.component('vnSearchbar', {
template: require('./searchbar.html'), template: require('./searchbar.html'),

View File

@ -2,7 +2,7 @@ module.exports = Self => {
Self.installMethod('filter', filterParams); Self.installMethod('filter', filterParams);
function filterParams(params) { function filterParams(params) {
let filter = { let filters = {
where: {}, where: {},
skip: (params.page - 1) * params.size, skip: (params.page - 1) * params.size,
limit: params.size, limit: params.size,
@ -20,7 +20,7 @@ module.exports = Self => {
delete params.order; delete params.order;
if (params.search) { if (params.search) {
filter.where.and = [ filters.where.and = [
{ {
or: [ or: [
{id: params.search}, {id: params.search},
@ -36,21 +36,18 @@ module.exports = Self => {
delete params.itemSize; delete params.itemSize;
} }
let keys = Object.keys(params); Object.keys(params).forEach(
if (keys.length) { key => {
keys.forEach( if (filters.where.and) {
key => { let filter = {};
if (filter.where.and) { filter[key] = (key === 'description' || key === 'name') ? {regexp: params[key]} : params[key];
let filter = {}; filters.where.and.push(filter);
filter[key] = (key === 'description') ? {regexp: params[key]} : params[key]; } else {
filter.where.and.push(filter); filters.where[key] = (key === 'description' || key === 'name') ? {regexp: params[key]} : params[key];
} else {
filter.where[key] = (key === 'description') ? {regexp: params[key]} : params[key];
}
} }
); }
} );
return filter; return filters;
} }
}; };