Merge branch 'dev' of https://git.verdnatura.es/salix into dev

This commit is contained in:
Juan 2018-03-13 14:37:56 +01:00
commit abb874530c
15 changed files with 125 additions and 84 deletions

2
Jenkinsfile vendored
View File

@ -8,6 +8,8 @@ env.BRANCH_NAME = branchName;
env.TAG = "${env.BUILD_NUMBER}";
env.salixUser="${env.salixUser}";
env.salixPassword="${env.salixPassword}";
env.salixHost = "${env.productionSalixHost}";
env.salixPort = "${env.productionSalixPort}";
switch (branchName){
case branchTest:

View File

@ -5,7 +5,7 @@
"validations" : true,
"routes": [
{
"url": "/clients",
"url": "/clients?q",
"state": "clients",
"component": "vn-client-index",
"acl": ["employee"]
@ -30,7 +30,7 @@
},
"menu": {
"description": "Basic data",
"icon": "person"
"icon": "settings"
}
},
{
@ -54,7 +54,7 @@
},
"menu": {
"description": "Pay method",
"icon": "assignment"
"icon": "icon-payment"
}
},
{
@ -94,7 +94,7 @@
},
"menu": {
"description": "Web access",
"icon": "language"
"icon": "cloud"
}
},
{
@ -186,7 +186,7 @@
"component": "vn-client-invoices",
"menu": {
"description": "Invoices",
"icon": "insert_drive_file"
"icon": "icon-invoices"
}
},
{
@ -204,7 +204,7 @@
},
"menu": {
"description": "Recovery",
"icon": "credit_card"
"icon": "icon-recovery"
}
}, {
"url": "/create",

View File

@ -15,7 +15,7 @@
</vn-horizontal>
<vn-horizontal>
<vn-textfield vn-one label="Business name" field="$ctrl.client.socialName"></vn-textfield>
<vn-textfield vn-one label="User name" field="$ctrl.client.userName"></vn-textfield>
<vn-textfield vn-one label="Web user" field="$ctrl.client.userName"></vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-textfield vn-one label="Email" field="$ctrl.client.email" info="You can save multiple emails"></vn-textfield>

View File

@ -1,7 +1,7 @@
Name: Nombre
Tax number: NIF/CIF
Business name: Razón social
User name: Nombre de usuario
Web user: Usuario Web
Email: Correo electrónico
Create and edit: Crear y editar
Create: Crear

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 class="vn-list">
<vn-card>

View File

@ -14,7 +14,7 @@
<vn-icon
ng-click="$ctrl.preview($event)"
vn-tooltip="Preview"
icon="icon-preview">
icon="desktop_windows">
</vn-icon>
</vn-horizontal>
</vn-horizontal>

View File

@ -1,6 +1,18 @@
.icon-tags:before { content: '\e800'; }
.icon-tree:before { content: '\e801'; }
.icon-clone2:before { content: '\e802'; }
.icon-preview:before { content: '\e803'; }
.icon-history:before { content: '\f1da'; }
.icon-barcode:before { content: '\e800'; } /* '' */
.icon-volume:before { content: '\e801'; } /* '' */
.icon-bucket:before { content: '\e802'; } /* '' */
.icon-disabled:before { content: '\e80b'; } /* '' */
.icon-invoices:before { content: '\e80c'; } /* '' */
.icon-noweb:before { content: '\e812'; } /* '' */
.icon-payment:before { content: '\e813'; } /* '' */
.icon-recovery:before { content: '\e815'; } /* '' */
.icon-risk:before { content: '\e816'; } /* '' */
.icon-lines:before { content: '\e819'; } /* '' */
.icon-volum:before { content: '\e81b'; } /* '' */
.icon-components:before { content: '\e81c'; } /* '' */
.icon-clone:before { content: '\e81d'; } /* '' */
.icon-addperson:before { content: '\e81e'; } /* '' */
.icon-bin:before { content: '\e81f'; } /* '' */
.icon-sms:before { content: '\e820'; } /* '' */
.icon-tags:before { content: '\e821'; } /* '' */

View File

@ -11,7 +11,7 @@
"component": "ui-view"
},
{
"url": "/list",
"url": "/list?q",
"state": "item.index",
"component": "vn-item-list"
},
@ -35,7 +35,7 @@
},
"menu": {
"description": "Basic data",
"icon": "folder"
"icon": "settings"
},
"acl": ["buyer"]
},
@ -48,7 +48,7 @@
},
"menu": {
"description": "Tags",
"icon": "folder"
"icon": "icon-tags"
},
"acl": ["buyer"]
},
@ -70,7 +70,7 @@
},
"menu": {
"description": "History",
"icon": "folder"
"icon": "history"
}
},
{
@ -107,7 +107,7 @@
},
"menu": {
"description": "Barcode",
"icon": "folder"
"icon": "icon-barcode"
},
"acl": ["buyer","replenisher"]
},{

View File

@ -20,12 +20,12 @@
<vn-icon
ng-click="$ctrl.clone($event)"
vn-tooltip="Clone"
icon="icon-clone2">
icon="icon-clone">
</vn-icon>
<vn-icon
ng-click="$ctrl.preview($event)"
vn-tooltip="Preview"
icon="icon-preview">
icon="desktop_windows">
</vn-icon>
</vn-horizontal>
</vn-horizontal>

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 class="vn-list">
<vn-card>

View File

@ -1,7 +1,7 @@
import ngModule from '../../module';
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.$scope = $scope;
this.$document = $document;
@ -9,46 +9,52 @@ export default class Controller {
this.vnPopover = vnPopover;
this.$timeout = $timeout;
this.stringSearch = '';
this.$state = $state;
this.deregisterCallback = $transitions.onStart({},
transition => this.changeState(transition));
}
clearFilter() {
this.index.filter = {
page: 1,
size: 20
};
}
/**
* String search to JSON filter
*/
getFiltersFromSearch() {
let toFind = this.stringSearch;
let find;
if (this.stringSearch) {
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
find = toFind.match(/((([\w_]+):([\w_]+))|([\w_]+):\(([\w_ ]+)\))/gi);
// remove pattern key:value or key:(extra value) from string and returns string
this.index.filter.search = (toFind.replace(/((([\w_]+):([\w_]+))|([\w_]+):\(([\w_ ]+)\))/gi, '')).trim();
if (find)
for (let i = 0; i < find.length; i++) {
let aux = find[i].split(':');
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, '');
this.index.filter[property] = value.trim();
result[property] = value.trim();
}
}
if (remnantString) {
result.search = remnantString;
}
}
return result;
}
/**
* JSON filter to string search
*
* @param {Object} filter The filter
*/
createFilterSearch(filter) {
createStringFromObject(filterObject) {
let search = [];
let keys = Object.keys(filter);
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 = filter[k];
let value = filterObject[k];
if (typeof value === 'string' && value.indexOf(' ') !== -1) {
search.push(`${k}:(${value})`);
@ -57,42 +63,59 @@ export default class Controller {
}
}
});
if (filterObject.search)
search.unshift(filterObject.search);
}
if (this.index.filter.search) {
search.push(this.index.filter.search);
}
delete this.index.filter.search;
this.stringSearch = (search.length) ? search.join(' ') : '';
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) {
this.getFiltersFromSearch();
filter = this.getFiltersFromString(this.stringSearch);
}
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?
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);
if (this.data)
childCtrl.data = Object.assign({}, this.data);
event.preventDefault();
}
onChildSubmit(filter) {
this.createFilterSearch(filter);
this.index.filter = {
page: 1,
size: 20
};
this.stringSearch = this.createStringFromObject(filter);
this.clearFilter();
this.$timeout(() => {
this.onSubmit();
});
}
onSubmit() {
let filter = {};
if (this.stringSearch) {
this.getFiltersFromSearch();
filter = this.getFiltersFromString(this.stringSearch);
}
this.setFilter(filter);
if (this.onSearch)
this.onSearch();
@ -103,12 +126,25 @@ export default class Controller {
angular.element(this.child).remove();
}
delete this.child;
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', '$document', '$compile', 'vnPopover', '$timeout'];
Controller.$inject = ['$element', '$scope', '$document', '$compile', 'vnPopover', '$timeout', '$state', '$transitions'];
ngModule.component('vnSearchbar', {
template: require('./searchbar.html'),

View File

@ -150,8 +150,8 @@ export default {
itemsIndex: {
createItemButton: `${components.vnFloatButton}`,
searchResult: `vn-item-product a`,
searchResultPreviewButton: `vn-item-product .buttons > [icon="icon-preview"]`,
searchResultCloneButton: `vn-item-product .buttons > [icon="icon-clone2"]`,
searchResultPreviewButton: `vn-item-product .buttons > [icon="desktop_windows"]`,
searchResultCloneButton: `vn-item-product .buttons > [icon="icon-clone"]`,
acceptClonationAlertButton: `vn-item-list [vn-id="clone"] [response="ACCEPT"]`,
searchItemInput: `${components.vnTextfield}`,
searchButton: `${components.vnSearchBar} > vn-icon-button > button`,

View File

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

View File

@ -25,12 +25,6 @@ module.exports = function(Self) {
Self.validatesUniquenessOf('socialName', {
message: 'La razón social debe ser única'
});
Self.validatesFormatOf('postcode', {
message: 'El código postal solo debe contener números',
allowNull: true,
allowBlank: true,
with: /^\d+$/
});
Self.validatesFormatOf('email', {
message: 'Correo electrónico inválido',
allowNull: true,