Automatic pagination with vnPagination, improved vnSearchbar
This commit is contained in:
parent
a015b790b5
commit
9fa12d4baf
|
@ -75,20 +75,20 @@
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
vn-two
|
vn-two
|
||||||
margin-large-right
|
|
||||||
label="Description"
|
label="Description"
|
||||||
model="observation.description"
|
model="observation.description"
|
||||||
rule="addressObservation.description">
|
rule="addressObservation.description">
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
<vn-auto pad-medium-top>
|
<vn-none>
|
||||||
<vn-icon
|
<vn-icon-button
|
||||||
pointer
|
|
||||||
medium-grey
|
medium-grey
|
||||||
|
margin-medium-v
|
||||||
vn-tooltip="Remove note"
|
vn-tooltip="Remove note"
|
||||||
icon="remove_circle_outline"
|
icon="remove_circle_outline"
|
||||||
ng-click="$ctrl.removeObservation($index)">
|
ng-click="$ctrl.removeObservation($index)"
|
||||||
</vn-icon>
|
tabindex="-1">
|
||||||
</vn-one>
|
</vn-icon-button>
|
||||||
|
</vn-none>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
</div>
|
</div>
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
|
|
|
@ -1,25 +1,30 @@
|
||||||
<mg-ajax path="/client/api/Clients/filter" options="vnIndexNonAuto"></mg-ajax>
|
<vn-crud-model
|
||||||
|
vn-id="model"
|
||||||
|
url="/item/api/Clients"
|
||||||
|
filter="::$ctrl.filter"
|
||||||
|
limit="4"
|
||||||
|
data="clients"
|
||||||
|
auto-load="false">
|
||||||
|
</vn-crud-model>
|
||||||
<div margin-medium>
|
<div margin-medium>
|
||||||
<div class="vn-list">
|
<div class="vn-list">
|
||||||
<vn-card>
|
<vn-card pad-medium-h>
|
||||||
<vn-horizontal>
|
<vn-searchbar
|
||||||
<vn-searchbar vn-one
|
panel="vn-client-search-panel"
|
||||||
index="index"
|
model="model"
|
||||||
on-search="$ctrl.search(index)"
|
expr-builder="$ctrl.exprBuilder(param, value)">
|
||||||
advanced="true"
|
|
||||||
popover="vn-client-search-panel"
|
|
||||||
ignore-keys = "['page', 'size', 'search']">
|
|
||||||
</vn-searchbar>
|
</vn-searchbar>
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
</vn-card>
|
||||||
<vn-card margin-medium-top>
|
<vn-card margin-medium-v>
|
||||||
<vn-item-client
|
<vn-item-client
|
||||||
ng-repeat="client in index.model.instances track by client.id"
|
ng-repeat="client in clients track by client.id"
|
||||||
client="client">
|
client="::client">
|
||||||
</vn-item-client>
|
</vn-item-client>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
<vn-paging index="index" total="index.model.count"></vn-paging>
|
<vn-pagination
|
||||||
<!-- <vn-auto-paging index="index" total="index.model.count" items="$ctrl.clients"></vn-auto-paging> -->
|
model="model"
|
||||||
|
scroll-selector="ui-view">
|
||||||
|
</vn-pagination>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a ui-sref="client.create" vn-bind="+" fixed-bottom-right>
|
<a ui-sref="client.create" vn-bind="+" fixed-bottom-right>
|
||||||
|
|
|
@ -2,23 +2,42 @@ import ngModule from '../module';
|
||||||
import './item-client';
|
import './item-client';
|
||||||
|
|
||||||
export default class Controller {
|
export default class Controller {
|
||||||
|
|
||||||
constructor($scope) {
|
constructor($scope) {
|
||||||
this.$scope = $scope;
|
this.$ = $scope;
|
||||||
this.clientSelected = null;
|
this.clientSelected = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
search(index) {
|
exprBuilder(param, value) {
|
||||||
index.accept();
|
switch (param) {
|
||||||
/* this.clients = [];
|
case 'search':
|
||||||
index.accept().then(res => {
|
return {
|
||||||
this.clients = res.instances;
|
or: [
|
||||||
}); */
|
{id: value},
|
||||||
|
{name: {regexp: value}}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
case 'phone':
|
||||||
|
return {
|
||||||
|
or: [
|
||||||
|
{phone: value},
|
||||||
|
{mobile: value}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
case 'name':
|
||||||
|
case 'socialName':
|
||||||
|
case 'city':
|
||||||
|
return {[param]: {regexp: value}};
|
||||||
|
case 'id':
|
||||||
|
case 'fi':
|
||||||
|
case 'postcode':
|
||||||
|
case 'email':
|
||||||
|
return {[param]: value};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
openSummary(client) {
|
openSummary(client) {
|
||||||
this.clientSelected = client;
|
this.clientSelected = client;
|
||||||
this.$scope.dialogSummaryClient.show();
|
this.$.dialogSummaryClient.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Controller.$inject = ['$scope'];
|
Controller.$inject = ['$scope'];
|
||||||
|
|
|
@ -3,3 +3,4 @@ Phone: Teléfono
|
||||||
Town/City: Ciudad
|
Town/City: Ciudad
|
||||||
Email: Correo electrónico
|
Email: Correo electrónico
|
||||||
Create client: Crear cliente
|
Create client: Crear cliente
|
||||||
|
View client: Ver cliente
|
|
@ -1,22 +1,22 @@
|
||||||
<div pad-large style="min-width: 30em">
|
<div pad-large style="min-width: 30em">
|
||||||
<form ng-submit="$ctrl.onSearch()">
|
<form ng-submit="$ctrl.onSearch()">
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-textfield vn-one label="Client id" model="$ctrl.filter.id" vn-focus></vn-textfield>
|
<vn-textfield vn-one label="Client id" model="filter.id" vn-focus></vn-textfield>
|
||||||
<vn-textfield vn-one label="Tax number" model="$ctrl.filter.fi"></vn-textfield>
|
<vn-textfield vn-one label="Tax number" model="filter.fi"></vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-textfield vn-one label="Name" model="$ctrl.filter.name"></vn-textfield>
|
<vn-textfield vn-one label="Name" model="filter.name"></vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-textfield vn-one label="Social name" model="$ctrl.filter.socialName"></vn-textfield>
|
<vn-textfield vn-one label="Social name" model="filter.socialName"></vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-textfield vn-one label="Town/City" model="$ctrl.filter.city"></vn-textfield>
|
<vn-textfield vn-one label="Town/City" model="filter.city"></vn-textfield>
|
||||||
<vn-textfield vn-one label="Postcode" model="$ctrl.filter.postcode"></vn-textfield>
|
<vn-textfield vn-one label="Postcode" model="filter.postcode"></vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-textfield vn-one label="Email" model="$ctrl.filter.email"></vn-textfield>
|
<vn-textfield vn-one label="Email" model="filter.email"></vn-textfield>
|
||||||
<vn-textfield vn-one label="Phone" model="$ctrl.filter.phone"></vn-textfield>
|
<vn-textfield vn-one label="Phone" model="filter.phone"></vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal margin-large-top>
|
<vn-horizontal margin-large-top>
|
||||||
<vn-submit label="Search"></vn-submit>
|
<vn-submit label="Search"></vn-submit>
|
||||||
|
|
|
@ -1,18 +1,7 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
|
import SearchPanel from 'core/src/components/searchbar/search-panel';
|
||||||
export default class Controller {
|
|
||||||
constructor() {
|
|
||||||
// onSubmit() is defined by @vnSearchbar
|
|
||||||
this.onSubmit = () => {};
|
|
||||||
}
|
|
||||||
|
|
||||||
onSearch() {
|
|
||||||
this.onSubmit(this.filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Controller.$inject = [];
|
|
||||||
|
|
||||||
ngModule.component('vnClientSearchPanel', {
|
ngModule.component('vnClientSearchPanel', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
controller: Controller
|
controller: SearchPanel
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,6 +3,7 @@ import './style.scss';
|
||||||
|
|
||||||
export default class IconButton {
|
export default class IconButton {
|
||||||
constructor($element) {
|
constructor($element) {
|
||||||
|
if ($element[0].getAttribute('tabindex') == null)
|
||||||
$element[0].tabIndex = 0;
|
$element[0].tabIndex = 0;
|
||||||
$element.on("keyup", event => this.onKeyDown(event, $element));
|
$element.on("keyup", event => this.onKeyDown(event, $element));
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,32 +2,16 @@
|
||||||
|
|
||||||
vn-icon-button {
|
vn-icon-button {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
text-align: center;
|
|
||||||
color: rgba($main-01, 0.7);
|
color: rgba($main-01, 0.7);
|
||||||
|
font-size: 18pt;
|
||||||
transition: color 200ms ease-in-out;
|
transition: color 200ms ease-in-out;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&.button {
|
& > vn-icon {
|
||||||
background-color: $main-01;
|
|
||||||
color: white;
|
|
||||||
width: 64px;
|
|
||||||
height: 36px;
|
|
||||||
box-shadow: rgba(0, 0, 0, 0.14) 0px 2px 2px 0px, rgba(0, 0, 0, 0.2) 0px 3px 1px -2px, rgba(0, 0, 0, 0.12) 0px 1px 5px 0px;
|
|
||||||
border-radius: 2px;
|
|
||||||
}
|
|
||||||
&.button:focus {
|
|
||||||
will-change: box-shadow;
|
|
||||||
box-shadow: 0 0 8px rgba(0,0,0,.18),0 8px 16px rgba(0,0,0,.36);
|
|
||||||
transition: box-shadow .2s cubic-bezier(.4,0,1,1),background-color .2s cubic-bezier(.4,0,.2,1),color .2s cubic-bezier(.4,0,.2,1);
|
|
||||||
}
|
|
||||||
&.button i {
|
|
||||||
margin-top: 6px;
|
|
||||||
}
|
|
||||||
& > i,
|
|
||||||
& > i.material-icons {
|
|
||||||
display: block;
|
display: block;
|
||||||
font-size: inherit;
|
font-size: inherit;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
&:not(.button):hover {
|
&:not(.button):hover {
|
||||||
color: $main-01;
|
color: $main-01;
|
||||||
|
|
|
@ -3,7 +3,6 @@ import './rest-model/crud-model';
|
||||||
import './rest-model/rest-model';
|
import './rest-model/rest-model';
|
||||||
import './watcher/watcher';
|
import './watcher/watcher';
|
||||||
import './textfield/textfield';
|
import './textfield/textfield';
|
||||||
import './paging/paging';
|
|
||||||
import './icon/icon';
|
import './icon/icon';
|
||||||
import './dialog/dialog';
|
import './dialog/dialog';
|
||||||
import './confirm/confirm';
|
import './confirm/confirm';
|
||||||
|
@ -34,4 +33,7 @@ import './switch/switch';
|
||||||
import './float-button/float-button';
|
import './float-button/float-button';
|
||||||
import './step-control/step-control';
|
import './step-control/step-control';
|
||||||
import './label-value/label-value';
|
import './label-value/label-value';
|
||||||
|
import './paging/paging';
|
||||||
import './auto-paging/auto-paging';
|
import './auto-paging/auto-paging';
|
||||||
|
import './pagination/pagination';
|
||||||
|
import './searchbar/searchbar';
|
||||||
|
|
|
@ -2,7 +2,7 @@ import ngModule from '../../module';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
|
|
||||||
ngModule.component('vnLabelValue', {
|
ngModule.component('vnLabelValue', {
|
||||||
template: require('../label-value/label-value.html'),
|
template: require('./label-value.html'),
|
||||||
replace: true,
|
replace: true,
|
||||||
transclude: true,
|
transclude: true,
|
||||||
bindings: {
|
bindings: {
|
||||||
|
|
|
@ -12,13 +12,17 @@ export default class ModelProxy {
|
||||||
|
|
||||||
set orgData(value) {
|
set orgData(value) {
|
||||||
this._orgData = value;
|
this._orgData = value;
|
||||||
this._data = [];
|
|
||||||
// this._data.splice(0, this._data.length);
|
// this._data.splice(0, this._data.length);
|
||||||
|
|
||||||
|
if (this.Row) {
|
||||||
|
this._data = [];
|
||||||
|
|
||||||
for (let i = 0; i < value.length; i++) {
|
for (let i = 0; i < value.length; i++) {
|
||||||
let row = new this.Row(value[i], i);
|
let row = new this.Row(value[i], i);
|
||||||
this._data.push(row);
|
this._data.push(row);
|
||||||
}
|
}
|
||||||
|
} else
|
||||||
|
this._data = value;
|
||||||
|
|
||||||
this.resetChanges();
|
this.resetChanges();
|
||||||
}
|
}
|
||||||
|
@ -112,6 +116,11 @@ export default class ModelProxy {
|
||||||
|
|
||||||
this.resetChanges();
|
this.resetChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dataChanged() {
|
||||||
|
if (this.onDataChange)
|
||||||
|
this.onDataChange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ngModule.component('vnModelProxy', {
|
ngModule.component('vnModelProxy', {
|
||||||
|
@ -120,6 +129,7 @@ ngModule.component('vnModelProxy', {
|
||||||
orgData: '<?',
|
orgData: '<?',
|
||||||
data: '=?',
|
data: '=?',
|
||||||
fields: '<?',
|
fields: '<?',
|
||||||
link: '<?'
|
link: '<?',
|
||||||
|
onDataChange: '&?'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<div
|
||||||
|
ng-if="$ctrl.model.moreRows">
|
||||||
|
<vn-icon-button
|
||||||
|
ng-if="!$ctrl.model.isLoading"
|
||||||
|
icon="more_horiz"
|
||||||
|
vn-tooltip="Load more"
|
||||||
|
ng-click="$ctrl.model.loadMore()">
|
||||||
|
</vn-icon-button>
|
||||||
|
<vn-spinner
|
||||||
|
ng-if="$ctrl.model.isLoading"
|
||||||
|
enable="$ctrl.model.isLoading">
|
||||||
|
</vn-spinner>
|
||||||
|
</div>
|
|
@ -0,0 +1,75 @@
|
||||||
|
import ngModule from '../../module';
|
||||||
|
import Component from '../../lib/component';
|
||||||
|
import './style.scss';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pagination component that automatically loads more rows when
|
||||||
|
* the user scrolls down an element.
|
||||||
|
*
|
||||||
|
* @property {CrudModel} model The model used for pagination
|
||||||
|
* @property {String} scrollSelector The the scrollable element selector
|
||||||
|
* @property {HTMLElement} scrollElement The scrollable element
|
||||||
|
* @property {Number} scrollOffset The distance, in pixels, until the end that activates the loading of the next rows
|
||||||
|
*/
|
||||||
|
class Pagination extends Component {
|
||||||
|
constructor($element, $scope) {
|
||||||
|
super($element, $scope);
|
||||||
|
this.scrollOffset = 20;
|
||||||
|
this.scrollHandler = e => this.onScroll(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
$onInit() {
|
||||||
|
if (!this._scrollElement)
|
||||||
|
this.scrollElement = document.body;
|
||||||
|
}
|
||||||
|
|
||||||
|
set scrollSelector(value) {
|
||||||
|
this._scrollSelector = value;
|
||||||
|
this.scrollElement = document.querySelector(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
get scrollSelector() {
|
||||||
|
return this._scrollSelector;
|
||||||
|
}
|
||||||
|
|
||||||
|
set scrollElement(value) {
|
||||||
|
if (this._scrollElement)
|
||||||
|
this._scrollElement.removeEventListener('scroll', this.scrollHandler);
|
||||||
|
|
||||||
|
this._scrollElement = value;
|
||||||
|
|
||||||
|
if (value)
|
||||||
|
this._scrollElement.addEventListener('scroll', this.scrollHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
get scrollElement() {
|
||||||
|
return this._scrollElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
onScroll() {
|
||||||
|
let scrollElement = this.scrollElement;
|
||||||
|
let shouldLoad =
|
||||||
|
scrollElement.scrollTop + scrollElement.clientHeight >= (scrollElement.scrollHeight - this.scrollOffset)
|
||||||
|
&& !this.model.isLoading;
|
||||||
|
|
||||||
|
if (shouldLoad) {
|
||||||
|
this.model.loadMore();
|
||||||
|
this.$.$apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$onDestroy() {
|
||||||
|
this.scrollElement = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngModule.component('vnPagination', {
|
||||||
|
template: require('./pagination.html'),
|
||||||
|
bindings: {
|
||||||
|
model: '<',
|
||||||
|
scrollSelector: '@?',
|
||||||
|
scrollElement: '<?',
|
||||||
|
scrollOffset: '<?'
|
||||||
|
},
|
||||||
|
controller: Pagination
|
||||||
|
});
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
vn-pagination {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
& > div > vn-icon-button {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,32 +10,80 @@ export default class CrudModel extends ModelProxy {
|
||||||
this.autoLoad = true;
|
this.autoLoad = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get isLoading() {
|
||||||
|
return this.canceler != null;
|
||||||
|
}
|
||||||
|
|
||||||
$onInit() {
|
$onInit() {
|
||||||
if (this.autoLoad)
|
if (this.autoLoad)
|
||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
refresh() {
|
refresh(usFilter, usData) {
|
||||||
if (!this.url) return;
|
if (!this.url) return;
|
||||||
|
|
||||||
let filter = this.filter;
|
let myFilter = {
|
||||||
|
|
||||||
if (!filter) {
|
|
||||||
let where = Object.assign({}, this.link, this.where);
|
|
||||||
filter = {
|
|
||||||
fields: this.fields,
|
fields: this.fields,
|
||||||
where: where,
|
where: mergeWhere(this.link, this.where),
|
||||||
include: this.include,
|
include: this.include,
|
||||||
order: this.order,
|
order: this.order,
|
||||||
limit: this.limit
|
limit: this.limit,
|
||||||
|
userData: this.userData
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let filter = this.filter;
|
||||||
|
filter = mergeFilters(myFilter, filter);
|
||||||
|
filter = mergeFilters(usFilter, filter);
|
||||||
|
return this.sendRequest(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
let urlFilter = encodeURIComponent(JSON.stringify(filter));
|
cancelRequest() {
|
||||||
|
if (this.canceler) {
|
||||||
|
this.canceler.resolve();
|
||||||
|
this.canceler = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return this.$http.get(`${this.url}?filter=${urlFilter}`).then(res => {
|
sendRequest(filter, append) {
|
||||||
this.orgData = res.data;
|
this.cancelRequest();
|
||||||
});
|
this.canceler = this.$q.defer();
|
||||||
|
let options = {timeout: this.canceler.promise};
|
||||||
|
let json = encodeURIComponent(JSON.stringify(filter));
|
||||||
|
return this.$http.get(`${this.url}?filter=${json}`, options).then(
|
||||||
|
json => this.onRemoteDone(json, filter, append),
|
||||||
|
json => this.onRemoteError(json)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
onRemoteDone(json, filter, append) {
|
||||||
|
let data = json.data;
|
||||||
|
|
||||||
|
if (append)
|
||||||
|
this.orgData = this.orgData.concat(data);
|
||||||
|
else
|
||||||
|
this.orgData = data;
|
||||||
|
|
||||||
|
this.currentFilter = filter;
|
||||||
|
this.moreRows = filter.limit && data.length == filter.limit;
|
||||||
|
this.onRequestEnd();
|
||||||
|
this.dataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
onRemoteError(err) {
|
||||||
|
this.onRequestEnd();
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
|
onRequestEnd() {
|
||||||
|
this.canceler = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadMore() {
|
||||||
|
if (this.moreRows) {
|
||||||
|
let filter = Object.assign({}, this.currentFilter);
|
||||||
|
filter.skip = (filter.skip || 0) + filter.limit;
|
||||||
|
this.sendRequest(filter, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getChanges() {
|
getChanges() {
|
||||||
|
@ -97,7 +145,87 @@ ngModule.component('vnCrudModel', {
|
||||||
order: '@?',
|
order: '@?',
|
||||||
limit: '<?',
|
limit: '<?',
|
||||||
filter: '<?',
|
filter: '<?',
|
||||||
|
userData: '<?',
|
||||||
primaryKey: '@?',
|
primaryKey: '@?',
|
||||||
autoLoad: '<?'
|
autoLoad: '<?'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Passes a loopback fields filter to an object.
|
||||||
|
*
|
||||||
|
* @param {Object} fields The fields object or array
|
||||||
|
* @return {Object} The fields as object
|
||||||
|
*/
|
||||||
|
function fieldsToObject(fields) {
|
||||||
|
let fieldsObj = {};
|
||||||
|
|
||||||
|
if (Array.isArray(fields))
|
||||||
|
for (let field of fields)
|
||||||
|
fieldsObj[field] = true;
|
||||||
|
else if (typeof fields == 'object')
|
||||||
|
for (let field in fields)
|
||||||
|
if (fields[field])
|
||||||
|
fieldsObj[field] = true;
|
||||||
|
|
||||||
|
return fieldsObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merges two loopback fields filters.
|
||||||
|
*
|
||||||
|
* @param {Object|Array} src The source fields
|
||||||
|
* @param {Object|Array} dst The destination fields
|
||||||
|
* @return {Array} The merged fields as an array
|
||||||
|
*/
|
||||||
|
function mergeFields(src, dst) {
|
||||||
|
let fields = {};
|
||||||
|
Object.assign(fields,
|
||||||
|
fieldsToObject(src),
|
||||||
|
fieldsToObject(dst)
|
||||||
|
);
|
||||||
|
return Object.keys(fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merges two loopback where filters.
|
||||||
|
*
|
||||||
|
* @param {Object|Array} src The source where
|
||||||
|
* @param {Object|Array} dst The destination where
|
||||||
|
* @return {Array} The merged wheres
|
||||||
|
*/
|
||||||
|
function mergeWhere(src, dst) {
|
||||||
|
let and = [];
|
||||||
|
if (src) and.push(src);
|
||||||
|
if (dst) and.push(dst);
|
||||||
|
return and.length > 1 ? {and} : and[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Merges two loopback filters returning the merged filter.
|
||||||
|
*
|
||||||
|
* @param {Object} src The source filter
|
||||||
|
* @param {Object} dst The destination filter
|
||||||
|
* @return {Object} The result filter
|
||||||
|
*/
|
||||||
|
function mergeFilters(src, dst) {
|
||||||
|
let res = Object.assign({}, dst);
|
||||||
|
|
||||||
|
if (!src)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
if (src.fields)
|
||||||
|
res.fields = mergeFields(src.fields, res.fields);
|
||||||
|
if (src.where)
|
||||||
|
res.where = mergeWhere(res.where, src.where);
|
||||||
|
if (src.include)
|
||||||
|
res.include = src.include;
|
||||||
|
if (src.order)
|
||||||
|
res.order = src.order;
|
||||||
|
if (src.limit)
|
||||||
|
res.limit = src.limit;
|
||||||
|
if (src.userData)
|
||||||
|
res.userData = src.userData;
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
import Component from '../../lib/component';
|
||||||
|
|
||||||
|
export default class extends Component {
|
||||||
|
set filter(value) {
|
||||||
|
this.$.filter = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get filter() {
|
||||||
|
return this.$.filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
onSearch() {
|
||||||
|
if (!this.onSubmit)
|
||||||
|
throw new Error('SearchPanel::onSubmit() method not defined');
|
||||||
|
|
||||||
|
this.onSubmit(this.filter);
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,11 +5,11 @@
|
||||||
ng-click="$ctrl.clearFilter(); $ctrl.onSubmit()"
|
ng-click="$ctrl.clearFilter(); $ctrl.onSubmit()"
|
||||||
style="cursor: pointer; padding-top: 23px">
|
style="cursor: pointer; padding-top: 23px">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
<vn-textfield vn-one label="Search" model="$ctrl.stringSearch"></vn-textfield>
|
<vn-textfield vn-one label="Search" model="$ctrl.searchString"></vn-textfield>
|
||||||
<vn-icon
|
<vn-icon
|
||||||
pad-medium-top
|
pad-medium-top
|
||||||
ng-if="$ctrl.advanced"
|
ng-if="$ctrl.panel"
|
||||||
ng-click="$ctrl.onpenFilters($event)"
|
ng-click="$ctrl.openPanel($event)"
|
||||||
icon="keyboard_arrow_down"
|
icon="keyboard_arrow_down"
|
||||||
style="cursor: pointer; color: #aaa">
|
style="cursor: pointer; color: #aaa">
|
||||||
</vn-icon>
|
</vn-icon>
|
|
@ -0,0 +1,200 @@
|
||||||
|
import ngModule from '../../module';
|
||||||
|
import Component from '../../lib/component';
|
||||||
|
import './style.scss';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An input specialized to perform searches, it allows to use a panel
|
||||||
|
* for advanced searches when the panel property is defined.
|
||||||
|
* When model and exprBuilder properties are used, the model is updated
|
||||||
|
* automatically with an and-filter exprexion in which each operand is built
|
||||||
|
* by calling the exprBuilder function for each non-null parameter.
|
||||||
|
*
|
||||||
|
* @property {Object} filter A key-value object with filter parameters
|
||||||
|
* @property {Function} onSearch Function to call when search is submited
|
||||||
|
* @property {SearchPanel} panel The panel used for advanced searches
|
||||||
|
* @property {CrudModel} model The model used for searching
|
||||||
|
* @property {Function} exprBuilder If defined, is used to build each non-null param expresion
|
||||||
|
*/
|
||||||
|
export default class Controller extends Component {
|
||||||
|
constructor($element, $scope, $compile, $state, $transitions) {
|
||||||
|
super($element, $scope);
|
||||||
|
this.$compile = $compile;
|
||||||
|
this.$state = $state;
|
||||||
|
this.deregisterCallback = $transitions.onStart({},
|
||||||
|
transition => this.changeState(transition));
|
||||||
|
|
||||||
|
this.filter = {};
|
||||||
|
this.searchString = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$onInit() {
|
||||||
|
if (this.$state.params.q)
|
||||||
|
this.filter = JSON.parse(decodeURIComponent(this.$state.params.q));
|
||||||
|
|
||||||
|
this.refreshString();
|
||||||
|
this.doSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
changeState(transition) {
|
||||||
|
return transition._targetState._identifier.name !== this.$state.current.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
openPanel(event) {
|
||||||
|
if (event.defaultPrevented) return;
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
this.$panel = this.$compile(`<${this.panel}/>`)(this.$.$new());
|
||||||
|
let panel = this.$panel.isolateScope().$ctrl;
|
||||||
|
panel.filter = this.filter;
|
||||||
|
panel.onSubmit = filter => this.onPanelSubmit(filter);
|
||||||
|
|
||||||
|
this.$.popover.parent = this.element;
|
||||||
|
this.$.popover.child = this.$panel[0];
|
||||||
|
this.$.popover.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
onPopoverClose() {
|
||||||
|
this.$panel.scope().$destroy();
|
||||||
|
this.$panel.remove();
|
||||||
|
this.$panel = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
onPanelSubmit(filter) {
|
||||||
|
this.$.popover.hide();
|
||||||
|
|
||||||
|
for (let param in filter)
|
||||||
|
if (filter[param] == null)
|
||||||
|
delete filter[param];
|
||||||
|
|
||||||
|
this.filter = filter;
|
||||||
|
this.refreshString();
|
||||||
|
this.doSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshString() {
|
||||||
|
this.searchString = this.getStringFromObject(this.filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit() {
|
||||||
|
this.filter = this.getObjectFromString(this.searchString);
|
||||||
|
this.doSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
doSearch() {
|
||||||
|
this.pushFilterToState(this.filter);
|
||||||
|
|
||||||
|
if (this.onSearch)
|
||||||
|
this.onSearch({filter: this.filter});
|
||||||
|
|
||||||
|
if (this.model) {
|
||||||
|
if (!this.exprBuilder)
|
||||||
|
throw new Error('exprBuilder property should be defined when model is assigned');
|
||||||
|
|
||||||
|
let and = [];
|
||||||
|
|
||||||
|
for (let param in this.filter) {
|
||||||
|
let value = this.filter[param];
|
||||||
|
if (value == null) continue;
|
||||||
|
let expr = this.exprBuilder({param, value});
|
||||||
|
if (expr) and.push(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
let lbFilter = and.length > 0 ? {where: {and}} : null;
|
||||||
|
this.model.refresh(lbFilter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pushFilterToState(filter) {
|
||||||
|
let history = window.history || {pushState: () => {
|
||||||
|
console.error('Error in history.pushState(): Browser incompatibility error');
|
||||||
|
}};
|
||||||
|
let aux = window.location.hash.split('?q=');
|
||||||
|
if (Object.keys(filter).length)
|
||||||
|
history.pushState({}, null, `${aux[0]}?q=${encodeURIComponent(JSON.stringify(filter))}`);
|
||||||
|
else
|
||||||
|
history.pushState({}, null, aux[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds pattern key:value or key:(extra value) and passes it to object.
|
||||||
|
*
|
||||||
|
* @param {String} searchString The search string
|
||||||
|
* @return {Object} The parsed object
|
||||||
|
*/
|
||||||
|
getObjectFromString(searchString) {
|
||||||
|
let result = {};
|
||||||
|
if (searchString) {
|
||||||
|
let regex = /((([\w_]+):([\w_]+))|([\w_]+):\(([\w_ ]+)\))/gi;
|
||||||
|
let findPattern = searchString.match(regex);
|
||||||
|
let remnantString = searchString.replace(regex, '').trim();
|
||||||
|
if (findPattern) {
|
||||||
|
for (let i = 0; i < findPattern.length; i++) {
|
||||||
|
let aux = findPattern[i].split(':');
|
||||||
|
let property = aux[0];
|
||||||
|
let value = aux[1].replace(/\(|\)/g, '');
|
||||||
|
result[property] = value.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (remnantString)
|
||||||
|
result.search = remnantString;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Passes an object to pattern key:value or key:(extra value).
|
||||||
|
*
|
||||||
|
* @param {Object} searchObject The search object
|
||||||
|
* @return {String} The passed string
|
||||||
|
*/
|
||||||
|
getStringFromObject(searchObject) {
|
||||||
|
let search = [];
|
||||||
|
|
||||||
|
if (searchObject) {
|
||||||
|
let keys = Object.keys(searchObject);
|
||||||
|
keys.forEach(key => {
|
||||||
|
if (key == 'search') return;
|
||||||
|
|
||||||
|
let value = searchObject[key];
|
||||||
|
let valueString;
|
||||||
|
|
||||||
|
if (typeof value === 'string' && value.indexOf(' ') !== -1)
|
||||||
|
valueString = `(${value})`;
|
||||||
|
else if (value instanceof Date)
|
||||||
|
valueString = value.toJSON();
|
||||||
|
else
|
||||||
|
switch (typeof value) {
|
||||||
|
case 'number':
|
||||||
|
case 'string':
|
||||||
|
case 'boolean':
|
||||||
|
valueString = `${value}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valueString)
|
||||||
|
search.push(`${key}:${valueString}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (searchObject.search)
|
||||||
|
search.unshift(searchObject.search);
|
||||||
|
}
|
||||||
|
|
||||||
|
return search.length ? search.join(' ') : '';
|
||||||
|
}
|
||||||
|
|
||||||
|
$onDestroy() {
|
||||||
|
this.deregisterCallback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Controller.$inject = ['$element', '$scope', '$compile', '$state', '$transitions'];
|
||||||
|
|
||||||
|
ngModule.component('vnSearchbar', {
|
||||||
|
template: require('./searchbar.html'),
|
||||||
|
bindings: {
|
||||||
|
filter: '<?',
|
||||||
|
onSearch: '&',
|
||||||
|
panel: '@',
|
||||||
|
model: '<?',
|
||||||
|
exprBuilder: '&?'
|
||||||
|
},
|
||||||
|
controller: Controller
|
||||||
|
});
|
|
@ -1,7 +1,6 @@
|
||||||
vn-searchbar {
|
vn-searchbar {
|
||||||
padding-top: 6px;
|
padding-top: 6px;
|
||||||
padding-left: 16px;
|
display: block;
|
||||||
padding-right: 16px;
|
|
||||||
|
|
||||||
& > form > vn-horizontal > vn-icon-button {
|
& > form > vn-horizontal > vn-icon-button {
|
||||||
color: black;
|
color: black;
|
|
@ -11,4 +11,5 @@ Hide: Hide
|
||||||
Next: Next
|
Next: Next
|
||||||
Finalize: Finalize
|
Finalize: Finalize
|
||||||
Previous: Back
|
Previous: Back
|
||||||
|
Load more: Load more
|
||||||
Auto-scroll interrupted, please adjust the search: Auto-scroll interrupted, please adjust the search
|
Auto-scroll interrupted, please adjust the search: Auto-scroll interrupted, please adjust the search
|
|
@ -11,4 +11,5 @@ Hide: Ocultar
|
||||||
Next: Siguiente
|
Next: Siguiente
|
||||||
Finalize: Finalizar
|
Finalize: Finalizar
|
||||||
Previous: Anterior
|
Previous: Anterior
|
||||||
|
Load more: Cargar más
|
||||||
Auto-scroll interrupted, please adjust the search: Auto-scroll interrumpido, por favor ajusta la búsqueda
|
Auto-scroll interrupted, please adjust the search: Auto-scroll interrumpido, por favor ajusta la búsqueda
|
|
@ -1,77 +0,0 @@
|
||||||
<div pad-large style="min-width: 30em">
|
|
||||||
<form ng-submit="$ctrl.onSearch()">
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Id"
|
|
||||||
model="$ctrl.filter.id"
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Name"
|
|
||||||
model="$ctrl.filter.name"
|
|
||||||
vn-focus>
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Description"
|
|
||||||
model="$ctrl.filter.description">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
url="/item/api/ItemTypes"
|
|
||||||
label="Type"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
field="$ctrl.filter.typeFk">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
url="/item/api/Producers"
|
|
||||||
label="Producer"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
field="$ctrl.filter.producerFk">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
url="/item/api/Origins"
|
|
||||||
label="Origin"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
field="$ctrl.filter.originFk">
|
|
||||||
</vn-autocomplete>
|
|
||||||
<vn-autocomplete
|
|
||||||
vn-one
|
|
||||||
url="/item/api/Inks"
|
|
||||||
label="Ink"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
field="$ctrl.filter.inkFk">
|
|
||||||
</vn-autocomplete>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Category"
|
|
||||||
model="$ctrl.filter.category">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="Size"
|
|
||||||
type="number"
|
|
||||||
model="$ctrl.filter.itemSize">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal margin-large-top>
|
|
||||||
<vn-submit label="Search"></vn-submit>
|
|
||||||
</vn-horizontal>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
|
@ -1,16 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
|
|
||||||
class Controller {
|
|
||||||
constructor() {
|
|
||||||
this.onSubmit = () => {};
|
|
||||||
}
|
|
||||||
|
|
||||||
onSearch() {
|
|
||||||
this.onSubmit(this.filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnItemFilterPanel', {
|
|
||||||
template: require('./index.html'),
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -1,26 +1,30 @@
|
||||||
<mg-ajax path="/item/api/Items/filter" options="vnIndexNonAuto"></mg-ajax>
|
<vn-crud-model
|
||||||
|
vn-id="model"
|
||||||
|
url="/item/api/Items"
|
||||||
|
filter="::$ctrl.filter"
|
||||||
|
limit="4"
|
||||||
|
data="items"
|
||||||
|
auto-load="false">
|
||||||
|
</vn-crud-model>
|
||||||
<div margin-medium>
|
<div margin-medium>
|
||||||
<div class="vn-list">
|
<div class="vn-list">
|
||||||
<vn-card>
|
<vn-card pad-medium-h>
|
||||||
<vn-horizontal>
|
|
||||||
<vn-searchbar
|
<vn-searchbar
|
||||||
vn-one
|
panel="vn-item-search-panel"
|
||||||
index="index"
|
model="model"
|
||||||
on-search="$ctrl.search(index)"
|
expr-builder="$ctrl.exprBuilder(param, value)">
|
||||||
advanced="true"
|
|
||||||
popover="vn-item-filter-panel"
|
|
||||||
ignore-keys = "['page', 'size', 'search']">
|
|
||||||
</vn-searchbar>
|
</vn-searchbar>
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
</vn-card>
|
||||||
<vn-card margin-medium-top>
|
<vn-card margin-medium-v>
|
||||||
<vn-item-product
|
<vn-item-product
|
||||||
ng-repeat="item in index.model.instances track by item.id"
|
ng-repeat="item in items track by item.id"
|
||||||
item="item">
|
item="::item">
|
||||||
</vn-item-product>
|
</vn-item-product>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
<vn-paging index="index" total="index.model.count"></vn-paging>
|
<vn-pagination
|
||||||
<!-- <vn-auto-paging index="index" total="index.model.count" items="$ctrl.items"></vn-auto-paging> -->
|
model="model"
|
||||||
|
scroll-selector="ui-view">
|
||||||
|
</vn-pagination>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a ui-sref="item.create" vn-bind="+" fixed-bottom-right>
|
<a ui-sref="item.create" vn-bind="+" fixed-bottom-right>
|
||||||
|
|
|
@ -3,46 +3,68 @@ import './product';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
|
|
||||||
class Controller {
|
class Controller {
|
||||||
|
|
||||||
constructor($http, $state, $scope) {
|
constructor($http, $state, $scope) {
|
||||||
this.$http = $http;
|
this.$http = $http;
|
||||||
this.$state = $state;
|
this.$state = $state;
|
||||||
this.$scope = $scope;
|
this.$ = $scope;
|
||||||
this.model = {};
|
|
||||||
this.itemSelected = null;
|
this.itemSelected = null;
|
||||||
this.items = [];
|
|
||||||
|
this.filter = {
|
||||||
|
include: [
|
||||||
|
{relation: 'itemType',
|
||||||
|
scope: {
|
||||||
|
fields: ['name', 'workerFk'],
|
||||||
|
include: {
|
||||||
|
relation: 'worker',
|
||||||
|
fields: ['firstName', 'name']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
order: 'name ASC'
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
search(index) {
|
exprBuilder(param, value) {
|
||||||
index.accept();
|
switch (param) {
|
||||||
/* this.items = [];
|
case 'search':
|
||||||
index.accept().then(res => {
|
return {
|
||||||
this.items = res.instances;
|
or: [
|
||||||
}); */
|
{id: value},
|
||||||
|
{name: {regexp: value}}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
case 'name':
|
||||||
|
case 'description':
|
||||||
|
return {[param]: {regexp: value}};
|
||||||
|
case 'id':
|
||||||
|
case 'typeFk':
|
||||||
|
return {[param]: value};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cloneItem(item) {
|
cloneItem(item) {
|
||||||
this.itemSelected = item;
|
this.itemSelected = item;
|
||||||
this.$scope.clone.show();
|
this.$.clone.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
onCloneAccept(response) {
|
onCloneAccept(response) {
|
||||||
if (response == 'ACCEPT' && this.itemSelected) {
|
if (!(response == 'ACCEPT' && this.itemSelected))
|
||||||
|
return;
|
||||||
|
|
||||||
this.$http.post(`/item/api/Items/${this.itemSelected.id}/clone`).then(res => {
|
this.$http.post(`/item/api/Items/${this.itemSelected.id}/clone`).then(res => {
|
||||||
if (res && res.data && res.data.id) {
|
if (res && res.data && res.data.id)
|
||||||
this.$state.go('item.card.tags', {id: res.data.id});
|
this.$state.go('item.card.tags', {id: res.data.id});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
this.itemSelected = null;
|
this.itemSelected = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
showItemPreview(item) {
|
showItemPreview(item) {
|
||||||
this.itemSelected = item;
|
this.itemSelected = item;
|
||||||
this.$scope.preview.show();
|
this.$.preview.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$http', '$state', '$scope'];
|
Controller.$inject = ['$http', '$state', '$scope'];
|
||||||
|
|
||||||
ngModule.component('vnItemIndex', {
|
ngModule.component('vnItemIndex', {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
@import "./colors";
|
||||||
|
|
||||||
vn-item-product {
|
vn-item-product {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
|
@ -2,7 +2,7 @@ export * from './module';
|
||||||
|
|
||||||
import './index';
|
import './index';
|
||||||
import './filter-item-list';
|
import './filter-item-list';
|
||||||
import './filter-panel';
|
import './search-panel';
|
||||||
import './create';
|
import './create';
|
||||||
import './card';
|
import './card';
|
||||||
import './descriptor';
|
import './descriptor';
|
||||||
|
|
|
@ -43,3 +43,4 @@ Add barcode: Añadir código de barras
|
||||||
Remove barcode: Quitar código de barras
|
Remove barcode: Quitar código de barras
|
||||||
Buyer: Comprador
|
Buyer: Comprador
|
||||||
No results: Sin resultados
|
No results: Sin resultados
|
||||||
|
Tag: Etiqueta
|
|
@ -0,0 +1,84 @@
|
||||||
|
<mg-ajax path="/item/api/Tags" options="mgIndex as tags"></mg-ajax>
|
||||||
|
<div style="min-width: 30em; max-height: 540px; overflow: auto;">
|
||||||
|
<form pad-large ng-submit="$ctrl.onSearch()">
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-textfield
|
||||||
|
vn-one
|
||||||
|
label="Id"
|
||||||
|
model="filter.id"
|
||||||
|
vn-focus>
|
||||||
|
</vn-textfield>
|
||||||
|
<vn-textfield
|
||||||
|
vn-one
|
||||||
|
label="Name"
|
||||||
|
model="filter.name">
|
||||||
|
</vn-textfield>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-autocomplete
|
||||||
|
vn-one
|
||||||
|
vn-focus
|
||||||
|
url="/item/api/ItemTypes"
|
||||||
|
label="Type"
|
||||||
|
show-field="name"
|
||||||
|
value-field="id"
|
||||||
|
field="filter.typeFk">
|
||||||
|
</vn-autocomplete>
|
||||||
|
<vn-textfield
|
||||||
|
vn-one
|
||||||
|
label="Description"
|
||||||
|
model="filter.description">
|
||||||
|
</vn-textfield>
|
||||||
|
</vn-horizontal>
|
||||||
|
<!--
|
||||||
|
<vn-horizontal ng-repeat="itemTag in filter.tags">
|
||||||
|
<vn-autocomplete
|
||||||
|
vn-id="tag"
|
||||||
|
vn-one
|
||||||
|
field="itemTag.tagFk"
|
||||||
|
data="tags.model"
|
||||||
|
show-field="name"
|
||||||
|
label="Tag"
|
||||||
|
on-change="itemTag.value = null">
|
||||||
|
</vn-autocomplete>
|
||||||
|
<vn-textfield
|
||||||
|
vn-two
|
||||||
|
ng-show="tag.selection.isFree !== false"
|
||||||
|
vn-id="text"
|
||||||
|
label="Value"
|
||||||
|
model="itemTag.value">
|
||||||
|
</vn-textfield>
|
||||||
|
<vn-autocomplete
|
||||||
|
vn-two
|
||||||
|
ng-show="tag.selection.isFree === false"
|
||||||
|
url="{{$ctrl.getSourceTable(tag.selection)}}"
|
||||||
|
label="Value"
|
||||||
|
field="itemTag.value"
|
||||||
|
show-field="name"
|
||||||
|
value-field="name">
|
||||||
|
</vn-autocomplete>
|
||||||
|
<vn-none>
|
||||||
|
<vn-icon-button
|
||||||
|
medium-grey
|
||||||
|
margin-medium-v
|
||||||
|
vn-tooltip="Remove tag"
|
||||||
|
icon="remove_circle_outline"
|
||||||
|
ng-click="filter.tags.splice($index, 1)"
|
||||||
|
tabindex="-1">
|
||||||
|
</vn-icon-button>
|
||||||
|
</vn-none>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-icon-button
|
||||||
|
vn-bind="+"
|
||||||
|
vn-tooltip="Add tag"
|
||||||
|
icon="add_circle"
|
||||||
|
ng-click="filter.tags.push({})">
|
||||||
|
</vn-icon-button>
|
||||||
|
</vn-horizontal>
|
||||||
|
-->
|
||||||
|
<vn-horizontal margin-large-top>
|
||||||
|
<vn-submit label="Search"></vn-submit>
|
||||||
|
</vn-horizontal>
|
||||||
|
</form>
|
||||||
|
</div>
|
|
@ -0,0 +1,32 @@
|
||||||
|
import ngModule from '../module';
|
||||||
|
import SearchPanel from 'core/src/components/searchbar/search-panel';
|
||||||
|
|
||||||
|
class Controller extends SearchPanel {
|
||||||
|
set filter(value) {
|
||||||
|
if (!value.tags)
|
||||||
|
value.tags = [{}];
|
||||||
|
|
||||||
|
this.$.filter = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get filter() {
|
||||||
|
return this.$.filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSourceTable(selection) {
|
||||||
|
if (!selection || selection.isFree === true)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (selection.sourceTable)
|
||||||
|
return '/api/'
|
||||||
|
+ selection.sourceTable.charAt(0).toUpperCase()
|
||||||
|
+ selection.sourceTable.substring(1) + 's';
|
||||||
|
else if (selection.sourceTable == null)
|
||||||
|
return `/api/ItemTags/filterItemTags/${selection.id}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngModule.component('vnItemSearchPanel', {
|
||||||
|
template: require('./index.html'),
|
||||||
|
controller: Controller
|
||||||
|
});
|
|
@ -48,14 +48,16 @@
|
||||||
rule="itemTag.priority"
|
rule="itemTag.priority"
|
||||||
vn-acl="buyer">
|
vn-acl="buyer">
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
<vn-icon
|
<vn-none>
|
||||||
pad-medium-top
|
<vn-icon-button
|
||||||
pointer
|
|
||||||
medium-grey
|
medium-grey
|
||||||
|
margin-medium-v
|
||||||
vn-tooltip="Remove tag"
|
vn-tooltip="Remove tag"
|
||||||
icon="remove_circle_outline"
|
icon="remove_circle_outline"
|
||||||
ng-click="$ctrl.removeTag($index)">
|
ng-click="$ctrl.removeTag($index)"
|
||||||
</vn-icon>
|
tabindex="-1">
|
||||||
|
</vn-icon-button>
|
||||||
|
</vn-none>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-one>
|
<vn-one>
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
|
|
|
@ -4,4 +4,3 @@ import './main-menu/main-menu';
|
||||||
import './left-menu/left-menu';
|
import './left-menu/left-menu';
|
||||||
import './left-menu/menu-item';
|
import './left-menu/menu-item';
|
||||||
import './topbar/topbar';
|
import './topbar/topbar';
|
||||||
import './searchbar/searchbar';
|
|
||||||
|
|
|
@ -1,160 +0,0 @@
|
||||||
import ngModule from '../../module';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
export default class Controller {
|
|
||||||
constructor($element, $scope, $compile, $timeout, $state, $transitions) {
|
|
||||||
this.element = $element[0];
|
|
||||||
this.$ = $scope;
|
|
||||||
this.$compile = $compile;
|
|
||||||
this.$timeout = $timeout;
|
|
||||||
this.stringSearch = '';
|
|
||||||
this.$state = $state;
|
|
||||||
this.deregisterCallback = $transitions.onStart({},
|
|
||||||
transition => this.changeState(transition));
|
|
||||||
}
|
|
||||||
|
|
||||||
clearFilter() {
|
|
||||||
this.index.filter = {
|
|
||||||
page: 1,
|
|
||||||
size: 20
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
setFilter(filterObject) {
|
|
||||||
this.clearFilter();
|
|
||||||
Object.assign(this.index.filter, filterObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
getFiltersFromString(stringSearch) {
|
|
||||||
let result = {};
|
|
||||||
if (stringSearch) {
|
|
||||||
// find pattern key:value or key:(extra value) and returns array
|
|
||||||
let findPattern = stringSearch.match(/((([\w_]+):([\w_]+))|([\w_]+):\(([\w_ ]+)\))/gi);
|
|
||||||
let remnantString = (stringSearch.replace(/((([\w_]+):([\w_]+))|([\w_]+):\(([\w_ ]+)\))/gi, '')).trim();
|
|
||||||
if (findPattern) {
|
|
||||||
for (let i = 0; i < findPattern.length; i++) {
|
|
||||||
let aux = findPattern[i].split(':');
|
|
||||||
let property = aux[0];
|
|
||||||
let value = aux[1].replace(/\(|\)/g, '');
|
|
||||||
result[property] = value.trim();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (remnantString) {
|
|
||||||
result.search = remnantString;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
createStringFromObject(filterObject) {
|
|
||||||
let search = [];
|
|
||||||
let keys = Object.keys(filterObject);
|
|
||||||
if (keys.length) {
|
|
||||||
keys.forEach(k => {
|
|
||||||
let ignore = (this.ignoreKeys && this.ignoreKeys instanceof Array && this.ignoreKeys.indexOf(k) !== -1);
|
|
||||||
if (!ignore) {
|
|
||||||
let value = filterObject[k];
|
|
||||||
|
|
||||||
if (typeof value === 'string' && value.indexOf(' ') !== -1) {
|
|
||||||
search.push(`${k}:(${value})`);
|
|
||||||
} else if (typeof value !== 'object') {
|
|
||||||
search.push(`${k}:${value}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (filterObject.search)
|
|
||||||
search.unshift(filterObject.search);
|
|
||||||
}
|
|
||||||
return (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) {
|
|
||||||
let filter = {};
|
|
||||||
if (this.stringSearch) {
|
|
||||||
filter = this.getFiltersFromString(this.stringSearch);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.$child = this.$compile(`<${this.popover}/>`)(this.$.$new());
|
|
||||||
|
|
||||||
var childCtrl = this.$child.isolateScope().$ctrl;
|
|
||||||
childCtrl.filter = Object.assign({}, filter);
|
|
||||||
childCtrl.onSubmit = filter => this.onChildSubmit(filter);
|
|
||||||
if (this.data)
|
|
||||||
childCtrl.data = Object.assign({}, this.data);
|
|
||||||
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
this.$.popover.parent = this.element;
|
|
||||||
this.$.popover.child = this.$child[0];
|
|
||||||
this.$.popover.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
onPopoverClose() {
|
|
||||||
this.$child.scope().$destroy();
|
|
||||||
this.$child.remove();
|
|
||||||
this.$child = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
onChildSubmit(filter) {
|
|
||||||
this.$.popover.hide();
|
|
||||||
this.stringSearch = this.createStringFromObject(filter);
|
|
||||||
this.clearFilter();
|
|
||||||
this.$timeout(() => this.onSubmit());
|
|
||||||
}
|
|
||||||
|
|
||||||
onSubmit() {
|
|
||||||
let filter = {};
|
|
||||||
if (this.stringSearch) {
|
|
||||||
filter = this.getFiltersFromString(this.stringSearch);
|
|
||||||
}
|
|
||||||
this.setFilter(filter);
|
|
||||||
|
|
||||||
if (this.onSearch)
|
|
||||||
this.onSearch();
|
|
||||||
|
|
||||||
this.pushFiltersToState(filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
$onDestroy() {
|
|
||||||
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', '$compile', '$timeout', '$state', '$transitions'];
|
|
||||||
|
|
||||||
ngModule.component('vnSearchbar', {
|
|
||||||
template: require('./searchbar.html'),
|
|
||||||
bindings: {
|
|
||||||
index: '<',
|
|
||||||
onSearch: '&',
|
|
||||||
advanced: '=',
|
|
||||||
popover: '@',
|
|
||||||
ignoreKeys: '<?',
|
|
||||||
data: '<?'
|
|
||||||
},
|
|
||||||
controller: Controller
|
|
||||||
});
|
|
|
@ -64,7 +64,6 @@ html [vn-auto], vn-auto, .vn-auto {
|
||||||
flex-basis: auto;
|
flex-basis: auto;
|
||||||
}
|
}
|
||||||
html [vn-none], vn-none, .vn-none {
|
html [vn-none], vn-none, .vn-none {
|
||||||
flex: 1;
|
|
||||||
flex: none;
|
flex: none;
|
||||||
}
|
}
|
||||||
html [vn-one], vn-one, .vn-one {
|
html [vn-one], vn-one, .vn-one {
|
||||||
|
|
|
@ -1,55 +1,54 @@
|
||||||
<mg-ajax path="/ticket/api/Tickets/filter" options="vnIndexNonAuto"></mg-ajax>
|
<vn-crud-model
|
||||||
<div margin-large>
|
vn-id="model"
|
||||||
<div>
|
url="/ticket/api/Tickets"
|
||||||
<vn-card pad-medium>
|
filter="::$ctrl.filter"
|
||||||
<vn-title>TICKETS</vn-title>
|
limit="10"
|
||||||
<vn-horizontal class="vn-list">
|
data="tickets"
|
||||||
<vn-searchbar vn-one
|
auto-load="false">
|
||||||
index="index"
|
</vn-crud-model>
|
||||||
on-search="$ctrl.search(index)"
|
<div margin-medium>
|
||||||
ignore-keys = "['page', 'size', 'search']">
|
<div class="vn-list">
|
||||||
|
<vn-card pad-medium-h>
|
||||||
|
<vn-searchbar
|
||||||
|
panel="vn-ticket-search-panel"
|
||||||
|
model="model"
|
||||||
|
expr-builder="$ctrl.exprBuilder(param, value)">
|
||||||
</vn-searchbar>
|
</vn-searchbar>
|
||||||
</vn-horizontal>
|
</vn-card>
|
||||||
<vn-horizontal>
|
</div>
|
||||||
|
<vn-card margin-medium-v pad-medium>
|
||||||
<table class="vn-grid">
|
<table class="vn-grid">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th></th>
|
<th translate number>Id</th>
|
||||||
<th number translate>ID Ticket</th>
|
<th translate>Salesperson</th>
|
||||||
<th translate>Comercial</th>
|
|
||||||
<th translate>Date</th>
|
<th translate>Date</th>
|
||||||
<th translate>Hora</th>
|
<th translate>Hour</th>
|
||||||
<th translate>Alias</th>
|
<th translate>Alias</th>
|
||||||
<th translate>Provincia</th>
|
<th translate>Province</th>
|
||||||
<th translate>Estado</th>
|
<th translate>State</th>
|
||||||
<th translate>Agencia</th>
|
<th translate>Agency</th>
|
||||||
<th translate>Almacen</th>
|
<th translate>Warehouse</th>
|
||||||
<th number translate>Factura</th>
|
<th translate number>Invoice</th>
|
||||||
<th number translate>Ruta</th>
|
<th translate number>Route</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="ticket in index.model.instances track by ticket.id"
|
<tr ng-repeat="ticket in tickets"
|
||||||
class="{{::$ctrl.compareDate(ticket.shipped)}} clickable"
|
class="{{::$ctrl.compareDate(ticket.shipped)}} clickable"
|
||||||
ui-sref="ticket.card.summary({id: {{::ticket.id}}})">
|
ui-sref="ticket.card.summary({id: {{::ticket.id}}})">
|
||||||
<td>
|
|
||||||
<!-- <i pointer
|
|
||||||
class="material-icons"
|
|
||||||
vn-tooltip="delete expedition"
|
|
||||||
ng-click="$ctrl.deleteExpedition(expedition)">warning</i> -->
|
|
||||||
</td>
|
|
||||||
<th number>{{::ticket.id}}</th>
|
<th number>{{::ticket.id}}</th>
|
||||||
<td translate>{{::ticket.client.salesPerson.name | dashIfEmpty}}</td>
|
<td >{{::ticket.client.salesPerson.name | dashIfEmpty}}</td>
|
||||||
<td translate>{{::ticket.shipped | date:'dd/MM/yyyy'}}</td>
|
<td >{{::ticket.shipped | date:'dd/MM/yyyy'}}</td>
|
||||||
<td translate>{{::ticket.shipped | date:'HH:MM'}}</td>
|
<td >{{::ticket.shipped | date:'HH:MM'}}</td>
|
||||||
<td translate>{{::ticket.nickname}}</td>
|
<td >{{::ticket.nickname}}</td>
|
||||||
<td translate>{{::ticket.address.province.name}}</td>
|
<td >{{::ticket.address.province.name}}</td>
|
||||||
<td translate>{{::ticket.tracking.state.name}}</td>
|
<td >{{::ticket.tracking.state.name}}</td>
|
||||||
<td translate>{{::ticket.agencyMode.name}}</td>
|
<td >{{::ticket.agencyMode.name}}</td>
|
||||||
<td translate>{{::ticket.warehouse.name}}</td>
|
<td >{{::ticket.warehouse.name}}</td>
|
||||||
<td number translate>{{::ticket.refFk | dashIfEmpty}}</td>
|
<td number >{{::ticket.refFk | dashIfEmpty}}</td>
|
||||||
<td number translate>{{::ticket.routeFk | dashIfEmpty}}</td>
|
<td number >{{::ticket.routeFk | dashIfEmpty}}</td>
|
||||||
<td>
|
<td>
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
ng-click="$ctrl.preview($event, ticket)"
|
ng-click="$ctrl.preview($event, ticket)"
|
||||||
|
@ -60,11 +59,11 @@
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</vn-horizontal>
|
|
||||||
</vn-card>
|
</vn-card>
|
||||||
<vn-paging vn-one index="index" total="index.model.count"></vn-paging>
|
<vn-pagination
|
||||||
<!-- <vn-auto-paging vn-one index="index" total="index.model.count" items="$ctrl.tickets"></vn-auto-paging> -->
|
model="model"
|
||||||
</div>
|
scroll-selector="ui-view">
|
||||||
|
</vn-pagination>
|
||||||
</div>
|
</div>
|
||||||
<a ui-sref="ticket.create" vn-bind="+" fixed-bottom-right>
|
<a ui-sref="ticket.create" vn-bind="+" fixed-bottom-right>
|
||||||
<vn-float-button icon="add"></vn-float-button>
|
<vn-float-button icon="add"></vn-float-button>
|
||||||
|
|
|
@ -1,11 +1,82 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
import './ticket-item';
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
export default class Controller {
|
export default class Controller {
|
||||||
constructor($scope) {
|
constructor($scope) {
|
||||||
this.$scope = $scope;
|
this.$ = $scope;
|
||||||
this.ticketSelected = null;
|
this.ticketSelected = null;
|
||||||
|
|
||||||
|
this.filter = {
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
relation: 'address',
|
||||||
|
scope: {
|
||||||
|
fields: ['provinceFk'],
|
||||||
|
include: {
|
||||||
|
relation: 'province',
|
||||||
|
scope: {
|
||||||
|
fields: ['name']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
relation: 'warehouse',
|
||||||
|
scope: {
|
||||||
|
fields: ['name']
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
relation: 'agencyMode',
|
||||||
|
scope: {
|
||||||
|
fields: ['name']
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
relation: 'tracking',
|
||||||
|
scope: {
|
||||||
|
fields: ['stateFk'],
|
||||||
|
include: {
|
||||||
|
relation: 'state',
|
||||||
|
scope: {
|
||||||
|
fields: ['name']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
relation: 'client',
|
||||||
|
scope: {
|
||||||
|
fields: ['salesPersonFk'],
|
||||||
|
include: {
|
||||||
|
relation: 'salesPerson',
|
||||||
|
scope: {
|
||||||
|
fields: ['name']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
order: 'shipped DESC'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
exprBuilder(param, value) {
|
||||||
|
switch (param) {
|
||||||
|
case 'search':
|
||||||
|
return {
|
||||||
|
or: [
|
||||||
|
{id: value},
|
||||||
|
{nickname: {regexp: value}}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
case 'from':
|
||||||
|
return {shipped: {gte: value}};
|
||||||
|
case 'to':
|
||||||
|
return {shipped: {lte: value}};
|
||||||
|
case 'nickname':
|
||||||
|
return {[param]: {regexp: value}};
|
||||||
|
case 'id':
|
||||||
|
case 'clientFk':
|
||||||
|
case 'agencyModeFk':
|
||||||
|
case 'warehouseFk':
|
||||||
|
return {[param]: value};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compareDate(date) {
|
compareDate(date) {
|
||||||
|
@ -26,17 +97,9 @@ export default class Controller {
|
||||||
preview(event, ticket) {
|
preview(event, ticket) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopImmediatePropagation();
|
event.stopImmediatePropagation();
|
||||||
this.$scope.dialogSummaryTicket.show();
|
this.$.dialogSummaryTicket.show();
|
||||||
this.ticketSelected = ticket;
|
this.ticketSelected = ticket;
|
||||||
}
|
}
|
||||||
|
|
||||||
search(index) {
|
|
||||||
index.accept();
|
|
||||||
/* this.tickets = [];
|
|
||||||
index.accept().then(res => {
|
|
||||||
this.tickets = res.instances;
|
|
||||||
}); */
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$scope'];
|
Controller.$inject = ['$scope'];
|
||||||
|
|
|
@ -34,14 +34,14 @@ describe('ticket', () => {
|
||||||
it('should call preventDefault and stopImmediatePropagation from event and show', () => {
|
it('should call preventDefault and stopImmediatePropagation from event and show', () => {
|
||||||
let event = jasmine.createSpyObj('event', ['preventDefault', 'stopImmediatePropagation']);
|
let event = jasmine.createSpyObj('event', ['preventDefault', 'stopImmediatePropagation']);
|
||||||
|
|
||||||
controller.$scope = {dialogSummaryTicket: {show: () => {}}};
|
controller.$ = {dialogSummaryTicket: {show: () => {}}};
|
||||||
spyOn(controller.$scope.dialogSummaryTicket, 'show');
|
spyOn(controller.$.dialogSummaryTicket, 'show');
|
||||||
let ticket = {};
|
let ticket = {};
|
||||||
controller.preview(event, ticket);
|
controller.preview(event, ticket);
|
||||||
|
|
||||||
expect(event.preventDefault).toHaveBeenCalledWith();
|
expect(event.preventDefault).toHaveBeenCalledWith();
|
||||||
expect(event.stopImmediatePropagation).toHaveBeenCalledWith();
|
expect(event.stopImmediatePropagation).toHaveBeenCalledWith();
|
||||||
expect(controller.$scope.dialogSummaryTicket.show).toHaveBeenCalledWith();
|
expect(controller.$.dialogSummaryTicket.show).toHaveBeenCalledWith();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -1,3 +0,0 @@
|
||||||
vn-ticket-item {
|
|
||||||
display: block;
|
|
||||||
}
|
|
|
@ -1,20 +0,0 @@
|
||||||
<a
|
|
||||||
ui-sref="ticket.card.summary({ id: {{::$ctrl.ticket.id}} })"
|
|
||||||
translate-attr="{title: 'View ticket'}"
|
|
||||||
class="vn-list-item">
|
|
||||||
<vn-horizontal ng-click="$ctrl.onClick($event)">
|
|
||||||
<vn-one>
|
|
||||||
<h6>{{::$ctrl.ticket.nickname}}</h6>
|
|
||||||
<vn-label-value label="Id"
|
|
||||||
value="{{::$ctrl.ticket.id}}">
|
|
||||||
</vn-label-value>
|
|
||||||
</vn-one>
|
|
||||||
<vn-horizontal class="buttons">
|
|
||||||
<vn-icon
|
|
||||||
ng-click="$ctrl.preview($event)"
|
|
||||||
vn-tooltip="Preview"
|
|
||||||
icon="desktop_windows">
|
|
||||||
</vn-icon>
|
|
||||||
</vn-horizontal>
|
|
||||||
</vn-horizontal>
|
|
||||||
</a>
|
|
|
@ -1,24 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
|
|
||||||
class Controller {
|
|
||||||
onClick(event) {
|
|
||||||
if (event.defaultPrevented)
|
|
||||||
event.stopImmediatePropagation();
|
|
||||||
}
|
|
||||||
|
|
||||||
preview(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
this.index.openSummary(this.ticket);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ngModule.component('vnTicketItem', {
|
|
||||||
controller: Controller,
|
|
||||||
template: require('./ticket-item.html'),
|
|
||||||
bindings: {
|
|
||||||
ticket: '<'
|
|
||||||
},
|
|
||||||
require: {
|
|
||||||
index: '^vnTicketIndex'
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
<div pad-large style="min-width: 30em">
|
||||||
|
<form ng-submit="$ctrl.onSearch()">
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-textfield
|
||||||
|
vn-one
|
||||||
|
label="Nickname"
|
||||||
|
model="filter.nickname"
|
||||||
|
vn-focus>
|
||||||
|
</vn-textfield>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-textfield
|
||||||
|
vn-one
|
||||||
|
label="Ticket id"
|
||||||
|
model="filter.id">
|
||||||
|
</vn-textfield>
|
||||||
|
<vn-textfield
|
||||||
|
vn-one
|
||||||
|
label="Client id"
|
||||||
|
model="filter.clientFk">
|
||||||
|
</vn-textfield>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-date-picker
|
||||||
|
vn-one
|
||||||
|
label="From"
|
||||||
|
model="filter.from">
|
||||||
|
</vn-date-picker>
|
||||||
|
<vn-date-picker
|
||||||
|
vn-one
|
||||||
|
label="To"
|
||||||
|
model="filter.to">
|
||||||
|
</vn-date-picker>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-autocomplete
|
||||||
|
vn-one
|
||||||
|
label="Agency"
|
||||||
|
field="filter.agencyModeFk"
|
||||||
|
url="/api/AgencyModes"
|
||||||
|
show-field="name"
|
||||||
|
value-field="id">
|
||||||
|
<tpl-item>{{name}}</tpl-item>
|
||||||
|
</vn-autocomplete>
|
||||||
|
<vn-autocomplete
|
||||||
|
vn-one
|
||||||
|
label="Warehouse"
|
||||||
|
field="filter.warehouseFk"
|
||||||
|
url="/api/Warehouses"
|
||||||
|
show-field="name"
|
||||||
|
value-field="id">
|
||||||
|
</vn-autocomplete>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal margin-large-top>
|
||||||
|
<vn-submit label="Search"></vn-submit>
|
||||||
|
</vn-horizontal>
|
||||||
|
</form>
|
||||||
|
</div>
|
|
@ -0,0 +1,7 @@
|
||||||
|
import ngModule from '../module';
|
||||||
|
import SearchPanel from 'core/src/components/searchbar/search-panel';
|
||||||
|
|
||||||
|
ngModule.component('vnTicketSearchPanel', {
|
||||||
|
template: require('./index.html'),
|
||||||
|
controller: SearchPanel
|
||||||
|
});
|
|
@ -0,0 +1,7 @@
|
||||||
|
Ticket id: Id ticket
|
||||||
|
Client id: Id cliente
|
||||||
|
Nickname: Alias
|
||||||
|
From: Desde
|
||||||
|
To: Hasta
|
||||||
|
Agency: Agencia
|
||||||
|
Warehouse: Almacén
|
|
@ -1,5 +1,6 @@
|
||||||
export * from './module';
|
export * from './module';
|
||||||
|
|
||||||
|
import './search-panel';
|
||||||
import './index';
|
import './index';
|
||||||
import './create';
|
import './create';
|
||||||
import './card';
|
import './card';
|
||||||
|
|
|
@ -192,7 +192,7 @@ export default {
|
||||||
itemTags: {
|
itemTags: {
|
||||||
goToItemIndexButton: 'vn-item-descriptor [ui-sref="item.index"]',
|
goToItemIndexButton: 'vn-item-descriptor [ui-sref="item.index"]',
|
||||||
tagsButton: `vn-menu-item a[ui-sref="item.card.tags"]`,
|
tagsButton: `vn-menu-item a[ui-sref="item.card.tags"]`,
|
||||||
firstRemoveTagButton: `vn-item-tags vn-horizontal:nth-child(2) > vn-icon[icon="remove_circle_outline"]`,
|
firstRemoveTagButton: `vn-item-tags vn-horizontal:nth-child(2) vn-icon-button[icon="remove_circle_outline"]`,
|
||||||
firstTagSelect: `vn-item-tags vn-horizontal:nth-child(2) > vn-autocomplete[field="itemTag.tagFk"] input`,
|
firstTagSelect: `vn-item-tags vn-horizontal:nth-child(2) > vn-autocomplete[field="itemTag.tagFk"] input`,
|
||||||
firstTagDisabled: `vn-item-tags vn-horizontal:nth-child(2) > vn-autocomplete > div > div > input`,
|
firstTagDisabled: `vn-item-tags vn-horizontal:nth-child(2) > vn-autocomplete > div > div > input`,
|
||||||
firstTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(2) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
firstTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(2) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
||||||
|
@ -218,7 +218,7 @@ export default {
|
||||||
fifthTagSelectOptionFive: `vn-item-tags vn-horizontal:nth-child(6) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(5)`,
|
fifthTagSelectOptionFive: `vn-item-tags vn-horizontal:nth-child(6) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(5)`,
|
||||||
fifthValueInput: `vn-item-tags vn-horizontal:nth-child(6) > vn-textfield[label="Value"] > div > input`,
|
fifthValueInput: `vn-item-tags vn-horizontal:nth-child(6) > vn-textfield[label="Value"] > div > input`,
|
||||||
fifthRelevancyInput: `vn-horizontal:nth-child(6) > vn-textfield[label="Relevancy"] > div > input`,
|
fifthRelevancyInput: `vn-horizontal:nth-child(6) > vn-textfield[label="Relevancy"] > div > input`,
|
||||||
addItemTagButton: `vn-icon[icon="add_circle"]`,
|
addItemTagButton: `vn-icon-button[icon="add_circle"]`,
|
||||||
submitItemTagsButton: `${components.vnSubmit}`
|
submitItemTagsButton: `${components.vnSubmit}`
|
||||||
},
|
},
|
||||||
itemTax: {
|
itemTax: {
|
||||||
|
|
|
@ -23,7 +23,7 @@ describe('Ticket', () => {
|
||||||
it('should search for the ticket with id 1', () => {
|
it('should search for the ticket with id 1', () => {
|
||||||
return nightmare
|
return nightmare
|
||||||
.wait(selectors.ticketsIndex.searchTicketInput)
|
.wait(selectors.ticketsIndex.searchTicketInput)
|
||||||
.type(selectors.ticketsIndex.searchTicketInput, '1')
|
.type(selectors.ticketsIndex.searchTicketInput, 'id:1')
|
||||||
.click(selectors.ticketsIndex.searchButton)
|
.click(selectors.ticketsIndex.searchButton)
|
||||||
.waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1)
|
.waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1)
|
||||||
.countSearchResults(selectors.ticketsIndex.searchResult)
|
.countSearchResults(selectors.ticketsIndex.searchResult)
|
||||||
|
|
|
@ -23,7 +23,7 @@ describe('Ticket', () => {
|
||||||
it('should search for the ticket with id 1', () => {
|
it('should search for the ticket with id 1', () => {
|
||||||
return nightmare
|
return nightmare
|
||||||
.wait(selectors.ticketsIndex.searchTicketInput)
|
.wait(selectors.ticketsIndex.searchTicketInput)
|
||||||
.type(selectors.ticketsIndex.searchTicketInput, '1')
|
.type(selectors.ticketsIndex.searchTicketInput, 'id:1')
|
||||||
.click(selectors.ticketsIndex.searchButton)
|
.click(selectors.ticketsIndex.searchButton)
|
||||||
.waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1)
|
.waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1)
|
||||||
.countSearchResults(selectors.ticketsIndex.searchResult)
|
.countSearchResults(selectors.ticketsIndex.searchResult)
|
||||||
|
|
|
@ -25,7 +25,7 @@ describe('Ticket', () => {
|
||||||
it('should search for the ticket 1', () => {
|
it('should search for the ticket 1', () => {
|
||||||
return nightmare
|
return nightmare
|
||||||
.wait(selectors.ticketsIndex.searchResult)
|
.wait(selectors.ticketsIndex.searchResult)
|
||||||
.type(selectors.ticketsIndex.searchTicketInput, 1)
|
.type(selectors.ticketsIndex.searchTicketInput, 'id:1')
|
||||||
.click(selectors.ticketsIndex.searchButton)
|
.click(selectors.ticketsIndex.searchButton)
|
||||||
.waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1)
|
.waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1)
|
||||||
.countSearchResults(selectors.ticketsIndex.searchResult)
|
.countSearchResults(selectors.ticketsIndex.searchResult)
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
// it('should search for the ticket 1', () => {
|
// it('should search for the ticket 1', () => {
|
||||||
// return nightmare
|
// return nightmare
|
||||||
// .wait(selectors.ticketsIndex.searchResult)
|
// .wait(selectors.ticketsIndex.searchResult)
|
||||||
// .type(selectors.ticketsIndex.searchTicketInput, 1)
|
// .type(selectors.ticketsIndex.searchTicketInput, 'id:1')
|
||||||
// .click(selectors.ticketsIndex.searchButton)
|
// .click(selectors.ticketsIndex.searchButton)
|
||||||
// .waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1)
|
// .waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1)
|
||||||
// .countSearchResults(selectors.ticketsIndex.searchResult)
|
// .countSearchResults(selectors.ticketsIndex.searchResult)
|
||||||
|
|
|
@ -25,7 +25,7 @@ describe('Ticket', () => {
|
||||||
it('should search for the ticket 1', () => {
|
it('should search for the ticket 1', () => {
|
||||||
return nightmare
|
return nightmare
|
||||||
.wait(selectors.ticketsIndex.searchResult)
|
.wait(selectors.ticketsIndex.searchResult)
|
||||||
.type(selectors.ticketsIndex.searchTicketInput, 1)
|
.type(selectors.ticketsIndex.searchTicketInput, 'id:1')
|
||||||
.click(selectors.ticketsIndex.searchButton)
|
.click(selectors.ticketsIndex.searchButton)
|
||||||
.waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1)
|
.waitForNumberOfElements(selectors.ticketsIndex.searchResult, 1)
|
||||||
.countSearchResults(selectors.ticketsIndex.searchResult)
|
.countSearchResults(selectors.ticketsIndex.searchResult)
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
"angular-translate-loader-partial": "^2.18.1",
|
"angular-translate-loader-partial": "^2.18.1",
|
||||||
"flatpickr": "^4.4.6",
|
"flatpickr": "^4.4.6",
|
||||||
"fs-extra": "^5.0.0",
|
"fs-extra": "^5.0.0",
|
||||||
|
"js-yaml": "^3.10.0",
|
||||||
"material-design-lite": "^1.3.0",
|
"material-design-lite": "^1.3.0",
|
||||||
"mg-crud": "^1.1.2",
|
"mg-crud": "^1.1.2",
|
||||||
"npm": "^5.8.0",
|
"npm": "^5.8.0",
|
||||||
|
@ -55,7 +56,6 @@
|
||||||
"html-loader": "^0.4.4",
|
"html-loader": "^0.4.4",
|
||||||
"jasmine": "^2.9.0",
|
"jasmine": "^2.9.0",
|
||||||
"jasmine-spec-reporter": "^4.2.1",
|
"jasmine-spec-reporter": "^4.2.1",
|
||||||
"js-yaml": "^3.10.0",
|
|
||||||
"karma": "^1.7.1",
|
"karma": "^1.7.1",
|
||||||
"karma-chrome-launcher": "^2.2.0",
|
"karma-chrome-launcher": "^2.2.0",
|
||||||
"karma-firefox-launcher": "^1.1.0",
|
"karma-firefox-launcher": "^1.1.0",
|
||||||
|
|
|
@ -40,6 +40,7 @@ module.exports = function(Self) {
|
||||||
street: data.street,
|
street: data.street,
|
||||||
city: data.city,
|
city: data.city,
|
||||||
provinceFk: data.provinceFk,
|
provinceFk: data.provinceFk,
|
||||||
|
countryFk: data.countryFk,
|
||||||
isEqualizated: data.isEqualizated
|
isEqualizated: data.isEqualizated
|
||||||
};
|
};
|
||||||
newClient = await Self.create(client);
|
newClient = await Self.create(client);
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
module.exports = function(Client) {
|
|
||||||
Client.installMethod('filter', filterClients);
|
|
||||||
|
|
||||||
function filterClients(params) {
|
|
||||||
let filters = {
|
|
||||||
where: {},
|
|
||||||
skip: (params.page - 1) * params.size,
|
|
||||||
limit: params.size
|
|
||||||
};
|
|
||||||
|
|
||||||
delete params.page;
|
|
||||||
delete params.size;
|
|
||||||
|
|
||||||
if (params.search) {
|
|
||||||
filters.where.and = [
|
|
||||||
{
|
|
||||||
or: [
|
|
||||||
{id: params.search},
|
|
||||||
{name: {regexp: params.search}}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
];
|
|
||||||
delete params.search;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.phone) {
|
|
||||||
let phones = [
|
|
||||||
{phone: params.phone},
|
|
||||||
{mobile: params.phone}
|
|
||||||
];
|
|
||||||
if (filters.where.and) {
|
|
||||||
filters.where.and.push(
|
|
||||||
{
|
|
||||||
or: phones
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
filters.where.or = phones;
|
|
||||||
}
|
|
||||||
delete params.phone;
|
|
||||||
}
|
|
||||||
|
|
||||||
let properties = Object.keys(params);
|
|
||||||
if (properties.length) {
|
|
||||||
properties.forEach(
|
|
||||||
property => {
|
|
||||||
let propertyToBeEqual = (property === 'postcode' || property === 'fi' || property === 'id');
|
|
||||||
if (filters.where.and) {
|
|
||||||
let filter = {};
|
|
||||||
filter[property] = propertyToBeEqual ? params[property] : {regexp: params[property]};
|
|
||||||
filters.where.and.push(filter);
|
|
||||||
} else {
|
|
||||||
filters.where[property] = propertyToBeEqual ? params[property] : {regexp: params[property]};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return filters;
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,62 +0,0 @@
|
||||||
module.exports = Self => {
|
|
||||||
Self.installMethod('filter', filterParams);
|
|
||||||
|
|
||||||
function filterParams(params) {
|
|
||||||
let filter = {
|
|
||||||
where: {},
|
|
||||||
skip: (params.page - 1) * params.size,
|
|
||||||
limit: params.size,
|
|
||||||
order: params.order || 'name ASC', // name, relevancy DESC
|
|
||||||
include: [
|
|
||||||
{relation: 'itemType',
|
|
||||||
scope: {
|
|
||||||
fields: ['name', 'workerFk'],
|
|
||||||
include: {
|
|
||||||
relation: 'worker',
|
|
||||||
fields: ['firstName', 'name']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{relation: 'origin'},
|
|
||||||
{relation: 'ink'},
|
|
||||||
{relation: 'producer'},
|
|
||||||
{relation: 'intrastat'},
|
|
||||||
{relation: 'expence'}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
delete params.page;
|
|
||||||
delete params.size;
|
|
||||||
delete params.order;
|
|
||||||
|
|
||||||
if (params.search) {
|
|
||||||
filter.where.and = [
|
|
||||||
{
|
|
||||||
or: [
|
|
||||||
{id: params.search},
|
|
||||||
{name: {regexp: params.search}}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
];
|
|
||||||
delete params.search;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.itemSize) {
|
|
||||||
params.size = params.itemSize;
|
|
||||||
delete params.itemSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(params).forEach(
|
|
||||||
key => {
|
|
||||||
if (filter.where.and) {
|
|
||||||
let filter = {};
|
|
||||||
filter[key] = (key === 'description' || key === 'name') ? {regexp: params[key]} : params[key];
|
|
||||||
filter.where.and.push(filter);
|
|
||||||
} else {
|
|
||||||
filter.where[key] = (key === 'description' || key === 'name') ? {regexp: params[key]} : params[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return filter;
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,87 +0,0 @@
|
||||||
module.exports = Self => {
|
|
||||||
Self.installMethod('filter', filterParams);
|
|
||||||
|
|
||||||
function filterParams(params) {
|
|
||||||
let filters = {
|
|
||||||
where: {},
|
|
||||||
skip: (params.page - 1) * params.size,
|
|
||||||
limit: params.size,
|
|
||||||
order: params.order || 'created DESC',
|
|
||||||
include: [
|
|
||||||
{
|
|
||||||
relation: 'address',
|
|
||||||
scope: {
|
|
||||||
fields: ['provinceFk'],
|
|
||||||
include: {
|
|
||||||
relation: 'province',
|
|
||||||
scope: {
|
|
||||||
fields: ['name']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
relation: 'warehouse',
|
|
||||||
scope: {
|
|
||||||
fields: ['name']
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
relation: 'agencyMode',
|
|
||||||
scope: {
|
|
||||||
fields: ['name']
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
relation: 'tracking',
|
|
||||||
scope: {
|
|
||||||
fields: ['stateFk'],
|
|
||||||
include: {
|
|
||||||
relation: 'state',
|
|
||||||
scope: {
|
|
||||||
fields: ['name']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
relation: 'client',
|
|
||||||
scope: {
|
|
||||||
fields: ['salesPersonFk'],
|
|
||||||
include: {
|
|
||||||
relation: 'salesPerson',
|
|
||||||
scope: {
|
|
||||||
fields: ['name']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
delete params.page;
|
|
||||||
delete params.size;
|
|
||||||
delete params.order;
|
|
||||||
|
|
||||||
if (params.search) {
|
|
||||||
filters.where.and = [
|
|
||||||
{
|
|
||||||
or: [
|
|
||||||
{id: params.search},
|
|
||||||
{name: {regexp: params.search}}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
];
|
|
||||||
delete params.search;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(params).forEach(
|
|
||||||
key => {
|
|
||||||
if (filters.where.and) {
|
|
||||||
let filter = {};
|
|
||||||
filter[key] = (key === 'nickname') ? {regexp: params[key]} : params[key];
|
|
||||||
filters.where.and.push(filter);
|
|
||||||
} else {
|
|
||||||
filters.where[key] = (key === 'nickname') ? {regexp: params[key]} : params[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return filters;
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -10,7 +10,6 @@ module.exports = Self => {
|
||||||
require('../methods/client/card')(Self);
|
require('../methods/client/card')(Self);
|
||||||
require('../methods/client/createWithUser')(Self);
|
require('../methods/client/createWithUser')(Self);
|
||||||
require('../methods/client/listWorkers')(Self);
|
require('../methods/client/listWorkers')(Self);
|
||||||
require('../methods/client/filter')(Self);
|
|
||||||
require('../methods/client/hasCustomerRole')(Self);
|
require('../methods/client/hasCustomerRole')(Self);
|
||||||
require('../methods/client/isValidClient')(Self);
|
require('../methods/client/isValidClient')(Self);
|
||||||
require('../methods/client/activeSalesPerson')(Self);
|
require('../methods/client/activeSalesPerson')(Self);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
let UserError = require('../helpers').UserError;
|
let UserError = require('../helpers').UserError;
|
||||||
|
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
require('../methods/item/filter')(Self);
|
|
||||||
require('../methods/item/clone')(Self);
|
require('../methods/item/clone')(Self);
|
||||||
require('../methods/item/updateTaxes')(Self);
|
require('../methods/item/updateTaxes')(Self);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
require('../methods/ticket/changeTime')(Self);
|
require('../methods/ticket/changeTime')(Self);
|
||||||
require('../methods/ticket/changeWorker')(Self);
|
require('../methods/ticket/changeWorker')(Self);
|
||||||
require('../methods/ticket/filter')(Self);
|
|
||||||
require('../methods/ticket/getVolume')(Self);
|
require('../methods/ticket/getVolume')(Self);
|
||||||
require('../methods/ticket/getTotalVolume')(Self);
|
require('../methods/ticket/getTotalVolume')(Self);
|
||||||
require('../methods/ticket/summary')(Self);
|
require('../methods/ticket/summary')(Self);
|
||||||
|
|
Loading…
Reference in New Issue