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

This commit is contained in:
Javi Gallego 2018-03-09 14:51:50 +01:00
commit c0fbfa458e
38 changed files with 1303 additions and 1464 deletions

View File

@ -41,6 +41,9 @@ export default class Controller {
this._setDirtyForm(); this._setDirtyForm();
} }
} }
if (this.observations.length === 0 && Object.keys(this.observationsOld).length === 0) {
this._unsetDirtyForm();
}
} }
_submitObservations(objectObservations) { _submitObservations(objectObservations) {
return this.$http.post(`/client/api/AddressObservations/crudAddressObservations`, objectObservations); return this.$http.post(`/client/api/AddressObservations/crudAddressObservations`, objectObservations);

View File

@ -12,16 +12,18 @@
<vn-check <vn-check
vn-one vn-one
label="Enable web access" label="Enable web access"
field="$ctrl.account.active"> field="$ctrl.account.active"
vn-acl="employee"
acl-conditional-to-employee="{{$ctrl.canEnableCheckBox}}">
</vn-check> </vn-check>
</vn-horizontal> </vn-horizontal>
<vn-horizontal> <vn-horizontal>
<vn-textfield <vn-textfield
vn-focus
vn-one vn-one
margin-medium-top margin-medium-top
label="User" label="User"
field="$ctrl.account.name" field="$ctrl.account.name">
vn-focus>
</vn-textfield> </vn-textfield>
</vn-horizontal> </vn-horizontal>
</vn-card> </vn-card>
@ -47,7 +49,7 @@
</vn-textfield> </vn-textfield>
</tpl-body> </tpl-body>
<tpl-buttons> <tpl-buttons>
<button response="CANCEL" translate>Cancel</button> <input type="button" response="CANCEL" translate-attr="{value: 'Cancel'}"/>
<button response="ACCEPT" translate>Change password</button> <button response="ACCEPT" translate>Change password</button>
</tpl-buttons> </tpl-buttons>
</vn-dialog> </vn-dialog>

View File

@ -6,21 +6,30 @@ export default class Controller {
this.$http = $http; this.$http = $http;
this.vnApp = vnApp; this.vnApp = vnApp;
this.canChangePassword = false; this.canChangePassword = false;
this.canEnableCheckBox = true;
} }
$onChanges() { $onChanges() {
if (this.client) { if (this.client) {
this.account = this.client.account; this.account = this.client.account;
this.isCustomer(); this.isCustomer();
this.checkConditions();
} }
} }
isCustomer() { isCustomer() {
if (this.client && this.client.id) { if (this.client.id) {
this.$http.get(`/client/api/Clients/${this.client.id}/hasCustomerRole`).then(res => { this.$http.get(`/client/api/Clients/${this.client.id}/hasCustomerRole`).then(res => {
this.canChangePassword = (res.data) ? res.data.isCustomer : false; this.canChangePassword = res.data && res.data.isCustomer;
});
}
}
checkConditions() {
if (this.client.id) {
this.$http.get(`/client/api/Clients/${this.client.id}/isValidClient`).then(res => {
this.canEnableCheckBox = res.data;
}); });
} else {
this.canChangePassword = false;
} }
} }
@ -31,7 +40,7 @@ export default class Controller {
} }
onPassChange(response) { onPassChange(response) {
if (response == 'ACCEPT' && this.canChangePassword) if (response == 'ACCEPT')
try { try {
if (!this.newPassword) if (!this.newPassword)
throw new Error(`Passwords can't be empty`); throw new Error(`Passwords can't be empty`);

View File

@ -1,22 +1,23 @@
<vn-vertical ng-click="$ctrl.showDropDown = true" tabindex="0"> <div>
<vn-textfield vn-auto <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
label="{{$ctrl.label}}" <input
model="$ctrl.displayValue" type="button"
readonly="$ctrl.readonly" class="mdl-textfield__input"
tab-index="-1"> ng-click="$ctrl.onMouseDown($event)"
</vn-textfield> ng-keydown="$ctrl.onKeyDown($event)">
<vn-drop-down vn-auto </input>
items="$ctrl.items" <div class="icons">
show="$ctrl.showDropDown" <vn-icon
selected="$ctrl.field" icon="clear"
filter="true" class="clear"
load-more="$ctrl.getItems()" ng-click="$ctrl.onClearClick($event)"
show-load-more="$ctrl.maxRow" translate-attr="{title: 'Clear'}">
remove-load-more="$ctrl.removeLoadMore" </vn-icon>
filter-action="$ctrl.findItems(search)" </div>
item-width="$ctrl.width" <label class="mdl-textfield__label" translate>{{::$ctrl.label}}</label>
multiple="$ctrl.multiple" </div>
parent = "$ctrl.element"> <vn-drop-down
<vn-item ng-transclude="tplItem">{{$parent.item[$ctrl.showField]}}</vn-item> vn-id="drop-down"
on-select="$ctrl.onDropDownSelect(value)">
</vn-drop-down> </vn-drop-down>
</vn-vertical> </div>

474
client/core/src/components/autocomplete/autocomplete.js Normal file → Executable file
View File

@ -1,381 +1,255 @@
import ngModule from '../../module'; import ngModule from '../../module';
import Component from '../../lib/component'; import Component from '../../lib/component';
import copyObject from '../../lib/copy';
import './style.scss'; import './style.scss';
class Autocomplete extends Component { /**
constructor($element, $scope, $http, $timeout, $filter) { * Input with option selector.
super($element); *
this.$element = $element; * @property {String} valueField The data field name that should be shown
this.$scope = $scope; * @property {String} showFiled The data field name that should be used as value
* @property {Array} data Static data for the autocomplete
* @property {Object} intialData A initial data to avoid the server request used to get the selection
* @property {Boolean} multiple Wether to allow multiple selection
*/
export default class Autocomplete extends Component {
constructor($element, $scope, $http, $transclude) {
super($element, $scope);
this.$http = $http; this.$http = $http;
this.$timeout = $timeout; this.$transclude = $transclude;
this.$filter = $filter;
this._showDropDown = false; this._field = undefined;
this.finding = false; this._selection = null;
this.findMore = false;
this._value = null;
this._field = null;
this._preLoad = false;
this.maxRow = 10;
this.showField = 'name';
this.valueField = 'id'; this.valueField = 'id';
this.items = copyObject(this.data) || []; this.showField = 'name';
this.displayValueMultiCheck = [];
this._multiField = []; this._multiField = [];
this.readonly = true; this.readonly = true;
this.removeLoadMore = false;
this.form = null; this.form = null;
this.findForm = false; this.input = this.element.querySelector('.mdl-textfield__input');
}
componentHandler.upgradeElement(
get showDropDown() { this.element.querySelector('.mdl-textfield'));
return this._showDropDown;
}
set showDropDown(value) {
if (value && this.url && !this._preLoad) {
this._preLoad = true;
this.getItems();
}
if (value && !this.width) {
let rectangle = this.$element[0].getBoundingClientRect();
this.width = Math.round(rectangle.width) - 10;
}
this._showDropDown = value;
}
get displayValue() {
return this._value;
}
set displayValue(value) {
let val = (value === undefined || value === '') ? null : value;
if (this.multiple && val) {
let index = this.displayValueMultiCheck.indexOf(val);
if (index === -1)
this.displayValueMultiCheck.push(val);
else
this.displayValueMultiCheck.splice(index, 1);
this._value = this.displayValueMultiCheck.join(', ');
} else {
this._value = val;
}
if (value === null) {
this.field = null;
if (this.multiple && this.items.length) {
this.displayValueMultiCheck = [];
this.items.map(item => {
item.checked = false;
return item;
});
}
}
} }
/**
* @type {any} The autocomplete value.
*/
get field() { get field() {
return this.multiple ? this._multiField : this._field; return this._field;
} }
set field(value) { set field(value) {
if (!angular.equals(value, this.field)) { if (angular.equals(value, this._field))
this.finding = true; return;
if (value && value.hasOwnProperty(this.valueField)) {
this._field = value[this.valueField];
if (this.multiple) {
this.setMultiField(value[this.valueField]);
}
this.setDirtyForm();
} else {
this.setValue(value);
}
if (value && value.hasOwnProperty(this.showField)) this._field = value;
this.displayValue = value[this.showField]; this.refreshSelection();
this.finding = false;
if (this.onChange) if (this.onChange)
this.onChange({item: this._field}); this.onChange(value);
}
} }
set initialData(value) { /**
if (value && value.hasOwnProperty(this.valueField)) { * @type {Object} The selected data object, you can use this property
this._field = value[this.valueField]; * to prevent requests to display the initial value.
if (this.multiple) { */
this._multiField = [value[this.valueField]]; get selection() {
} return this._selection;
if (value.hasOwnProperty(this.showField)) {
this.displayValue = value[this.showField];
}
}
} }
setMultiField(val) { set selection(value) {
if (val && typeof val === 'object' && val[this.valueField]) { this._selection = value;
val = val[this.valueField]; this.refreshDisplayed();
}
if (val === null) {
this._multiField = [];
} else {
let index = this._multiField.indexOf(val);
if (index === -1) {
this._multiField.push(val);
} else {
this._multiField.splice(index, 1);
}
}
} }
setValue(value) { selectionIsValid(selection) {
if (value) { return selection
let data = this.items; && selection[this.valueField] == this._field
&& selection[this.showField] != null;
}
if (data && data.length) refreshSelection() {
for (let i = 0; i < data.length; i++) if (this.selectionIsValid(this._selection))
if (data[i][this.valueField] === value) { return;
this.showItem(data[i]);
let value = this._field;
if (value && this.valueField && this.showField) {
if (this.selectionIsValid(this.initialData)) {
this.selection = this.initialData;
return; return;
} }
this.requestItem(value); let data = this.data;
} else {
this._field = null; if (!data && this.$.dropDown)
this.setMultiField(null); data = this.$.dropDown.$.model.data;
this.displayValue = '';
} if (data)
for (let i = 0; i < data.length; i++)
if (data[i][this.valueField] === value) {
this.selection = data[i];
return;
} }
requestItem(value) { if (this.url) {
if (!value) return; this.requestSelection(value);
return;
}
} else
this.selection = null;
}
requestSelection(value) {
let where = {}; let where = {};
if (this.multiple)
where[this.valueField] = {inq: this.field};
else
where[this.valueField] = value; where[this.valueField] = value;
let filter = { let filter = {
fields: this.getRequestFields(), fields: this.getFields(),
where: where where: where
}; };
let json = JSON.stringify(filter); let json = encodeURIComponent(JSON.stringify(filter));
this.$http.get(`${this.url}?filter=${json}`).then( this.$http.get(`${this.url}?filter=${json}`).then(
json => this.onItemRequest(json.data), json => this.onSelectionRequest(json.data),
json => this.onItemRequest(null) () => this.onSelectionRequest(null)
); );
} }
onItemRequest(data) { onSelectionRequest(data) {
if (data && data.length > 0) if (data && data.length > 0) {
this.showItem(data[0]); if (this.multiple)
this.selection = data;
else else
this.showItem(null); this.selection = data[0];
} else
this.selection = null;
} }
showItem(item) { refreshDisplayed() {
this.displayValue = item ? item[this.showField] : ''; let display = '';
this.field = item;
if (this._selection && this.showField) {
if (this.multiple && Array.isArray(this._selection)) {
for (var item of this._selection) {
if (display.length > 0) display += ', ';
display += item[this.showField];
}
} else {
display = this._selection[this.showField];
}
} }
getRequestFields() { this.input.value = display;
let fields = {}; this.mdlUpdate();
fields[this.valueField] = true; }
fields[this.showField] = true;
if (this._selectFields) getFields() {
for (let field of this._selectFields) let fields = [];
fields[field] = true; fields.push(this.valueField);
fields.push(this.showField);
if (this.selectFields)
for (let field of this.selectFields)
fields.push(field);
return fields; return fields;
} }
getOrder() { mdlUpdate() {
return this.order ? this.order : `${this.showField} ASC`; let field = this.element.querySelector('.mdl-textfield');
let mdlField = field.MaterialTextfield;
if (mdlField) mdlField.updateClasses_();
} }
findItems(search) { setValue(value) {
if (this.url && search && !this.finding) { this.field = value;
this.maxRow = false; if (this.form) this.form.$setDirty();
let filter = {};
if (this.filterSearch) {
let toSearch = this.filterSearch.replace(/search/g, search);
filter = this.$scope.$eval(toSearch);
} else {
filter = {where: {name: {regexp: search}}};
if (this.filter && this.filter.where) {
Object.assign(filter.where, this.filter.where);
}
}
filter.order = this.getOrder();
let json = JSON.stringify(filter);
this.finding = true;
this.$http.get(`${this.url}?filter=${json}`).then(
json => {
this.items = [];
json.data.forEach(
el => {
if (this.multiple) {
el.checked = this.field.indexOf(el[this.valueField]) !== -1;
}
this.items.push(el);
}
);
this.finding = false;
},
() => {
this.finding = false;
}
);
} else if (search && !this.url && this.data) {
this.items = this.$filter('filter')(this.data, search);
} else if (!search && !this.finding) {
this.maxRow = 10;
this.items = [];
this.getItems();
}
} }
getItems() { onDropDownSelect(value) {
if (this.url === undefined) { this.setValue(value);
this.items = copyObject(this.data); this.field = value;
this.maxRow = false;
this.removeLoadMore = true;
} else {
let filter = {};
if (!this.finding) {
this.finding = true;
if (this.maxRow) {
if (this.items) {
filter.skip = this.items.length;
}
filter.limit = this.maxRow;
filter.order = this.getOrder();
}
if (this.filter) {
Object.assign(filter, this.filter);
} }
let json = JSON.stringify(filter); onClearClick(event) {
event.preventDefault();
this.removeLoadMore = false; this.setValue(null);
this.$http.get(`${this.url}?filter=${json}`).then(
json => {
if (json.data.length) {
json.data.forEach(
el => {
if (this.multiple) {
el.checked = this.field.indexOf(el[this.valueField]) !== -1;
}
this.items.push(el);
}
);
if (filter.skip === 0 && this.maxRow && json.data.length < this.maxRow) {
this.removeLoadMore = true;
}
} else {
this.maxRow = false;
}
this.finding = false;
},
() => {
this.finding = false;
}
);
}
}
}
_parentForm() {
this.findForm = true;
let formScope = this.$scope;
while (formScope && !formScope.form && formScope.$id > 1) {
formScope = formScope.$parent;
}
this.form = formScope ? formScope.form || null : null;
}
setDirtyForm() {
if (!this.form && !this.findForm) {
this._parentForm();
}
if (this.form) {
this.form.$setDirty();
}
} }
$onInit() { onKeyDown(event) {
this.findMore = this.url && this.maxRow; if (event.defaultPrevented) return;
this.mouseFocus = false;
this.focused = false;
this.$element.bind('mouseover', e => { switch (event.keyCode) {
this.$timeout(() => { case 38: // Up
this.mouseFocus = true; case 40: // Down
this.showDropDown = this.focused; case 13: // Enter
}); this.showDropDown();
break;
default:
if (event.key.length == 1)
this.showDropDown(event.key);
else
return;
}
event.preventDefault();
}
onMouseDown(event) {
event.preventDefault();
this.showDropDown();
}
showDropDown(search) {
Object.assign(this.$.dropDown.$.model, {
url: this.url,
staticData: this.data
}); });
this.$element.bind('mouseout', () => { Object.assign(this.$.dropDown, {
this.$timeout(() => { valueField: this.valueField,
this.mouseFocus = false; showField: this.showField,
this.showDropDown = this.focused; selectFields: this.getFields(),
where: this.where,
order: this.order,
parent: this.input,
multiple: this.multiple,
limit: this.limit,
$transclude: this.$transclude
}); });
}); this.$.dropDown.show(search);
this.$element.bind('focusin', e => {
this.$timeout(() => {
this.focused = true;
this.showDropDown = true;
});
});
this.$element.bind('focusout', e => {
this.$timeout(() => {
this.focused = false;
this.showDropDown = this.mouseFocus;
});
});
}
$onDestroy() {
this.$element.unbind('mouseover');
this.$element.unbind('mouseout');
this.$element.unbind('focusin');
this.$element.unbind('focusout');
}
$onChanges(objectChange) {
if (objectChange.data && objectChange.data.currentValue && objectChange.data.currentValue.length) {
this.items = copyObject(objectChange.data.currentValue);
this.maxRow = false;
this.removeLoadMore = true;
} }
} }
Autocomplete.$inject = ['$element', '$scope', '$http', '$transclude'];
}
Autocomplete.$inject = ['$element', '$scope', '$http', '$timeout', '$filter'];
ngModule.component('vnAutocomplete', { ngModule.component('vnAutocomplete', {
template: require('./autocomplete.html'), template: require('./autocomplete.html'),
controller: Autocomplete, controller: Autocomplete,
bindings: { bindings: {
url: '@?', url: '@?',
data: '<?',
showField: '@?', showField: '@?',
valueField: '@?', valueField: '@?',
selectFields: '@?', selectFields: '<?',
initialData: '<?', where: '@?',
onChange: '&?',
data: '<?',
field: '=',
label: '@',
multiple: '@?',
order: '@?', order: '@?',
filter: '<?', label: '@',
filterSearch: '@?' initialData: '<?',
field: '=?',
limit: '<?',
showFilter: '<?',
selection: '<?',
multiple: '<?',
onChange: '&?'
}, },
transclude: { transclude: {
tplItem: '?tplItem' tplItem: '?tplItem'
},
require: {
form: '?^form'
} }
}); });

View File

@ -1,208 +1,74 @@
import './autocomplete.js'; import './autocomplete.js';
import template from './autocomplete.html';
describe('Component vnAutocomplete', () => { describe('Component vnAutocomplete', () => {
let $componentController; let $element;
let $scope; let $scope;
let $httpBackend; let $httpBackend;
let $timeout;
let $element;
let controller; let controller;
let data = {id: 1, name: 'Bruce Wayne'};
beforeEach(() => { beforeEach(() => {
angular.mock.module('client'); angular.mock.module('client');
}); });
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_, _$timeout_) => { beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_, _$timeout_) => {
$componentController = _$componentController_;
$scope = $rootScope.$new(); $scope = $rootScope.$new();
$element = angular.element(`<div>${template}</div>`);
$httpBackend = _$httpBackend_; $httpBackend = _$httpBackend_;
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({}); $httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
$timeout = _$timeout_; controller = _$componentController_('vnAutocomplete', {$element, $scope, $httpBackend, $transclude: null});
$element = angular.element('<div></div>');
controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
})); }));
describe('showDropDown() setter', () => { describe('field() setter/getter', () => {
it(`should set _showDropDown value`, () => { it(`should set field controllers property`, () => {
controller._showDropDown = ''; controller.field = data.id;
controller.showDropDown = 'some value';
expect(controller._showDropDown).toEqual('some value'); expect(controller.field).toEqual(data.id);
}); });
it(`should set _showDropDown value`, () => { it(`should set selection finding an existing item in the initialData property`, () => {
controller._showDropDown = ''; controller.valueField = 'id';
controller.showDropDown = 'some value'; controller.showField = 'name';
controller.initialData = data;
controller.field = data.id;
expect(controller._showDropDown).toEqual('some value'); expect(controller.selection).toEqual(data);
});
}); });
describe('displayValue() setter', () => { it(`should set selection finding an existing item in the data property`, () => {
it(`should display value in a formated way`, () => { controller.valueField = 'id';
let value = 'some value'; controller.showField = 'name';
controller.displayValue = value; controller.data = [data];
controller.field = data.id;
expect(controller._value).toEqual(value); expect(controller.selection).toEqual(data);
}); });
describe('when the autocomeplete is multiple', () => { it(`should set selection to null when can't find an existing item in the data property`, () => {
it(`should display values separated with commas`, () => { controller.valueField = 'id';
controller.multiple = true; controller.showField = 'name';
controller.displayValue = 'some value'; controller.field = data.id;
controller.displayValue = 'another value';
expect(controller._value).toEqual('some value, another value'); expect(controller.selection).toEqual(null);
});
});
}); });
describe('field() setter', () => { it(`should perform a query if the item id isn't present in the data property`, () => {
describe('when value is an object', () => { controller.valueField = 'id';
it(`should set _field controllers property`, () => { controller.showField = 'name';
controller.field = {id: 1, name: 'Bruce Wayne'}; controller.url = 'localhost';
controller.field = data.id;
expect(controller._field).toEqual(1); let filter = {
}); fields: ['id', 'name'],
where: {id: data.id}
};
let json = encodeURIComponent(JSON.stringify(filter));
it(`should set _multifield controllers property `, () => { $httpBackend.expectGET(`localhost?filter=${json}`);
controller.multiple = true; controller.field = data.id;
controller.field = {id: 1, name: 'Bruce Wayne'};
expect(controller._field).toEqual(1);
expect(controller._multiField[0]).toEqual(1);
controller.field = {id: 1, name: 'Bruce Wayne'};
expect(controller._multiField).toEqual([]);
expect(controller._field).toEqual(1);
});
it(`should set _multifield value and remove it if called a second type with same value`, () => {
controller.multiple = true;
controller.field = {id: 1, name: 'Bruce Wayne'};
expect(controller._field).toEqual(1);
expect(controller._multiField[0]).toEqual(1);
controller.field = {id: 1, name: 'Bruce Wayne'};
expect(controller._multiField).toEqual([]);
expect(controller._field).toEqual(1);
});
it(`should set displayValue finding an existing item in the controller.items property`, () => {
controller.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}];
controller.field = {id: 2, name: 'Bruce Wayne'};
expect(controller.displayValue).toEqual('Bruce Wayne');
});
});
describe('when value is a number', () => {
it(`should set _field controller property finding an existing item in the controller.items property`, () => {
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}];
controller.field = 2;
expect(controller._field).toEqual(2);
});
it(`should set _multifield value and remove it if called a second type with same value finding an existing item in the controller.items property`, () => {
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}];
controller.multiple = true;
controller.field = 2;
expect(controller._multiField[0]).toEqual(2);
controller.field = 2;
expect(controller._multiField).toEqual([]);
});
it(`should perform a query if the item id isn't present in the controller.items property`, () => {
controller.url = 'test.com';
$httpBackend.expectGET(`${controller.url}?filter={"fields":{"id":true,"name":true},"where":{"id":3}}`);
controller.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}];
controller.field = 3;
$httpBackend.flush();
});
it(`should set displayValue finding an existing item in the controller.items property`, () => {
controller.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}];
controller.field = 2;
expect(controller.displayValue).toEqual('Bruce Wayne');
});
it(`should set field performing a query as the item id isn't present in the controller.items property`, () => {
controller.url = 'test.com';
$httpBackend.expectGET(`${controller.url}?filter={"fields":{"id":true,"name":true},"where":{"id":3}}`);
controller.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}];
controller.field = 3;
$httpBackend.flush(); $httpBackend.flush();
}); });
}); });
}); });
describe('findItems()', () => {
it(`should perform a search and store the result in controller items`, () => {
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
controller.url = 'test.com';
let search = 'The Joker';
let json = JSON.stringify({where: {name: {regexp: search}}, order: controller.getOrder()});
$httpBackend.whenGET(`${controller.url}?filter=${json}`).respond([{id: 3, name: 'The Joker'}]);
$httpBackend.expectGET(`${controller.url}?filter=${json}`);
controller.findItems(search);
$httpBackend.flush();
expect(controller.items[0]).toEqual({id: 3, name: 'The Joker'});
});
it(`should perform a search and store the result in controller items with filterSearch`, () => {
let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
controller.url = 'test.com';
let search = 'The Joker';
controller.filterSearch = "{where: {name: {regexp: 'search'}}}";
let json = JSON.stringify({where: {name: {regexp: search}}, order: controller.getOrder()});
$httpBackend.whenGET(`${controller.url}?filter=${json}`).respond([{id: 3, name: 'The Joker'}]);
$httpBackend.expectGET(`${controller.url}?filter=${json}`);
controller.findItems(search);
$httpBackend.flush();
expect(controller.items[0]).toEqual({id: 3, name: 'The Joker'});
});
it(`should perform a search with multiple true and store the result in controller items with the checked property defined`, () => {
controller.url = 'test.com';
let search = 'Joker';
controller.multiple = true;
let json = JSON.stringify({where: {name: {regexp: search}}, order: controller.getOrder()});
$httpBackend.whenGET(`${controller.url}?filter=${json}`).respond([{id: 3, name: 'The Joker'}, {id: 4, name: 'Joker'}]);
$httpBackend.expectGET(`${controller.url}?filter=${json}`);
controller.findItems(search);
$httpBackend.flush();
expect(controller.items).toEqual([{id: 3, name: 'The Joker', checked: false}, {id: 4, name: 'Joker', checked: false}]);
});
it(`should call getItems function if there's no search value`, () => {
controller.url = 'test.com';
spyOn(controller, 'getItems');
controller.findItems();
expect(controller.getItems).toHaveBeenCalledWith();
});
});
describe('getItems()', () => {
it(`should perfom a query to fill the items without filter`, () => {
controller.url = 'test.com';
$httpBackend.whenGET(`${controller.url}?filter={"skip":0,"limit":10,"order":"name ASC"}`).respond([{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}]);
$httpBackend.expectGET(`${controller.url}?filter={"skip":0,"limit":10,"order":"name ASC"}`);
controller.getItems();
$httpBackend.flush();
expect(controller.items).toEqual([{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}]);
});
});
});

67
client/core/src/components/autocomplete/style.scss Normal file → Executable file
View File

@ -1,3 +1,47 @@
vn-autocomplete > div > .mdl-textfield {
position: relative;
width: 100%;
& > input {
cursor: pointer;
height: 26px;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
&:focus {
outline: none;
}
&::-moz-focus-inner {
border: 0;
}
}
& > .icons {
display: none;
position: absolute;
right: 0;
top: 1.3em;
height: 1em;
color: #888;
border-radius: .2em;
background-color: rgba(255, 255, 255, .8);
& > vn-icon {
cursor: pointer;
font-size: 18px;
&:hover {
color: #333;
}
}
}
&:hover > .icons,
& > input:focus + .icons {
display: block;
}
}
ul.vn-autocomplete { ul.vn-autocomplete {
list-style-type: none; list-style-type: none;
padding: 1em; padding: 1em;
@ -23,26 +67,3 @@ ul.vn-autocomplete {
} }
} }
} }
vn-autocomplete {
position: relative;
vn-vertical {
outline:none;
}
.mdl-chip__action {
position: absolute;
top: 0px;
right: -6px;
margin: 22px 0px;
background: transparent;
}
.material-icons {
font-size: 18px;
}
vn-drop-down{
margin-top: 47px;
}
vn-drop-down .dropdown-body .filter vn-icon {
margin-left: -26px;
}
}

View File

@ -37,14 +37,16 @@ export default class Dialog extends Component {
show() { show() {
if (this.shown) return; if (this.shown) return;
this.shown = true; this.shown = true;
this.keypressHandler = e => this.onKeypress(e); this.keyDownHandler = e => this.onkeyDown(e);
this.document.addEventListener('keypress', this.keypressHandler); this.document.addEventListener('keydown', this.keyDownHandler);
this.element.style.display = 'flex'; this.element.style.display = 'flex';
this.transitionTimeout = this.transitionTimeout = setTimeout(() => this.$element.addClass('shown'), 30);
setTimeout(() => this.$element.addClass('shown'), 30);
if (this.onOpen) if (this.onOpen)
this.onOpen(); this.onOpen();
let firstFocusable = this.element.querySelector('input, textarea');
if (firstFocusable) firstFocusable.focus();
} }
/** /**
* Hides the dialog calling the response handler. * Hides the dialog calling the response handler.
@ -68,7 +70,7 @@ export default class Dialog extends Component {
realHide() { realHide() {
if (!this.shown) return; if (!this.shown) return;
this.element.style.display = 'none'; this.element.style.display = 'none';
this.document.removeEventListener('keypress', this.keypressHandler); this.document.removeEventListener('keydown', this.keyDownHandler);
this.lastEvent = null; this.lastEvent = null;
this.shown = false; this.shown = false;
this.transitionTimeout = this.transitionTimeout =
@ -94,7 +96,7 @@ export default class Dialog extends Component {
if (event != this.lastEvent) if (event != this.lastEvent)
this.hide(); this.hide();
} }
onKeypress(event) { onkeyDown(event) {
if (event.keyCode == 27) // Esc if (event.keyCode == 27) // Esc
this.hide(); this.hide();
} }

View File

@ -28,7 +28,10 @@
display: block; display: block;
width: 20em; width: 20em;
} }
button { button,
input[type="button"],
input[type="submit"],
input[type="reset"] {
text-transform: uppercase; text-transform: uppercase;
background-color: transparent; background-color: transparent;
border: none; border: none;
@ -55,7 +58,10 @@
margin-top: 1.5em; margin-top: 1.5em;
text-align: right; text-align: right;
button { button,
input[type="button"],
input[type="submit"],
input[type="reset"] {
color: #ffa410; color: #ffa410;
font-family: vn-font-bold; font-family: vn-font-bold;
padding: .7em; padding: .7em;

62
client/core/src/components/drop-down/drop-down.html Normal file → Executable file
View File

@ -1,28 +1,36 @@
<vn-vertical class="dropdown-body" ng-if="$ctrl.show"> <div
<vn-auto ng-show="$ctrl.filter" class="filter"> class="body"
<vn-horizontal> ng-mousedown="$ctrl.onMouseDown($event)">
<input vn-one placeholder="{{'Search' | translate}}" type="text" ng-model="$ctrl.search"/> <div ng-show="$ctrl.showFilter" class="filter">
<vn-icon vn-none icon="clear" ng-click="$ctrl.clearSearch()"></vn-icon> <input
</vn-horizontal> type="text"
</vn-auto> ng-model="$ctrl.search"
<vn-auto> tabindex="-1"
<ul class="dropdown"> class="search"
<li ng-blur="$ctrl.onFocusOut()"
ng-repeat="item in $ctrl.itemsFiltered track by $index" translate-attr="{placeholder: 'Search'}"/>
ng-click="$ctrl.selectItem(item)" <vn-icon
ng-class="{'active': $index === $ctrl.activeOption, 'checked': item.checked}" icon="clear"
ng-mouseover="$ctrl.activeOption = $index" ng-click="$ctrl.onClearClick()"
> translate-attr="{title: 'Clear'}">
<input type="checkbox" ng-checked="item.checked" ng-if="$ctrl.multiple"> </vn-icon>
<div ng-transclude="vnItem">{{item.name}}</div> </div>
</li> <vn-model
<li vn-id="model"
ng-if="$ctrl.loadMore&&!$ctrl.removeLoadMore" on-data-change="$ctrl.onModelDataChange()">
class="dropdown__loadMore" </vn-model>
ng-class="{'active': $ctrl.itemsFiltered.length === $ctrl.activeOption, 'noMore' : !$ctrl.showLoadMore}" <div class="list">
ng-click="$ctrl.loadItems()" <ul
translate="{{$ctrl.showLoadMore ? 'Show More' : 'No more results'}}" class="dropdown"
></li> tabindex="-1"
ng-click="$ctrl.onContainerClick($event)">
</ul> </ul>
</vn-auto> <div
</vn-vertical> ng-if="$ctrl.statusText"
ng-click="$ctrl.onLoadMoreClick($event)"
class="status"
translate>
{{$ctrl.statusText}}
</div>
</div>
</div>

590
client/core/src/components/drop-down/drop-down.js Normal file → Executable file
View File

@ -1,44 +1,48 @@
import ngModule from '../../module'; import ngModule from '../../module';
import validKey from '../../lib/key-codes'; import Component from '../../lib/component';
import './style.scss'; import './style.scss';
import './model';
export default class DropDown { export default class DropDown extends Component {
constructor($element, $filter, $timeout) { constructor($element, $scope, $transclude, $timeout, $http, $translate) {
this.$element = $element; super($element, $scope);
this.$filter = $filter; this.$transclude = $transclude;
this.$timeout = $timeout; this.$timeout = $timeout;
this.$translate = $translate;
this._search = null; this.valueField = 'id';
this.itemsFiltered = []; this.showField = 'name';
this._search = undefined;
this._shown = false;
this._activeOption = -1; this._activeOption = -1;
this._focusingFilter = false; this.showLoadMore = true;
this._tryToShow = 0; this.showFilter = true;
this.input = this.element.querySelector('.search');
this.body = this.element.querySelector('.body');
this.container = this.element.querySelector('ul');
this.list = this.element.querySelector('.list');
this.docKeyDownHandler = e => this.onDocKeyDown(e);
this.docFocusInHandler = e => this.onDocFocusIn(e);
this.element.addEventListener('mousedown',
e => this.onBackgroundMouseDown(e));
this.element.addEventListener('focusin',
e => this.onFocusIn(e));
this.list.addEventListener('scroll',
e => this.onScroll(e));
} }
get container() { get shown() {
return this.$element[0].querySelector('ul.dropdown'); return this._shown;
} }
get show() { set shown(value) {
return this._show; if (value)
} this.show();
else
set show(value) { this.hide();
let oldValue = this.show;
// It wait up to 1 second if the dropdown opens but there is no data to show
if (value && !oldValue && !this.itemsFiltered.length && this._tryToShow < 4) {
this.$timeout(() => {
this._tryToShow++;
this.show = true;
if (this.activeOption === -1) {
this.activeOption = 0;
}
}, 250);
} else {
this._tryToShow = 0;
this._show = value;
this._toggleDropDown(value, oldValue);
}
} }
get search() { get search() {
@ -46,242 +50,390 @@ export default class DropDown {
} }
set search(value) { set search(value) {
let val = (value === undefined || value === '') ? null : value; value = value == '' || value == null ? null : value;
this._search = val; if (value === this._search) return;
if (this.filterAction) this._search = value;
this.onFilterRest(); this.$.model.clear();
else
this.filterItems(); this.$timeout.cancel(this.searchTimeout);
this.searchTimeout = this.$timeout(() => {
this.refreshModel();
this.searchTimeout = null;
}, 350);
this.buildList();
}
get statusText() {
let model = this.$.model;
let data = model.data;
let statusText = null;
if (model.isLoading || this.searchTimeout)
statusText = 'Loading...';
else if (data == null)
statusText = 'No data';
else if (model.moreRows)
statusText = 'Load More';
else if (data.length === 0)
statusText = 'No results found';
return statusText;
}
get model() {
return this.$.model;
} }
get activeOption() { get activeOption() {
return this._activeOption; return this._activeOption;
} }
set activeOption(value) { /**
if (value < 0) { * Shows the drop-down. If a parent is specified it is shown in a visible
value = 0; * relative position to it.
} else if (value >= this.itemsFiltered.length) { *
value = this.showLoadMore ? this.itemsFiltered.length : this.itemsFiltered.length - 1; * @param {String} search The initial search term or %null
} */
this.$timeout(() => { show(search) {
this._activeOption = value; if (this._shown) return;
if (value && value >= this.itemsFiltered.length - 3 && !this.removeLoadMore) { this._shown = true;
this.loadItems(); this._activeOption = -1;
} this.search = search;
}); this.buildList();
this.element.style.display = 'block';
this.list.scrollTop = 0;
this.$timeout(() => this.$element.addClass('shown'), 40);
this.document.addEventListener('keydown', this.docKeyDownHandler);
this.document.addEventListener('focusin', this.docFocusInHandler);
this.relocate();
this.input.focus();
} }
_toggleDropDown(value, oldValue) { /**
this.$timeout(() => { * Hides the drop-down.
this._eventScroll(value); */
this._calculatePosition(value, oldValue); hide() {
}); if (!this._shown) return;
this._shown = false;
this.element.style.display = '';
this.$element.removeClass('shown');
this.document.removeEventListener('keydown', this.docKeyDownHandler);
this.document.removeEventListener('focusin', this.docFocusInHandler);
if (this.parent)
this.parent.focus();
} }
_eventScroll(add, num) { /**
let count = num || 0; * Repositions the drop-down to a correct location relative to the parent.
if (add) { */
if (this.container) { relocate() {
this.container.addEventListener('scroll', e => this.loadFromScroll(e)); if (!this.parent) return;
// this.$timeout(() => { // falla al entrar por primera vez xq pierde el foco y cierra el dropdown
// this._setFocusInFilterInput();
// });
} else if (count < 4) {
count++;
this.$timeout(() => { // wait angular ngIf
this._eventScroll(add, count);
}, 250);
}
} else if (this.container) {
this.container.removeEventListener('scroll', e => this.loadFromScroll(e));
}
}
_setFocusInFilterInput() { let style = this.body.style;
let inputFilterSearch = this.$element[0].querySelector('input'); style.width = '';
this._focusingFilter = true; style.height = '';
if (inputFilterSearch)
this.$timeout(() => {
inputFilterSearch.focus();
this._focusingFilter = false;
}, 250);
}
_background(create) {
let el = document.getElementById('ddBack');
if (el) {
el.parentNode.removeChild(el);
}
if (create) {
el = document.createElement('div');
el.id = 'ddBack';
document.body.appendChild(el);
}
}
_calculatePosition(value, oldValue) {
if (value && !oldValue) {
if (this.parent === undefined) {
this.parent = this.$element.parent().parent();
}
let parentRect = this.parent.getBoundingClientRect(); let parentRect = this.parent.getBoundingClientRect();
let elemetRect = this.$element[0].getBoundingClientRect(); let bodyRect = this.body.getBoundingClientRect();
let instOffset = parentRect.bottom + elemetRect.height;
if (instOffset >= window.innerHeight) { let top = parentRect.top + parentRect.height;
this._background(true); let height = bodyRect.height;
this.$element.addClass('fixed-dropDown'); let width = Math.max(bodyRect.width, parentRect.width);
this.$element.css('top', `${(parentRect.top - elemetRect.height)}px`);
this.$element.css('left', `${(parentRect.x)}px`); let margin = 10;
this.$element.css('height', `${elemetRect.height}px`);
if (top + height + margin > window.innerHeight)
top = Math.max(parentRect.top - height, margin);
style.top = `${top}px`;
style.left = `${parentRect.left}px`;
style.width = `${width}px`;
if (height + margin * 2 > window.innerHeight)
style.height = `${window.innerHeight - margin * 2}px`;
} }
} else if (!value && oldValue) {
this.$element.removeAttr('style'); /**
if (this.itemWidth) { * Activates a option and scrolls the drop-down to that option.
this.$element.css('width', this.itemWidth + 'px'); *
* @param {Number} option The option index
*/
moveToOption(option) {
this.activateOption(option);
let list = this.list;
let li = this.activeLi;
if (!li) return;
let liRect = li.getBoundingClientRect();
let listRect = list.getBoundingClientRect();
if (liRect.bottom > listRect.bottom)
list.scrollTop += liRect.bottom - listRect.bottom;
else if (liRect.top < listRect.top)
list.scrollTop -= listRect.top - liRect.top;
} }
this.$element.removeClass('fixed-dropDown');
this._background(); /**
* Activates a option.
*
* @param {Number} option The option index
*/
activateOption(option) {
this._activeOption = option;
if (this.activeLi)
this.activeLi.className = '';
let data = this.$.model.data;
if (option >= 0 && data && option < data.length) {
this.activeLi = this.container.children[option];
this.activeLi.className = 'active';
} }
} }
filterItems() { /**
this.itemsFiltered = this.search ? this.$filter('filter')(this.items, this.search) : this.items; * Selects an option.
*
* @param {Number} option The option index
*/
selectOption(option) {
if (option != -1) {
let data = this.$.model.data;
let item = data ? data[option] : null;
let value = item ? item[this.valueField] : null;
if (this.multiple) {
if (!Array.isArray(this.selection)) {
this.selection = [];
this.field = [];
} }
onFilterRest() { this.selection.push(item);
if (this.filterAction) { this.field.push(value);
this.filterAction({search: this.search}); } else {
} this.selection = item;
this.field = value;
} }
clearSearch() { if (this.onSelect)
this.onSelect({value: value});
}
if (!this.multiple)
this.hide();
}
refreshModel() {
this.$.model.filter = {
fields: this.selectFields,
where: this.getWhere(this._search),
order: this.getOrder(),
limit: this.limit || 8
};
this.$.model.refresh(this._search);
}
getWhere(search) {
if (search == '' || search == null)
return undefined;
if (this.where) {
let jsonFilter = this.where.replace(/search/g, search);
return this.$.$eval(jsonFilter);
}
let where = {};
where[this.showField] = {regexp: search};
return where;
}
getOrder() {
if (this.order)
return this.order;
else if (this.showField)
return `${this.showField} ASC`;
return undefined;
}
onMouseDown(event) {
this.lastMouseEvent = event;
}
onBackgroundMouseDown(event) {
if (event != this.lastMouseEvent)
this.hide();
}
onFocusIn(event) {
this.lastFocusEvent = event;
}
onDocFocusIn(event) {
if (event !== this.lastFocusEvent && event.originalTarget !== this.parent)
this.hide();
}
onClearClick() {
this.search = null; this.search = null;
} }
selectOption() { onScroll() {
if (this.activeOption >= 0 && this.activeOption < this.items.length && this.items[this.activeOption]) { let list = this.list;
this.selected = this.items[this.activeOption]; let shouldLoad =
this.show = false; list.scrollTop + list.clientHeight >= (list.scrollHeight - 40)
this.clearSearch(); && !this.$.model.isLoading;
} else if (this.showLoadMore && this.activeOption === this.items.length) {
this.loadMore(); if (shouldLoad)
} this.$.model.loadMore();
} }
onKeydown(event) { onLoadMoreClick(event) {
if (this.show) {
if (event.keyCode === 13) { // Enter
this.$timeout(() => {
this.selectOption();
});
event.preventDefault(); event.preventDefault();
} else if (event.keyCode === 27) { // Escape this.$.model.loadMore();
this.clearSearch();
} else if (event.keyCode === 38) { // Arrow up
this.activeOption--;
this.$timeout(() => {
this.setScrollPosition();
}, 100);
} else if (event.keyCode === 40) { // Arrow down
this.activeOption++;
this.$timeout(() => {
this.setScrollPosition();
}, 100);
} else if (event.keyCode === 35) { // End
this.activeOption = this.itemsFiltered.length - 1;
this.$timeout(() => {
this.setScrollPosition();
}, 100);
} else if (event.keyCode === 36) { // Start
this.activeOption = 0;
this.$timeout(() => {
this.setScrollPosition();
}, 100);
} else if (this.filter) {
let oldValue = this.search || '';
if (validKey(event)) {
this.search = oldValue + String.fromCharCode(event.keyCode);
} else if (event.keyCode === 8) { // backSpace
this.search = oldValue.slice(0, -1);
} }
} /* else {
console.error(`Error: keyCode ${event.keyCode} not supported`); onContainerClick(event) {
} */ if (event.defaultPrevented) return;
let index = getPosition(this.container, event);
if (index != -1) this.selectOption(index);
} }
onModelDataChange() {
this.buildList();
} }
setScrollPosition() {
let child = this.$element[0].querySelector('ul.dropdown li.active'); onDocKeyDown(event) {
if (child) { if (event.defaultPrevented) return;
let childRect = child.getBoundingClientRect();
let containerRect = this.container.getBoundingClientRect(); let data = this.$.model.data;
if (typeof child.scrollIntoView === 'function' && (childRect.top > containerRect.top + containerRect.height || childRect.top < containerRect.top)) { let option = this.activeOption;
child.scrollIntoView(); let nOpts = data ? data.length - 1 : 0;
switch (event.keyCode) {
case 13: // Enter
this.selectOption(option);
break;
case 27: // Escape
this.hide();
break;
case 38: // Up
this.moveToOption(option <= 0 ? nOpts : option - 1);
break;
case 40: // Down
this.moveToOption(option >= nOpts ? 0 : option + 1);
break;
case 35: // End
this.moveToOption(nOpts);
break;
case 36: // Start
this.moveToOption(0);
break;
default:
return;
} }
event.preventDefault();
this.$.$applyAsync();
} }
}
selectItem(item) { buildList() {
this.selected = item; this.destroyScopes();
this.scopes = [];
let hasTemplate = this.$transclude &&
this.$transclude.isSlotFilled('tplItem');
let fragment = this.document.createDocumentFragment();
let data = this.$.model.data;
if (data) {
for (let i = 0; i < data.length; i++) {
let li = this.document.createElement('li');
fragment.appendChild(li);
if (this.multiple) { if (this.multiple) {
item.checked = !item.checked; let check = this.document.createElement('input');
this.show = true; check.type = 'checkbox';
li.appendChild(check);
if (this.field && this.field.indexOf(data[i][this.valueField]) != -1)
check.checked = true;
}
if (hasTemplate) {
this.$transclude((clone, scope) => {
Object.assign(scope, data[i]);
li.appendChild(clone[0]);
this.scopes[i] = scope;
}, null, 'tplItem');
} else { } else {
this.show = false; let text = this.document.createTextNode(data[i][this.showField]);
li.appendChild(text);
} }
} }
loadItems() {
if (this.showLoadMore && this.loadMore) {
this.loadMore();
}
this.show = true;
}
loadFromScroll(e) {
let containerRect = e.target.getBoundingClientRect();
if (e.target.scrollHeight - e.target.scrollTop - containerRect.height <= 50) {
this.loadItems();
}
}
$onChanges(changesObj) {
if (changesObj.show && changesObj.itemWidth && changesObj.itemWidth.currentValue) {
this.$element.css('width', changesObj.itemWidth.currentValue + 'px');
}
if (changesObj.items) {
this.filterItems();
}
}
$onInit() {
if (this.parent)
this.parent.addEventListener('keydown', e => this.onKeydown(e));
}
$onDestroy() {
if (this.parent)
this.parent.removeEventListener('keydown', e => this.onKeydown(e));
}
} }
DropDown.$inject = ['$element', '$filter', '$timeout']; this.container.innerHTML = '';
this.container.appendChild(fragment);
this.activateOption(this._activeOption);
this.relocate();
}
destroyScopes() {
if (this.scopes)
for (let scope of this.scopes)
scope.$destroy();
}
$onDestroy() {
this.destroyScopes();
}
}
DropDown.$inject = ['$element', '$scope', '$transclude', '$timeout', '$http', '$translate'];
/**
* Gets the position of an event element relative to a parent.
*
* @param {HTMLElement} parent The parent element
* @param {Event} event The event object
* @return {Number} The element index
*/
function getPosition(parent, event) {
let target = event.target;
let children = parent.children;
if (target === parent)
return -1;
while (target.parentNode !== parent)
target = target.parentNode;
for (let i = 0; i < children.length; i++)
if (children[i] === target)
return i;
return -1;
}
ngModule.component('vnDropDown', { ngModule.component('vnDropDown', {
template: require('./drop-down.html'), template: require('./drop-down.html'),
controller: DropDown, controller: DropDown,
bindings: { bindings: {
items: '<', field: '=?',
show: '<', data: '<?',
filter: '@?', selection: '=?',
selected: '=', search: '<?',
search: '=?', limit: '<?',
loadMore: '&?', showFilter: '<?',
removeLoadMore: '<?',
filterAction: '&?',
showLoadMore: '<?',
itemWidth: '<?',
parent: '<?', parent: '<?',
multiple: '<?' multiple: '<?',
onSelect: '&?'
}, },
transclude: { transclude: {
vnItem: '?vnItem' tplItem: '?tplItem'
} }
}); });

View File

@ -1,9 +1,13 @@
import './drop-down.js'; import './drop-down.js';
import template from './drop-down.html';
describe('Component vnDropDown', () => { describe('Component vnDropDown', () => {
let $componentController; let $componentController;
let $timeout; let $timeout;
let $element; let $element;
let $scope;
let $httpBackend;
let $q;
let $filter; let $filter;
let controller; let controller;
@ -11,337 +15,34 @@ describe('Component vnDropDown', () => {
angular.mock.module('client'); angular.mock.module('client');
}); });
beforeEach(angular.mock.inject((_$componentController_, _$timeout_, _$filter_, _$httpBackend_) => { beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$timeout_, _$httpBackend_, _$q_, _$filter_) => {
_$httpBackend_.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
$componentController = _$componentController_; $componentController = _$componentController_;
$element = angular.element('<div><ul><li></li></ul></div>'); $element = angular.element(`<div>${template}</div>`);
$timeout = _$timeout_; $timeout = _$timeout_;
$q = _$q_;
$filter = _$filter_; $filter = _$filter_;
controller = $componentController('vnDropDown', {$element, $timeout, $filter}); $scope = $rootScope.$new();
$httpBackend = _$httpBackend_;
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
$scope.model = $componentController('vnModel', {$httpBackend, $q, $filter});
controller = $componentController('vnDropDown', {$element, $scope, $transclude: null, $timeout, $httpBackend, $translate: null});
controller.parent = angular.element('<vn-parent></vn-parent>')[0]; controller.parent = angular.element('<vn-parent></vn-parent>')[0];
})); }));
describe('show() setter', () => { describe('show() method', () => {
it(`should define controllers _show using the value received as argument`, () => { it(`should define controllers _show using the value received as argument`, () => {
controller._show = 'old value'; controller.show();
controller.show = 'new value';
expect(controller._show).toEqual('new value'); expect(controller.shown).toEqual(true);
}); });
}); });
describe('search()', () => { describe('hide() method', () => {
it(`should set controllers _search property with the value received`, () => { it(`should define controllers _show using the value received as argument`, () => {
controller.search = 'some filter valiue'; controller.hide();
expect(controller._search).toEqual('some filter valiue'); expect(controller.shown).toEqual(false);
});
it(`should set controllers _search property to null as the value received is an empty string`, () => {
controller.search = '';
expect(controller._search).toEqual(null);
});
it(`should call onFilterRest() if controllers filterAction is defined`, () => {
controller.filterAction = true;
spyOn(controller, 'onFilterRest');
controller.search = 'some filter valiue';
expect(controller.onFilterRest).toHaveBeenCalledWith();
});
it(`should call filterItems() if controllers filterAction is undefined`, () => {
controller.filterAction = undefined;
spyOn(controller, 'filterItems');
controller.search = 'some filter valiue';
expect(controller.filterItems).toHaveBeenCalledWith();
});
});
describe('activeOption() setter', () => {
it(`should set _activeOption as items.length if showLoadMore is defined if activeOption is bigger than items.length then call loadItems()`, () => {
spyOn(controller, 'loadItems');
controller.showLoadMore = true;
controller.itemsFiltered = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
controller.activeOption = 10;
$timeout.flush();
expect(controller.activeOption).toEqual(4);
expect(controller.loadItems).toHaveBeenCalledWith();
});
it(`should set _activeOption as activeOption if showLoadMore is defined if activeOption is smaller than items.length then call loadItems()`, () => {
spyOn(controller, 'loadItems');
controller.showLoadMore = true;
controller.itemsFiltered = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
controller.activeOption = 2;
$timeout.flush();
expect(controller.activeOption).toEqual(2);
expect(controller.loadItems).toHaveBeenCalledWith();
});
it(`should set _activeOption as items.length -1 if showLoadMore is not defined then call loadItems()`, () => {
spyOn(controller, 'loadItems');
controller.showLoadMore = undefined;
controller.itemsFiltered = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
controller.activeOption = 10;
$timeout.flush();
expect(controller.activeOption).toEqual(3);
expect(controller.loadItems).toHaveBeenCalledWith();
});
it(`should define _activeOption as activeOption and never call loadItems()`, () => {
spyOn(controller, 'loadItems');
controller.itemsFiltered = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}, {id: 5, name: 'Doctor X'}];
controller.activeOption = 1;
$timeout.flush();
expect(controller.activeOption).toEqual(1);
expect(controller.loadItems).not.toHaveBeenCalledWith();
});
});
describe('filterItems() setter', () => {
it(`should set _itemsFiltered using the value of items`, () => {
controller.items = [{id: 1, name: 'Batman'}];
controller.filterItems();
expect(controller.itemsFiltered).toEqual(controller.items);
});
it(`should set _itemsFiltered with the filtered value of items`, () => {
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
controller.search = 'Batman';
controller.filterItems();
expect(controller.itemsFiltered).toEqual([Object({id: 1, name: 'Batman'})]);
});
it(`should set _itemsFiltered an empty array`, () => {
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
controller.search = 'the Joker';
expect(controller.itemsFiltered.length).toEqual(0);
});
});
describe('onFilterRest()', () => {
it(`should call the filterAction() with a constructed object as argument`, () => {
controller.filterAction = () => {};
controller.search = 'Batman';
spyOn(controller, 'filterAction');
controller.onFilterRest();
expect(controller.filterAction).toHaveBeenCalledWith({search: controller.search});
});
});
describe('$onChanges()', () => {
it(`should set the width css of the $element`, () => {
let argumentObject = {show: true, itemWidth: {currentValue: 100}};
spyOn(controller.$element, 'css');
controller.$onChanges(argumentObject);
expect(controller.$element.css).toHaveBeenCalledWith('width', '100px');
});
it(`should set the width css of the $element`, () => {
let argumentObject = {items: {id: 1, name: 'Batman'}};
spyOn(controller, 'filterItems');
controller.$onChanges(argumentObject);
expect(controller.filterItems).toHaveBeenCalledWith();
});
});
describe('clearSearch()', () => {
it(`should set the controllers search property to null`, () => {
controller.search = true;
controller.clearSearch();
expect(controller.search).toEqual(null);
});
});
describe('selectOption()', () => {
it(`should set controllers selected and show properties then call clearSearch() as _activeOption is smaller than items.length`, () => {
spyOn(controller, 'clearSearch');
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
controller._activeOption = 0;
controller.selectOption();
expect(controller.selected).toEqual(controller.items[controller._activeOption]);
expect(controller._show).toEqual(false);
expect(controller.clearSearch).toHaveBeenCalledWith();
});
it(`should not set controllers selected, show and never call clearSearch() as _activeOption is bigger than items.length`, () => {
spyOn(controller, 'clearSearch');
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
controller._activeOption = 100;
controller.selectOption();
expect(controller.selected).not.toBeDefined();
expect(controller._show).not.toBeDefined();
expect(controller.clearSearch).not.toHaveBeenCalledWith();
});
it(`should call loadMore() if the activeValue equals items.length`, () => {
controller.loadMore = () => {};
spyOn(controller, 'loadMore');
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
controller._activeOption = 4;
controller.showLoadMore = 4;
controller.selectOption();
expect(controller.loadMore).toHaveBeenCalledWith();
});
});
describe('onKeydown()', () => {
it(`should call selectOption() and preventDefault() if Enter key is pressed`, () => {
spyOn(controller, 'selectOption');
controller._show = true;
controller.element = document.createElement('div');
let event = {target: controller.element, preventDefault: () => {}};
event.keyCode = 13;
spyOn(event, 'preventDefault');
controller.onKeydown(event);
$timeout.flush();
expect(controller.selectOption).toHaveBeenCalledWith();
expect(event.preventDefault).toHaveBeenCalledWith();
});
it(`should call clearSearch() Esc key is pressed`, () => {
spyOn(controller, 'clearSearch');
controller._show = true;
controller.element = document.createElement('div');
let event = {target: controller.element};
event.keyCode = 27;
controller.onKeydown(event);
expect(controller.clearSearch).toHaveBeenCalledWith();
});
it(`should call clearSearch() Esc key is pressed and take off 1 from _activeOption`, () => {
controller.itemsFiltered = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
spyOn(controller, 'setScrollPosition');
controller._show = true;
controller.element = document.createElement('div');
let event = {target: controller.element};
event.keyCode = 38;
controller._activeOption = 1;
controller.onKeydown(event);
$timeout.flush();
expect(controller.setScrollPosition).toHaveBeenCalledWith();
expect(controller._activeOption).toEqual(0);
});
it(`should call clearSearch() Esc key is pressed and add up 1 to _activeOption`, () => {
controller.itemsFiltered = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
spyOn(controller, 'setScrollPosition');
controller._show = true;
controller.element = document.createElement('div');
let event = {target: controller.element};
event.keyCode = 40;
controller._activeOption = 1;
controller.onKeydown(event);
$timeout.flush();
expect(controller.setScrollPosition).toHaveBeenCalledWith();
expect(controller._activeOption).toEqual(2);
});
});
describe('setScrollPosition()', () => {
it(`should call child.scrollIntoView if defined `, () => {
$element[0].firstChild.setAttribute('class', 'dropdown');
$element[0].firstChild.firstChild.setAttribute('class', 'active');
let child = $element[0].firstChild.firstChild;
spyOn(child, 'getBoundingClientRect').and.returnValue({top: 100});
let container = $element[0].firstChild;
spyOn(container, 'getBoundingClientRect').and.returnValue({top: 10, height: 70});
child.scrollIntoView = () => {};
spyOn(child, 'scrollIntoView');
controller._activeOption = 0;
controller.setScrollPosition();
expect(child.scrollIntoView).toHaveBeenCalledWith();
});
});
describe('selectItem()', () => {
it(`should pass item to selected and set controller._show to false`, () => {
let item = {id: 1, name: 'Batman'};
controller.selectItem(item);
expect(controller.selected).toEqual(item);
expect(controller._show).toEqual(false);
});
it(`should pass item to selected and set controller._show to true if the controller.multiple is defined`, () => {
let item = {id: 1, name: 'Batman'};
controller.multiple = true;
controller.selectItem(item);
expect(controller.selected).toEqual(item);
expect(controller._show).not.toBeDefined();
});
});
describe('loadItems()', () => {
it(`should set controller.show to true`, () => {
controller.show = false;
controller.itemsFiltered = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
controller.loadItems();
expect(controller.show).toEqual(true);
});
it(`should call loadMore() and then set controller._show to true if there are items`, () => {
controller.showLoadMore = () => {};
controller.loadMore = () => {};
spyOn(controller, 'loadMore');
controller.itemsFiltered = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
controller.loadItems();
expect(controller._show).toEqual(true);
expect(controller.loadMore).toHaveBeenCalledWith();
});
it(`should call loadMore() and then set controller._show to undefined if there are not items`, () => {
controller.showLoadMore = () => {};
controller.loadMore = () => {};
spyOn(controller, 'loadMore');
controller.itemsFiltered = [];
controller.loadItems();
expect(controller._show).not.toBeDefined();
expect(controller.loadMore).toHaveBeenCalledWith();
});
});
describe('$onInit()', () => {
it(`should add an event listener to the parent element`, () => {
spyOn(controller.parent, 'addEventListener');
controller.$onInit();
expect(controller.parent.addEventListener).toHaveBeenCalledWith('keydown', jasmine.any(Function));
});
});
describe('$onDestroy()', () => {
it(`should remove an event listener from the parent element`, () => {
spyOn(controller.parent, 'removeEventListener');
controller.$onDestroy();
expect(controller.parent.removeEventListener).toHaveBeenCalledWith('keydown', jasmine.any(Function));
}); });
}); });
}); });

View File

@ -0,0 +1,107 @@
import ngModule from '../../module';
export default class Model {
constructor($http, $q, $filter) {
this.$http = $http;
this.$q = $q;
this.$filter = $filter;
this.filter = null;
this.clear();
}
get isLoading() {
return this.canceler != null;
}
loadMore() {
if (this.moreRows) {
let filter = Object.assign({}, this.myFilter);
filter.skip += filter.limit;
this.sendRequest(filter, true);
}
}
clear() {
this.cancelRequest();
this.data = null;
this.moreRows = false;
this.dataChanged();
}
refresh(search) {
if (this.url) {
let filter = Object.assign({}, this.filter);
if (filter.limit)
filter.skip = 0;
this.clear();
this.sendRequest(filter);
} else if (this.staticData) {
if (search)
this.data = this.$filter('filter')(this.staticData, search);
else
this.data = this.staticData;
this.dataChanged();
}
}
cancelRequest() {
if (this.canceler) {
this.canceler.resolve();
this.canceler = null;
this.request = null;
}
}
sendRequest(filter, append) {
this.cancelRequest();
this.canceler = this.$q.defer();
let options = {timeout: this.canceler.promise};
let json = encodeURIComponent(JSON.stringify(filter));
this.request = 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.data = this.data.concat(data);
else
this.data = data;
this.myFilter = filter;
this.moreRows = filter.limit && data.length == filter.limit;
this.onRequestEnd();
this.dataChanged();
}
onRemoteError(json) {
this.onRequestEnd();
}
onRequestEnd() {
this.request = null;
this.canceler = null;
}
dataChanged() {
if (this.onDataChange)
this.onDataChange();
}
}
Model.$inject = ['$http', '$q', '$filter'];
ngModule.component('vnModel', {
controller: Model,
bindings: {
url: '@?',
staticData: '<?',
data: '=?',
limit: '<?',
onDataChange: '&?'
}
});

127
client/core/src/components/drop-down/style.scss Normal file → Executable file
View File

@ -1,80 +1,95 @@
vn-drop-down { vn-drop-down {
position: absolute;
z-index: 10; z-index: 10;
padding: 0 15px; position: fixed;
margin-left: -15px; display: none;
background: transparent; top: 0;
max-height: 446px; left: 0;
overflow: hidden; right: 0;
.dropdown-body{ bottom: 0;
background: white;
border: 1px solid #A7A7A7; &.shown {
.filter{ & > .body {
padding: 5px 9px 5px 5px; transform: translateY(0);
input{ opacity: 1;
height: 25px;
padding-left: 5px;
} }
vn-icon{ }
font-size: 16px; & > .body {
margin-left: -20px; position: fixed;
margin-top: 7px; box-shadow: 0 .1em .4em rgba(1, 1, 1, .4);
border-radius: .1em;
background-color: white;
display: flex;
flex-direction: column;
transform: translateY(-.4em);
opacity: 0;
transition-property: opacity, transform;
transition-duration: 250ms;
transition-timing-function: ease-in-out;
& > .filter {
position: relative;
& > .search {
display: block;
width: 100%;
box-sizing: border-box;
border: none;
border-bottom: 1px solid #ccc;
padding: .7em;
}
& > vn-icon[icon=clear] {
display: none;
cursor: pointer; cursor: pointer;
position: absolute;
right: .5em;
top: .7em;
height: 1em;
color: #888;
border-radius: 50%;
background-color: rgba(255, 255, 255, .8);
font-size: 18px;
&:hover { &:hover {
color: red; color: #333;
} }
} }
&:hover > vn-icon[icon=clear] {
display: block;
} }
}
& > .list {
max-height: 12.2em;
overflow: auto;
ul { ul {
padding: 0; padding: 0;
margin: 0; margin: 0;
background: white; }
max-height: 378px; li, .status {
overflow-y: auto;
li {
outline: none; outline: none;
list-style-type: none; list-style-type: none;
padding: 5px 10px; padding: .6em;
cursor: pointer; cursor: pointer;
white-space: nowrap; white-space: nowrap;
&.dropdown__loadMore{ transition: background-color 250ms ease-out;
color: rgb(255,171,64); display: flex;
font-weight: 700;
& > input[type=checkbox] {
margin: 0;
margin-right: .6em;
} }
&.dropdown__loadMore.noMore{ &:hover {
color:#424242; background-color: rgba(0, 0, 0, .1);
font-weight: 700;
opacity: 0.7;
} }
input[type=checkbox]{ &.active {
float: left;
margin: 5px 5px 0 0;
}
}
li.active{
background-color: #3D3A3B; background-color: #3D3A3B;
color: white; color: white;
} }
} }
} .status {
} color: #ffab40;
#ddBack { font-weight: bold;
position: fixed; }
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: transparent;
}
vn-drop-down.fixed-dropDown {
position: fixed;
margin: 0;
padding: 0;
.dropdown-body{
height: 100%;
ul{
border-bottom: 1px solid #A7A7A7;
} }
} }
} }

View File

@ -15,6 +15,7 @@ export default class Controller extends Component {
this.button = $element[0].querySelector('button'); this.button = $element[0].querySelector('button');
this.textNode = this.snackbar.querySelector('.text'); this.textNode = this.snackbar.querySelector('.text');
} }
/** /**
* Shows a notification. * Shows a notification.
* *
@ -29,14 +30,13 @@ export default class Controller extends Component {
this.button.textContent = this.button.textContent =
data.actionText || this.$translate.instant('Hide'); data.actionText || this.$translate.instant('Hide');
this.documentClickHandler = e => this.onDocumentClick(e); this.timeoutId = setTimeout(() =>
document.addEventListener('click', this.documentClickHandler); this.hide(), data.timeout || 6000);
this.timeoutId = setTimeout(() => this.hide(),
data.timeout || 6000);
this.transitionTimeout = this.transitionTimeout = setTimeout(() =>
setTimeout(() => this.$snackbar.addClass('shown'), 30); this.$snackbar.addClass('shown'), 30);
} }
/** /**
* Shows an error. * Shows an error.
* *
@ -46,38 +46,38 @@ export default class Controller extends Component {
this.$snackbar.addClass('error'); this.$snackbar.addClass('error');
this.show(data); this.show(data);
} }
/** /**
* Hides the snackbar. * Hides the snackbar.
*/ */
hide() { hide() {
if (!this.shown) return; if (!this.shown) return;
clearTimeout(this.timeoutId); clearTimeout(this.timeoutId);
document.removeEventListener('click', this.documentClickHandler);
this.shown = false; this.shown = false;
this.hideTimeout = setTimeout(() => this.onTransitionEnd(), 250); this.hideTimeout = setTimeout(() => this.onTransitionEnd(), 250);
this.transitionTimeout = this.transitionTimeout =
setTimeout(() => this.$snackbar.removeClass('shown'), 30); setTimeout(() => this.$snackbar.removeClass('shown'), 30);
} }
onTransitionEnd() { onTransitionEnd() {
this.$snackbar.removeClass('error'); this.$snackbar.removeClass('error');
this.textNode.textContent = ''; this.textNode.textContent = '';
this.button.textContent = ''; this.button.textContent = '';
this.actionHandler = null; this.actionHandler = null;
} }
onDocumentClick(event) {
if (event === this.event) return;
this.hide();
}
onSnackbarClick(event) { onSnackbarClick(event) {
this.event = event; this.event = event;
} }
onButtonClick() { onButtonClick() {
if (this.actionHandler) if (this.actionHandler)
this.actionHandler(); this.actionHandler();
else else
this.hide(); this.hide();
} }
clearTimeouts() { clearTimeouts() {
clearTimeout(this.timeoutId); clearTimeout(this.timeoutId);
clearTimeout(this.hideTimeout); clearTimeout(this.hideTimeout);
@ -86,6 +86,7 @@ export default class Controller extends Component {
this.hideTimeout = null; this.hideTimeout = null;
this.transitionTimeout = null; this.transitionTimeout = null;
} }
$onDestroy() { $onDestroy() {
this.clearTimeouts(); this.clearTimeouts();
} }

View File

@ -12,17 +12,21 @@
<vn-auto style="position: relative" pad-medium text-center> <vn-auto style="position: relative" pad-medium text-center>
<img <img
ng-src="http://verdnatura.es/vn-image-data/catalog/200x200/{{::$ctrl.item.image}}" ng-src="http://verdnatura.es/vn-image-data/catalog/200x200/{{::$ctrl.item.image}}"
zoom-image="http://verdnatura.es/vn-image-data/catalog/900x900/{{::$ctrl.item.image}}" on-error-src/> zoom-image="http://verdnatura.es/vn-image-data/catalog/900x900/{{::$ctrl.item.image}}"
<a href="https://www.verdnatura.es/#!form=admin/items&filter={{::$ctrl.item.id}}" target="_blank"><vn-float-button icon="edit" on-error-src/>
style="position: absolute; bottom: 1em; right: 1em;" <a href="https://www.verdnatura.es/#!form=admin/items&filter={{::$ctrl.item.id}}" target="_blank">
vn-visible-by="administrative"></vn-float-button> <vn-float-button
icon="edit"
style="position: absolute; margin: 1em; bottom: 0; right: 0;"
vn-visible-by="administrative">
</vn-float-button>
</a> </a>
</vn-auto> </vn-auto>
<vn-auto pad-medium> <vn-auto pad-medium>
<h6>{{$ctrl.item.name}}</h6> <h6>{{$ctrl.item.name}}</h6>
<div><vn-label translate>Id</vn-label> {{$ctrl.item.id}}</div> <div><vn-label translate>Id</vn-label> {{$ctrl.item.id}}</div>
<div ng-repeat="itemTag in $ctrl.itemTags | limitTo:4"> <div ng-repeat="itemTag in $ctrl.itemTags | limitTo:4">
<div><vn-label translate>{{$ctrl.tags[itemTag.tagFk].name}}</vn-label>: {{itemTag.value}}</div> <div><vn-label translate>{{$ctrl.tags[itemTag.tagFk].name}}</vn-label> {{itemTag.value}}</div>
</div> </div>
</vn-auto> </vn-auto>
</vn-vertical> </vn-vertical>

View File

@ -32,14 +32,20 @@
</vn-one> </vn-one>
<vn-one margin-medium> <vn-one margin-medium>
<vn-vertical> <vn-vertical>
<h5 translate>Tags</h5> <h5 translate>Tax</h5>
<p ng-repeat="tag in $ctrl.tags track by tag.id"> <p ng-repeat="tax in $ctrl.taxes track by $index">
<span translate>{{tag.tag.name}}</span>: <b>{{tag.value}}</b> <span translate>{{tax.country.country}}</span>: <b>{{tax.taxClass.description}}</b>
</p> </p>
</vn-vertical> </vn-vertical>
</vn-one> </vn-one>
</vn-horizontal> </vn-horizontal>
<vn-horizontal> <vn-horizontal>
<vn-one margin-medium>
<h5 translate>Tags</h5>
<p ng-repeat="tag in $ctrl.tags track by tag.id">
<span translate>{{tag.tag.name}}</span>: <b>{{tag.value}}</b>
</p>
</vn-one>
<vn-one margin-medium> <vn-one margin-medium>
<vn-vertical> <vn-vertical>
<h5 translate>Nicho</h5> <h5 translate>Nicho</h5>

View File

@ -17,6 +17,25 @@ class ItemSummary {
}); });
} }
_getTaxes() {
let filter = {
fields: ['id', 'countryFk', 'taxClassFk'],
include: [{
relation: 'country',
scope: {fields: ['country']}
}, {
relation: 'taxClass',
scope: {fields: ['id', 'description']}
}]
};
let urlFilter = encodeURIComponent(JSON.stringify(filter));
let url = `/item/api/Items/${this.item.id}/taxes?filter=${urlFilter}`;
this.$http.get(url).then(json => {
this.taxes = json.data;
});
}
_getBotanical() { _getBotanical() {
let filter = { let filter = {
where: {itemFk: this.item.id}, where: {itemFk: this.item.id},
@ -58,6 +77,7 @@ class ItemSummary {
this._getTags(); this._getTags();
this._getBarcodes(); this._getBarcodes();
this._getNiches(); this._getNiches();
this._getTaxes();
if (!this.item.botanical) if (!this.item.botanical)
this._getBotanical(); this._getBotanical();
} }

View File

@ -1,5 +1,5 @@
<vn-horizontal> <vn-horizontal>
<ul style="list-style-type: none; margin: 0; padding: 0; width: 100%; color: #666;"> <ul style="list-style-type: none; margin: 0; padding: 0; width: 100%;">
<vn-menu-item ng-repeat="item in $ctrl.items" item="::item"></vn-menu-item> <vn-menu-item ng-repeat="item in $ctrl.items" item="::item"></vn-menu-item>
</ul> </ul>
</vn-horizontal> </vn-horizontal>

View File

@ -1,5 +1,5 @@
import ngModule from '../../module'; import ngModule from '../../module';
import './style.css'; import './style.scss';
export default class LeftMenu { export default class LeftMenu {
constructor(aclService, $state) { constructor(aclService, $state) {

View File

@ -1,7 +1,9 @@
<li ng-class="{active: $ctrl.item.active}"> <li ng-class="{active: $ctrl.item.active}">
<a ui-sref="{{::$ctrl.item.href}}" style="display: block; text-decoration: none; color: inherit; padding: .5em 2em;"> <a ui-sref="{{::$ctrl.item.href}}"
<i class="material-icons" style="float: right; margin-left: .4em;">keyboard_arrow_right</i> class="vn-clickable"
<i class="material-icons" style="vertical-align: middle; margin-right: .4em;">{{::$ctrl.item.icon}}</i> style="display: block; text-decoration: none; padding: .5em 2em;">
<vn-icon icon="keyboard_arrow_right" class="material-icons" style="float: right; margin-left: .4em;"></vn-icon>
<vn-icon icon="{{::$ctrl.item.icon}}" class="material-icons" style="vertical-align: middle; margin-right: .4em;"></vn-icon>
<span translate>{{::$ctrl.item.description}}</span> <span translate>{{::$ctrl.item.description}}</span>
</a> </a>
</li> </li>

View File

@ -1,7 +0,0 @@
vn-menu-item a:hover {
color: white !important;
background-color: #424242;
}
vn-menu-item li.active{
background-color: #E6E6E6;
}

View File

@ -0,0 +1,7 @@
vn-menu-item {
& > li.active {
background-color: #424242;
color: white;
}
}

View File

@ -24,15 +24,6 @@ html [fixed-bottom-right] {
bottom: 2em; bottom: 2em;
right: 2em; right: 2em;
} }
vn-label {
font-size: .9em;
color: #666;
}
vn-button-bar {
display: block;
margin-top: $margin-small;
}
html [text-center], .text-center { html [text-center], .text-center {
text-align: center; text-align: center;
} }
@ -105,6 +96,33 @@ html [noDrop], .noDrop{
cursor: no-drop; cursor: no-drop;
} }
a {
color: inherit;
}
.vn-clickable {
cursor: pointer;
transition: background-color 250ms ease-out;
&:hover {
background-color: rgba(0, 0, 0, .1);
}
}
button {
@extend .vn-clickable;
}
vn-label {
font-size: .9em;
color: #666;
}
vn-button-bar {
display: block;
margin-top: $margin-small;
}
vn-main-block { vn-main-block {
display:block; display:block;
max-width: 1920px; max-width: 1920px;
@ -118,6 +136,7 @@ vn-main-block {
padding-bottom: 1em; padding-bottom: 1em;
} }
} }
.vn-descriptor { .vn-descriptor {
& .header { & .header {
background: #ffa410; background: #ffa410;
@ -130,15 +149,15 @@ vn-main-block {
font-size: 2.5em; font-size: 2.5em;
} }
& > a { & > a {
@extend .vn-clickable;
display: flex; display: flex;
align-items: center; align-items: center;
padding: .5em; padding: .5em;
color: white; color: white;
text-decoration: none; text-decoration: none;
transition: background-color 250ms ease-out;
&:hover {
background-color: rgba(1, 1, 1, 0.1);
}
& > vn-icon { & > vn-icon {
font-size: 1.8em; font-size: 1.8em;
} }
@ -154,19 +173,12 @@ vn-main-block {
.vn-list-item { .vn-list-item {
@extend .pad-medium; @extend .pad-medium;
@extend .border-solid-bottom; @extend .border-solid-bottom;
@extend .vn-clickable;
display: block; display: block;
text-decoration: none; text-decoration: none;
color: inherit; color: inherit;
&:hover {
color: white;
background-color: #424242;
vn-label {
color: #aaa;
}
}
& > vn-horizontal > .buttons { & > vn-horizontal > .buttons {
align-items: center; align-items: center;
@ -174,6 +186,7 @@ vn-main-block {
opacity: .4; opacity: .4;
color: #ffa410; color: #ffa410;
margin-left: .5em; margin-left: .5em;
transition: opacity 250ms ease-out;
&:hover { &:hover {
opacity: 1; opacity: 1;

View File

@ -25,8 +25,8 @@ export default {
socialName: `${components.vnTextfield}[name="socialName"]`, socialName: `${components.vnTextfield}[name="socialName"]`,
userName: `${components.vnTextfield}[name="userName"]`, userName: `${components.vnTextfield}[name="userName"]`,
email: `${components.vnTextfield}[name="email"]`, email: `${components.vnTextfield}[name="email"]`,
salesPersonInput: `${components.vnAutocomplete}[field="$ctrl.client.salesPersonFk"] > vn-vertical > ${components.vnTextfield}`, salesPersonInput: `vn-autocomplete[field="$ctrl.client.salesPersonFk"] input`,
salesBruceBannerOption: `${components.vnAutocomplete}[field="$ctrl.client.salesPersonFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(1)`, salesBruceBannerOption: `vn-autocomplete[field="$ctrl.client.salesPersonFk"] vn-drop-down ul > li:nth-child(1)`,
createButton: `${components.vnSubmit}` createButton: `${components.vnSubmit}`
}, },
clientBasicData: { clientBasicData: {
@ -37,10 +37,10 @@ export default {
mobileInput: `${components.vnTextfield}[name="mobile"]`, mobileInput: `${components.vnTextfield}[name="mobile"]`,
faxInput: `${components.vnTextfield}[name="fax"]`, faxInput: `${components.vnTextfield}[name="fax"]`,
emailInput: `${components.vnTextfield}[name="email"]`, emailInput: `${components.vnTextfield}[name="email"]`,
salesPersonInput: `${components.vnAutocomplete}[field="$ctrl.client.salesPersonFk"] > vn-vertical > ${components.vnTextfield}`, salesPersonInput: `${components.vnAutocomplete}[field="$ctrl.client.salesPersonFk"] input`,
salesPersonOptionOne: `${components.vnAutocomplete}[field="$ctrl.client.salesPersonFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(1)`, salesPersonOptionOne: `${components.vnAutocomplete}[field="$ctrl.client.salesPersonFk"] vn-drop-down ul > li:nth-child(1)`,
channelInput: `${components.vnAutocomplete}[field="$ctrl.client.contactChannelFk"] > vn-vertical > ${components.vnTextfield}`, channelInput: `${components.vnAutocomplete}[field="$ctrl.client.contactChannelFk"] input`,
channelMetropolisOption: `${components.vnAutocomplete}[field="$ctrl.client.contactChannelFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(3)`, channelMetropolisOption: `${components.vnAutocomplete}[field="$ctrl.client.contactChannelFk"] vn-drop-down ul > li:nth-child(3)`,
saveButton: `${components.vnSubmit}` saveButton: `${components.vnSubmit}`
}, },
clientFiscalData: { clientFiscalData: {
@ -52,10 +52,10 @@ export default {
addressInput: `${components.vnTextfield}[name="street"]`, addressInput: `${components.vnTextfield}[name="street"]`,
cityInput: `${components.vnTextfield}[name="city"]`, cityInput: `${components.vnTextfield}[name="city"]`,
postcodeInput: `${components.vnTextfield}[name="postcode"]`, postcodeInput: `${components.vnTextfield}[name="postcode"]`,
provinceInput: `${components.vnAutocomplete}[field="$ctrl.client.provinceFk"] > vn-vertical > ${components.vnTextfield}`, provinceInput: `${components.vnAutocomplete}[field="$ctrl.client.provinceFk"] input`,
provinceFifthOption: `${components.vnAutocomplete}[field="$ctrl.client.provinceFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(5)`, provinceFifthOption: `${components.vnAutocomplete}[field="$ctrl.client.provinceFk"] vn-drop-down ul > li:nth-child(5)`,
countryInput: `${components.vnAutocomplete}[field="$ctrl.client.countryFk"] > vn-vertical > ${components.vnTextfield}`, countryInput: `${components.vnAutocomplete}[field="$ctrl.client.countryFk"] input`,
countryThirdOption: `${components.vnAutocomplete}[field="$ctrl.client.countryFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(3)`, countryThirdOption: `${components.vnAutocomplete}[field="$ctrl.client.countryFk"] vn-drop-down ul > li:nth-child(3)`,
activeCheckboxLabel: `${components.vnCheck}[label='Active'] > label`, activeCheckboxLabel: `${components.vnCheck}[label='Active'] > label`,
invoiceByAddressCheckboxInput: `${components.vnCheck}[label='Invoice by address'] > label > input`, invoiceByAddressCheckboxInput: `${components.vnCheck}[label='Invoice by address'] > label > input`,
verifiedDataCheckboxInput: `${components.vnCheck}[label='Verified data'] > label > input`, verifiedDataCheckboxInput: `${components.vnCheck}[label='Verified data'] > label > input`,
@ -66,9 +66,9 @@ export default {
}, },
clientPayMethod: { clientPayMethod: {
payMethodButton: `${components.vnMenuItem}[ui-sref="clientCard.billingData"]`, payMethodButton: `${components.vnMenuItem}[ui-sref="clientCard.billingData"]`,
payMethodInput: `${components.vnAutocomplete}[field="$ctrl.client.payMethodFk"] > vn-vertical > ${components.vnTextfield}`, payMethodInput: `${components.vnAutocomplete}[field="$ctrl.client.payMethodFk"] input`,
payMethodIBANOption: `${components.vnAutocomplete}[field="$ctrl.client.payMethodFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(5)`, payMethodIBANOption: `${components.vnAutocomplete}[field="$ctrl.client.payMethodFk"] vn-drop-down ul > li:nth-child(5)`,
payMethodOptionOne: `${components.vnAutocomplete}[field="$ctrl.client.payMethodFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(2)`, payMethodOptionOne: `${components.vnAutocomplete}[field="$ctrl.client.payMethodFk"] vn-drop-down ul > li:nth-child(2)`,
IBANInput: `${components.vnTextfield}[name="iban"]`, IBANInput: `${components.vnTextfield}[name="iban"]`,
dueDayInput: `${components.vnTextfield}[name="dueDay"]`, dueDayInput: `${components.vnTextfield}[name="dueDay"]`,
cancelNotificationButton: 'vn-client-billing-data > vn-confirm button[response=CANCEL]', cancelNotificationButton: 'vn-client-billing-data > vn-confirm button[response=CANCEL]',
@ -85,10 +85,10 @@ export default {
streetAddressInput: `${components.vnTextfield}[name="street"]`, streetAddressInput: `${components.vnTextfield}[name="street"]`,
postcodeInput: `${components.vnTextfield}[name="postalCode"]`, postcodeInput: `${components.vnTextfield}[name="postalCode"]`,
cityInput: `${components.vnTextfield}[name="city"]`, cityInput: `${components.vnTextfield}[name="city"]`,
provinceInput: `${components.vnAutocomplete}[field="$ctrl.address.provinceFk"] > vn-vertical > ${components.vnTextfield}`, provinceInput: `${components.vnAutocomplete}[field="$ctrl.address.provinceFk"] input`,
provinceSecondOption: `${components.vnAutocomplete}[field="$ctrl.address.provinceFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(2)`, provinceSecondOption: `${components.vnAutocomplete}[field="$ctrl.address.provinceFk"] vn-drop-down ul > li:nth-child(2)`,
agencyInput: `${components.vnAutocomplete}[field="$ctrl.address.agencyModeFk"] > vn-vertical > ${components.vnTextfield}`, agencyInput: `${components.vnAutocomplete}[field="$ctrl.address.agencyModeFk"] input`,
agenctySecondOption: `${components.vnAutocomplete}[field="$ctrl.address.agencyModeFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(2)`, agenctySecondOption: `${components.vnAutocomplete}[field="$ctrl.address.agencyModeFk"] vn-drop-down ul > li:nth-child(2)`,
phoneInput: `${components.vnTextfield}[name="phone"]`, phoneInput: `${components.vnTextfield}[name="phone"]`,
mobileInput: `${components.vnTextfield}[name="mobile"]`, mobileInput: `${components.vnTextfield}[name="mobile"]`,
defaultAddress: 'vn-client-addresses > vn-vertical > vn-card > div > vn-horizontal:nth-child(2) > vn-one > vn-horizontal > vn-one > div:nth-child(2)', defaultAddress: 'vn-client-addresses > vn-vertical > vn-card > div > vn-horizontal:nth-child(2) > vn-one > vn-horizontal > vn-one > div:nth-child(2)',
@ -98,14 +98,14 @@ export default {
activeCheckbox: `${components.vnCheck}[label='Enabled'] > label > input`, activeCheckbox: `${components.vnCheck}[label='Enabled'] > label > input`,
equalizationTaxCheckboxLabel: `${components.vnCheck}[label='Is equalizated'] > label > input`, equalizationTaxCheckboxLabel: `${components.vnCheck}[label='Is equalizated'] > label > input`,
addAddressNoteButton: `${components.vnIcon}[icon="add_circle"]`, addAddressNoteButton: `${components.vnIcon}[icon="add_circle"]`,
firstObservationTypeSelect: `${components.vnAutocomplete}[field="observation.observationTypeFk"]:nth-child(1) > vn-vertical > ${components.vnTextfield}`, firstObservationTypeSelect: `${components.vnAutocomplete}[field="observation.observationTypeFk"]:nth-child(1) input`,
firstObservationTypeSelectOptionOne: `${components.vnAutocomplete}[field="observation.observationTypeFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(1)`, firstObservationTypeSelectOptionOne: `${components.vnAutocomplete}[field="observation.observationTypeFk"] vn-drop-down ul > li:nth-child(1)`,
firstObservationDescriptionInput: `vn-horizontal:nth-child(3) > vn-textfield[label="Description"] > div > input`, firstObservationDescriptionInput: `vn-horizontal:nth-child(3) > vn-textfield[label="Description"] > div > input`,
secondObservationTypeSelect: `${components.vnAutocomplete}[field="observation.observationTypeFk"]:nth-child(2) > vn-vertical > ${components.vnTextfield}`, secondObservationTypeSelect: `${components.vnAutocomplete}[field="observation.observationTypeFk"]:nth-child(2) input`,
secondObservationTypeSelectOptionTwo: `${components.vnAutocomplete}[field="observation.observationTypeFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(2)`, secondObservationTypeSelectOptionTwo: `${components.vnAutocomplete}[field="observation.observationTypeFk"] vn-drop-down ul > li:nth-child(2)`,
secondObservationDescriptionInput: `vn-horizontal:nth-child(4) > vn-textfield[label="Description"] > div > input`, secondObservationDescriptionInput: `vn-horizontal:nth-child(4) > vn-textfield[label="Description"] > div > input`,
thirdObservationTypeSelect: `${components.vnAutocomplete}[field="observation.observationTypeFk"]:nth-child(3) > vn-vertical > ${components.vnTextfield}`, thirdObservationTypeSelect: `${components.vnAutocomplete}[field="observation.observationTypeFk"]:nth-child(3) input`,
thirdObservationTypeSelectOptionThree: `${components.vnAutocomplete}[field="observation.observationTypeFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(3)`, thirdObservationTypeSelectOptionThree: `${components.vnAutocomplete}[field="observation.observationTypeFk"] vn-drop-down ul > li:nth-child(3)`,
thirdObservationDescriptionInput: `vn-horizontal:nth-child(5) > vn-textfield[label="Description"] > div > input`, thirdObservationDescriptionInput: `vn-horizontal:nth-child(5) > vn-textfield[label="Description"] > div > input`,
saveButton: `${components.vnSubmit}` saveButton: `${components.vnSubmit}`
}, },
@ -134,8 +134,8 @@ export default {
addGreugeFloatButton: `${components.vnFloatButton}`, addGreugeFloatButton: `${components.vnFloatButton}`,
amountInput: `${components.vnTextfield}[name="amount"]`, amountInput: `${components.vnTextfield}[name="amount"]`,
descriptionInput: `${components.vnTextfield}[name="description"]`, descriptionInput: `${components.vnTextfield}[name="description"]`,
typeInput: `${components.vnAutocomplete}[field="$ctrl.greuge.greugeTypeFk"] > vn-vertical > ${components.vnTextfield}`, typeInput: `${components.vnAutocomplete}[field="$ctrl.greuge.greugeTypeFk"] input`,
typeSecondOption: `${components.vnAutocomplete}[field="$ctrl.greuge.greugeTypeFk"] > vn-vertical > vn-drop-down > vn-vertical > vn-auto:nth-child(2) > ul > li`, typeSecondOption: `${components.vnAutocomplete}[field="$ctrl.greuge.greugeTypeFk"] vn-drop-down ul > li`,
saveButton: `${components.vnSubmit}`, saveButton: `${components.vnSubmit}`,
firstGreugeText: 'vn-client-greuge-list .list-element' firstGreugeText: 'vn-client-greuge-list .list-element'
}, },
@ -159,54 +159,54 @@ export default {
}, },
itemCreateView: { itemCreateView: {
name: `${components.vnTextfield}[name="name"]`, name: `${components.vnTextfield}[name="name"]`,
typeSelect: `${components.vnAutocomplete}[field="$ctrl.item.typeFk"] > vn-vertical > ${components.vnTextfield}`, typeSelect: `${components.vnAutocomplete}[field="$ctrl.item.typeFk"] input`,
typeSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.item.typeFk"] > vn-vertical > vn-drop-down > vn-vertical > vn-auto > ul > li:nth-child(2)`, typeSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.item.typeFk"] vn-drop-down ul > li:nth-child(2)`,
intrastatSelect: `${components.vnAutocomplete}[field="$ctrl.item.intrastatFk"] > vn-vertical > ${components.vnTextfield}`, intrastatSelect: `${components.vnAutocomplete}[field="$ctrl.item.intrastatFk"] input`,
intrastatSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.item.intrastatFk"] > vn-vertical > vn-drop-down > vn-vertical > vn-auto > ul > li:nth-child(2)`, intrastatSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.item.intrastatFk"] vn-drop-down ul > li:nth-child(2)`,
originSelect: `${components.vnAutocomplete}[field="$ctrl.item.originFk"] > vn-vertical > ${components.vnTextfield}`, originSelect: `${components.vnAutocomplete}[field="$ctrl.item.originFk"] input`,
originSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.item.originFk"] > vn-vertical > vn-drop-down > vn-vertical > vn-auto > ul > li:nth-child(2)`, originSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.item.originFk"] vn-drop-down ul > li:nth-child(2)`,
expenceSelect: `${components.vnAutocomplete}[field="$ctrl.item.expenceFk"] > vn-vertical > ${components.vnTextfield}`, expenceSelect: `${components.vnAutocomplete}[field="$ctrl.item.expenceFk"] input`,
expenceSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.item.expenceFk"] > vn-vertical > vn-drop-down > vn-vertical > vn-auto > ul > li:nth-child(2)`, expenceSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.item.expenceFk"] vn-drop-down ul > li:nth-child(2)`,
createButton: `${components.vnSubmit}` createButton: `${components.vnSubmit}`
}, },
itemBasicData: { itemBasicData: {
goToItemIndexButton: 'vn-item-descriptor [ui-sref="item.index"]', goToItemIndexButton: 'vn-item-descriptor [ui-sref="item.index"]',
basicDataButton: `${components.vnMenuItem}[ui-sref="item.card.data"]`, basicDataButton: `${components.vnMenuItem}[ui-sref="item.card.data"]`,
typeSelect: `${components.vnAutocomplete}[field="$ctrl.item.typeFk"] > vn-vertical > ${components.vnTextfield}`, typeSelect: `${components.vnAutocomplete}[field="$ctrl.item.typeFk"] input`,
typeSelectOptionTwo: `${components.vnAutocomplete}[field="$ctrl.item.typeFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(2)`, typeSelectOptionTwo: `${components.vnAutocomplete}[field="$ctrl.item.typeFk"] vn-drop-down ul > li:nth-child(2)`,
intrastatSelect: `${components.vnAutocomplete}[field="$ctrl.item.intrastatFk"] > vn-vertical > ${components.vnTextfield}`, intrastatSelect: `${components.vnAutocomplete}[field="$ctrl.item.intrastatFk"] input`,
intrastatSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.item.intrastatFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(1)`, intrastatSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.item.intrastatFk"] vn-drop-down ul > li:nth-child(1)`,
nameInput: `vn-horizontal:nth-child(2) > ${components.vnTextfield}`, nameInput: `vn-horizontal:nth-child(2) > ${components.vnTextfield}`,
relevancyInput: `vn-horizontal:nth-child(3) > ${components.vnTextfield}`, relevancyInput: `vn-horizontal:nth-child(3) > ${components.vnTextfield}`,
originSelect: `${components.vnAutocomplete}[field="$ctrl.item.originFk"] > vn-vertical > ${components.vnTextfield}`, originSelect: `${components.vnAutocomplete}[field="$ctrl.item.originFk"] input`,
originSelectOptionTwo: `${components.vnAutocomplete}[field="$ctrl.item.originFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(2)`, originSelectOptionTwo: `${components.vnAutocomplete}[field="$ctrl.item.originFk"] vn-drop-down ul > li:nth-child(2)`,
expenceSelect: `${components.vnAutocomplete}[field="$ctrl.item.expenceFk"] > vn-vertical > ${components.vnTextfield}`, expenceSelect: `${components.vnAutocomplete}[field="$ctrl.item.expenceFk"] input`,
expenceSelectOptionTwo: `${components.vnAutocomplete}[field="$ctrl.item.expenceFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(2)`, expenceSelectOptionTwo: `${components.vnAutocomplete}[field="$ctrl.item.expenceFk"] vn-drop-down ul > li:nth-child(2)`,
submitBasicDataButton: `${components.vnSubmit}` submitBasicDataButton: `${components.vnSubmit}`
}, },
itemTags: { itemTags: {
goToItemIndexButton: 'vn-item-descriptor [ui-sref="item.index"]', goToItemIndexButton: 'vn-item-descriptor [ui-sref="item.index"]',
tagsButton: `${components.vnMenuItem}[ui-sref="item.card.tags"]`, tagsButton: `${components.vnMenuItem}[ui-sref="item.card.tags"]`,
firstTagSelect: `vn-item-tags vn-horizontal:nth-child(2) > ${components.vnAutocomplete}[field="itemTag.tagFk"] > vn-vertical > ${components.vnTextfield}`, firstTagSelect: `vn-item-tags vn-horizontal:nth-child(2) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`,
firstTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(2) > ${components.vnAutocomplete}[field="itemTag.tagFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(1)`, firstTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(2) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
firstValueInput: `vn-item-tags vn-horizontal:nth-child(2) > vn-textfield[label="Value"] > div > input`, firstValueInput: `vn-item-tags vn-horizontal:nth-child(2) > vn-textfield[label="Value"] > div > input`,
firstRelevancyInput: `vn-horizontal:nth-child(2) > vn-textfield[label="Relevancy"] > div > input`, firstRelevancyInput: `vn-horizontal:nth-child(2) > vn-textfield[label="Relevancy"] > div > input`,
secondTagSelect: `vn-item-tags vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="itemTag.tagFk"] > vn-vertical > ${components.vnTextfield}`, secondTagSelect: `vn-item-tags vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`,
secondTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="itemTag.tagFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(1)`, secondTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
secondValueInput: `vn-item-tags vn-horizontal:nth-child(3) > vn-textfield[label="Value"] > div > input`, secondValueInput: `vn-item-tags vn-horizontal:nth-child(3) > vn-textfield[label="Value"] > div > input`,
secondRelevancyInput: `vn-horizontal:nth-child(3) > vn-textfield[label="Relevancy"] > div > input`, secondRelevancyInput: `vn-horizontal:nth-child(3) > vn-textfield[label="Relevancy"] > div > input`,
thirdTagSelect: `vn-item-tags vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemTag.tagFk"] > vn-vertical > ${components.vnTextfield}`, thirdTagSelect: `vn-item-tags vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`,
thirdTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemTag.tagFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(1)`, thirdTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
thirdValueInput: `vn-item-tags vn-horizontal:nth-child(4) > vn-textfield[label="Value"] > div > input`, thirdValueInput: `vn-item-tags vn-horizontal:nth-child(4) > vn-textfield[label="Value"] > div > input`,
thirdRelevancyInput: `vn-horizontal:nth-child(4) > vn-textfield[label="Relevancy"] > div > input`, thirdRelevancyInput: `vn-horizontal:nth-child(4) > vn-textfield[label="Relevancy"] > div > input`,
fourthTagSelect: `vn-item-tags vn-horizontal:nth-child(5) > ${components.vnAutocomplete}[field="itemTag.tagFk"] > vn-vertical > ${components.vnTextfield}`, fourthTagSelect: `vn-item-tags vn-horizontal:nth-child(5) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`,
fourthTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(5) > ${components.vnAutocomplete}[field="itemTag.tagFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(1)`, fourthTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(5) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
fourthValueInput: `vn-item-tags vn-horizontal:nth-child(5) > vn-textfield[label="Value"] > div > input`, fourthValueInput: `vn-item-tags vn-horizontal:nth-child(5) > vn-textfield[label="Value"] > div > input`,
fourthRelevancyInput: `vn-horizontal:nth-child(5) > vn-textfield[label="Relevancy"] > div > input`, fourthRelevancyInput: `vn-horizontal:nth-child(5) > vn-textfield[label="Relevancy"] > div > input`,
fifthRemoveTagButton: `vn-item-tags vn-horizontal:nth-child(6) > ${components.vnIcon}[icon="remove_circle_outline"]`, fifthRemoveTagButton: `vn-item-tags vn-horizontal:nth-child(6) > ${components.vnIcon}[icon="remove_circle_outline"]`,
fifthTagSelect: `vn-item-tags vn-horizontal:nth-child(6) > ${components.vnAutocomplete}[field="itemTag.tagFk"] > vn-vertical > ${components.vnTextfield}`, fifthTagSelect: `vn-item-tags vn-horizontal:nth-child(6) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`,
fifthTagSelectOptionFive: `vn-item-tags vn-horizontal:nth-child(6) > ${components.vnAutocomplete}[field="itemTag.tagFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(5)`, fifthTagSelectOptionFive: `vn-item-tags vn-horizontal:nth-child(6) > ${components.vnAutocomplete}[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: `${components.vnIcon}[icon="add_circle"]`, addItemTagButton: `${components.vnIcon}[icon="add_circle"]`,
@ -214,12 +214,12 @@ export default {
}, },
itemTax: { itemTax: {
taxButton: `${components.vnMenuItem}[ui-sref="item.card.tax"]`, taxButton: `${components.vnMenuItem}[ui-sref="item.card.tax"]`,
firstClassSelect: `vn-horizontal:nth-child(2) > ${components.vnAutocomplete}[field="tax.taxClassFk"] > vn-vertical > ${components.vnTextfield}`, firstClassSelect: `vn-horizontal:nth-child(2) > ${components.vnAutocomplete}[field="tax.taxClassFk"] input`,
firstClassSelectOptionTwo: `vn-horizontal:nth-child(2) > ${components.vnAutocomplete} > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(2)`, firstClassSelectOptionTwo: `vn-horizontal:nth-child(2) > ${components.vnAutocomplete} vn-drop-down ul > li:nth-child(2)`,
secondClassSelect: `vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="tax.taxClassFk"] > vn-vertical > ${components.vnTextfield}`, secondClassSelect: `vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="tax.taxClassFk"] input`,
secondClassSelectOptionOne: `vn-horizontal:nth-child(3) > ${components.vnAutocomplete} > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(1)`, secondClassSelectOptionOne: `vn-horizontal:nth-child(3) > ${components.vnAutocomplete} vn-drop-down ul > li:nth-child(1)`,
thirdClassSelect: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="tax.taxClassFk"] > vn-vertical > ${components.vnTextfield}`, thirdClassSelect: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="tax.taxClassFk"] input`,
thirdClassSelectOptionTwo: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete} > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(2)`, thirdClassSelectOptionTwo: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete} vn-drop-down ul > li:nth-child(2)`,
submitTaxButton: `${components.vnSubmit}` submitTaxButton: `${components.vnSubmit}`
}, },
itemBarcodes: { itemBarcodes: {
@ -232,11 +232,11 @@ export default {
itemNiches: { itemNiches: {
nicheButton: `${components.vnMenuItem}[ui-sref="item.card.niche"]`, nicheButton: `${components.vnMenuItem}[ui-sref="item.card.niche"]`,
addNicheButton: `${components.vnIcon}[icon="add_circle"]`, addNicheButton: `${components.vnIcon}[icon="add_circle"]`,
firstWarehouseSelect: `${components.vnAutocomplete}[field="itemNiche.warehouseFk"] > vn-vertical > ${components.vnTextfield}`, firstWarehouseSelect: `${components.vnAutocomplete}[field="itemNiche.warehouseFk"] input`,
firstWarehouseSelectSecondOption: `${components.vnAutocomplete}[field="itemNiche.warehouseFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(2)`, firstWarehouseSelectSecondOption: `${components.vnAutocomplete}[field="itemNiche.warehouseFk"] vn-drop-down ul > li:nth-child(2)`,
secondWarehouseSelect: `vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] > vn-vertical > ${components.vnTextfield}`, secondWarehouseSelect: `vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] input`,
thirdWarehouseSelect: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] > vn-vertical > ${components.vnTextfield}`, thirdWarehouseSelect: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] input`,
thirdWarehouseSelectFourthOption: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(4)`, thirdWarehouseSelectFourthOption: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] vn-drop-down ul > li:nth-child(4)`,
secondNicheRemoveButton: `vn-horizontal:nth-child(3) > vn-one > ${components.vnIcon}[icon="remove_circle_outline"]`, secondNicheRemoveButton: `vn-horizontal:nth-child(3) > vn-one > ${components.vnIcon}[icon="remove_circle_outline"]`,
firstCodeInput: `vn-horizontal:nth-child(2) > ${components.vnTextfield}`, firstCodeInput: `vn-horizontal:nth-child(2) > ${components.vnTextfield}`,
secondCodeInput: `vn-horizontal:nth-child(3) > ${components.vnTextfield}`, secondCodeInput: `vn-horizontal:nth-child(3) > ${components.vnTextfield}`,
@ -246,19 +246,20 @@ export default {
itemBotanical: { itemBotanical: {
botanicalButton: `${components.vnMenuItem}[ui-sref="item.card.botanical"]`, botanicalButton: `${components.vnMenuItem}[ui-sref="item.card.botanical"]`,
botanicalInput: `vn-horizontal:nth-child(2) > ${components.vnTextfield}`, botanicalInput: `vn-horizontal:nth-child(2) > ${components.vnTextfield}`,
genusSelect: `${components.vnAutocomplete}[field="$ctrl.botanical.genusFk"] > vn-vertical > ${components.vnTextfield}`, genusSelect: `${components.vnAutocomplete}[field="$ctrl.botanical.genusFk"] input`,
genusSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.botanical.genusFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(1)`, genusSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.botanical.genusFk"] vn-drop-down ul > li:nth-child(1)`,
genusSelectOptionTwo: `${components.vnAutocomplete}[field="$ctrl.botanical.genusFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(2)`, genusSelectOptionTwo: `${components.vnAutocomplete}[field="$ctrl.botanical.genusFk"] vn-drop-down ul > li:nth-child(2)`,
speciesSelect: `${components.vnAutocomplete}[field="$ctrl.botanical.specieFk"] > vn-vertical > ${components.vnTextfield}`, speciesSelect: `${components.vnAutocomplete}[field="$ctrl.botanical.specieFk"] input`,
speciesSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.botanical.specieFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(1)`, speciesSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.botanical.specieFk"] vn-drop-down ul > li:nth-child(1)`,
speciesSelectOptionTwo: `${components.vnAutocomplete}[field="$ctrl.botanical.specieFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(2)`, speciesSelectOptionTwo: `${components.vnAutocomplete}[field="$ctrl.botanical.specieFk"] vn-drop-down ul > li:nth-child(2)`,
submitBotanicalButton: `${components.vnSubmit}` submitBotanicalButton: `${components.vnSubmit}`
}, },
itemSummary: { itemSummary: {
basicData: `${components.vnItemSummary} > vn-horizontal:nth-child(1) > vn-one:nth-child(2) > vn-vertical > p:nth-child(2)`, basicData: `${components.vnItemSummary} > vn-horizontal:nth-child(1) > vn-one:nth-child(2) > vn-vertical > p:nth-child(2)`,
tags: `${components.vnItemSummary} > vn-horizontal:nth-child(1) > vn-one:nth-child(3) > vn-vertical > p`, vat: `${components.vnItemSummary} > vn-horizontal:nth-child(1) > vn-one:nth-child(3) > vn-vertical > p`,
niche: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(1) > vn-vertical > p:nth-child(2)`, tags: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(1) > p`,
botanical: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(2) > vn-vertical > p`, niche: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(2) > vn-vertical > p:nth-child(2)`,
barcode: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(3) > vn-vertical > p` botanical: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(3) > vn-vertical > p`,
barcode: `${components.vnItemSummary} > vn-horizontal:nth-child(2) > vn-one:nth-child(4) > vn-vertical > p`
} }
}; };

View File

@ -122,7 +122,7 @@ describe('Add address path', () => {
.waitToClick(selectors.clientAddresses.saveButton) .waitToClick(selectors.clientAddresses.saveButton)
.waitForSnackbar() .waitForSnackbar()
.then(result => { .then(result => {
expect(result).toContain('Some fields are invalid'); expect(result).toContain('Error:');
}); });
}); });
}); });

View File

@ -3,18 +3,16 @@ const routes = require('../routes');
const restoreFixtures = require('../../../../../services/db/testing_fixtures'); const restoreFixtures = require('../../../../../services/db/testing_fixtures');
describe('Auth routes', () => { describe('Auth routes', () => {
let fixturesToApply = {tables: ['`salix`.`user`'], inserts: [ let sqlStatements = {deletes: `
`INSERT INTO salix.user(id,username,password,email) DELETE FROM salix.user WHERE id = 102;
VALUES `, inserts: ``, updates: ``};
(10, 'JessicaJones', 'ac754a330530832ba1bf7687f577da91', 'JessicaJones@verdnatura.es');`
]};
beforeEach(done => { beforeEach(() => {
restoreFixtures(fixturesToApply, done); restoreFixtures(sqlStatements);
}); });
afterAll(done => { afterAll(() => {
restoreFixtures(fixturesToApply, done); restoreFixtures(sqlStatements);
}); });
let User = app.models.User; let User = app.models.User;
@ -33,17 +31,6 @@ describe('Auth routes', () => {
req = {body: {}}; req = {body: {}};
}); });
describe('when the user exists and the password is correct', () => {
it('should login and return the token', done => {
req.body.user = 'developer';
req.body.password = 'nightmare';
res.json = response => {
expect(response.token).toBeDefined();
done();
};
loginFunction(req, res);
});
describe('when the user doesnt exist but the client does and the password is correct', () => { describe('when the user doesnt exist but the client does and the password is correct', () => {
it('should create the user login and return the token', done => { it('should create the user login and return the token', done => {
spyOn(User, 'upsertWithWhere').and.callThrough(); spyOn(User, 'upsertWithWhere').and.callThrough();
@ -58,6 +45,17 @@ describe('Auth routes', () => {
}); });
}); });
describe('when the user exists and the password is correct', () => {
it('should login and return the token', done => {
req.body.user = 'developer';
req.body.password = 'nightmare';
res.json = response => {
expect(response.token).toBeDefined();
done();
};
loginFunction(req, res);
});
it('should define the url to continue upon login', done => { it('should define the url to continue upon login', done => {
req.body.user = 'developer'; req.body.user = 'developer';
req.body.password = 'nightmare'; req.body.password = 'nightmare';

View File

@ -163,14 +163,15 @@ INSERT INTO `vn`.`address`(`id`, `nickname`, `street`, `city`, `postalCode`, `pr
(118, '18', 'Somewhere over the rainbow', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), (118, '18', 'Somewhere over the rainbow', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0),
(119, '19', 'Somewhere in Alberic', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), (119, '19', 'Somewhere in Alberic', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0),
(120, '20', 'Somewhere in Montortal', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0), (120, '20', 'Somewhere in Montortal', 'Silla', 46460, 1, NULL, NULL, 1, 0, 109, 2, NULL, NULL, 0),
(121, 'my other address', 'NY roofs', 'Silla', 46460, 1, NULL, NULL, 1, 0, 102, 2, NULL, NULL, 0), (121, 'my other address', 'the bat cave', 'Silla', 46460, 1, NULL, NULL, 1, 0, 101, 2, NULL, NULL, 0),
(122, 'my other address', 'The phone box', 'Silla', 46460, 1, NULL, NULL, 1, 0, 103, 2, NULL, NULL, 0), (122, 'my other address', 'NY roofs', 'Silla', 46460, 1, NULL, NULL, 1, 0, 102, 2, NULL, NULL, 0),
(123, 'my other address', 'Stark tower', 'Silla', 46460, 1, NULL, NULL, 1, 0, 104, 2, NULL, NULL, 0), (123, 'my other address', 'The phone box', 'Silla', 46460, 1, NULL, NULL, 1, 0, 103, 2, NULL, NULL, 0),
(124, 'my other address', 'The plastic cell', 'Silla', 46460, 1, NULL, NULL, 1, 0, 105, 2, NULL, NULL, 0), (124, 'my other address', 'Stark tower', 'Silla', 46460, 1, NULL, NULL, 1, 0, 104, 2, NULL, NULL, 0),
(125, 'my other address', 'Many places', 'Silla', 46460, 1, NULL, NULL, 1, 0, 106, 2, NULL, NULL, 0), (125, 'my other address', 'The plastic cell', 'Silla', 46460, 1, NULL, NULL, 1, 0, 105, 2, NULL, NULL, 0),
(126, 'my other address', 'Your pocket', 'Silla', 46460, 1, NULL, NULL, 1, 0, 107, 2, NULL, NULL, 0), (126, 'my other address', 'Many places', 'Silla', 46460, 1, NULL, NULL, 1, 0, 106, 2, NULL, NULL, 0),
(127, 'my other address', 'Cerebro', 'Silla', 46460, 1, NULL, NULL, 1, 0, 108, 2, NULL, NULL, 0), (127, 'my other address', 'Your pocket', 'Silla', 46460, 1, NULL, NULL, 1, 0, 107, 2, NULL, NULL, 0),
(128, 'my other address', 'Luke Cages Bar', 'Silla', 46460, 1, NULL, NULL, 1, 0, 110, 2, NULL, NULL, 0); (128, 'my other address', 'Cerebro', 'Silla', 46460, 1, NULL, NULL, 1, 0, 108, 2, NULL, NULL, 0),
(129, 'my other address', 'Luke Cages Bar', 'Silla', 46460, 1, NULL, NULL, 1, 0, 110, 2, NULL, NULL, 0);
INSERT INTO `vn`.`clientCredit`(`id`, `clientFk`, `workerFk`, `amount`, `created`) INSERT INTO `vn`.`clientCredit`(`id`, `clientFk`, `workerFk`, `amount`, `created`)
VALUES VALUES

View File

@ -16,26 +16,23 @@ let errorHandler = callback => {
}; };
}; };
let insertFixtures = (inserts, callback) => { let insertFixtures = async function(sqlStatements) {
connection.query(inserts[0], errorHandler(callback)); try {
// connection.query('SET FOREIGN_KEY_CHECKS = 1'); if (sqlStatements.deletes.length)
}; await connection.query(sqlStatements.deletes);
if (sqlStatements.inserts.length)
let truncate = (tables, callback) => { await connection.query(sqlStatements.inserts);
let truncatesSQL = tables.reduce((accumulator, currentValue, i) => { if (sqlStatements.updates.length)
let sql = 'TRUNCATE TABLE ' + currentValue + '; '; await connection.query(sqlStatements.updates);
return (`${accumulator}${sql}`); } catch (error) {
}, ''); errorHandler(error);
}
connection.query(truncatesSQL.slice(0, -2), errorHandler(callback));
}; };
connection.connect(); connection.connect();
module.exports = function restoreFixtures(fixturesToApply, callback) { module.exports = function restoreFixtures(sqlStatements) {
connection.query('SET FOREIGN_KEY_CHECKS = 0', () => { connection.query('SET FOREIGN_KEY_CHECKS = 0', () => {
truncate(fixturesToApply.tables, () => { insertFixtures(sqlStatements);
insertFixtures(fixturesToApply.inserts, callback);
});
}); });
}; };

View File

@ -0,0 +1,50 @@
module.exports = Self => {
Self.remoteMethod('isValidClient', {
description: 'Checks if the user havent got the role employee, is active and has verified data',
accessType: 'READ',
accepts: [
{
arg: 'id',
type: 'string',
required: true,
description: 'The user id',
http: {source: 'path'}
}, {
arg: 'context',
type: 'object',
required: true,
description: 'Filter defining where',
http: function(context) {
return context.req.query;
}
}
],
returns: {
type: 'boolean',
root: true
},
http: {
path: `/:id/isValidClient`,
verb: 'GET'
}
});
Self.isValidClient = async function(id) {
let query =
`SELECT r.name
FROM salix.Account A
JOIN vn.client C ON A.id = C.id
JOIN salix.RoleMapping rm ON rm.principalId = A.id
JOIN salix.Role r ON r.id = rm.roleId
WHERE A.id = ? AND C.isActive AND C.isTaxDataChecked`;
let roleNames = await Self.rawSql(query, [id]);
if (!roleNames.length) return false;
roleNames.forEach(role => {
if (role.name === 'employee')
return false;
});
return true;
};
};

View File

@ -3,58 +3,19 @@ const catchErrors = require('../../../../../../services/utils/jasmineHelpers').c
const restoreFixtures = require('../../../../../../services/db/testing_fixtures'); const restoreFixtures = require('../../../../../../services/db/testing_fixtures');
describe('Client addressesPropagateRe', () => { describe('Client addressesPropagateRe', () => {
let fixturesToApply = {tables: ['`account`.`user`', '`vn2008`.`Clientes`', '`vn2008`.`Consignatarios`'], inserts: [ let sqlStatements = {deletes: ``, inserts: ``, updates:
`INSERT INTO account.user(id,name,password,role,active,email) `UPDATE vn.address SET isEqualizated = 0 WHERE clientFk = 101;`
VALUES };
(1, 'BruceWayne', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'BruceWayne@verdnatura.es'), beforeEach(() => {
(2, 'PetterParker', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'PetterParker@verdnatura.es'), restoreFixtures(sqlStatements);
(3, 'ClarkKent', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'ClarkKent@verdnatura.es'),
(4, 'TonyStark', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'TonyStark@verdnatura.es'),
(5, 'MaxEisenhardt', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'MaxEisenhardt@verdnatura.es'),
(6, 'DavidCharlesHaller', 'ac754a330530832ba1bf7687f577da91', 18, 1, 'DavidCharlesHaller@verdnatura.es'),
(7, 'HankPym', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'HankPym@verdnatura.es'),
(8, 'CharlesXavier', 'ac754a330530832ba1bf7687f577da91', 18, 1, 'CharlesXavier@verdnatura.es'),
(9, 'BruceBanner', 'ac754a330530832ba1bf7687f577da91', 18, 1, 'BruceBanner@verdnatura.es'),
(10, 'JessicaJones', 'ac754a330530832ba1bf7687f577da91', 9, 1, 'JessicaJones@verdnatura.es'),
(11, 'Cyborg', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'cyborg@verdnatura.es');
INSERT INTO salix.Address(id, consignee, street, city, postcode, provinceFk, phone, mobile, isEnabled, isDefaultAddress, clientFk, defaultAgencyFk, longitude, latitude, isEqualizated)
VALUES
(1, 'Bruce Wayne', 'The Bat cave', 'Silla', 46460, 1, NULL, NULL, 1, 1, 1, 2, NULL, NULL, 0),
(2, 'Petter Parker', 'NY roofs', 'Silla', 46460, 1, NULL, NULL, 1, 1, 2, 2, NULL, NULL, 0),
(3, 'Clark Kenn', 'The phone box', 'Silla', 46460, 1, NULL, NULL, 1, 1, 3, 2, NULL, NULL, 0),
(4, 'Tony Stark', 'Stark tower', 'Silla', 46460, 1, NULL, NULL, 1, 1, 4, 2, NULL, NULL, 0),
(5, 'Max Eisenhardt', 'The plastic cell', 'Silla', 46460, 1, NULL, NULL, 1, 1, 5, 2, NULL, NULL, 0),
(6, 'David Charles Haller', 'Many places', 'Silla', 46460, 1, NULL, NULL, 1, 1, 6, 2, NULL, NULL, 0),
(7, 'Hank Pym', 'Your pocket', 'Silla', 46460, 1, NULL, NULL, 1, 1, 7, 2, NULL, NULL, 0),
(8, 'Charles Xavier', 'Cerebro', 'Silla', 46460, 1, NULL, NULL, 1, 1, 8, 2, NULL, NULL, 0),
(9, 'Bruce Banner', 'Somewhere in Thailand', 'Silla', 46460, 1, NULL, NULL, 1, 1, 9, 2, NULL, NULL, 0),
(10,'Jessica Jones', 'Luke Cages Bar', 'Silla', 46460, 1, NULL, NULL, 1, 1, 10, 2, NULL, NULL, 0);
INSERT INTO vn.client(id,name,fi,socialName,contact,street,city,postcode,phone,mobile,fax,isRelevant,email,iban,dueDay,accountingAccount,isEqualizated,provinceFk,hasToInvoice,credit,countryFk,isActive,gestdocFk,quality,payMethodFk,created,isToBeMailed,contactChannelFk,hasSepaVnl,hasCoreVnl,hasCoreVnh,riskCalculated,clientTypeFk,mailAddress,cplusTerIdNifFk,hasToInvoiceByAddress,isTaxDataChecked,isFreezed,creditInsurance,isCreatedAsServed,hasInvoiceSimplified,salesPersonFk,isVies,eypbc)
VALUES
(1, 'Bruce Wayne', '74451390E', 'Batman', 'Alfred', '1007 Mountain Drive, Gotham', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'BruceWayne@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 1, 0, 1),
(2, 'Petter Parker', '87945234L', 'Spider-Man', 'Aunt May', '20 Ingram Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'PetterParker@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 1, 0, 1),
(3, 'Clark Kent', '06815934E', 'Super-Man', 'lois lane', '344 Clinton Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'ClarkKent@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 1, 0, 1),
(4, 'Tony Stark', '06089160W', 'Iron-Man', 'Pepper Potts', '10880 Malibu Point', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'TonyStark@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 1, 0, 1),
(5, 'Max Eisenhardt', '39182496H', 'Magneto', 'Rogue', 'Unknown Whereabouts', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'MaxEisenhardt@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 3, 0, 1),
(6, 'DavidCharlesHaller', '53136686Q', 'Legion', 'Charles Xavier', 'Evil hideout', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'DavidCharlesHaller@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 3, 0, 1),
(7, 'Hank Pym', '09854837G', 'Ant-Man', 'Hawk', 'Anthill', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'HankPym@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 3, 0, 1),
(8, 'Charles Xavier', '22641921P', 'Professor X', 'Beast', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'CharlesXavier@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 4, 0, 1),
(9, 'Bruce Banner', '16104829E', 'Hulk', 'Black widow', 'Somewhere in New York', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'BruceBanner@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 4, 0, 1),
(10, 'Jessica Jones', '58282869H', 'Jessica Jones', 'Luke Cage', 'NYCC 2015 Poster', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'JessicaJones@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 4, 0, 1);`
]};
beforeEach(done => {
restoreFixtures(fixturesToApply, done);
}); });
afterAll(done => { afterAll(() => {
restoreFixtures(fixturesToApply, done); restoreFixtures(sqlStatements);
}); });
it('should propagate the isEqualizated on both addresses of Mr Wayne', done => { it('should propagate the isEqualizated on both addresses of Mr Wayne', done => {
let id = 1; let id = 101;
let data = { let data = {
isEqualizated: true isEqualizated: true
}; };

View File

@ -3,13 +3,13 @@ const catchErrors = require('../../../../../../services/utils/jasmineHelpers').c
describe('Client card', () => { describe('Client card', () => {
it('should call the card() method to receive a formated card of Bruce Wayne', done => { it('should call the card() method to receive a formated card of Bruce Wayne', done => {
let id = 1; let id = 101;
let callback = (error, result) => { let callback = (error, result) => {
if (error) return catchErrors(done)(error); if (error) return catchErrors(done)(error);
expect(result).toEqual(jasmine.objectContaining({ expect(result).toEqual(jasmine.objectContaining({
id: 1, id: 101,
name: 'Bruce Wayne' name: 'Bruce Wayne'
})); }));
done(); done();

View File

@ -3,58 +3,18 @@ const catchErrors = require('../../../../../../services/utils/jasmineHelpers').c
const restoreFixtures = require('../../../../../../services/db/testing_fixtures'); const restoreFixtures = require('../../../../../../services/db/testing_fixtures');
describe('Client Create', () => { describe('Client Create', () => {
let fixturesToApply = {tables: ['`account`.`user`', '`vn2008`.`Clientes`', '`vn2008`.`Consignatarios`'], inserts: [ let sqlStatements = {deletes: `
`INSERT INTO account.user(id,name,password,role,active,email) DELETE FROM vn.address WHERE nickname = "Wade";
VALUES DELETE FROM vn.client WHERE name = "Wade";
(1, 'BruceWayne', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'BruceWayne@verdnatura.es'), DELETE FROM account.user WHERE name = "Deadpool";
(2, 'PetterParker', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'PetterParker@verdnatura.es'), `, inserts: ``, updates: ``};
(3, 'ClarkKent', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'ClarkKent@verdnatura.es'),
(4, 'TonyStark', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'TonyStark@verdnatura.es'),
(5, 'MaxEisenhardt', 'ac754a330530832ba1bf7687f577da91', 2, 1, 'MaxEisenhardt@verdnatura.es'),
(6, 'DavidCharlesHaller', 'ac754a330530832ba1bf7687f577da91', 18, 1, 'DavidCharlesHaller@verdnatura.es'),
(7, 'HankPym', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'HankPym@verdnatura.es'),
(8, 'CharlesXavier', 'ac754a330530832ba1bf7687f577da91', 18, 1, 'CharlesXavier@verdnatura.es'),
(9, 'BruceBanner', 'ac754a330530832ba1bf7687f577da91', 18, 1, 'BruceBanner@verdnatura.es'),
(10, 'JessicaJones', 'ac754a330530832ba1bf7687f577da91', 9, 1, 'JessicaJones@verdnatura.es'),
(11, 'Cyborg', 'ac754a330530832ba1bf7687f577da91', 1, 1, 'cyborg@verdnatura.es');
INSERT INTO account.user(name, password, role, active, email) beforeAll(() => {
SELECT name, MD5('nightmare'), id, 1, CONCAT(name, '@verdnatura.es') restoreFixtures(sqlStatements);
FROM account.role;
INSERT INTO salix.Address(id, consignee, street, city, postcode, provinceFk, phone, mobile, isEnabled, isDefaultAddress, clientFk, defaultAgencyFk, longitude, latitude, isEqualizated)
VALUES
(1, 'Bruce Wayne', 'The Bat cave', 'Silla', 46460, 1, NULL, NULL, 1, 1, 1, 2, NULL, NULL, 0),
(2, 'Petter Parker', 'NY roofs', 'Silla', 46460, 1, NULL, NULL, 1, 1, 2, 2, NULL, NULL, 0),
(3, 'Clark Kenn', 'The phone box', 'Silla', 46460, 1, NULL, NULL, 1, 1, 3, 2, NULL, NULL, 0),
(4, 'Tony Stark', 'Stark tower', 'Silla', 46460, 1, NULL, NULL, 1, 1, 4, 2, NULL, NULL, 0),
(5, 'Max Eisenhardt', 'The plastic cell', 'Silla', 46460, 1, NULL, NULL, 1, 1, 5, 2, NULL, NULL, 0),
(6, 'David Charles Haller', 'Many places', 'Silla', 46460, 1, NULL, NULL, 1, 1, 6, 2, NULL, NULL, 0),
(7, 'Hank Pym', 'Your pocket', 'Silla', 46460, 1, NULL, NULL, 1, 1, 7, 2, NULL, NULL, 0),
(8, 'Charles Xavier', 'Cerebro', 'Silla', 46460, 1, NULL, NULL, 1, 1, 8, 2, NULL, NULL, 0),
(9, 'Bruce Banner', 'Somewhere in Thailand', 'Silla', 46460, 1, NULL, NULL, 1, 1, 9, 2, NULL, NULL, 0),
(10,'Jessica Jones', 'Luke Cages Bar', 'Silla', 46460, 1, NULL, NULL, 1, 1, 10, 2, NULL, NULL, 0);
INSERT INTO vn.client(id,name,fi,socialName,contact,street,city,postcode,phone,mobile,fax,isRelevant,email,iban,dueDay,accountingAccount,isEqualizated,provinceFk,hasToInvoice,credit,countryFk,isActive,gestdocFk,quality,payMethodFk,created,isToBeMailed,contactChannelFk,hasSepaVnl,hasCoreVnl,hasCoreVnh,riskCalculated,clientTypeFk,mailAddress,cplusTerIdNifFk,hasToInvoiceByAddress,isTaxDataChecked,isFreezed,creditInsurance,isCreatedAsServed,hasInvoiceSimplified,salesPersonFk,isVies,eypbc)
VALUES
(1, 'Bruce Wayne', '74451390E', 'Batman', 'Alfred', '1007 Mountain Drive, Gotham', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'BruceWayne@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 1, 0, 1),
(2, 'Petter Parker', '87945234L', 'Spider-Man', 'Aunt May', '20 Ingram Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'PetterParker@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 1, 0, 1),
(3, 'Clark Kent', '06815934E', 'Super-Man', 'lois lane', '344 Clinton Street', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'ClarkKent@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 1, 0, 1),
(4, 'Tony Stark', '06089160W', 'Iron-Man', 'Pepper Potts', '10880 Malibu Point', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'TonyStark@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 1, 0, 1),
(5, 'Max Eisenhardt', '39182496H', 'Magneto', 'Rogue', 'Unknown Whereabouts', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'MaxEisenhardt@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 3, 0, 1),
(6, 'DavidCharlesHaller', '53136686Q', 'Legion', 'Charles Xavier', 'Evil hideout', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'DavidCharlesHaller@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 3, 0, 1),
(7, 'Hank Pym', '09854837G', 'Ant-Man', 'Hawk', 'Anthill', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'HankPym@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 3, 0, 1),
(8, 'Charles Xavier', '22641921P', 'Professor X', 'Beast', '3800 Victory Pkwy, Cincinnati, OH 45207, USA', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'CharlesXavier@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 4, 0, 1),
(9, 'Bruce Banner', '16104829E', 'Hulk', 'Black widow', 'Somewhere in New York', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'BruceBanner@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 4, 0, 1),
(10, 'Jessica Jones', '58282869H', 'Jessica Jones', 'Luke Cage', 'NYCC 2015 Poster', 'Silla', 46460, 1111111111, 222222222, 333333333, 1, 'JessicaJones@verdnatura.es', NULL, 0, 1234567890, 0, 1, 1, 300, 1, 1,NULL, 10, 5,CURDATE(), 1, 5, 1, 1, 1,'0000-00-00', 1, NULL, 1, 1, 1, 1, NULL, 0, 0, 4, 0, 1);`
]};
beforeEach(done => {
restoreFixtures(fixturesToApply, done);
}); });
afterAll(done => { afterAll(() => {
restoreFixtures(fixturesToApply, done); restoreFixtures(sqlStatements);
}); });
let newAccountData = { let newAccountData = {

View File

@ -3,7 +3,7 @@ const catchErrors = require('../../../../../../services/utils/jasmineHelpers').c
describe('Client hasCustomerRole', () => { describe('Client hasCustomerRole', () => {
it('should call the hasCustomerRole() method with a customer id', done => { it('should call the hasCustomerRole() method with a customer id', done => {
let id = 1; let id = 101;
let params = {}; let params = {};
let callback = (error, result) => { let callback = (error, result) => {

View File

@ -0,0 +1,57 @@
const app = require('../../../../../client/server/server');
describe('Client isValidClient', () => {
it('should call the isValidClient() method with a client id and receive true', done => {
let id = 101;
app.models.Client.isValidClient(id)
.then(result => {
expect(result).toBeTruthy();
done();
});
});
it('should call the isValidClient() method with a employee id and receive false', done => {
let id = 1;
app.models.Client.isValidClient(id)
.then(result => {
expect(result).toBeFalsy();
done();
});
});
it('should call the isValidClient() method with a unexistant id and receive false', done => {
let id = 999999;
app.models.Client.isValidClient(id)
.then(result => {
expect(result).toBeFalsy();
done();
});
});
it('should call the isValidClient() method with a invalid id and receive false', done => {
let id = 'Pepinillos';
app.models.Client.isValidClient(id)
.then(result => {
expect(result).toBeFalsy();
done();
});
});
it('should call the isValidClient() method with a customer id which isnt active and return false', done => {
let id = '106';
app.models.Client.isValidClient(id)
.then(result => {
expect(result).toBeFalsy();
done();
});
});
it('should call the isValidClient() method with a customer id which his data isnt verified and return false', done => {
let id = '110';
app.models.Client.isValidClient(id)
.then(result => {
expect(result).toBeFalsy();
done();
});
});
});

View File

@ -7,7 +7,7 @@ describe('Client listWorkers', () => {
.then(result => { .then(result => {
let amountOfEmployees = Object.keys(result).length; let amountOfEmployees = Object.keys(result).length;
expect(amountOfEmployees).toEqual(32); expect(amountOfEmployees).toEqual(37);
done(); done();
}) })
.catch(catchErrors(done)); .catch(catchErrors(done));

View File

@ -12,6 +12,7 @@ module.exports = function(Self) {
require('../methods/client/listWorkers')(Self); require('../methods/client/listWorkers')(Self);
require('../methods/client/filter')(Self); require('../methods/client/filter')(Self);
require('../methods/client/hasCustomerRole')(Self); require('../methods/client/hasCustomerRole')(Self);
require('../methods/client/isValidClient')(Self);
require('../methods/client/activeSalesPerson')(Self); require('../methods/client/activeSalesPerson')(Self);
require('../methods/client/addressesPropagateRe')(Self); require('../methods/client/addressesPropagateRe')(Self);