+
+
+
+ You changes the equivalent tax
+ Do you want to spread the change to their consignees?
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/client/client/src/fiscal-data/fiscal-data.js b/client/client/src/fiscal-data/fiscal-data.js
index 286693f83..6ef3c3931 100644
--- a/client/client/src/fiscal-data/fiscal-data.js
+++ b/client/client/src/fiscal-data/fiscal-data.js
@@ -1,7 +1,54 @@
import ngModule from '../module';
+export default class ClientFiscalData {
+ constructor($scope, $http, vnApp, $translate) {
+ this.$ = $scope;
+ this.$http = $http;
+ this.vnApp = vnApp;
+ this.translate = $translate;
+ this.equalizationTax = undefined;
+ this.copyData();
+ }
+
+ $onChanges() {
+ this.copyData();
+ }
+
+ copyData() {
+ if (this.client) {
+ this.equalizationTax = this.client.equalizationTax;
+ }
+ }
+
+ submit() {
+ return this.$.watcher.submit().then(
+ () => this.checkEtChanges());
+ }
+
+ checkEtChanges() {
+ let equals = this.equalizationTax == this.client.equalizationTax;
+ this.equalizationTax = this.client.equalizationTax;
+
+ if (!equals)
+ this.$.propagateEqualizationTax.show();
+ }
+
+ returnDialogEt(response) {
+ if (response === 'ACCEPT') {
+ this.$http.patch(`/client/api/Clients/${this.client.id}/addressesPropagateRe`, {isEqualizated: this.client.equalizationTax}).then(
+ res => {
+ if (res.data)
+ this.vnApp.showMessage(this.translate.instant('Equivalent tax spreaded'));
+ }
+ );
+ }
+ }
+}
+ClientFiscalData.$inject = ['$scope', '$http', 'vnApp', '$translate'];
+
ngModule.component('vnClientFiscalData', {
template: require('./fiscal-data.html'),
+ controller: ClientFiscalData,
bindings: {
client: '<'
}
diff --git a/client/client/src/index/index.spec.js b/client/client/src/index/index.spec.js
index 9a4fe5e0f..821cb4685 100644
--- a/client/client/src/index/index.spec.js
+++ b/client/client/src/index/index.spec.js
@@ -3,6 +3,7 @@ import './index.js';
describe('Client', () => {
describe('Component vnClientIndex', () => {
let $componentController;
+ let controller;
beforeEach(() => {
angular.mock.module('client');
@@ -10,17 +11,15 @@ describe('Client', () => {
beforeEach(angular.mock.inject(_$componentController_ => {
$componentController = _$componentController_;
+ controller = $componentController('vnClientIndex');
}));
it('should define and set model property as an empty object', () => {
- let controller = $componentController('vnClientIndex');
-
expect(controller.model).toEqual({});
});
describe('search()', () => {
it(`should set model's search to the search input`, () => {
- let controller = $componentController('vnClientIndex');
controller.model.search = 'batman';
let index = {
filter: {},
diff --git a/client/client/src/index/style.css b/client/client/src/index/style.css
index ba7f75844..b30351f09 100644
--- a/client/client/src/index/style.css
+++ b/client/client/src/index/style.css
@@ -11,6 +11,6 @@ vn-item-client a:hover {
background-color: #424242;
}
-.vn-item-client-name{
+.vn-item-client-name {
font-family: raleway-bold;
}
diff --git a/client/client/src/locale/es.json b/client/client/src/locale/es.json
index 3a36dab65..20089e85c 100644
--- a/client/client/src/locale/es.json
+++ b/client/client/src/locale/es.json
@@ -1,5 +1,14 @@
{
"Client": "Cliente",
"Clients": "Clientes",
- "Fiscal data": "Datos Fiscales"
-}
\ No newline at end of file
+ "Fiscal data": "Datos Fiscales",
+ "Has to invoice": "Factura",
+ "Invoice by mail": "Factura impresa",
+ "Country": "País",
+ "Street": "Domicilio fiscal",
+ "City": "Municipio",
+ "Postcode": "Código postal",
+ "Province": "Provincia",
+ "Save": "Guardar",
+ "Pay method" : "Forma de pago"
+}
diff --git a/client/client/src/note-create/note-create.spec.js b/client/client/src/note-create/note-create.spec.js
index 52d2cfcb9..1414835fd 100644
--- a/client/client/src/note-create/note-create.spec.js
+++ b/client/client/src/note-create/note-create.spec.js
@@ -4,6 +4,7 @@ describe('Client', () => {
describe('Component vnNoteCreate', () => {
let $componentController;
let $state;
+ let controller;
beforeEach(() => {
angular.mock.module('client');
@@ -13,11 +14,10 @@ describe('Client', () => {
$componentController = _$componentController_;
$state = _$state_;
$state.params.id = '1234';
+ controller = $componentController('vnNoteCreate', {$state: $state});
}));
it('should define clientFk using $state.params.id', () => {
- let controller = $componentController('vnNoteCreate', {$state: $state});
-
expect(controller.note.clientFk).toBe(1234);
expect(controller.note.client).toBe(undefined);
});
diff --git a/client/client/src/notes/notes.js b/client/client/src/notes/notes.js
index bd214cf49..7e0ec424a 100644
--- a/client/client/src/notes/notes.js
+++ b/client/client/src/notes/notes.js
@@ -6,11 +6,13 @@ export default class Controller {
this.$http = $http;
this.$state = $state;
}
+
$onChanges() {
if (this.client) {
this.getObservation(this.client.id);
}
}
+
getObservation(clientId) {
let json = JSON.stringify({where: {clientFk: this.client.id}, order: 'created DESC'});
this.$http.get(`/client/api/clientObservations?filter=${json}`).then(
@@ -19,6 +21,7 @@ export default class Controller {
}
);
}
+
newObservation() {
this.$state.go("clientCard.notes.create", {id: this.client.id});
}
diff --git a/client/client/src/notes/notes.spec.js b/client/client/src/notes/notes.spec.js
index 78d8092fc..1db229caa 100644
--- a/client/client/src/notes/notes.spec.js
+++ b/client/client/src/notes/notes.spec.js
@@ -5,6 +5,7 @@ describe('Client', () => {
let $componentController;
let $state;
let $httpBackend;
+ let controller;
beforeEach(() => {
angular.mock.module('client');
@@ -14,11 +15,11 @@ describe('Client', () => {
$componentController = _$componentController_;
$state = _$state_;
$httpBackend = _$httpBackend_;
+ controller = $componentController('vnClientNotes', {$httpBackend: $httpBackend, $state: $state});
}));
describe('$onChanges()', () => {
it(`should call getObservation() with the client id`, () => {
- let controller = $componentController('vnClientNotes', {$httpBackend: $httpBackend, $state: $state});
controller.client = {
id: 1234
};
@@ -31,19 +32,20 @@ describe('Client', () => {
describe('$getObservation()', () => {
it(`should request to GET the client notes`, () => {
- let controller = $componentController('vnClientNotes', {$httpBackend: $httpBackend, $state: $state});
controller.client = {id: '1234'};
- let json = JSON.stringify({where: {clientFk: '1234'}, order: 'created DESC'});
- $httpBackend.when('GET', `/client/api/clientObservations?filter=${json}`).respond('ok');
- $httpBackend.expectGET(`/client/api/clientObservations?filter=${json}`, {Accept: 'application/json, text/plain, */*'});
+ let jsonString = JSON.stringify({where: {clientFk: '1234'}, order: 'created DESC'});
+ let json = {data: 'some data'};
+ $httpBackend.when('GET', `/client/api/clientObservations?filter=${jsonString}`).respond(json);
+ $httpBackend.expectGET(`/client/api/clientObservations?filter=${jsonString}`, {Accept: 'application/json, text/plain, */*'});
controller.getObservation();
$httpBackend.flush();
+
+ expect(controller.observations).toEqual(json);
});
});
describe('$newObservation()', () => {
it(`should redirect the user to the newObservation view`, () => {
- let controller = $componentController('vnClientNotes', {$httpBackend: $httpBackend, $state: $state});
controller.client = {id: '1234'};
spyOn(controller.$state, 'go');
controller.newObservation();
diff --git a/client/client/src/notes/style.css b/client/client/src/notes/style.css
index b5e17c7a7..4d0f8eba7 100644
--- a/client/client/src/notes/style.css
+++ b/client/client/src/notes/style.css
@@ -1,3 +1,3 @@
-.notes-date{
+.notes-date {
font-family: raleway-bold;
}
\ No newline at end of file
diff --git a/client/client/src/search-panel/search-panel.js b/client/client/src/search-panel/search-panel.js
index 87f6308ce..3f78dc809 100644
--- a/client/client/src/search-panel/search-panel.js
+++ b/client/client/src/search-panel/search-panel.js
@@ -1,25 +1,28 @@
import ngModule from '../module';
export default class Controller {
- constructor($window) {
- this.$window = $window;
+ constructor(sessionStorage) {
+ this.sessionStorage = sessionStorage;
// onSubmit() is defined by @vnSearchbar
this.onSubmit = () => {};
}
+
onSearch() {
this.setStorageValue();
this.onSubmit(this.filter);
}
+
$onChanges() {
- var value = JSON.parse(this.$window.sessionStorage.getItem('filter'));
+ var value = this.sessionStorage.get('filter');
if (value !== undefined)
this.filter = value;
}
+
setStorageValue() {
- this.$window.sessionStorage.setItem('filter', JSON.stringify(this.filter));
+ this.sessionStorage.set('filter', this.filter);
}
}
-Controller.$inject = ['$window'];
+Controller.$inject = ['sessionStorage'];
ngModule.component('vnClientSearchPanel', {
template: require('./search-panel.html'),
diff --git a/client/client/src/search-panel/search-panel.spec.js b/client/client/src/search-panel/search-panel.spec.js
index eacc74ac3..e4b7b5634 100644
--- a/client/client/src/search-panel/search-panel.spec.js
+++ b/client/client/src/search-panel/search-panel.spec.js
@@ -3,20 +3,21 @@ import './search-panel.js';
describe('Client', () => {
describe('Component vnClientSearchPanel', () => {
let $componentController;
- let $window;
+ let sessionStorage;
+ let controller;
beforeEach(() => {
angular.mock.module('client');
});
- beforeEach(angular.mock.inject((_$componentController_, _$window_) => {
+ beforeEach(angular.mock.inject((_$componentController_, _sessionStorage_) => {
$componentController = _$componentController_;
- $window = _$window_;
+ sessionStorage = _sessionStorage_;
+ controller = $componentController('vnClientSearchPanel', {sessionStorage: sessionStorage});
}));
describe('onSearch()', () => {
- it(`should call setStorageValue() and onSubmit()`, () => {
- let controller = $componentController('vnClientSearchPanel', {$window: $window});
+ it('should call setStorageValue() and onSubmit()', () => {
spyOn(controller, 'setStorageValue');
spyOn(controller, 'onSubmit');
controller.setStorageValue();
@@ -28,14 +29,12 @@ describe('Client', () => {
});
describe('$onChanges()', () => {
- it(`should set filter properties using the search values`, () => {
- let controller = $componentController('vnClientSearchPanel', {$window: $window});
-
+ it('should set filter properties using the search values', () => {
expect(controller.filter).not.toBeDefined();
- spyOn(JSON, 'parse').and.returnValue({data: 'data'});
+ spyOn(sessionStorage, 'get').and.returnValue({data: 'data'});
controller.$onChanges();
- expect(controller.filter).toBe(JSON.parse({data: 'data'}));
+ expect(controller.filter).toBe(sessionStorage.get({data: 'data'}));
});
});
});
diff --git a/client/client/src/web-access/web-access.html b/client/client/src/web-access/web-access.html
index 7d7cc4f92..71a251247 100644
--- a/client/client/src/web-access/web-access.html
+++ b/client/client/src/web-access/web-access.html
@@ -8,9 +8,15 @@
- Web access
-
-
+
+ Web access
+
+
+
+
+
+
+
diff --git a/client/client/src/web-access/web-access.js b/client/client/src/web-access/web-access.js
index dc61eac82..696d8a0ad 100644
--- a/client/client/src/web-access/web-access.js
+++ b/client/client/src/web-access/web-access.js
@@ -29,6 +29,7 @@ export default class Controller {
this.repeatPassword = '';
this.$.$apply();
}
+
onPassChange(response) {
if (response == 'ACCEPT' && this.canChangePassword)
try {
diff --git a/client/client/src/web-access/web-access.spec.js b/client/client/src/web-access/web-access.spec.js
index 55a762d37..584ad58c1 100644
--- a/client/client/src/web-access/web-access.spec.js
+++ b/client/client/src/web-access/web-access.spec.js
@@ -5,6 +5,7 @@ describe('Component VnClientWebAccess', () => {
let $httpBackend;
let $scope;
let vnApp;
+ let controller;
beforeEach(() => {
angular.mock.module('client');
@@ -16,11 +17,11 @@ describe('Component VnClientWebAccess', () => {
$httpBackend = _$httpBackend_;
vnApp = _vnApp_;
spyOn(vnApp, 'showError');
+ controller = $componentController('vnClientWebAccess', {$scope: $scope});
}));
describe('$onChanges()', () => {
it(`should pass client's account data to account then call isCustomer function`, () => {
- let controller = $componentController('vnClientWebAccess', {$scope: $scope});
spyOn(controller, 'isCustomer');
controller.client = {client: 'Bruce Wayne', account: 'Wayne Industries'};
controller.account = {};
@@ -33,7 +34,6 @@ describe('Component VnClientWebAccess', () => {
describe('isCustomer()', () => {
it(`should perform a query if client is defined with an ID`, () => {
- let controller = $componentController('vnClientWebAccess', {$scope: $scope});
controller.client = {id: '1234'};
controller.isCustomer();
@@ -45,7 +45,6 @@ describe('Component VnClientWebAccess', () => {
describe('onPassOpen()', () => {
it('should set passwords to empty values', () => {
- let controller = $componentController('vnClientWebAccess', {$scope: $scope});
controller.newPassword = 'm24x8';
controller.repeatPassword = 'm24x8';
controller.onPassOpen();
@@ -57,7 +56,6 @@ describe('Component VnClientWebAccess', () => {
describe('onPassChange()', () => {
it('should request to update the password', () => {
- let controller = $componentController('vnClientWebAccess', {$scope: $scope});
controller.client = {id: '1234'};
controller.newPassword = 'm24x8';
controller.repeatPassword = 'm24x8';
@@ -70,7 +68,6 @@ describe('Component VnClientWebAccess', () => {
describe(`when password is empty`, () => {
it(`should throw Passwords can't be empty error`, () => {
- let controller = $componentController('vnClientWebAccess', {$scope: $scope});
controller.client = {id: '1234'};
controller.newPassword = '';
controller.canChangePassword = true;
@@ -82,7 +79,6 @@ describe('Component VnClientWebAccess', () => {
describe(`when passwords don't match`, () => {
it(`should throw Passwords don't match error`, () => {
- let controller = $componentController('vnClientWebAccess', {$scope: $scope});
controller.client = {id: '1234'};
controller.newPassword = 'm24x8';
controller.canChangePassword = true;
diff --git a/client/core/src/autocomplete/autocomplete.js b/client/core/src/autocomplete/autocomplete.js
index a4e04a9be..853267592 100644
--- a/client/core/src/autocomplete/autocomplete.js
+++ b/client/core/src/autocomplete/autocomplete.js
@@ -1,14 +1,16 @@
import {module} from '../module';
import Component from '../lib/component';
+import copyObject from '../lib/copy';
import './style.scss';
class Autocomplete extends Component {
- constructor($element, $scope, $http, $timeout) {
+ constructor($element, $scope, $http, $timeout, $filter) {
super($element);
this.$element = $element;
this.$scope = $scope;
this.$http = $http;
this.$timeout = $timeout;
+ this.$filter = $filter;
this._showDropDown = false;
this.finding = false;
@@ -20,7 +22,7 @@ class Autocomplete extends Component {
this.showField = this.showField || 'name';
this.valueField = this.valueField || 'id';
this.order = this.order || 'name ASC';
- this.items = this.data || [];
+ this.items = copyObject(this.data) || [];
this.displayValueMultiCheck = [];
this._multiField = [];
this.readonly = true;
@@ -30,6 +32,7 @@ class Autocomplete extends Component {
get showDropDown() {
return this._showDropDown;
}
+
set showDropDown(value) {
if (value && this.url && !this._preLoad) {
this._preLoad = true;
@@ -75,6 +78,7 @@ class Autocomplete extends Component {
get field() {
return this.multiple ? this._multiField : this._field;
}
+
set field(value) {
if (!angular.equals(value, this.field)) {
this.finding = true;
@@ -101,7 +105,7 @@ class Autocomplete extends Component {
if (value && value.hasOwnProperty(this.valueField)) {
this._field = value[this.valueField];
if (this.multiple) {
- this._multiField = [value[this.valueField]]
+ this._multiField = [value[this.valueField]];
}
if (value.hasOwnProperty(this.showField)) {
this.displayValue = value[this.showField];
@@ -162,6 +166,7 @@ class Autocomplete extends Component {
json => this.onItemRequest(null)
);
}
+
onItemRequest(data) {
if (data && data.length > 0)
this.showItem(data[0]);
@@ -187,12 +192,19 @@ class Autocomplete extends Component {
}
findItems(search) {
- if (!this.url)
- return this.items ? this.items : [];
-
- if (search && !this.finding) {
+ if (this.url && search && !this.finding) {
this.maxRow = false;
- let filter = {where: {name: {regexp: search}}};
+ 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.order;
let json = JSON.stringify(filter);
this.finding = true;
this.$http.get(`${this.url}?filter=${json}`).then(
@@ -212,54 +224,67 @@ class Autocomplete extends Component {
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() {
- let filter = {};
- if (!this.finding) {
- this.finding = true;
+ if (this.url === undefined) {
+ this.items = copyObject(this.data);
+ 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.order;
- }
-
- let json = JSON.stringify(filter);
-
- this.removeLoadMore = false;
-
- 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;
+ if (this.maxRow) {
+ if (this.items) {
+ filter.skip = this.items.length;
}
- this.finding = false;
- },
- () => {
- this.finding = false;
+ filter.limit = this.maxRow;
+ filter.order = this.order;
}
- );
+ if (this.filter) {
+ Object.assign(filter, this.filter);
+ }
+
+ let json = JSON.stringify(filter);
+
+ this.removeLoadMore = false;
+
+ 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;
+ }
+ );
+ }
}
}
+
$onInit() {
this.findMore = this.url && this.maxRow;
this.mouseFocus = false;
@@ -299,9 +324,16 @@ class Autocomplete extends Component {
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', '$timeout'];
+}
+Autocomplete.$inject = ['$element', '$scope', '$http', '$timeout', '$filter'];
module.component('vnAutocomplete', {
template: require('./autocomplete.html'),
@@ -317,7 +349,9 @@ module.component('vnAutocomplete', {
field: '=',
label: '@',
multiple: '@?',
- order: '@?'
+ order: '@?',
+ filter: '',
+ filterSearch: '@?'
},
transclude: {
tplItem: '?tplItem'
diff --git a/client/core/src/autocomplete/autocomplete.spec.js b/client/core/src/autocomplete/autocomplete.spec.js
index 5c920bba8..7f8acb427 100644
--- a/client/core/src/autocomplete/autocomplete.spec.js
+++ b/client/core/src/autocomplete/autocomplete.spec.js
@@ -6,6 +6,7 @@ describe('Component vnAutocomplete', () => {
let $httpBackend;
let $timeout;
let $element;
+ let controller;
beforeEach(() => {
angular.mock.module('client');
@@ -17,11 +18,11 @@ describe('Component vnAutocomplete', () => {
$httpBackend = _$httpBackend_;
$timeout = _$timeout_;
$element = angular.element('');
+ controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
}));
describe('showDropDown() setter', () => {
it(`should set _showDropDown value`, () => {
- let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
controller._showDropDown = '';
controller.showDropDown = 'some value';
@@ -29,7 +30,6 @@ describe('Component vnAutocomplete', () => {
});
it(`should set _showDropDown value`, () => {
- let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
controller._showDropDown = '';
controller.showDropDown = 'some value';
@@ -39,7 +39,6 @@ describe('Component vnAutocomplete', () => {
describe('displayValue() setter', () => {
it(`should display value in a formated way`, () => {
- let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
let value = 'some value';
controller.displayValue = value;
@@ -48,7 +47,6 @@ describe('Component vnAutocomplete', () => {
describe('when the autocomeplete is multiple', () => {
it(`should display values separated with commas`, () => {
- let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
controller.multiple = true;
controller.displayValue = 'some value';
controller.displayValue = 'another value';
@@ -61,14 +59,12 @@ describe('Component vnAutocomplete', () => {
describe('field() setter', () => {
describe('when value is an object', () => {
it(`should set _field controllers property`, () => {
- let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
controller.field = {id: 1, name: 'Bruce Wayne'};
expect(controller._field).toEqual(1);
});
it(`should set _multifield controllers property `, () => {
- let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
controller.multiple = true;
controller.field = {id: 1, name: 'Bruce Wayne'};
@@ -82,7 +78,6 @@ describe('Component vnAutocomplete', () => {
});
it(`should set _multifield value and remove it if called a second type with same value`, () => {
- let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
controller.multiple = true;
controller.field = {id: 1, name: 'Bruce Wayne'};
@@ -96,7 +91,6 @@ describe('Component vnAutocomplete', () => {
});
it(`should set displayValue finding an existing item in the controller.items property`, () => {
- let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
controller.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}];
controller.field = {id: 2, name: 'Bruce Wayne'};
@@ -106,7 +100,6 @@ describe('Component vnAutocomplete', () => {
describe('when value is a number', () => {
it(`should set _field controller property finding an existing item in the controller.items property`, () => {
- let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}];
controller.field = 2;
@@ -114,7 +107,6 @@ describe('Component vnAutocomplete', () => {
});
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`, () => {
- let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}];
controller.multiple = true;
controller.field = 2;
@@ -127,16 +119,15 @@ describe('Component vnAutocomplete', () => {
});
it(`should perform a query if the item id isn't present in the controller.items property`, () => {
- let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout}, {url: 'test.com'});
- $httpBackend.whenGET('test.com?filter={"fields":{"id":true,"name":true},"where":{"id":3}}').respond();
- $httpBackend.expectGET('test.com?filter={"fields":{"id":true,"name":true},"where":{"id":3}}');
+ controller.url = 'test.com';
+ $httpBackend.whenGET(`${controller.url}?filter={"fields":{"id":true,"name":true},"where":{"id":3}}`).respond();
+ $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`, () => {
- let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
controller.items = [{id: 1, name: 'test1'}, {id: 2, name: 'Bruce Wayne'}];
controller.field = 2;
@@ -144,9 +135,9 @@ describe('Component vnAutocomplete', () => {
});
it(`should set field performing a query as the item id isn't present in the controller.items property`, () => {
- let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout}, {url: 'test.com'});
- $httpBackend.whenGET('test.com?filter={"fields":{"id":true,"name":true},"where":{"id":3}}').respond();
- $httpBackend.expectGET('test.com?filter={"fields":{"id":true,"name":true},"where":{"id":3}}');
+ controller.url = 'test.com';
+ $httpBackend.whenGET(`${controller.url}?filter={"fields":{"id":true,"name":true},"where":{"id":3}}`).respond();
+ $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();
@@ -154,28 +145,28 @@ describe('Component vnAutocomplete', () => {
});
});
- describe('findItem()', () => {
- it(`should return items empty array if the controller does not provide a url and have no items defined`, () => {
- let controller = $componentController('vnIconMenu', {$scope, $element, $httpBackend, $timeout});
- controller.findItems('some search value');
-
- expect(controller.items).not.toBeDefined();
- });
-
- it(`should return items array if the controller does not provide a url`, () => {
- let controller = $componentController('vnIconMenu', {$scope, $element, $httpBackend, $timeout});
- controller.items = ['Batman', 'Bruce Wayne'];
- controller.findItems('some search value');
-
- expect(controller.items.length).toEqual(2);
- });
-
+ describe('findItems()', () => {
it(`should perform a search and store the result in controller items`, () => {
- let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout}, {url: 'test.com'});
+ let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout});
+ controller.url = 'test.com';
let search = 'The Joker';
- let json = JSON.stringify({where: {name: {regexp: search}}});
- $httpBackend.whenGET(`test.com?filter=${json}`).respond([{id: 3, name: 'The Joker'}]);
- $httpBackend.expectGET(`test.com?filter=${json}`);
+ let json = JSON.stringify({where: {name: {regexp: search}}, order: controller.order});
+ $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: {surname: {regexp: 'search'}}}";
+ let json = JSON.stringify({where: {surname: {regexp: search}}, order: controller.order});
+ $httpBackend.whenGET(`${controller.url}?filter=${json}`).respond([{id: 3, name: 'The Joker'}]);
+ $httpBackend.expectGET(`${controller.url}?filter=${json}`);
controller.findItems(search);
$httpBackend.flush();
@@ -183,12 +174,12 @@ describe('Component vnAutocomplete', () => {
});
it(`should perform a search with multiple true and store the result in controller items with the checked property defined`, () => {
- let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout}, {url: 'test.com'});
+ controller.url = 'test.com';
let search = 'Joker';
controller.multiple = true;
- let json = JSON.stringify({where: {name: {regexp: search}}});
- $httpBackend.whenGET(`test.com?filter=${json}`).respond([{id: 3, name: 'The Joker'}, {id: 4, name: 'Joker'}]);
- $httpBackend.expectGET(`test.com?filter=${json}`);
+ let json = JSON.stringify({where: {name: {regexp: search}}, order: controller.order});
+ $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();
@@ -196,7 +187,7 @@ describe('Component vnAutocomplete', () => {
});
it(`should call getItems function if there's no search value`, () => {
- let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout}, {url: 'test.com'});
+ controller.url = 'test.com';
spyOn(controller, 'getItems');
controller.findItems();
@@ -206,9 +197,9 @@ describe('Component vnAutocomplete', () => {
describe('getItems()', () => {
it(`should perfom a query to fill the items without filter`, () => {
- let controller = $componentController('vnAutocomplete', {$scope, $element, $httpBackend, $timeout}, {url: 'test.com'});
- $httpBackend.whenGET(`test.com?filter={"skip":0,"limit":10,"order":"name ASC"}`).respond([{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}]);
- $httpBackend.expectGET(`test.com?filter={"skip":0,"limit":10,"order":"name ASC"}`);
+ 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();
diff --git a/client/core/src/check/check.js b/client/core/src/check/check.js
index 5976a6625..aea298be9 100644
--- a/client/core/src/check/check.js
+++ b/client/core/src/check/check.js
@@ -2,6 +2,7 @@ import {module as _module} from '../module';
import * as resolveFactory from '../lib/resolveDefaultComponents';
import * as normalizerFactory from '../lib/inputAttrsNormalizer';
import * as util from '../lib/util';
+import './style.css';
const _NAME = 'check';
export const NAME = util.getName(_NAME);
diff --git a/client/core/src/check/style.css b/client/core/src/check/style.css
new file mode 100644
index 000000000..1088ad05e
--- /dev/null
+++ b/client/core/src/check/style.css
@@ -0,0 +1,3 @@
+vn-check {
+ float: left;
+}
\ No newline at end of file
diff --git a/client/core/src/column-header/column-header.js b/client/core/src/column-header/column-header.js
index b153f0987..2f5f4d3c3 100644
--- a/client/core/src/column-header/column-header.js
+++ b/client/core/src/column-header/column-header.js
@@ -21,6 +21,12 @@ export default class ColumnHeader {
}
return showArrow;
}
+ $onInit() {
+ if (this.defaultOrder) {
+ this.order = this.defaultOrder;
+ this.onClick();
+ }
+ }
}
ColumnHeader.$inject = [];
@@ -29,7 +35,8 @@ module.component('vnColumnHeader', {
bindings: {
field: '@?',
text: '@?',
- className: '@?'
+ className: '@?',
+ defaultOrder: '@?'
},
require: {
gridHeader: '^^vnGridHeader'
diff --git a/client/core/src/column-header/column-header.spec.js b/client/core/src/column-header/column-header.spec.js
index 247b75993..5c6d29d73 100644
--- a/client/core/src/column-header/column-header.spec.js
+++ b/client/core/src/column-header/column-header.spec.js
@@ -2,6 +2,7 @@ import './column-header.js';
describe('Component vnColumnHeader', () => {
let $componentController;
+ let controller;
beforeEach(() => {
angular.mock.module('client');
@@ -9,11 +10,12 @@ describe('Component vnColumnHeader', () => {
beforeEach(angular.mock.inject(_$componentController_ => {
$componentController = _$componentController_;
+ controller = $componentController('vnColumnHeader', {});
}));
describe('onClick()', () => {
it(`should change the ordenation to DESC (descendant) if it was ASC (ascendant)`, () => {
- let controller = $componentController('vnColumnHeader', {}, {gridHeader: {selectColum: () => {}}});
+ controller.gridHeader = {selectColum: () => {}};
controller.order = 'ASC';
controller.onClick();
@@ -21,7 +23,7 @@ describe('Component vnColumnHeader', () => {
});
it(`should change the ordenation to ASC (ascendant) if it wasnt ASC`, () => {
- let controller = $componentController('vnColumnHeader', {}, {gridHeader: {selectColum: () => {}}});
+ controller.gridHeader = {selectColum: () => {}};
controller.order = 'DESC or any other value that might occur';
controller.onClick();
@@ -29,7 +31,7 @@ describe('Component vnColumnHeader', () => {
});
it(`should call the selectColum() function after changing a value`, () => {
- let controller = $componentController('vnColumnHeader', {}, {gridHeader: {selectColum: () => {}}});
+ controller.gridHeader = {selectColum: () => {}};
controller.order = 'Change me!';
spyOn(controller.gridHeader, 'selectColum');
controller.onClick();
@@ -40,7 +42,7 @@ describe('Component vnColumnHeader', () => {
describe('showArrow()', () => {
it(`should return true when the type is DESC and MouseIsOver`, () => {
- let controller = $componentController('vnColumnHeader', {}, {gridHeader: {selectColum: () => {}}});
+ controller.gridHeader = {selectColum: () => {}};
controller.mouseIsOver = true;
let result = controller.showArrow('DESC');
@@ -48,7 +50,7 @@ describe('Component vnColumnHeader', () => {
});
it(`should return true if many conditions are true`, () => {
- let controller = $componentController('vnColumnHeader', {}, {gridHeader: {currentColumn: {field: 'fields should be identical'}}});
+ controller.gridHeader = {currentColumn: {field: 'fields should be identical'}};
controller.field = 'fields should be identical';
controller.order = 'ASC';
let result = controller.showArrow('ASC');
@@ -57,7 +59,7 @@ describe('Component vnColumnHeader', () => {
});
it(`should return false without type being DESC or any other values being true`, () => {
- let controller = $componentController('vnColumnHeader', {}, {gridHeader: {currentColumn: {field: 'this field isnt the same as controllers field'}}});
+ controller.gridHeader = {currentColumn: {field: 'fields should be identical'}};
controller.field = 'I am the controllers field';
controller.order = 'ASC';
let result = controller.showArrow('ASC');
@@ -65,4 +67,22 @@ describe('Component vnColumnHeader', () => {
expect(result).toEqual(false);
});
});
+
+ describe('onInit()', () => {
+ it(`should never call onClick()`, () => {
+ spyOn(controller, 'onClick');
+ controller.$onInit();
+
+ expect(controller.onClick).not.toHaveBeenCalledWith();
+ });
+
+ it(`should define controllers order as per defaultOrder then call onClick()`, () => {
+ controller.defaultOrder = 'ASC';
+ spyOn(controller, 'onClick');
+ controller.$onInit();
+
+ expect(controller.order).toEqual('ASC');
+ expect(controller.onClick).toHaveBeenCalledWith();
+ });
+ });
});
diff --git a/client/core/src/datePicker/datePicker.html b/client/core/src/datePicker/datePicker.html
index b4cb4c83f..d91f0a53f 100644
--- a/client/core/src/datePicker/datePicker.html
+++ b/client/core/src/datePicker/datePicker.html
@@ -1,19 +1,21 @@
-
+
-
-
+ rule="{{::$ctrl.rule}}"/>
+
+
+ query_builder
+ clear
+
+
\ No newline at end of file
diff --git a/client/core/src/datePicker/datePicker.js b/client/core/src/datePicker/datePicker.js
index 43f34d9df..2ebed10d6 100644
--- a/client/core/src/datePicker/datePicker.js
+++ b/client/core/src/datePicker/datePicker.js
@@ -27,7 +27,9 @@ class DatePicker extends Component {
this.enabled = true;
this._modelView = null;
this._model = undefined;
-
+ this._optionsChecked = false;
+ this.hasFocus = false;
+ this.hasMouseIn = false;
componentHandler.upgradeElement($element[0].firstChild);
}
@@ -37,7 +39,8 @@ class DatePicker extends Component {
set model(value) {
this._model = value;
if (value && !this.modelView) {
- let initialDateFormat = (this.iniOptions && this.iniOptions.dateFormat) ? this.iniOptions.dateFormat : 'Y-m-d';
+ let options = this._getOptions();
+ let initialDateFormat = (options && options.dateFormat) ? options.dateFormat : 'Y-m-d';
let format = this._formatFlat2Angular(initialDateFormat);
this.modelView = this.$filter('date')(value, format);
}
@@ -135,9 +138,12 @@ class DatePicker extends Component {
}
}
- $onInit() {
- if (!this.iniOptions)
+ _getOptions() {
+ if (this.iniOptions && this._optionsChecked) {
+ return this.iniOptions;
+ } else if (!this.iniOptions) {
this.iniOptions = {};
+ }
if (!this.iniOptions.locale)
this.iniOptions.locale = this.$translate.use();
@@ -157,9 +163,14 @@ class DatePicker extends Component {
}
);
}
+ this._optionsChecked = true;
+ return this.iniOptions;
+ }
- if (this.input)
- this.vp = new Flatpickr(this.input, this.iniOptions);
+ $onInit() {
+ this.iniOptions = this._getOptions();
+ this.isTimePicker = (this.iniOptions && this.iniOptions.enableTime && this.iniOptions.noCalendar);
+ this.vp = new Flatpickr(this.input, this.iniOptions);
}
$onDestroy() {
if (this.vp)
diff --git a/client/core/src/datePicker/datePicker.spec.js b/client/core/src/datePicker/datePicker.spec.js
index ebea87ccf..bd0807dd7 100644
--- a/client/core/src/datePicker/datePicker.spec.js
+++ b/client/core/src/datePicker/datePicker.spec.js
@@ -6,36 +6,35 @@ describe('Component vnDatePicker', () => {
let $timeout;
let $element;
let $translate;
+ let controller;
beforeEach(() => {
angular.mock.module('client');
});
- beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$timeout_) => {
+ beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$timeout_, _$translate_) => {
$componentController = _$componentController_;
$scope = $rootScope.$new();
$timeout = _$timeout_;
$element = angular.element(``);
- $translate = {};
+ $translate = _$translate_;
+ controller = $componentController('vnDatePicker', {$scope, $element, $translate, $timeout});
}));
describe('_formatFlat2Angular()', () => {
it(`should format date from Y-m-d to yyyy-MM-dd`, () => {
- let controller = $componentController('vnDatePicker', {$scope, $element, $translate, $timeout});
let formatedDate = controller._formatFlat2Angular(`Y-m-d`);
expect(formatedDate).toBe('yyyy-MM-dd');
});
it(`should format date from d-m-Y to dd-MM-yyyy`, () => {
- let controller = $componentController('vnDatePicker', {$scope, $element, $translate, $timeout});
let formatedDate = controller._formatFlat2Angular(`d-m-Y`);
expect(formatedDate).toBe('dd-MM-yyyy');
});
it(`should split the given string into parts`, () => {
- let controller = $componentController('vnDatePicker', {$scope, $element, $translate, $timeout});
controller.iniOptions = {dateFormat: 'd/m/Y'};
controller.model = '2017-12-23';
diff --git a/client/core/src/datePicker/style.scss b/client/core/src/datePicker/style.scss
index f1bd30dab..d729ba947 100644
--- a/client/core/src/datePicker/style.scss
+++ b/client/core/src/datePicker/style.scss
@@ -1,12 +1,18 @@
vn-date-picker {
+ div {
+ outline: none; //remove chrome outline
+ }
.mdl-chip__action {
- position: absolute;
+ position: absolute;
+ width: auto;
top: 0px;
right: -6px;
margin: 22px 0px;
background-color: white;
}
.material-icons {
- font-size: 18px;
+ font-size: 18px;
+ float: right;
+ margin-right: 5px;
}
}
\ No newline at end of file
diff --git a/client/core/src/dialog/dialog.spec.js b/client/core/src/dialog/dialog.spec.js
index 5102966d4..e13242d6b 100644
--- a/client/core/src/dialog/dialog.spec.js
+++ b/client/core/src/dialog/dialog.spec.js
@@ -1,8 +1,7 @@
-import './dialog.js';
-
describe('Component vnDialog', () => {
let $componentController;
let $element;
+ let controller;
beforeEach(() => {
angular.mock.module('client');
@@ -11,13 +10,15 @@ describe('Component vnDialog', () => {
beforeEach(angular.mock.inject(_$componentController_ => {
$componentController = _$componentController_;
$element = angular.element('');
+ controller = $componentController('vnDialog', {$element});
}));
describe('show()', () => {
it(`should define keypressHandler function, call addEventListener function and define element.style.display to block then call onOpen function`, () => {
window.innerHeight = 600;
window.innerWidth = 800;
- let controller = $componentController('vnDialog', {$element}, {onOpen: () => {}, dialog: {style: {}, offsetWidth: 780, offsetHeight: 581}});
+ controller.onOpen = () => {};
+ controller.dialog = {style: {}, offsetWidth: 780, offsetHeight: 581};
spyOn(controller.document, 'addEventListener');
spyOn(controller, 'onOpen');
controller.show();
@@ -31,7 +32,7 @@ describe('Component vnDialog', () => {
it(`should define keypressHandler function, call addEventListener function and define element.style.display to block and never call onOpen function`, () => {
window.innerHeight = 600;
window.innerWidth = 800;
- let controller = $componentController('vnDialog', {$element}, {dialog: {style: {}, offsetWidth: 781, offsetHeight: 581}});
+ controller.dialog = {style: {}, offsetWidth: 781, offsetHeight: 581};
spyOn(controller.document, 'addEventListener');
controller.show();
@@ -44,7 +45,6 @@ describe('Component vnDialog', () => {
describe('hide()', () => {
it(`should call fireResponse() and realHide()`, () => {
- let controller = $componentController('vnDialog', {$element});
spyOn(controller, 'fireResponse');
spyOn(controller, 'realHide');
controller.hide();
@@ -56,7 +56,6 @@ describe('Component vnDialog', () => {
describe('fireResponse()', () => {
it(`should return cancel as false`, () => {
- let controller = $componentController('vnDialog', {$element});
let result = controller.fireResponse('I am the answer!');
expect(controller.onResponse).not.toBeDefined();
@@ -65,9 +64,9 @@ describe('Component vnDialog', () => {
it(`should return onResponse()`, () => {
let text = 'I am the answer!';
- let controller = $componentController('vnDialog', {$element}, {onResponse: () => {
+ controller.onResponse = () => {
return {response: text};
- }});
+ };
let result = controller.fireResponse(text);
expect(result.response).toEqual(text);
@@ -76,7 +75,6 @@ describe('Component vnDialog', () => {
describe('realHide()', () => {
it(`should set element.style.display and lastEvent properties and call removeEvenListener()`, () => {
- let controller = $componentController('vnDialog', {$element});
spyOn(controller.document, 'removeEventListener');
expect(controller.element.style.display).not.toEqual('none');
@@ -91,7 +89,6 @@ describe('Component vnDialog', () => {
describe('onButtonClick()', () => {
it(`should call realHide if cancel isn't false`, () => {
- let controller = $componentController('vnDialog', {$element});
controller.element = document.createElement('div');
controller.element.className = 'tpl-buttons';
let childElement = document.createElement('div');
@@ -106,7 +103,6 @@ describe('Component vnDialog', () => {
});
it(`should call fireResponse with the value of response`, () => {
- let controller = $componentController('vnDialog', {$element});
controller.element = document.createElement('div');
controller.element.className = 'tpl-buttons';
let childElement = document.createElement('div');
@@ -125,7 +121,6 @@ describe('Component vnDialog', () => {
describe('onDialogMouseDown()', () => {
it(`should set controller's lastEvent property`, () => {
- let controller = $componentController('vnDialog', {$element});
controller.element = document.createElement('div');
let event = {target: controller.element};
controller.onDialogMouseDown(event);
@@ -136,7 +131,6 @@ describe('Component vnDialog', () => {
describe('onBackgroundMouseDown()', () => {
it(`shouldn't call hide() function as event equals lastEvent`, () => {
- let controller = $componentController('vnDialog', {$element});
controller.element = document.createElement('div');
let event = {target: controller.element};
controller.lastEvent = event;
@@ -147,7 +141,6 @@ describe('Component vnDialog', () => {
});
it(`should call hide() function as event doesn't equal lastEvent`, () => {
- let controller = $componentController('vnDialog', {$element});
controller.element = document.createElement('div');
let event = {target: controller.element};
controller.lastEvent = event;
@@ -161,7 +154,6 @@ describe('Component vnDialog', () => {
describe('onKeypress()', () => {
it(`should call hide() if the key pressed equal the code 27`, () => {
- let controller = $componentController('vnDialog', {$element});
controller.element = document.createElement('div');
let event = {target: controller.element};
event.keyCode = 27;
@@ -172,7 +164,6 @@ describe('Component vnDialog', () => {
});
it(`should't call hide() as the key pressed equal the code 999`, () => {
- let controller = $componentController('vnDialog', {$element});
controller.element = document.createElement('div');
let event = {target: controller.element};
event.keyCode = 999;
diff --git a/client/core/src/directives/acl.js b/client/core/src/directives/acl.js
index 713c61e27..362dad65d 100644
--- a/client/core/src/directives/acl.js
+++ b/client/core/src/directives/acl.js
@@ -19,8 +19,8 @@ function vnAcl(aclService, $timeout) {
$timeout(() => {
input.setAttribute("disabled", "true");
});
- $element[0].querySelectorAll('i, vn-drop-down').forEach(i => {
- i.parentNode.removeChild(i);
+ $element[0].querySelectorAll('i, vn-drop-down').forEach(element => {
+ element.parentNode.removeChild(element);
});
}
} else {
diff --git a/client/core/src/directives/dialog.js b/client/core/src/directives/dialog.js
index d4ac65b45..5ee10258e 100644
--- a/client/core/src/directives/dialog.js
+++ b/client/core/src/directives/dialog.js
@@ -11,7 +11,8 @@ export function directive() {
restrict: 'A',
link: function($scope, $element, $attrs) {
$element.on('click', function(event) {
- let dialog = $scope[kebabToCamel($attrs.vnDialog)];
+ let dialogKey = kebabToCamel($attrs.vnDialog);
+ let dialog = $scope[dialogKey];
if (dialog instanceof Dialog)
dialog.show();
event.preventDefault();
diff --git a/client/core/src/directives/focus.js b/client/core/src/directives/focus.js
index 39ae0f196..bf4d86122 100644
--- a/client/core/src/directives/focus.js
+++ b/client/core/src/directives/focus.js
@@ -2,6 +2,8 @@ import {module} from '../module';
/**
* Sets the focus and selects the text on the input.
+ *
+ * @return {Object} The directive
*/
export function directive() {
return {
diff --git a/client/core/src/directives/repeat.js b/client/core/src/directives/repeat.js
deleted file mode 100644
index 643b86a4a..000000000
--- a/client/core/src/directives/repeat.js
+++ /dev/null
@@ -1,16 +0,0 @@
-import {module} from '../module';
-
-directive.$inject = ['$compile'];
-function directive($compile) {
- return {
- restrict: 'A',
- priority: 9999,
- link: function(scope, element, attrs) {
- element.removeAttr('vn-repeat');
- element.attr('ng-repeat', attrs.vnRepeat);
- $compile(element)(scope);
- }
- };
-}
-
-module.directive('vnRepeat', directive);
diff --git a/client/core/src/directives/specs/acl.spec.js b/client/core/src/directives/specs/acl.spec.js
new file mode 100644
index 000000000..615de5146
--- /dev/null
+++ b/client/core/src/directives/specs/acl.spec.js
@@ -0,0 +1,54 @@
+describe('Directive acl', () => {
+ let scope;
+ let element;
+ let compile;
+ let $timeout;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ compile = (hasPermissions, _element) => {
+ inject(($compile, $rootScope, aclService, _$timeout_) => {
+ spyOn(aclService, 'aclPermission').and.returnValue(hasPermissions);
+ scope = $rootScope.$new();
+ $timeout = _$timeout_;
+ element = angular.element(_element);
+ $compile(element)(scope);
+ scope.$digest();
+ });
+ };
+
+ it('should not disable the input element as the user has permision', () => {
+ let html = ``;
+ compile(true, html);
+ let input = element.find('input');
+
+ expect(input).toBeDefined();
+ expect(input.attr('disabled')).toBeFalsy();
+ });
+
+ it('should delete the element as the user does not have permission and there is no action', () => {
+ let html = ``;
+ compile(false, html);
+
+ expect(element.children().length).toEqual(0);
+ });
+
+ it('should disable the element as the action is to disable it but the user has no permission but present', () => {
+ let html = ``;
+ compile(false, html);
+ let input = element.find('input');
+ $timeout.flush();
+
+ expect(input).toBeDefined();
+ expect(input.attr('disabled')).toBeTruthy();
+ });
+
+ it('should delete any element with the tag i and vn-drop-down', () => {
+ let html = ``;
+ compile(false, html);
+
+ expect(element.find('i').length).toBe(0);
+ });
+});
diff --git a/client/core/src/directives/specs/dialog.spec.js b/client/core/src/directives/specs/dialog.spec.js
new file mode 100644
index 000000000..38d4ed9e2
--- /dev/null
+++ b/client/core/src/directives/specs/dialog.spec.js
@@ -0,0 +1,37 @@
+describe('Directive dialog', () => {
+ let $scope;
+ let $element;
+ let element;
+ let compile;
+ let $componentController;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ compile = _element => {
+ inject(($compile, $rootScope) => {
+ $scope = $rootScope.$new();
+ $scope.myDialog = controller;
+ element = angular.element(_element);
+ $compile(element)($scope);
+ $scope.$digest();
+ });
+ };
+
+ beforeEach(angular.mock.inject(_$componentController_ => {
+ $componentController = _$componentController_;
+ $element = angular.element('');
+ controller = $componentController('vnDialog', {$element});
+ }));
+
+ it('should call show() function if dialog is a instance of vnDialog', () => {
+ let html = ``;
+ spyOn(controller, 'show');
+ compile(html);
+ element[0].click();
+
+ expect(controller.show).toHaveBeenCalledWith();
+ });
+});
diff --git a/client/core/src/directives/specs/focus.spec.js b/client/core/src/directives/specs/focus.spec.js
new file mode 100644
index 000000000..f610e9ffb
--- /dev/null
+++ b/client/core/src/directives/specs/focus.spec.js
@@ -0,0 +1,55 @@
+describe('Directive focus', () => {
+ let $scope;
+ let $element;
+ let compile;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ compile = (_element, _childElement) => {
+ inject(($compile, $rootScope) => {
+ $scope = $rootScope.$new();
+ $element = angular.element(_element);
+ if (_childElement) {
+ let childElement = angular.element(_childElement);
+ $element[0] < childElement;
+ $element[0].firstChild.focus = jasmine.createSpy(focus);
+ }
+ $element[0].focus = jasmine.createSpy('focus');
+ $element[0].select = jasmine.createSpy('select');
+ $compile($element)($scope);
+ $scope.$digest();
+ });
+ };
+
+ it('should call the querySelector function upon the input to redefine it with the expected selector then call focus', () => {
+ let html = ``;
+ let childHtml = '';
+ compile(html, childHtml);
+
+ expect($element[0].firstChild.focus).toHaveBeenCalled();
+ });
+
+ it('should print a warning message on console', () => {
+ let html = ``;
+ console.warn = jasmine.createSpy('warn');
+ compile(html);
+
+ expect(console.warn).toHaveBeenCalledWith(`vnFocus: Can't find a focusable element`);
+ });
+
+ it('should call focus function on the element', () => {
+ let html = ``;
+ compile(html);
+
+ expect($element[0].focus).toHaveBeenCalledWith();
+ });
+
+ it('should call select function on the element', () => {
+ let html = ``;
+ compile(html);
+
+ expect($element[0].select).toHaveBeenCalledWith();
+ });
+});
diff --git a/client/core/src/directives/specs/id.spec.js b/client/core/src/directives/specs/id.spec.js
new file mode 100644
index 000000000..5755d1ea9
--- /dev/null
+++ b/client/core/src/directives/specs/id.spec.js
@@ -0,0 +1,43 @@
+describe('Directive vnId', () => {
+ let $scope;
+ let $element;
+ let compile;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ compile = _element => {
+ inject(($compile, $rootScope) => {
+ $scope = $rootScope.$new();
+ $element = angular.element(_element);
+ $compile($element)($scope);
+ $scope.$digest();
+ });
+ };
+
+ it(`should throw an error when there's no id defined`, () => {
+ let html = `
`;
+
+ expect(() => {
+ compile(html);
+ }).toThrow(new Error(`vnId: Attribute can't be null`));
+ });
+
+ it(`should throw an error when these's no controller defined in $element[0]`, () => {
+ let html = ``;
+
+ expect(() => {
+ compile(html);
+ }).toThrow(new Error(`vnId: Can't find controller for element '1'`));
+ });
+
+ it(`should set the controller into the $scope as there are no errors being thrown`, () => {
+ let html = `
`;
+
+ expect($scope['1']).not.toBeDefined();
+ compile(html);
+
+ expect($scope['1']).toBeDefined();
+ });
+});
diff --git a/client/core/src/directives/specs/validation.spec.js b/client/core/src/directives/specs/validation.spec.js
new file mode 100644
index 000000000..e69de29bb
diff --git a/client/core/src/drop-down/drop-down.spec.js b/client/core/src/drop-down/drop-down.spec.js
index 4e2b8d5b9..23fab3b08 100644
--- a/client/core/src/drop-down/drop-down.spec.js
+++ b/client/core/src/drop-down/drop-down.spec.js
@@ -5,6 +5,7 @@ describe('Component vnDropDown', () => {
let $timeout;
let $element;
let $filter;
+ let controller;
beforeEach(() => {
angular.mock.module('client');
@@ -15,11 +16,11 @@ describe('Component vnDropDown', () => {
$element = angular.element('
');
$timeout = _$timeout_;
$filter = _$filter_;
+ controller = $componentController('vnDropDown', {$element, $timeout, $filter});
}));
describe('show() setter', () => {
it(`should define controllers _show using the value received as argument`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
controller._show = 'old value';
controller.show = 'new value';
@@ -29,21 +30,18 @@ describe('Component vnDropDown', () => {
describe('search()', () => {
it(`should set controllers _search property with the value received`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
controller.search = 'some filter valiue';
expect(controller._search).toEqual('some filter valiue');
});
it(`should set controllers _search property to null as the value received is an empty string`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
controller.search = '';
expect(controller._search).toEqual(null);
});
it(`should call onFilterRest() if controllers filterAction is defined`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
controller.filterAction = true;
spyOn(controller, 'onFilterRest');
controller.search = 'some filter valiue';
@@ -52,7 +50,6 @@ describe('Component vnDropDown', () => {
});
it(`should call filterItems() if controllers filterAction is undefined`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
controller.filterAction = undefined;
spyOn(controller, 'filterItems');
controller.search = 'some filter valiue';
@@ -63,7 +60,6 @@ describe('Component vnDropDown', () => {
describe('activeOption() setter', () => {
it(`should set _activeOption as items.length if showLoadMore is defined if activeOption is bigger than items.length then call loadItems()`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
spyOn(controller, 'loadItems');
controller.showLoadMore = true;
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
@@ -75,7 +71,6 @@ describe('Component vnDropDown', () => {
});
it(`should set _activeOption as activeOption if showLoadMore is defined if activeOption is smaller than items.length then call loadItems()`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
spyOn(controller, 'loadItems');
controller.showLoadMore = true;
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
@@ -87,7 +82,6 @@ describe('Component vnDropDown', () => {
});
it(`should set _activeOption as items.length -1 if showLoadMore is not defined then call loadItems()`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
spyOn(controller, 'loadItems');
controller.showLoadMore = undefined;
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
@@ -99,7 +93,6 @@ describe('Component vnDropDown', () => {
});
it(`should define _activeOption as activeOption and never call loadItems()`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
spyOn(controller, 'loadItems');
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}, {id: 5, name: 'Doctor X'}];
controller.activeOption = 1;
@@ -112,7 +105,6 @@ describe('Component vnDropDown', () => {
describe('filterItems() setter', () => {
it(`should set _itemsFiltered using the value of items`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
controller.items = [{id: 1, name: 'Batman'}];
controller.filterItems();
@@ -120,7 +112,6 @@ describe('Component vnDropDown', () => {
});
it(`should set _itemsFiltered with the filtered value of items`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
controller.search = 'Batman';
controller.filterItems();
@@ -129,7 +120,6 @@ describe('Component vnDropDown', () => {
});
it(`should set _itemsFiltered an empty array`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
controller.search = 'the Joker';
@@ -139,7 +129,7 @@ describe('Component vnDropDown', () => {
describe('onFilterRest()', () => {
it(`should call the filterAction() with a constructed object as argument`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter}, {filterAction: () => {}});
+ controller.filterAction = () => {};
controller.search = 'Batman';
spyOn(controller, 'filterAction');
controller.onFilterRest();
@@ -150,7 +140,6 @@ describe('Component vnDropDown', () => {
describe('$onChanges()', () => {
it(`should set the top css of the $element`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
let argumentObject = {show: true, top: {currentValue: 100}};
spyOn(controller.$element, 'css');
controller.$onChanges(argumentObject);
@@ -159,7 +148,6 @@ describe('Component vnDropDown', () => {
});
it(`should set the width css of the $element`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
let argumentObject = {show: true, itemWidth: {currentValue: 100}};
spyOn(controller.$element, 'css');
controller.$onChanges(argumentObject);
@@ -168,7 +156,6 @@ describe('Component vnDropDown', () => {
});
it(`should set the width css of the $element`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
let argumentObject = {items: {id: 1, name: 'Batman'}};
spyOn(controller, 'filterItems');
controller.$onChanges(argumentObject);
@@ -179,7 +166,6 @@ describe('Component vnDropDown', () => {
describe('clearSearch()', () => {
it(`should set the controllers search property to null`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
controller.search = true;
controller.clearSearch();
@@ -189,7 +175,6 @@ describe('Component vnDropDown', () => {
describe('selectOption()', () => {
it(`should set controllers selected and show properties then call clearSearch() as _activeOption is smaller than items.length`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
spyOn(controller, 'clearSearch');
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
controller._activeOption = 0;
@@ -201,7 +186,6 @@ describe('Component vnDropDown', () => {
});
it(`should not set controllers selected, show and never call clearSearch() as _activeOption is bigger than items.length`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
spyOn(controller, 'clearSearch');
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
controller._activeOption = 100;
@@ -213,7 +197,7 @@ describe('Component vnDropDown', () => {
});
it(`should call loadMore() if the activeValue equals items.length`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter}, {loadMore: () => {}});
+ 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;
@@ -226,7 +210,6 @@ describe('Component vnDropDown', () => {
describe('onKeydown()', () => {
it(`should call selectOption() and preventDefault() if Enter key is pressed`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
spyOn(controller, 'selectOption');
controller._show = true;
controller.element = document.createElement('div');
@@ -241,7 +224,6 @@ describe('Component vnDropDown', () => {
});
it(`should call clearSearch() Esc key is pressed`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
spyOn(controller, 'clearSearch');
controller._show = true;
controller.element = document.createElement('div');
@@ -253,7 +235,6 @@ describe('Component vnDropDown', () => {
});
it(`should call clearSearch() Esc key is pressed and take off 1 from _activeOption`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
spyOn(controller, 'setScrollPosition');
controller._show = true;
@@ -269,7 +250,6 @@ describe('Component vnDropDown', () => {
});
it(`should call clearSearch() Esc key is pressed and add up 1 to _activeOption`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
controller.items = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
spyOn(controller, 'setScrollPosition');
controller._show = true;
@@ -291,7 +271,6 @@ describe('Component vnDropDown', () => {
let child = $element[0].firstChild.firstChild;
child.scrollIntoView = () => {};
spyOn(child, 'scrollIntoView');
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
controller._activeOption = 0;
controller.setScrollPosition();
@@ -301,7 +280,6 @@ describe('Component vnDropDown', () => {
describe('selectItem()', () => {
it(`should pass item to selected and set controller._show to false`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
let item = {id: 1, name: 'Batman'};
controller.selectItem(item);
@@ -310,7 +288,6 @@ describe('Component vnDropDown', () => {
});
it(`should pass item to selected and set controller._show to true if the controller.multiple is defined`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
let item = {id: 1, name: 'Batman'};
controller.multiple = true;
controller.selectItem(item);
@@ -322,14 +299,14 @@ describe('Component vnDropDown', () => {
describe('loadItems()', () => {
it(`should set controller._show to true`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
controller.loadItems();
expect(controller._show).toEqual(true);
});
it(`should call loadMore() and then set controller._show to true`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter}, {showLoadMore: () => {}, loadMore: () => {}});
+ controller.showLoadMore = () => {};
+ controller.loadMore = () => {};
spyOn(controller, 'loadMore');
controller.loadItems();
@@ -340,7 +317,6 @@ describe('Component vnDropDown', () => {
describe('$onInit()', () => {
it(`should add an event listener to the parent element`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
spyOn(controller.parent, 'addEventListener');
controller.$onInit();
@@ -350,7 +326,6 @@ describe('Component vnDropDown', () => {
describe('$onDestroy()', () => {
it(`should remove an event listener from the parent element`, () => {
- let controller = $componentController('vnDropDown', {$element, $timeout, $filter});
spyOn(controller.parent, 'removeEventListener');
controller.$onDestroy();
diff --git a/client/core/src/grid-header/grid-header.spec.js b/client/core/src/grid-header/grid-header.spec.js
index 4b9e20da0..03294a348 100644
--- a/client/core/src/grid-header/grid-header.spec.js
+++ b/client/core/src/grid-header/grid-header.spec.js
@@ -2,6 +2,7 @@ import './grid-header.js';
describe('Component vnGridHeader', () => {
let $componentController;
+ let controller;
beforeEach(() => {
angular.mock.module('client');
@@ -9,11 +10,11 @@ describe('Component vnGridHeader', () => {
beforeEach(angular.mock.inject(_$componentController_ => {
$componentController = _$componentController_;
+ controller = $componentController('vnGridHeader', {});
}));
describe('selectColum()', () => {
it(`should set controller currentColumn to equal the argument received`, () => {
- let controller = $componentController('vnGridHeader', {});
let col = {columnStuff: 'some stuff'};
controller.selectColum(col);
@@ -21,7 +22,6 @@ describe('Component vnGridHeader', () => {
});
it(`should set controller currentColumn.order to undefined then set currentColumn to equal the argument received`, () => {
- let controller = $componentController('vnGridHeader', {});
controller.currentColumn = {field: 'some field', order: 'ordered'};
let col = {columnStuff: 'some stuff'};
controller.selectColum(col);
@@ -31,7 +31,6 @@ describe('Component vnGridHeader', () => {
});
it(`should set controller currentColumn.order to undefined then call onOrder passing currentColumn as argument`, () => {
- let controller = $componentController('vnGridHeader', {});
controller.onOrder = () => {};
spyOn(controller, 'onOrder');
let col = {columnStuff: 'some stuff'};
diff --git a/client/core/src/icon-menu/icon-menu.html b/client/core/src/icon-menu/icon-menu.html
index 9cf978b55..6f49a6f7e 100644
--- a/client/core/src/icon-menu/icon-menu.html
+++ b/client/core/src/icon-menu/icon-menu.html
@@ -1,5 +1,8 @@
-
+
{
let $httpBackend;
let $timeout;
let $scope;
+ let controller;
beforeEach(() => {
angular.mock.module('client');
@@ -17,19 +18,21 @@ describe('Component vnIconMenu', () => {
$timeout = _$timeout_;
$scope = $rootScope.$new();
$element = angular.element('');
+ controller = $componentController('vnIconMenu', {$scope, $element, $httpBackend, $timeout}, {url: 'test.com'});
}));
describe('component vnIconMenu', () => {
describe('findItem()', () => {
it(`should return items empty array if the controller does not provide a url and have no items defined`, () => {
- let controller = $componentController('vnIconMenu', {$scope, $element, $httpBackend, $timeout});
- controller.findItems('some search value');
+ controller.url = undefined;
+ controller.items = undefined;
+ let result = controller.findItems('some search value');
- expect(controller.items).not.toBeDefined();
+ expect(result).toEqual([]);
});
it(`should return items array if the controller does not provide a url`, () => {
- let controller = $componentController('vnIconMenu', {$scope, $element, $httpBackend, $timeout});
+ controller.url = undefined;
controller.items = ['Batman', 'Bruce Wayne'];
controller.findItems('some search value');
@@ -37,11 +40,10 @@ describe('Component vnIconMenu', () => {
});
it(`should perform a search and store the result in controller items`, () => {
- let controller = $componentController('vnIconMenu', {$scope, $element, $httpBackend, $timeout}, {url: 'test.com'});
let search = 'The Joker';
let json = JSON.stringify({where: {name: {regexp: search}}});
- $httpBackend.whenGET(`test.com?filter=${json}`).respond([{id: 3, name: 'The Joker'}]);
- $httpBackend.expectGET(`test.com?filter=${json}`);
+ $httpBackend.whenGET(`${controller.url}?filter=${json}`).respond([{id: 3, name: 'The Joker'}]);
+ $httpBackend.expectGET(`${controller.url}?filter=${json}`);
controller.findItems(search);
$httpBackend.flush();
@@ -49,7 +51,6 @@ describe('Component vnIconMenu', () => {
});
it(`should call getItems function if there's no search value`, () => {
- let controller = $componentController('vnIconMenu', {$scope, $element, $httpBackend, $timeout}, {url: 'test.com'});
spyOn(controller, 'getItems');
controller.findItems();
@@ -57,18 +58,27 @@ describe('Component vnIconMenu', () => {
});
});
- // implementation pending.
+ describe('getItems()', () => {
+ it(`should perform a query and then push elements found into controller.items`, () => {
+ controller.items = [];
+ $httpBackend.whenGET(`${controller.url}?filter={}`).respond([{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}]);
+ $httpBackend.expectGET(`${controller.url}?filter={}`);
+ controller.getItems();
+ $httpBackend.flush();
- // describe('getItems()', () => {
- // it(`should perfom a query to fill the items without filter`, () => {
- // let controller = $componentController('vnIconMenu', {$scope, $element, $httpBackend, $timeout}, {url: 'test.com'});
- // $httpBackend.whenGET(`test.com?filter={}`).respond([{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}]);
- // $httpBackend.expectGET(`test.com?filter={}`);
- // controller.getItems();
- // $httpBackend.flush();
+ expect(controller.items).toEqual([{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}]);
+ });
- // expect(controller.items).toEqual([{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce Wayne'}]);
- // });
- // });
+ it(`should perform a query and then set controller.maxRow to false if there are no items in the controller`, () => {
+ controller.items = [];
+ controller.maxRow = true;
+ $httpBackend.whenGET(`${controller.url}?filter={"skip":0,"limit":true,"order":"name ASC"}`).respond(controller.items);
+ $httpBackend.expectGET(`${controller.url}?filter={"skip":0,"limit":true,"order":"name ASC"}`);
+ controller.getItems();
+ $httpBackend.flush();
+
+ expect(controller.maxRow).toBeFalsy();
+ });
+ });
});
});
diff --git a/client/core/src/icon-menu/style.scss b/client/core/src/icon-menu/style.scss
index e4e6b4104..2d3919f4d 100644
--- a/client/core/src/icon-menu/style.scss
+++ b/client/core/src/icon-menu/style.scss
@@ -1,3 +1,12 @@
vn-icon-menu{
position: relative;
+ .icon-menu__button {
+ padding: 0 10px;
+ }
+ vn-icon{
+ float: left;
+ }
+ vn-icon.icon-menu__arrow_down{
+ margin:2px 0 0 5px;
+ }
}
\ No newline at end of file
diff --git a/client/core/src/icon/style.css b/client/core/src/icon/style.css
index 064195cd9..881f6d304 100644
--- a/client/core/src/icon/style.css
+++ b/client/core/src/icon/style.css
@@ -5,4 +5,4 @@ vn-icon {
vn-icon > i {
display: block;
font-size: inherit !important;
-}
\ No newline at end of file
+}
diff --git a/client/salix/src/aclService.js b/client/core/src/lib/aclService.js
similarity index 84%
rename from client/salix/src/aclService.js
rename to client/core/src/lib/aclService.js
index 63e75278c..78e5d2365 100644
--- a/client/salix/src/aclService.js
+++ b/client/core/src/lib/aclService.js
@@ -1,4 +1,7 @@
-import ngModule from './module';
+import {module} from '../module';
+
+var acl = window.salix ? window.salix.acl : {};
+module.constant('aclConstant', acl);
aclService.$inject = ['aclConstant'];
function aclService(aclConstant) {
@@ -29,4 +32,4 @@ function aclService(aclConstant) {
};
}
-ngModule.service('aclService', aclService);
+module.service('aclService', aclService);
diff --git a/client/core/src/lib/index.js b/client/core/src/lib/index.js
index c911e09a3..a081b5f87 100644
--- a/client/core/src/lib/index.js
+++ b/client/core/src/lib/index.js
@@ -4,6 +4,8 @@ import './template';
import './getTemplate';
import './app';
import './interceptor';
+import './aclService';
+import './storageServices';
export * from './util';
export {default as splitingRegister} from './splitingRegister';
diff --git a/client/core/src/lib/storageServices.js b/client/core/src/lib/storageServices.js
new file mode 100644
index 000000000..ee64b6f0c
--- /dev/null
+++ b/client/core/src/lib/storageServices.js
@@ -0,0 +1,66 @@
+import {module} from '../module';
+
+class VnStorage {
+ constructor() {
+ this._type = '';
+ this.prefix = 'vn';
+ }
+ set type(value) {
+ this._type = value;
+ this.checkSupport();
+ }
+ get type() {
+ return this._type;
+ }
+ get webStorage() {
+ return window[this.type];
+ }
+ checkSupport() {
+ try {
+ let supported = (this.type in window && window[this.type] !== null);
+ if (supported) {
+ let key = '__' + Math.round(Math.random() * 1e7);
+ let webStorage = window[this.type];
+ webStorage.setItem(key, '');
+ webStorage.removeItem(key);
+ }
+ } catch (e) {
+ console.error('VnStorage.notification.error', e.message);
+ return false;
+ }
+ }
+ get(param) {
+ let toRead = this.webStorage.getItem(`${this.prefix}.${param}`);
+ if (toRead && toRead.startsWith('jsonObject:')) {
+ toRead = JSON.parse(toRead.replace('jsonObject:', ''));
+ }
+ return toRead;
+ }
+ set(param, data) {
+ let toStorage = typeof data === 'object' ? `jsonObject:${JSON.stringify(data)}` : data;
+ this.webStorage.setItem(`${this.prefix}.${param}`, toStorage);
+ }
+ remove(param) {
+ this.webStorage.removeItem(`${this.prefix}.${param}`);
+ }
+ clear() {
+ this.webStorage.clear();
+ }
+}
+
+class SessionStorage extends VnStorage {
+ constructor() {
+ super();
+ this.type = 'sessionStorage';
+ }
+}
+
+class LocalStorage extends VnStorage {
+ constructor() {
+ super();
+ this.type = 'localStorage';
+ }
+}
+
+module.service('sessionStorage', SessionStorage);
+module.service('localStorage', LocalStorage);
diff --git a/client/core/src/multi-check/multi-check.html b/client/core/src/multi-check/multi-check.html
index 3ddd0e0a3..36f7f3ec7 100644
--- a/client/core/src/multi-check/multi-check.html
+++ b/client/core/src/multi-check/multi-check.html
@@ -1,4 +1,4 @@
-
+
diff --git a/client/core/src/multi-check/multi-check.js b/client/core/src/multi-check/multi-check.js
index 010c66aed..4ab7c87ce 100644
--- a/client/core/src/multi-check/multi-check.js
+++ b/client/core/src/multi-check/multi-check.js
@@ -2,15 +2,40 @@ import {module} from '../module';
import './multi-check.scss';
/**
* Draw checkbox with a drop-down and multi options
+ * @param {SmallInt} checkAll Primary input-check state: 0 -> uncheck, 1 -> checked, 2 -> indeterminate checked
* @param {Array} options List of options shown in drop-down
* @param {Array} models Elements to check / unCheck
* @param {String} className Optional css class name
*/
export default class MultiCheck {
- constructor() {
+ constructor($timeout) {
+ this.$timeout = $timeout;
this._checkAll = 0;
this._models = [];
- this.type = {};
+ this._type = {};
+ this.showDropDown = false;
+ }
+
+ get type() {
+ return this._type;
+ }
+
+ set type(value) {
+ if (value && value.id) {
+ this._type = value;
+ switch (value.id) {
+ case 'all':
+ this.checkAll = 1;
+ break;
+ case 'any':
+ this.checkAll = 0;
+ break;
+ default:
+ this.checkAll = 2;
+ break;
+ }
+ }
+ this._type = {};
this.showDropDown = false;
}
@@ -39,12 +64,12 @@ export default class MultiCheck {
if (this.type.id && this.type.id !== 'all' && this.type.id !== 'any') {
if (this.type.id.length > 3 && this.type.id.substr(0, 3) === 'no-') {
let label = this.type.id.replace('no-', '');
- checked = el[label] == null;
+ checked = Boolean(el[label]) === false;
} else if (this.type.id.length > 6 && this.type.id.substr(0, 6) === 'equal-') {
let label = this.type.id.replace('equal-', '');
checked = (el[label] && el[label] === this.type.name);
} else {
- checked = el[this.type.id] != null;
+ checked = Boolean(el[this.type.id]) === true;
}
} else {
checked = this.checkAll === 1;
@@ -59,25 +84,14 @@ export default class MultiCheck {
this.checkAll = 0;
}
- $doCheck() {
- if (this.type && this.type.id) {
- switch (this.type.id) {
- case 'all':
- this.checkAll = 1;
- break;
- case 'any':
- this.checkAll = 0;
- break;
- default:
- this.checkAll = 2;
- break;
- }
- this.type = {};
- }
+ onBlur() {
+ this.$timeout(() => {
+ this.showDropDown = false;
+ }, 200);
}
}
-MultiCheck.$inject = [];
+MultiCheck.$inject = ['$timeout'];
module.component('vnMultiCheck', {
template: require('./multi-check.html'),
@@ -85,7 +99,7 @@ module.component('vnMultiCheck', {
bindings: {
checkAll: '=',
options: '<',
- models: '=',
+ models: '<',
className: '@?'
}
});
diff --git a/client/core/src/multi-check/multi-check.spec.js b/client/core/src/multi-check/multi-check.spec.js
index 337cf1ac4..a221e3cc7 100644
--- a/client/core/src/multi-check/multi-check.spec.js
+++ b/client/core/src/multi-check/multi-check.spec.js
@@ -2,6 +2,7 @@ import './multi-check.js';
describe('Component vnMultiCheck', () => {
let $componentController;
+ let controller;
beforeEach(() => {
angular.mock.module('client');
@@ -9,11 +10,11 @@ describe('Component vnMultiCheck', () => {
beforeEach(angular.mock.inject(_$componentController_ => {
$componentController = _$componentController_;
+ controller = $componentController('vnMultiCheck', {});
}));
describe('models()', () => {
it(`should set controller _models property with the argument received`, () => {
- let controller = $componentController('vnMultiCheck', {});
let argument = 'I am the model';
controller.models = argument;
@@ -23,7 +24,6 @@ describe('Component vnMultiCheck', () => {
describe('checkAll()', () => {
it(`should set controller _checkAll property with the argument received then call switchChecks()`, () => {
- let controller = $componentController('vnMultiCheck', {});
let argument = 'I am the model';
spyOn(controller, 'switchChecks');
controller.checkAll = argument;
@@ -34,8 +34,7 @@ describe('Component vnMultiCheck', () => {
});
describe('switchChecks()', () => {
- it(`should set checked property inside each existing elemenet when begings with no-`, () => {
- let controller = $componentController('vnMultiCheck', {});
+ it(`should set checked property inside each existing elemenet when id begings with no-`, () => {
controller.type = {id: 'no-name'};
controller.models = [
{name: 'name'},
@@ -47,12 +46,11 @@ describe('Component vnMultiCheck', () => {
controller._checkAll = 1;
controller.switchChecks();
- expect(controller._models[0].checked).toBeFalsy();
+ expect(controller._models[0].checked).toBeTruthy();
expect(controller._models[1].checked).toBeTruthy();
});
- it(`should set checked property inside each existing elemenet when begings with equal-`, () => {
- let controller = $componentController('vnMultiCheck', {});
+ it(`should set checked property inside each existing elemenet when id begings with equal-`, () => {
controller.type = {id: 'equal-name', name: 'name'};
controller.models = [
{name: null},
@@ -64,12 +62,11 @@ describe('Component vnMultiCheck', () => {
controller._checkAll = 1;
controller.switchChecks();
- expect(controller._models[0].checked).toBeFalsy();
+ expect(controller._models[0].checked).toBeTruthy();
expect(controller._models[1].checked).toBeTruthy();
});
it(`should set checked property inside each existing elemenet when begings with anything but any, all, no- or equal-`, () => {
- let controller = $componentController('vnMultiCheck', {});
controller.type = {id: 'name'};
controller.models = [
{name: null},
@@ -81,13 +78,12 @@ describe('Component vnMultiCheck', () => {
controller._checkAll = 1;
controller.switchChecks();
- expect(controller._models[0].checked).toBeFalsy();
+ expect(controller._models[0].checked).toBeTruthy();
expect(controller._models[1].checked).toBeTruthy();
});
describe('when id is any', () => {
it('should set element checked property based on controller._checkAll', () => {
- let controller = $componentController('vnMultiCheck', {});
controller.type = {id: 'any'};
controller.models = [
{name: 'name'}
@@ -111,7 +107,6 @@ describe('Component vnMultiCheck', () => {
describe('when id is all', () => {
it('should set element checked property based on controller._checkAll property', () => {
- let controller = $componentController('vnMultiCheck', {});
controller.type = {id: 'all'};
controller.models = [
{name: 'name'}
@@ -136,7 +131,6 @@ describe('Component vnMultiCheck', () => {
describe('$onChanges()', () => {
it('should set controller.type to empty object and checkAll to zero', () => {
- let controller = $componentController('vnMultiCheck', {});
controller.type = {id: 'all'};
controller._checkAll = 1;
controller.$onChanges();
@@ -146,22 +140,21 @@ describe('Component vnMultiCheck', () => {
});
});
- describe('$doCheck()', () => {
+ describe('type setter', () => {
it('should set controller.type to empty object and checkAll based on controller.type.id', () => {
- let controller = $componentController('vnMultiCheck', {});
- controller.type = {id: 'all'};
+ let value = {id: 'all'};
controller._checkAll = 0;
- controller.$doCheck();
+ controller.type = value;
expect(controller.type).toEqual({});
expect(controller._checkAll).toEqual(1);
- controller.type = {id: 'any'};
- controller.$doCheck();
+ value = {id: 'any'};
+ controller.type = value;
expect(controller.type).toEqual({});
expect(controller._checkAll).toEqual(0);
- controller.type = {id: 'any other id name'};
- controller.$doCheck();
+ value = {id: 'any other id name'};
+ controller.type = value;
expect(controller.type).toEqual({});
expect(controller._checkAll).toEqual(2);
diff --git a/client/core/src/paging/paging.html b/client/core/src/paging/paging.html
index 6e2f56fd3..6e71f321d 100644
--- a/client/core/src/paging/paging.html
+++ b/client/core/src/paging/paging.html
@@ -1,6 +1,7 @@
{
let $componentController;
let $scope;
let $httpBackend;
+ let controller;
beforeEach(() => {
angular.mock.module('client');
@@ -13,11 +14,11 @@ describe('Component vnPaging', () => {
$componentController = _$componentController_;
$scope = $rootScope.$new();
$httpBackend = _$httpBackend_;
+ controller = $componentController('vnPaging', {$scope, $httpBackend});
}));
describe('$onChanges()', () => {
it(`should define numberPage and currentPage based on index.filter properties`, () => {
- let controller = $componentController('vnPaging', {$scope, $httpBackend});
controller.index = {filter: {size: 'something', page: 'something else'}};
controller.$onChanges({index: 'simpleChange', currentValue: 'current value', previousValue: 'previous value'});
@@ -26,7 +27,6 @@ describe('Component vnPaging', () => {
});
it(`should define numItems based on changes.total.currentValue`, () => {
- let controller = $componentController('vnPaging', {$scope, $httpBackend});
controller.index = {filter: {size: 'something', page: 'something else'}};
controller.$onChanges({total: {currentValue: 'current value'}});
@@ -36,7 +36,6 @@ describe('Component vnPaging', () => {
describe('onModelUpdated()', () => {
it(`should define controllers numItems as the result of page times size plus one`, () => {
- let controller = $componentController('vnPaging', {$scope, $httpBackend});
controller.numPerPage = 2;
controller.index = {
filter: {size: 10, page: 10},
@@ -50,8 +49,7 @@ describe('Component vnPaging', () => {
describe('onPageChange()', () => {
it(`should call accept() since pageChange property is undefined`, () => {
- let myIndex = {accept: () => {}, filter: {page: 0}};
- let controller = $componentController('vnPaging', {$scope, $httpBackend}, {index: myIndex});
+ controller.index = {accept: () => {}, filter: {page: 0}};
spyOn(controller.index, 'accept');
controller.onPageChange(100);
@@ -59,8 +57,7 @@ describe('Component vnPaging', () => {
});
it(`should call pageChange() since pageChange property isn't undefined`, () => {
- let myIndex = {accept: () => {}, filter: {page: 0}};
- let controller = $componentController('vnPaging', {$scope, $httpBackend}, {index: myIndex});
+ controller.index = {accept: () => {}, filter: {page: 0}};
controller.pageChange = true;
spyOn(controller, 'pageChange');
controller.onPageChange(100);
diff --git a/client/core/src/spinner/spinner.spec.js b/client/core/src/spinner/spinner.spec.js
new file mode 100644
index 000000000..d5bad0746
--- /dev/null
+++ b/client/core/src/spinner/spinner.spec.js
@@ -0,0 +1,63 @@
+import './spinner.js';
+
+describe('Component vnSpinner', () => {
+ let $componentController;
+ let $scope;
+ let $element;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, $rootScope) => {
+ $componentController = _$componentController_;
+ $scope = $rootScope.$new();
+ $element = angular.element('
');
+ controller = $componentController('vnSpinner', {$scope, $element});
+ }));
+
+ describe('enable()', () => {
+ it(`should call start() based on a boolean value passed as argument`, () => {
+ spyOn(controller, 'start');
+ spyOn(controller, 'stop');
+ controller.enable = true;
+
+ expect(controller.start).toHaveBeenCalledWith();
+ expect(controller.stop).not.toHaveBeenCalledWith();
+ });
+
+ it(`should call stop() based on a boolean value passed as argument`, () => {
+ spyOn(controller, 'start');
+ spyOn(controller, 'stop');
+ controller.enable = false;
+
+ expect(controller.start).not.toHaveBeenCalledWith();
+ expect(controller.stop).toHaveBeenCalledWith();
+ });
+ });
+
+ describe('start()', () => {
+ it(`should call start() on the controller.materialSpinner then set controllers._enable to be truthy`, () => {
+ controller.spinner = {MaterialSpinner: {start: () => {}}};
+ spyOn(controller.spinner.MaterialSpinner, 'start');
+ controller._enable = false;
+ controller.start();
+
+ expect(controller.spinner.MaterialSpinner.start).toHaveBeenCalledWith();
+ expect(controller._enable).toBeTruthy();
+ });
+ });
+
+ describe('stop()', () => {
+ it(`should call stop() on the controller.materialSpinner then set controllers._enable to be truthy`, () => {
+ controller.spinner = {MaterialSpinner: {stop: () => {}}};
+ spyOn(controller.spinner.MaterialSpinner, 'stop');
+ controller._enable = true;
+ controller.stop();
+
+ expect(controller.spinner.MaterialSpinner.stop).toHaveBeenCalledWith();
+ expect(controller._enable).toBeFalsy();
+ });
+ });
+});
diff --git a/client/core/src/textfield/textfield.spec.js b/client/core/src/textfield/textfield.spec.js
index 5140bfab8..9eea12b0c 100644
--- a/client/core/src/textfield/textfield.spec.js
+++ b/client/core/src/textfield/textfield.spec.js
@@ -6,6 +6,7 @@ describe('Component vnTextfield', () => {
let $attrs;
let $timeout;
let $element;
+ let controller;
beforeEach(() => {
angular.mock.module('client');
@@ -17,11 +18,11 @@ describe('Component vnTextfield', () => {
$attrs = {};
$timeout = _$timeout_;
$element = angular.element('');
+ controller = $componentController('vnTextfield', {$scope, $element, $attrs, $timeout});
}));
describe('value() setter', () => {
it(`should set _value, input.value and hasValue properties to null, '' and false then call mdlUpdate()`, () => {
- let controller = $componentController('vnTextfield', {$scope, $element, $attrs, $timeout});
spyOn(controller, 'mdlUpdate');
let testValue = '';
controller.value = testValue;
@@ -33,7 +34,6 @@ describe('Component vnTextfield', () => {
});
it(`should set _value, input.value and hasValue propertiest to test, test and true then call mdlUpdate()`, () => {
- let controller = $componentController('vnTextfield', {$scope, $element, $attrs, $timeout});
spyOn(controller, 'mdlUpdate');
let testValue = 'test';
controller.value = testValue;
diff --git a/client/core/src/watcher/watcher.js b/client/core/src/watcher/watcher.js
index bb6b753b2..2dbc5a2bc 100644
--- a/client/core/src/watcher/watcher.js
+++ b/client/core/src/watcher/watcher.js
@@ -59,7 +59,7 @@ export default class Watcher extends Component {
* Submits the data and goes back in the history.
*/
submitBack() {
- this.submit().then(
+ return this.submit().then(
() => this.window.history.back()
);
}
@@ -69,7 +69,7 @@ export default class Watcher extends Component {
* @param {String} state The state name
*/
submitGo(state) {
- this.submit().then(
+ return this.submit().then(
() => this.$state.go(state)
);
}
diff --git a/client/core/src/watcher/watcher.spec.js b/client/core/src/watcher/watcher.spec.js
new file mode 100644
index 000000000..0ed342e31
--- /dev/null
+++ b/client/core/src/watcher/watcher.spec.js
@@ -0,0 +1,293 @@
+import './watcher.js';
+import getModifiedData from '../lib/modified';
+
+describe('Component vnWatcher', () => {
+ let $componentController;
+ let $scope;
+ let $element;
+ let $state;
+ let $transitions;
+ let $httpBackend;
+ let vnApp;
+ let $translate;
+ let controller;
+
+ beforeEach(() => {
+ angular.mock.module('client');
+ });
+
+ beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$state_, _$transitions_, _$httpBackend_, _vnApp_, _$translate_) => {
+ $componentController = _$componentController_;
+ $scope = $rootScope.$new();
+ $element = angular.element('');
+ $state = _$state_;
+ vnApp = _vnApp_;
+ $transitions = _$transitions_;
+ $httpBackend = _$httpBackend_;
+ $translate = _$translate_;
+ controller = $componentController('vnWatcher', {$scope, $element, $state, vnApp, $transitions, $httpBackend, $translate});
+ }));
+
+ describe('$onInit()', () => {
+ it(`should call fetchData() if controllers get and url properties are defined`, () => {
+ controller.get = () => {};
+ controller.url = 'test.com';
+ spyOn(controller, 'fetchData');
+ controller.$onInit();
+
+ expect(controller.fetchData).toHaveBeenCalledWith();
+ });
+
+ it(`should throw an error if $onInit is called without url defined`, () => {
+ controller.get = () => {};
+
+ expect(function() {
+ controller.$onInit();
+ }).toThrow(new Error('Error: Parameter url ommitted'));
+ });
+ });
+
+ describe('$onChanges()', () => {
+ it(`should call updateOriginalData() if controllers data is defined`, () => {
+ controller.data = [];
+ spyOn(controller, 'updateOriginalData');
+ controller.$onChanges();
+
+ expect(controller.updateOriginalData).toHaveBeenCalledWith();
+ });
+ });
+
+ describe('$onDestroy()', () => {
+ it(`should call deregisterCallback()`, () => {
+ spyOn(controller, 'deregisterCallback');
+ controller.$onDestroy();
+
+ expect(controller.deregisterCallback).toHaveBeenCalledWith();
+ });
+ });
+
+ describe('fetchData()', () => {
+ it(`should perform a query then store the received data into controller.data and call updateOriginalData()`, () => {
+ spyOn(controller, 'updateOriginalData');
+ let json = {data: 'some data'};
+ controller.data = [1];
+ controller.idField = 0;
+ controller.url = 'test.com';
+ $httpBackend.whenGET('test.com/1').respond(json);
+ $httpBackend.expectGET('test.com/1');
+ controller.fetchData();
+ $httpBackend.flush();
+
+ expect(controller.data).toEqual({data: 'some data'});
+ expect(controller.updateOriginalData).toHaveBeenCalledWith();
+ });
+ });
+
+ describe('submitBack()', () => {
+ it(`should call controller.window.history.back() function after calling controllers submit() function`, done => {
+ spyOn(controller, 'submit').and.returnValue(Promise.resolve());
+ spyOn(controller.window.history, 'back');
+ controller.submitBack()
+ .then(() => {
+ expect(controller.submit).toHaveBeenCalledWith();
+ expect(controller.window.history.back).toHaveBeenCalledWith();
+ done();
+ });
+ });
+ });
+
+ describe('submitGo()', () => {
+ it(`should call controller.$state.go() function after calling controllers submit() function`, done => {
+ spyOn(controller, 'submit').and.returnValue(Promise.resolve());
+ spyOn(controller.$state, 'go');
+ let state = 'the state';
+ controller.submitGo(state)
+ .then(() => {
+ expect(controller.submit).toHaveBeenCalledWith();
+ expect(controller.$state.go).toHaveBeenCalledWith(state);
+ done();
+ });
+ });
+ });
+
+ describe('submit()', () => {
+ describe('when controller.form', () => {
+ it(`should call controller.form.setSubminted if controller.form is defined`, () => {
+ controller.form = {$setSubmitted: () => {}};
+ spyOn(controller.form, '$setSubmitted');
+ controller.submit();
+
+ expect(controller.form.$setSubmitted).toHaveBeenCalledWith();
+ });
+
+ it(`should call controller.invalidForm if controller.form.$valid is not defined`, () => {
+ controller.form = {$setSubmitted: () => {}};
+ spyOn(controller, 'invalidForm');
+ controller.submit();
+
+ expect(controller.invalidForm).toHaveBeenCalledWith(jasmine.any(Function));
+ });
+ });
+
+ describe('when !controller.dataChanged()', () => {
+ it(`should call controller.noChanges()`, () => {
+ spyOn(controller, 'noChanges');
+ controller.submit();
+
+ expect(controller.noChanges).toHaveBeenCalledWith(jasmine.any(Function));
+ });
+ });
+
+ describe('when controller.save()', () => {
+ it(`should set controller.save.model property`, () => {
+ controller.save = {};
+ controller.data = {originalInfo: 'original data', info: 'new data'};
+ controller.orgData = {originalInfo: 'original data'};
+ controller.submit();
+
+ expect(controller.save.model).toEqual({info: 'new data'});
+ });
+
+ it(`should call controller.save.accept() then controller.writeData`, done => {
+ controller.save = {accept: () => {}};
+ controller.data = {originalInfo: 'original data', info: 'new data'};
+ controller.orgData = {originalInfo: 'original data'};
+ spyOn(controller.save, 'accept').and.returnValue(Promise.resolve());
+ spyOn(controller, 'writeData').and.callThrough();
+ controller.submit()
+ .then(() => {
+ expect(controller.save.accept).toHaveBeenCalledWith();
+ expect(controller.writeData).toHaveBeenCalledWith(jasmine.any(Object), jasmine.any(Function));
+ done();
+ });
+ });
+ });
+
+ describe('when id is defined', () => {
+ it(`should perform a query then call controller.writeData()`, () => {
+ controller.dataChanged = () => {
+ return true;
+ };
+ controller.data = {id: 2};
+ controller.orgData = {id: 1};
+ let changedData = getModifiedData(controller.data, controller.orgData);
+ controller.idField = 'id';
+ controller.url = 'test.com';
+ let json = {data: 'some data'};
+ spyOn(controller, 'writeData').and.callThrough();
+ $httpBackend.whenPATCH(`${controller.url}/1`, changedData).respond(json);
+ $httpBackend.expectPATCH(`${controller.url}/1`);
+ controller.submit()
+ .then(() => {
+ expect(controller.writeData).toHaveBeenCalledWith(jasmine.any(Object), jasmine.any(Function));
+ done();
+ });
+ $httpBackend.flush();
+ });
+ });
+
+ it(`should perform a POST query then call controller.writeData()`, () => {
+ controller.dataChanged = () => {
+ return true;
+ };
+ controller.data = {id: 2};
+ controller.orgData = {id: 1};
+ controller.url = 'test.com';
+ let json = {data: 'some data'};
+ spyOn(controller, 'writeData').and.callThrough();
+ $httpBackend.whenPOST(`${controller.url}`, controller.data).respond(json);
+ $httpBackend.expectPOST(`${controller.url}`, controller.data);
+ controller.submit()
+ .then(() => {
+ expect(controller.writeData).toHaveBeenCalledWith(jasmine.any(Object), jasmine.any(Function));
+ done();
+ });
+ $httpBackend.flush();
+ });
+ });
+
+ describe('writeData()', () => {
+ it(`should call Object.asssign() function over controllers.data with json.data, then call updateOriginalData function and finally call resolve() function`, () => {
+ spyOn(controller, 'updateOriginalData');
+ controller.data = {};
+ let json = {data: 'some data'};
+ let resolve = jasmine.createSpy('resolve');
+ controller.writeData(json, resolve);
+
+ expect(controller.updateOriginalData).toHaveBeenCalledWith();
+ expect(resolve).toHaveBeenCalledWith(json);
+ });
+ });
+
+ describe('copyInNewObject()', () => {
+ it(`should return newCopy object if data was an object`, () => {
+ let data = {id: 1, Heroname: 'Batman', name: 'Bruce Wayne'};
+ let result = controller.copyInNewObject(data);
+
+ expect(result).toEqual(data);
+ });
+ });
+
+ describe('callback()', () => {
+ describe(`when dataChanged() returns true and there's no state in the controller`, () => {
+ it(`should define controller.state, call controller.$scope.confirm.show() and return false`, () => {
+ $scope.confirm = {show: jasmine.createSpy('show')};
+ controller.dataChanged = () => {
+ return true;
+ };
+ controller.state = undefined;
+ let transition = {to: () => {
+ return {name: 'Batman'};
+ }};
+ let result = controller.callback(transition);
+
+ expect(controller.state).toEqual('Batman');
+ expect(controller.$scope.confirm.show).toHaveBeenCalledWith();
+ expect(result).toBeFalsy();
+ });
+ });
+
+ describe(`when dataChanged() returns false and/or there's a state in the controller`, () => {
+ it(`should return true`, () => {
+ $scope.confirm = {show: jasmine.createSpy('show')};
+ controller.dataChanged = () => {
+ return false;
+ };
+ controller.state = 'the state';
+ let transition = {to: () => {
+ return {name: 'Batman'};
+ }};
+ let result = controller.callback(transition);
+
+ expect(result).toBeTruthy();
+ });
+ });
+ });
+
+ describe(`onConfirmResponse()`, () => {
+ describe(`when response is ACCEPT`, () => {
+ it(`should call Object.assing on controlle.data with controller.orgData then call go() on state`, () => {
+ let response = 'ACCEPT';
+ controller.data = {};
+ controller.orgData = {name: 'Batman'};
+ controller.$state = {go: jasmine.createSpy('go')};
+ controller.state = 'Batman';
+ controller.onConfirmResponse(response);
+
+ expect(controller.data).toEqual(controller.orgData);
+ expect(controller.$state.go).toHaveBeenCalledWith(controller.state);
+ });
+ });
+
+ describe(`when response is not ACCEPT`, () => {
+ it(`should set controller.state to null`, () => {
+ let response = 'anything but ACCEPT';
+ controller.state = 'Batman';
+ controller.onConfirmResponse(response);
+
+ expect(controller.state).toBeFalsy();
+ });
+ });
+ });
+});
+// 309
\ No newline at end of file
diff --git a/client/locator/index.js b/client/locator/index.js
new file mode 100644
index 000000000..d2b755cd8
--- /dev/null
+++ b/client/locator/index.js
@@ -0,0 +1 @@
+export * from './src/locator';
diff --git a/client/locator/routes.json b/client/locator/routes.json
new file mode 100644
index 000000000..b508fcc5f
--- /dev/null
+++ b/client/locator/routes.json
@@ -0,0 +1,14 @@
+{
+ "module": "locator",
+ "name": "Locator",
+ "icon": "add_location",
+ "validations" : false,
+ "routes": [
+ {
+ "url": "/locator",
+ "state": "locator",
+ "component": "vn-locator-index",
+ "acl": ["developer"]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/client/locator/src/index/index.html b/client/locator/src/index/index.html
new file mode 100644
index 000000000..4194c9db8
--- /dev/null
+++ b/client/locator/src/index/index.html
@@ -0,0 +1,39 @@
+
+
+
+ Routes locator
+
Contraseña: ******** (Va a recibir un correo para establecer la contraseña)
+
+
+
Cómo hacer un pedido
+
+
Para realizar un pedido en nuestra web, debe configurarlo indicando:
+
+
+
Si quiere recibir el pedido (por agencia o por nuestro propio reparto) o si lo prefiere recoger en alguno de nuestros almacenes.
+
La fecha en la que quiera recibir el pedido (se preparará el día anterior).
+
La dirección de entrega o el almacén donde quiera recoger el pedido.
+
+
+
En nuestra web y aplicaciones puedes visualizar el stock disponible de flor cortada, verdes, plantas, complementos y artificial.
+ Tenga en cuenta que dicho stock puede variar en función de la fecha seleccionada al configurar el pedido. Es importante CONFIRMAR los pedidos para que la mercancía quede reservada.
+
+
El reparto se realiza de lunes a sábado según la zona en la que se encuentre. Por regla general, los pedidos que se entregan por agencia, deben estar confirmados y pagados antes de las 17h
+ del día en que se preparan (el día anterior a recibirlos), aunque esto puede variar si el pedido se envía a través de nuestro reparto y según la zona.
+
+
Cómo pagar
+
+
Las formas de pago admitidas en Verdnatura son
+
+
+
Con tarjeta a través de nuestra plataforma web (al confirmar el pedido).
+
Mediante giro bancario mensual, modalidad que hay que solicitar y tramitar.
+
+
+
Cosas a tener en cuenta
+
+
Verdnatura vende EXCLUSIVAMENTE a profesionales, por lo que debe remitirnos el Modelo 036 ó 037,
+ para comprobar que está dado/a de alta en el epígrafe correspondiente al comercio de flores.
+
+
POLÍTICA DE RECLAMACIONES
+
+
Verdnatura aceptará las reclamaciones que se realicen dentro de los dos días naturales
+ siguientes a la recepción del pedido (incluyendo el mismo día de la recepción). Pasado este plazo no se aceptará ninguna reclamación.
+
+
Cualquier duda que le surja, no dude en consultarla, ¡estamos para atenderle!
+
+
\ No newline at end of file
diff --git a/services/mailer/application/template/UNUSED/printer-setup/locale/es.json b/services/mailer/application/template/client-welcome/locale/es.json
similarity index 60%
rename from services/mailer/application/template/UNUSED/printer-setup/locale/es.json
rename to services/mailer/application/template/client-welcome/locale/es.json
index 144cdc346..c99fe0c8e 100644
--- a/services/mailer/application/template/UNUSED/printer-setup/locale/es.json
+++ b/services/mailer/application/template/client-welcome/locale/es.json
@@ -1,15 +1,11 @@
{
- "subject": "Cambios en las condiciones de pago",
- "title": "Cambio en las condiciones",
+ "subject": "¡Le damos la bienvenida!",
+ "title": "¡LE DAMOS LA BIENVENIDA!",
"dear": "Estimado cliente",
- "bodyDescription": "Le informamos que han cambiado las condiciones de pago de su cuenta. A continuación le indicamos las nuevas condiciones:",
- "paymentMethod": "Método de pago",
- "paymentDay": "Día de pago",
- "everyMonth": "de cada mes",
- "cardPaymentAdvice": "Su modo de pago actual implica que deberá abonar el importe de los pedidos realizados en el mismo día para que se puedan enviar.",
- "accountPaymentAdviceBefore": "Su modo de pago actual implica que se le pasará un cargo a la cuenta",
- "accountPaymentAdviceAfter": "por el importe pendiente, al vencimiento establecido en las condiciones.",
- "notifyError": "En el caso de detectar algún error en los datos indicados o para cualquier aclaración, debe dirigirse a su comercial.",
+ "bodyDescription": "Siga las intrucciones especificadas en este correo para llevar a cabo la instalación de la impresora.",
+ "salesPersonNameText": "Soy tu comercial y mi nombre es",
+ "salesPersonPhoneText": "Teléfono y whatsapp",
+ "salesPersonEmailText": "Dirección de e-mail",
"actionButton": "Visita nuestra Web",
"infoButton": "Ayúdanos a mejorar",
"fiscalAddress": "VERDNATURA LEVANTE SL, B97367486 Avda. Espioca, 100, 46460 Silla _ www.verdnatura.es _ clientes@verdnatura.es",
diff --git a/services/mailer/application/template/notification-alias/notification-alias.js b/services/mailer/application/template/notification-alias/notification-alias.js
index 132d037f4..937e1bf8c 100644
--- a/services/mailer/application/template/notification-alias/notification-alias.js
+++ b/services/mailer/application/template/notification-alias/notification-alias.js
@@ -12,10 +12,10 @@ module.exports = class NotificationAlias {
database.pool.query(query, [params.alias], (error, result) => {
if (error || result.length == 0)
- return cb({status: 'REJECT', data: {message: 'No data found', error: error}});
+ return cb(new Error('No template data found'));
Object.assign(this, result[0]);
- cb({status: 'ACCEPT', data: {}});
+ cb();
});
}
diff --git a/services/mailer/application/template/payment-update/payment-update.js b/services/mailer/application/template/payment-update/payment-update.js
index 73fdb89c1..d126dc83a 100644
--- a/services/mailer/application/template/payment-update/payment-update.js
+++ b/services/mailer/application/template/payment-update/payment-update.js
@@ -17,25 +17,24 @@ module.exports = class PaymentUpdate {
WHERE c.id = ?`;
database.pool.query(query, [params.recipient], (error, result) => {
if (error || result.length == 0)
- return cb({status: 'REJECT', data: {message: 'No data found', error: error}});
+ return cb(new Error('No template data found'));
Object.assign(this, result[0]);
- cb({status: 'ACCEPT', data: {}});
+ cb();
});
}
get paymentDay() {
- if (this.payMethodFk != 5) {
+ if (this.payMethodFk != 5)
return `
+
+
\ No newline at end of file
diff --git a/services/mailer/application/template/printer-setup/locale/es.json b/services/mailer/application/template/printer-setup/locale/es.json
new file mode 100644
index 000000000..41a831524
--- /dev/null
+++ b/services/mailer/application/template/printer-setup/locale/es.json
@@ -0,0 +1,36 @@
+{
+ "subject": "Instalación y configuración de impresora",
+ "title": "¡GRACIAS POR SU CONFIANZA!",
+ "dear": "Estimado cliente",
+ "bodyDescription": "Siga las intrucciones especificadas en este correo para llevar a cabo la instalación de la impresora.",
+ "followGuide": "Puede utilizar como guía, el video del montaje del ribon y la cinta https://www.youtube.com/watch?v=qhb0kgQF3o8. También necesitará el QLabel, el programa para imprimir las cintas.",
+ "downloadFrom": "Puede descargarlo desde este enlace http://www.godexintl.com/en/product/type/Download/2967",
+ "sectionQLabelTitle": "Utilización de QLabel",
+ "sectionQLabelDescription": "Para utilizar el programa de impresión de cintas siga estos pasos:",
+ "sectionQLabelStep1": "Abra el programa QLabel.",
+ "sectionQLabelStep2": "Haga clic en el icono de la barra superior superior de la \"carpeta\".",
+ "sectionQLabelStep3": "Seleccione el archivo plantilla llamado \"model.ezp\".",
+ "sectionQLabelStep4": "Haga clic encima del texto con el boton secundario del ratón.",
+ "sectionQLabelStep5": "Elija la primera opcion \"setup\".",
+ "sectionQLabelStep6": "Cambie el texto para imprimir.",
+ "sectionQLabelStep7": "Haga clic en el boton \"Ok\".",
+ "sectionQLabelStep8": "Desplácese con el raton para ver la medida máxima.",
+ "sectionQLabelStep9": "Haga clic encima del texto con el botón secundario del ratón.",
+ "sectionQLabelStep10": "Elija la primera opcion \"Setup printer\".",
+ "sectionQLabelStep11": "Haga clic en la primera pestalla \"Label Setup\".",
+ "sectionQLabelStep12": "Modifique la propidad \"Paper Height\".",
+ "sectionQLabelStep13": "Haga clic en el boton \"Ok\".",
+ "sectionQLabelStep14": "Haga clic sobre el icono de la impresora.",
+ "sectionQLabelStep15": "Haga clic en \"Print\".",
+ "sectionHelpTitle": "¿Necesita ayuda?",
+ "sectionHelpDescription": "Si necesita ayuda, descárguese nuestro programa de soporte para poder conectarnos remotamente a su equipo y hacerle la instalación. Proporciónenos un horario de contacto para atenderle, y contactaremos con usted.",
+ "sectionHelpDownloadRemoteSupport": "Puede descargarse el programa desde este enlace http://soporte.verdnatura.es.",
+ "salesPersonNameText": "Soy su comercial y mi nombre es",
+ "salesPersonPhoneText": "Teléfono y whatsapp",
+ "salesPersonEmailText": "Dirección de e-mail",
+ "actionButton": "Visita nuestra Web",
+ "infoButton": "Ayúdanos a mejorar",
+ "fiscalAddress": "VERDNATURA LEVANTE SL, B97367486 Avda. Espioca, 100, 46460 Silla _ www.verdnatura.es _ clientes@verdnatura.es",
+ "privacy": "- AVISO - Este mensaje es privado y confidencial, y debe ser utilizado exclusivamente por la persona destinataria del mismo. Si usted ha recibido este mensaje por error, le rogamos lo comunique al remitente y borre dicho mensaje y cualquier documento adjunto que pudiera contener. Verdnatura Levante SL no renuncia a la confidencialidad ni a ningún privilegio por causa de transmisión errónea o mal funcionamiento. Igualmente no se hace responsable de los cambios, alteraciones, errores u omisiones que pudieran hacerse al mensaje una vez enviado.",
+ "privacyLaw": "En cumplimiento de lo dispuesto en la Ley Orgánica 15/1999, de Protección de Datos de Carácter Personal, le comunicamos que los datos personales que facilite se incluirán en ficheros automatizados de VERDNATURA LEVANTE S.L., pudiendo en todo momento ejercitar los derechos de acceso, rectificación, cancelación y oposición, comunicándolo por escrito al domicilio social de la entidad. La finalidad del fichero es la gestión administrativa, contabilidad, y facturación."
+}
\ No newline at end of file
diff --git a/services/mailer/application/template/printer-setup/printer-setup.js b/services/mailer/application/template/printer-setup/printer-setup.js
new file mode 100644
index 000000000..77147f459
--- /dev/null
+++ b/services/mailer/application/template/printer-setup/printer-setup.js
@@ -0,0 +1,42 @@
+var path = require('path');
+var database = require(path.join(__dirname, '../../database.js'));
+var format = require(path.join(__dirname, '../../util/format.js'));
+
+module.exports = class PrinterSetup {
+ getData(params, cb) {
+ let query = `SELECT
+ CONCAT(w.name, ' ', w.firstName) name,
+ w.phone AS phone,
+ CONCAT(u.name, '@verdnatura.es') AS email,
+ LOWER(ct.code) countryCode,
+ c.email recipient
+ FROM client c
+ LEFT JOIN worker w ON w.id = c.workerFk
+ LEFT JOIN account.user u ON u.id = w.userFk
+ JOIN country ct ON ct.id = c.countryFk
+ WHERE c.id = ?`;
+ database.pool.query(query, [params.recipient], (error, result) => {
+ if (error || result.length == 0)
+ return cb(new Error('No template data found'));
+
+ Object.assign(this, result[0]);
+ cb();
+ });
+ }
+
+ get salesPersonName() {
+ if (this.name)
+ return `
${this._.salesPersonNameText}: ${this.name}
`;
+ }
+
+ get salesPersonPhone() {
+ if (this.phone)
+ return `
`;
+ }
+};
diff --git a/services/mailer/application/template/sepa-core/attachment.json b/services/mailer/application/template/sepa-core/attachment.json
new file mode 100644
index 000000000..0637a088a
--- /dev/null
+++ b/services/mailer/application/template/sepa-core/attachment.json
@@ -0,0 +1 @@
+[]
\ No newline at end of file
diff --git a/services/mailer/application/template/UNUSED/printer-setup/index.html b/services/mailer/application/template/sepa-core/index.html
similarity index 89%
rename from services/mailer/application/template/UNUSED/printer-setup/index.html
rename to services/mailer/application/template/sepa-core/index.html
index caec77e90..df149cb9f 100644
--- a/services/mailer/application/template/UNUSED/printer-setup/index.html
+++ b/services/mailer/application/template/sepa-core/index.html
@@ -23,12 +23,6 @@
{{_.dear}},
{{_.bodyDescription}}
-
-
{{_.paymentMethod}}: {{payMethodName}}
- {{{paymentDay}}}
-
-
{{paymentAdvice}}
-
{{_.notifyError}}
diff --git a/services/mailer/application/template/sepa-core/locale/es.json b/services/mailer/application/template/sepa-core/locale/es.json
new file mode 100644
index 000000000..29e0ef1a9
--- /dev/null
+++ b/services/mailer/application/template/sepa-core/locale/es.json
@@ -0,0 +1,11 @@
+{
+ "subject": "Instalación y configuración de impresora",
+ "title": "¡GRACIAS POR SU CONFIANZA!",
+ "dear": "Estimado cliente",
+ "bodyDescription": "A continuación le adjuntamos el documento de domicilación de datos bancarios.",
+ "actionButton": "Visita nuestra Web",
+ "infoButton": "Ayúdanos a mejorar",
+ "fiscalAddress": "VERDNATURA LEVANTE SL, B97367486 Avda. Espioca, 100, 46460 Silla _ www.verdnatura.es _ clientes@verdnatura.es",
+ "privacy": "- AVISO - Este mensaje es privado y confidencial, y debe ser utilizado exclusivamente por la persona destinataria del mismo. Si usted ha recibido este mensaje por error, le rogamos lo comunique al remitente y borre dicho mensaje y cualquier documento adjunto que pudiera contener. Verdnatura Levante SL no renuncia a la confidencialidad ni a ningún privilegio por causa de transmisión errónea o mal funcionamiento. Igualmente no se hace responsable de los cambios, alteraciones, errores u omisiones que pudieran hacerse al mensaje una vez enviado.",
+ "privacyLaw": "En cumplimiento de lo dispuesto en la Ley Orgánica 15/1999, de Protección de Datos de Carácter Personal, le comunicamos que los datos personales que facilite se incluirán en ficheros automatizados de VERDNATURA LEVANTE S.L., pudiendo en todo momento ejercitar los derechos de acceso, rectificación, cancelación y oposición, comunicándolo por escrito al domicilio social de la entidad. La finalidad del fichero es la gestión administrativa, contabilidad, y facturación."
+}
\ No newline at end of file
diff --git a/services/mailer/application/template/sepa-core/sepa-core.js b/services/mailer/application/template/sepa-core/sepa-core.js
new file mode 100644
index 000000000..536448bf0
--- /dev/null
+++ b/services/mailer/application/template/sepa-core/sepa-core.js
@@ -0,0 +1,42 @@
+var path = require('path');
+var database = require(path.join(__dirname, '../../database.js'));
+var format = require(path.join(__dirname, '../../util/format.js'));
+
+module.exports = class SepaCore {
+ getData(params, cb) {
+ let query = `SELECT
+ CONCAT(w.name, ' ', w.firstName) name,
+ w.phone AS phone,
+ CONCAT(u.name, '@verdnatura.es') AS email,
+ LOWER(ct.code) countryCode,
+ c.email recipient
+ FROM client c
+ LEFT JOIN worker w ON w.id = c.workerFk
+ LEFT JOIN account.user u ON u.id = w.userFk
+ JOIN country ct ON ct.id = c.countryFk
+ WHERE c.id = ?`;
+ database.pool.query(query, [params.recipient], (error, result) => {
+ if (error || result.length == 0)
+ return cb(new Error('No template data found'));
+
+ Object.assign(this, result[0]);
+ cb();
+ });
+ }
+
+ get salesPersonName() {
+ if (this.name)
+ return `
${this._.salesPersonNameText}: ${this.name}
`;
+ }
+
+ get salesPersonPhone() {
+ if (this.phone)
+ return `