Merge branch 'dev' into test
This commit is contained in:
commit
d316b17899
|
@ -45,7 +45,7 @@ vn-login > div {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
width: 0;
|
width: 0;
|
||||||
top: .3em;
|
top: .3em;
|
||||||
right: 4em;
|
right: 3em;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<form name="form" ng-submit="watcher.submitGo('client.card.address.index')">
|
<form name="form" ng-submit="watcher.submitGo('client.card.address.index')">
|
||||||
<vn-card pad-large>
|
<vn-card pad-large>
|
||||||
<vn-title>Address</vn-title>
|
<vn-title>Address</vn-title>
|
||||||
<vn-horizontal>
|
<vn-horizontal pad-small-v>
|
||||||
<vn-check vn-one label="Default" field="$ctrl.address.isDefaultAddress"></vn-check>
|
<vn-check vn-one label="Default" field="$ctrl.address.isDefaultAddress"></vn-check>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
|
|
|
@ -15,41 +15,9 @@ describe('Client', () => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$state = _$state_;
|
$state = _$state_;
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
$state.params.addressId = '1';
|
$state.params.addressId = '1';
|
||||||
controller = $componentController('vnClientAddressEdit', {$state: $state});
|
controller = $componentController('vnClientAddressEdit', {$state: $state});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should define and set address property', () => {
|
|
||||||
expect(controller.address.id).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('_observationsEquals', () => {
|
|
||||||
it('should return true if two observations are equals independent of control attributes', () => {
|
|
||||||
let ob1 = {id: 1, observationTypeFk: 1, description: 'Spiderman rocks', showAddIcon: true};
|
|
||||||
let ob2 = {id: 1, observationTypeFk: 1, description: 'Spiderman rocks', showAddIcon: false};
|
|
||||||
let equals = controller.equalObservations(ob2, ob1);
|
|
||||||
|
|
||||||
expect(equals).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return false if two observations are not equals independent of control attributes', () => {
|
|
||||||
let ob1 = {id: 1, observationTypeFk: 1, description: 'Spiderman rocks', showAddIcon: true};
|
|
||||||
let ob2 = {id: 1, observationTypeFk: 1, description: 'Spiderman sucks', showAddIcon: true};
|
|
||||||
let equals = controller.equalObservations(ob2, ob1);
|
|
||||||
|
|
||||||
expect(equals).toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('$onInit()', () => {
|
|
||||||
it('should perform a GET query to receive the address observations', () => {
|
|
||||||
let filter = {where: {addressFk: 1}, include: {relation: 'observationType'}};
|
|
||||||
let res = ['some notes'];
|
|
||||||
$httpBackend.whenGET(`/client/api/AddressObservations?filter=${JSON.stringify(filter)}`).respond(res);
|
|
||||||
$httpBackend.expectGET(`/client/api/AddressObservations?filter=${JSON.stringify(filter)}`);
|
|
||||||
controller.$onInit();
|
|
||||||
$httpBackend.flush();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,19 +1,32 @@
|
||||||
|
|
||||||
<mg-ajax
|
<mg-ajax
|
||||||
path="/client/api/Addresses/{{edit.params.addressId}}"
|
path="/client/api/Addresses/{{edit.params.addressId}}"
|
||||||
actions="$ctrl.address = edit.model; $ctrl._setIconAdd();"
|
actions="$ctrl.address = edit.model"
|
||||||
options="mgEdit">
|
options="mgEdit">
|
||||||
</mg-ajax>
|
</mg-ajax>
|
||||||
<vn-watcher
|
<vn-watcher
|
||||||
vn-id="watcher"
|
vn-id="watcher"
|
||||||
|
data="$ctrl.address"
|
||||||
url="/client/api/Addresses"
|
url="/client/api/Addresses"
|
||||||
id-field="id"
|
id-field="id"
|
||||||
data="$ctrl.address"
|
form="form">
|
||||||
form="addressForm">
|
|
||||||
</vn-watcher>
|
</vn-watcher>
|
||||||
<form name="addressForm" ng-submit="$ctrl.submit()">
|
<vn-crud-model
|
||||||
|
vn-id="model"
|
||||||
|
url="/client/api/AddressObservations"
|
||||||
|
fields="['id', 'addressFk', 'observationTypeFk', 'description']"
|
||||||
|
link="{addressFk: $ctrl.$stateParams.addressId}"
|
||||||
|
data="observations">
|
||||||
|
</vn-crud-model>
|
||||||
|
<vn-crud-model
|
||||||
|
url="/client/api/ObservationTypes"
|
||||||
|
fields="['id', 'description']"
|
||||||
|
data="types">
|
||||||
|
</vn-crud-model>
|
||||||
|
<form name="form" ng-submit="$ctrl.submit()">
|
||||||
<vn-card pad-large>
|
<vn-card pad-large>
|
||||||
<vn-title>Address</vn-title>
|
<vn-title>Address</vn-title>
|
||||||
<vn-horizontal>
|
<vn-horizontal pad-small-v>
|
||||||
<vn-check vn-one label="Enabled" field="$ctrl.address.isActive"></vn-check>
|
<vn-check vn-one label="Enabled" field="$ctrl.address.isActive"></vn-check>
|
||||||
<vn-check
|
<vn-check
|
||||||
vn-one label="Is equalizated"
|
vn-one label="Is equalizated"
|
||||||
|
@ -49,32 +62,17 @@
|
||||||
<vn-textfield vn-one label="Phone" field="$ctrl.address.phone"></vn-textfield>
|
<vn-textfield vn-one label="Phone" field="$ctrl.address.phone"></vn-textfield>
|
||||||
<vn-textfield vn-one label="Mobile" field="$ctrl.address.mobile"></vn-textfield>
|
<vn-textfield vn-one label="Mobile" field="$ctrl.address.mobile"></vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-one margin-medium-top>
|
|
||||||
</vn-card>
|
|
||||||
</form>
|
|
||||||
<vn-watcher form="notesForm"></vn-watcher>
|
|
||||||
<form name="notesForm" ng-submit="$ctrl.submit()">
|
|
||||||
<vn-card pad-large>
|
|
||||||
<vn-title>Notes</vn-title>
|
<vn-title>Notes</vn-title>
|
||||||
<mg-ajax path="/client/api/ObservationTypes" options="mgIndex as observationsTypes"></mg-ajax>
|
<div name="observations">
|
||||||
<vn-horizontal ng-repeat="observation in $ctrl.observations track by $index">
|
<vn-horizontal ng-repeat="observation in observations">
|
||||||
<vn-autocomplete
|
<vn-autocomplete
|
||||||
ng-if="!observation.id"
|
|
||||||
vn-one
|
vn-one
|
||||||
vn-focus
|
vn-focus
|
||||||
initial-data="observation.observationType"
|
data="types"
|
||||||
field="observation.observationTypeFk"
|
field="observation.observationTypeFk"
|
||||||
data="observationsTypes.model"
|
|
||||||
show-field="description"
|
show-field="description"
|
||||||
label="Observation type">
|
label="Observation type">
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
<vn-textfield
|
|
||||||
ng-if="observation.id"
|
|
||||||
vn-one
|
|
||||||
label="Observation type"
|
|
||||||
model="observation.observationType.description"
|
|
||||||
disabled="true">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
vn-two
|
vn-two
|
||||||
margin-large-right
|
margin-large-right
|
||||||
|
@ -92,17 +90,15 @@
|
||||||
</vn-icon>
|
</vn-icon>
|
||||||
</vn-one>
|
</vn-one>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
</vn-one>
|
</div>
|
||||||
<vn-one>
|
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
pointer
|
pointer
|
||||||
vn-bind="+"
|
vn-bind="+"
|
||||||
vn-tooltip="Add note"
|
vn-tooltip="Add note"
|
||||||
icon="add_circle"
|
icon="add_circle"
|
||||||
ng-if="observationsTypes.model.length > $ctrl.observations.length"
|
ng-if="types.length > observations.length"
|
||||||
ng-click="$ctrl.addObservation()">
|
ng-click="model.insert()">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
</vn-one>
|
|
||||||
</vn-card>
|
</vn-card>
|
||||||
<vn-button-bar>
|
<vn-button-bar>
|
||||||
<vn-submit label="Save"></vn-submit>
|
<vn-submit label="Save"></vn-submit>
|
||||||
|
|
|
@ -1,151 +1,30 @@
|
||||||
import ngModule from '../../module';
|
import ngModule from '../../module';
|
||||||
|
|
||||||
export default class Controller {
|
export default class Controller {
|
||||||
constructor($state, $scope, $http, $q, $translate, vnApp) {
|
constructor($scope, $state) {
|
||||||
|
this.$ = $scope;
|
||||||
this.$state = $state;
|
this.$state = $state;
|
||||||
this.$scope = $scope;
|
this.$stateParams = $state.params;
|
||||||
this.$http = $http;
|
|
||||||
this.$q = $q;
|
|
||||||
this.$translate = $translate;
|
|
||||||
this.vnApp = vnApp;
|
|
||||||
|
|
||||||
this.address = {
|
|
||||||
id: parseInt($state.params.addressId)
|
|
||||||
};
|
|
||||||
this.observations = [];
|
|
||||||
this.oldObservations = {};
|
|
||||||
this.removedObservations = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
_setDirtyForm() {
|
|
||||||
if (this.$scope.form) {
|
|
||||||
this.$scope.form.$setDirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_unsetDirtyForm() {
|
|
||||||
if (this.$scope.form) {
|
|
||||||
this.$scope.form.$setPristine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addObservation() {
|
|
||||||
this.observations.push({observationTypeFk: null, addressFk: this.address.id, description: null});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
removeObservation(index) {
|
removeObservation(index) {
|
||||||
let item = this.observations[index];
|
this.$.watcher.setDirty();
|
||||||
if (item) {
|
this.$.model.remove(index);
|
||||||
this.observations.splice(index, 1);
|
|
||||||
if (item.id) {
|
|
||||||
this.removedObservations.push(item.id);
|
|
||||||
this._setDirtyForm();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.observations.length === 0 && Object.keys(this.oldObservations).length === 0) {
|
|
||||||
this._unsetDirtyForm();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_submitObservations(observationsObject) {
|
|
||||||
return this.$http.post(`/client/api/AddressObservations/crudAddressObservations`, observationsObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
equalObservations(oldObj, newObj) {
|
|
||||||
return oldObj.id === newObj.id && oldObj.observationTypeFk === newObj.observationTypeFk && oldObj.description === newObj.description;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
if (this.$scope.addressForm.$invalid || this.$scope.notesForm.$invalid) {
|
this.$.watcher.check();
|
||||||
this.vnApp.showMessage(
|
this.$.watcher.realSubmit()
|
||||||
this.$translate.instant('Some fields are invalid')
|
.then(() => this.$.model.save(true))
|
||||||
);
|
.then(() => {
|
||||||
return false;
|
this.$.watcher.setPristine();
|
||||||
}
|
this.$.watcher.notifySaved();
|
||||||
|
|
||||||
let canSubmitWatcher = this.$scope.watcher.dataChanged();
|
|
||||||
let canSubmitObservations;
|
|
||||||
let repeatedTypes = false;
|
|
||||||
let emptyFields = false;
|
|
||||||
let types = [];
|
|
||||||
let observationsObj = {
|
|
||||||
delete: this.removedObservations,
|
|
||||||
create: [],
|
|
||||||
update: []
|
|
||||||
};
|
|
||||||
|
|
||||||
this.observations.forEach(observation => {
|
|
||||||
let isNewObservation = observation.id === undefined;
|
|
||||||
|
|
||||||
if (observation.observationTypeFk && types.indexOf(observation.observationTypeFk) !== -1) {
|
|
||||||
repeatedTypes = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (observation.observationTypeFk === null || observation.description === null) {
|
|
||||||
emptyFields = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (observation.observationTypeFk)
|
|
||||||
types.push(observation.observationTypeFk);
|
|
||||||
|
|
||||||
if (isNewObservation && observation.observationTypeFk && observation.description) {
|
|
||||||
observationsObj.create.push(observation);
|
|
||||||
} else if (!isNewObservation && !this.equalObservations(this.oldObservations[observation.id], observation)) {
|
|
||||||
observationsObj.update.push(observation);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
canSubmitObservations = observationsObj.update.length > 0 || observationsObj.create.length > 0 || observationsObj.delete.length > 0;
|
|
||||||
|
|
||||||
if (repeatedTypes) {
|
|
||||||
this.vnApp.showMessage(
|
|
||||||
this.$translate.instant('The observation type must be unique')
|
|
||||||
);
|
|
||||||
} else if (emptyFields) {
|
|
||||||
this.vnApp.showMessage(
|
|
||||||
this.$translate.instant('No field can be blank')
|
|
||||||
);
|
|
||||||
} else if (canSubmitWatcher && !canSubmitObservations) {
|
|
||||||
this.$scope.watcher.submit().then(() => {
|
|
||||||
this.$state.go('client.card.address.index', {id: this.$state.params.id});
|
|
||||||
this.card.reload();
|
this.card.reload();
|
||||||
});
|
this.$state.go('client.card.address.index', {id: this.$stateParams.id});
|
||||||
} else if (!canSubmitWatcher && canSubmitObservations) {
|
|
||||||
this._submitObservations(observationsObj).then(() => {
|
|
||||||
this.$state.go('client.card.address.index', {id: this.$state.params.id});
|
|
||||||
});
|
|
||||||
} else if (canSubmitWatcher && canSubmitObservations) {
|
|
||||||
this.$q.all([this.$scope.watcher.submit(), this._submitObservations(observationsObj)]).then(() => {
|
|
||||||
this.$state.go('client.card.address.index', {id: this.$state.params.id});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.vnApp.showMessage(
|
|
||||||
this.$translate.instant('No changes to save')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
this._unsetDirtyForm();
|
|
||||||
}
|
|
||||||
|
|
||||||
_getAddressNotes() {
|
|
||||||
let filter = {
|
|
||||||
where: {addressFk: this.address.id},
|
|
||||||
include: {relation: 'observationType'}
|
|
||||||
};
|
|
||||||
this.$http.get(`/client/api/AddressObservations?filter=${JSON.stringify(filter)}`).then(res => {
|
|
||||||
this.observations = res.data;
|
|
||||||
res.data.forEach(item => {
|
|
||||||
this.oldObservations[item.id] = Object.assign({}, item);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
|
||||||
this._getAddressNotes();
|
|
||||||
}
|
}
|
||||||
}
|
Controller.$inject = ['$scope', '$state'];
|
||||||
Controller.$inject = ['$state', '$scope', '$http', '$q', '$translate', 'vnApp'];
|
|
||||||
|
|
||||||
ngModule.component('vnClientAddressEdit', {
|
ngModule.component('vnClientAddressEdit', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
|
|
|
@ -10,17 +10,19 @@
|
||||||
<vn-title>Basic data</vn-title>
|
<vn-title>Basic data</vn-title>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-textfield vn-one label="Comercial Name" field="$ctrl.client.name" vn-focus></vn-textfield>
|
<vn-textfield vn-one label="Comercial Name" field="$ctrl.client.name" vn-focus></vn-textfield>
|
||||||
<vn-textfield vn-one label="Contact" field="$ctrl.client.contact"></vn-textfield>
|
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-textfield vn-one label="Phone" field="$ctrl.client.phone"></vn-textfield>
|
<vn-textfield vn-one label="Contact" field="$ctrl.client.contact"></vn-textfield>
|
||||||
<vn-textfield vn-one label="Mobile" field="$ctrl.client.mobile"></vn-textfield>
|
|
||||||
<vn-textfield vn-one
|
<vn-textfield vn-one
|
||||||
label="Email"
|
label="Email"
|
||||||
field="$ctrl.client.email"
|
field="$ctrl.client.email"
|
||||||
info="You can save multiple emails">
|
info="You can save multiple emails">
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-textfield vn-one label="Phone" field="$ctrl.client.phone"></vn-textfield>
|
||||||
|
<vn-textfield vn-one label="Mobile" field="$ctrl.client.mobile"></vn-textfield>
|
||||||
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-autocomplete vn-one
|
<vn-autocomplete vn-one
|
||||||
initial-data="$ctrl.client.salesPerson"
|
initial-data="$ctrl.client.salesPerson"
|
||||||
|
|
|
@ -9,26 +9,31 @@
|
||||||
<vn-card pad-large>
|
<vn-card pad-large>
|
||||||
<vn-title>Pay method</vn-title>
|
<vn-title>Pay method</vn-title>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-autocomplete vn-two
|
<vn-autocomplete
|
||||||
|
vn-one
|
||||||
|
label="Pay method"
|
||||||
vn-acl="administrative, salesAssistant"
|
vn-acl="administrative, salesAssistant"
|
||||||
field="$ctrl.client.payMethodFk"
|
field="$ctrl.client.payMethodFk"
|
||||||
url="/client/api/PayMethods"
|
url="/client/api/PayMethods"
|
||||||
select-fields="ibanRequired"
|
select-fields="ibanRequired"
|
||||||
initial-data="$ctrl.client.payMethod"
|
initial-data="$ctrl.client.payMethod">
|
||||||
label="Pay method">
|
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
vn-two label="IBAN"
|
vn-one
|
||||||
field="$ctrl.client.iban"
|
label="Due day"
|
||||||
vn-acl="administrative, salesAssistant">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
vn-one label="Due day"
|
|
||||||
field="$ctrl.client.dueDay"
|
field="$ctrl.client.dueDay"
|
||||||
vn-acl="administrative, salesAssistant">
|
vn-acl="administrative, salesAssistant">
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal margin-medium-bottom>
|
<vn-horizontal>
|
||||||
|
<vn-textfield
|
||||||
|
vn-one
|
||||||
|
label="IBAN"
|
||||||
|
field="$ctrl.client.iban"
|
||||||
|
vn-acl="administrative, salesAssistant">
|
||||||
|
</vn-textfield>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal pad-small-v>
|
||||||
<vn-one>
|
<vn-one>
|
||||||
<vn-check
|
<vn-check
|
||||||
label="Received core VNH"
|
label="Received core VNH"
|
||||||
|
|
|
@ -6,22 +6,11 @@
|
||||||
save="post">
|
save="post">
|
||||||
</vn-watcher>
|
</vn-watcher>
|
||||||
<form name="form" ng-submit="$ctrl.onSubmit()" margin-medium>
|
<form name="form" ng-submit="$ctrl.onSubmit()" margin-medium>
|
||||||
<div style="max-width: 70em; margin: 0 auto;">
|
<div style="max-width: 50em; margin: 0 auto;">
|
||||||
<vn-card pad-large>
|
<vn-card pad-large>
|
||||||
<vn-title>Create client</vn-title>
|
<vn-title>Create client</vn-title>
|
||||||
<vn-horizontal>
|
|
||||||
<vn-textfield vn-two label="Business name" field="$ctrl.client.socialName"></vn-textfield>
|
|
||||||
<vn-textfield vn-one label="Tax number" field="$ctrl.client.fi"></vn-textfield>
|
|
||||||
<vn-check
|
|
||||||
vn-one
|
|
||||||
label="Is equalizated"
|
|
||||||
field="$ctrl.client.isEqualizated">
|
|
||||||
</vn-check>
|
|
||||||
</vn-horizontal>
|
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-textfield vn-two label="Comercial Name" field="$ctrl.client.name" vn-focus></vn-textfield>
|
<vn-textfield vn-two label="Comercial Name" field="$ctrl.client.name" vn-focus></vn-textfield>
|
||||||
<vn-textfield vn-one label="Web user" field="$ctrl.client.userName"></vn-textfield>
|
|
||||||
<vn-textfield vn-two label="Email" field="$ctrl.client.email" info="You can save multiple emails"></vn-textfield>
|
|
||||||
<vn-autocomplete vn-one
|
<vn-autocomplete vn-one
|
||||||
field="$ctrl.client.salesPersonFk"
|
field="$ctrl.client.salesPersonFk"
|
||||||
url="/client/api/Clients/activeSalesPerson"
|
url="/client/api/Clients/activeSalesPerson"
|
||||||
|
@ -31,6 +20,17 @@
|
||||||
<tpl-item>{{firstName}} {{name}}</tpl-item>
|
<tpl-item>{{firstName}} {{name}}</tpl-item>
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-textfield vn-two label="Business name" field="$ctrl.client.socialName"></vn-textfield>
|
||||||
|
<vn-textfield vn-one label="Tax number" field="$ctrl.client.fi"></vn-textfield>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-textfield
|
||||||
|
vn-two
|
||||||
|
label="Street"
|
||||||
|
field="$ctrl.client.street">
|
||||||
|
</vn-textfield>
|
||||||
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
vn-one
|
vn-one
|
||||||
|
@ -38,18 +38,22 @@
|
||||||
field="$ctrl.client.postcode">
|
field="$ctrl.client.postcode">
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
vn-two
|
vn-one
|
||||||
label="Street"
|
|
||||||
field="$ctrl.client.street">
|
|
||||||
</vn-textfield>
|
|
||||||
<vn-textfield
|
|
||||||
vn-two
|
|
||||||
label="City"
|
label="City"
|
||||||
field="$ctrl.client.city">
|
field="$ctrl.client.city">
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-autocomplete
|
||||||
|
vn-one
|
||||||
|
field="$ctrl.client.countryFk"
|
||||||
|
url="/client/api/Countries"
|
||||||
|
show-field="country"
|
||||||
|
value-field="id"
|
||||||
|
label="Country">
|
||||||
|
</vn-autocomplete>
|
||||||
<vn-autocomplete
|
<vn-autocomplete
|
||||||
vn-one
|
vn-one
|
||||||
initial-data="$ctrl.client.province"
|
|
||||||
field="$ctrl.client.provinceFk"
|
field="$ctrl.client.provinceFk"
|
||||||
url="/client/api/Provinces"
|
url="/client/api/Provinces"
|
||||||
show-field="name"
|
show-field="name"
|
||||||
|
@ -57,6 +61,26 @@
|
||||||
label="Province">
|
label="Province">
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
|
<vn-textfield
|
||||||
|
vn-one
|
||||||
|
label="Web user"
|
||||||
|
field="$ctrl.client.userName">
|
||||||
|
</vn-textfield>
|
||||||
|
<vn-textfield
|
||||||
|
vn-one
|
||||||
|
label="Email"
|
||||||
|
field="$ctrl.client.email"
|
||||||
|
info="You can save multiple emails">
|
||||||
|
</vn-textfield>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal pad-small-v>
|
||||||
|
<vn-check
|
||||||
|
vn-one
|
||||||
|
label="Is equalizated"
|
||||||
|
field="$ctrl.client.isEqualizated">
|
||||||
|
</vn-check>
|
||||||
|
</vn-horizontal>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
<vn-button-bar>
|
<vn-button-bar>
|
||||||
<vn-submit label="Create"></vn-submit>
|
<vn-submit label="Create"></vn-submit>
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
vn-one
|
vn-one
|
||||||
margin-medium-right
|
|
||||||
label="Credit"
|
label="Credit"
|
||||||
model="$ctrl.creditClassification.credit",
|
model="$ctrl.creditClassification.credit",
|
||||||
rule="CreditInsurance.credit"
|
rule="CreditInsurance.credit"
|
||||||
|
@ -13,7 +12,6 @@
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
vn-one
|
vn-one
|
||||||
argin-medium-right
|
|
||||||
label="Grade"
|
label="Grade"
|
||||||
model="$ctrl.creditClassification.grade"
|
model="$ctrl.creditClassification.grade"
|
||||||
rule="CreditInsurance.grade">
|
rule="CreditInsurance.grade">
|
||||||
|
|
|
@ -13,6 +13,7 @@ describe('Client', () => {
|
||||||
beforeEach(angular.mock.inject((_$componentController_, _$httpBackend_) => {
|
beforeEach(angular.mock.inject((_$componentController_, _$httpBackend_) => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
controller = $componentController('vnClientCreditInsuranceIndex');
|
controller = $componentController('vnClientCreditInsuranceIndex');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ describe('Client', () => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
let $state = {params: {classificationId: 1}};
|
let $state = {params: {classificationId: 1}};
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
controller = $componentController('vnClientCreditInsuranceInsuranceIndex', {$state: $state});
|
controller = $componentController('vnClientCreditInsuranceInsuranceIndex', {$state: $state});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ describe('Client', () => {
|
||||||
$state = _$state_;
|
$state = _$state_;
|
||||||
$state.params.id = 101;
|
$state.params.id = 101;
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
controller = $componentController('vnClientCreditCreate', {$scope: $scope}, {$state: $state});
|
controller = $componentController('vnClientCreditCreate', {$scope: $scope}, {$state: $state});
|
||||||
}));
|
}));
|
||||||
describe('onSubmit()', () => {
|
describe('onSubmit()', () => {
|
||||||
|
|
|
@ -13,6 +13,7 @@ describe('Descriptor', () => {
|
||||||
beforeEach(angular.mock.inject((_$componentController_, _$httpBackend_) => {
|
beforeEach(angular.mock.inject((_$componentController_, _$httpBackend_) => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
controller = $componentController('vnClientDescriptor');
|
controller = $componentController('vnClientDescriptor');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ describe('Client', () => {
|
||||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => {
|
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_) => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
$scope = $rootScope.$new();
|
$scope = $rootScope.$new();
|
||||||
controller = $componentController('vnClientFiscalData', {$scope: $scope});
|
controller = $componentController('vnClientFiscalData', {$scope: $scope});
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -24,13 +24,6 @@
|
||||||
vn-acl="administrative, salesAssistant, salesPerson"
|
vn-acl="administrative, salesAssistant, salesPerson"
|
||||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
<vn-check
|
|
||||||
vn-one
|
|
||||||
label="Is equalizated"
|
|
||||||
field="$ctrl.client.isEqualizated"
|
|
||||||
vn-acl="administrative, salesAssistant, salesPerson"
|
|
||||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
|
||||||
</vn-check>
|
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
|
@ -40,13 +33,6 @@
|
||||||
vn-acl="administrative, salesAssistant, salesPerson"
|
vn-acl="administrative, salesAssistant, salesPerson"
|
||||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
<vn-textfield
|
|
||||||
vn-one
|
|
||||||
label="City"
|
|
||||||
field="$ctrl.client.city"
|
|
||||||
vn-acl="administrative, salesAssistant, salesPerson"
|
|
||||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
|
||||||
</vn-textfield>
|
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
|
@ -56,17 +42,15 @@
|
||||||
vn-acl="administrative, salesAssistant, salesPerson"
|
vn-acl="administrative, salesAssistant, salesPerson"
|
||||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
<vn-autocomplete
|
<vn-textfield
|
||||||
vn-one
|
vn-one
|
||||||
initial-data="$ctrl.client.province"
|
label="City"
|
||||||
field="$ctrl.client.provinceFk"
|
field="$ctrl.client.city"
|
||||||
url="/client/api/Provinces"
|
|
||||||
show-field="name"
|
|
||||||
value-field="id"
|
|
||||||
label="Province"
|
|
||||||
vn-acl="administrative, salesAssistant, salesPerson"
|
vn-acl="administrative, salesAssistant, salesPerson"
|
||||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||||
</vn-autocomplete>
|
</vn-textfield>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
<vn-autocomplete
|
<vn-autocomplete
|
||||||
vn-one
|
vn-one
|
||||||
initial-data="$ctrl.client.country"
|
initial-data="$ctrl.client.country"
|
||||||
|
@ -78,8 +62,19 @@
|
||||||
vn-acl="administrative, salesAssistant, salesPerson"
|
vn-acl="administrative, salesAssistant, salesPerson"
|
||||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
|
<vn-autocomplete
|
||||||
|
vn-one
|
||||||
|
initial-data="$ctrl.client.province"
|
||||||
|
field="$ctrl.client.provinceFk"
|
||||||
|
url="/client/api/Provinces"
|
||||||
|
show-field="name"
|
||||||
|
value-field="id"
|
||||||
|
label="Province"
|
||||||
|
vn-acl="administrative, salesAssistant, salesPerson"
|
||||||
|
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||||
|
</vn-autocomplete>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal margin-small-bottom>
|
<vn-horizontal pad-small-v>
|
||||||
<vn-check
|
<vn-check
|
||||||
vn-one
|
vn-one
|
||||||
label="Active"
|
label="Active"
|
||||||
|
@ -94,21 +89,8 @@
|
||||||
vn-acl="administrative, salesAssistant, salesPerson"
|
vn-acl="administrative, salesAssistant, salesPerson"
|
||||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||||
</vn-check>
|
</vn-check>
|
||||||
<vn-check
|
|
||||||
vn-two
|
|
||||||
label="Invoice by address"
|
|
||||||
field="$ctrl.client.hasToInvoiceByAddress"
|
|
||||||
vn-acl="administrative, salesAssistant, salesPerson"
|
|
||||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
|
||||||
</vn-check>
|
|
||||||
<vn-check
|
|
||||||
vn-two
|
|
||||||
label="Verified data"
|
|
||||||
field="$ctrl.client.isTaxDataChecked"
|
|
||||||
vn-acl="administrative, salesAssistant, salesAssistant">
|
|
||||||
</vn-check>
|
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal pad-small-v>
|
||||||
<vn-check
|
<vn-check
|
||||||
vn-one
|
vn-one
|
||||||
label="Has to invoice"
|
label="Has to invoice"
|
||||||
|
@ -116,6 +98,15 @@
|
||||||
vn-acl="administrative, salesAssistant, salesPerson"
|
vn-acl="administrative, salesAssistant, salesPerson"
|
||||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||||
</vn-check>
|
</vn-check>
|
||||||
|
<vn-check
|
||||||
|
vn-one
|
||||||
|
label="Vies"
|
||||||
|
field="$ctrl.client.isVies"
|
||||||
|
vn-acl="administrative, salesAssistant, salesPerson"
|
||||||
|
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||||
|
</vn-check>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal pad-small-v>
|
||||||
<vn-check
|
<vn-check
|
||||||
vn-one
|
vn-one
|
||||||
label="Invoice by mail"
|
label="Invoice by mail"
|
||||||
|
@ -125,12 +116,27 @@
|
||||||
</vn-check>
|
</vn-check>
|
||||||
<vn-check
|
<vn-check
|
||||||
vn-one
|
vn-one
|
||||||
label="Vies"
|
label="Invoice by address"
|
||||||
field="$ctrl.client.isVies"
|
field="$ctrl.client.hasToInvoiceByAddress"
|
||||||
vn-acl="administrative, salesAssistant, salesPerson"
|
vn-acl="administrative, salesAssistant, salesPerson"
|
||||||
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||||
</vn-check>
|
</vn-check>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
|
<vn-horizontal pad-small-v>
|
||||||
|
<vn-check
|
||||||
|
vn-one
|
||||||
|
label="Is equalizated"
|
||||||
|
field="$ctrl.client.isEqualizated"
|
||||||
|
vn-acl="administrative, salesAssistant, salesPerson"
|
||||||
|
acl-conditional-to-salesPerson="{{!$ctrl.client.isTaxDataChecked}}">
|
||||||
|
</vn-check>
|
||||||
|
<vn-check
|
||||||
|
vn-one
|
||||||
|
label="Verified data"
|
||||||
|
field="$ctrl.client.isTaxDataChecked"
|
||||||
|
vn-acl="administrative, salesAssistant, salesAssistant">
|
||||||
|
</vn-check>
|
||||||
|
</vn-horizontal>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
<vn-button-bar>
|
<vn-button-bar>
|
||||||
<vn-submit
|
<vn-submit
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<form name="form" ng-submit="watcher.submit()">
|
<form name="form" ng-submit="watcher.submit()">
|
||||||
<vn-card pad-large>
|
<vn-card pad-large>
|
||||||
<vn-title>Web access</vn-title>
|
<vn-title>Web access</vn-title>
|
||||||
<vn-horizontal>
|
<vn-horizontal pad-small-v>
|
||||||
<vn-check
|
<vn-check
|
||||||
vn-one
|
vn-one
|
||||||
label="Enable web access"
|
label="Enable web access"
|
||||||
|
@ -20,7 +20,6 @@
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
vn-focus
|
vn-focus
|
||||||
vn-one
|
vn-one
|
||||||
margin-medium-top
|
|
||||||
label="User"
|
label="User"
|
||||||
field="$ctrl.account.name">
|
field="$ctrl.account.name">
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
|
|
|
@ -62,6 +62,15 @@ export default class Autocomplete extends Input {
|
||||||
this.refreshDisplayed();
|
this.refreshDisplayed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
set data(value) {
|
||||||
|
this._data = value;
|
||||||
|
this.refreshSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
get data() {
|
||||||
|
return this._data;
|
||||||
|
}
|
||||||
|
|
||||||
selectionIsValid(selection) {
|
selectionIsValid(selection) {
|
||||||
return selection
|
return selection
|
||||||
&& selection[this.valueField] == this._field
|
&& selection[this.valueField] == this._field
|
||||||
|
@ -212,7 +221,7 @@ export default class Autocomplete extends Input {
|
||||||
showDropDown(search) {
|
showDropDown(search) {
|
||||||
Object.assign(this.$.dropDown.$.model, {
|
Object.assign(this.$.dropDown.$.model, {
|
||||||
url: this.url,
|
url: this.url,
|
||||||
staticData: this.data
|
staticData: this._data
|
||||||
});
|
});
|
||||||
|
|
||||||
asignProps(this, this.$.dropDown, [
|
asignProps(this, this.$.dropDown, [
|
||||||
|
@ -220,9 +229,9 @@ export default class Autocomplete extends Input {
|
||||||
'showField',
|
'showField',
|
||||||
'where',
|
'where',
|
||||||
'order',
|
'order',
|
||||||
|
'limit',
|
||||||
'showFilter',
|
'showFilter',
|
||||||
'multiple',
|
'multiple',
|
||||||
'limit',
|
|
||||||
'$transclude'
|
'$transclude'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,7 @@ describe('Component vnAutocomplete', () => {
|
||||||
};
|
};
|
||||||
let json = encodeURIComponent(JSON.stringify(filter));
|
let json = encodeURIComponent(JSON.stringify(filter));
|
||||||
|
|
||||||
|
$httpBackend.whenGET(`localhost?filter=${json}`).respond({});
|
||||||
$httpBackend.expectGET(`localhost?filter=${json}`);
|
$httpBackend.expectGET(`localhost?filter=${json}`);
|
||||||
controller.field = data.id;
|
controller.field = data.id;
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import "colors";
|
@import "effects";
|
||||||
|
|
||||||
vn-autocomplete > div > .mdl-textfield {
|
vn-autocomplete > div > .mdl-textfield {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -44,13 +44,12 @@ ul.vn-autocomplete {
|
||||||
max-height: 300px;
|
max-height: 300px;
|
||||||
|
|
||||||
li {
|
li {
|
||||||
|
@extend %clickable;
|
||||||
display: block;
|
display: block;
|
||||||
padding: .8em;
|
padding: .8em;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
&.active,
|
&.active {
|
||||||
&:hover {
|
|
||||||
background-color: $hover;
|
background-color: $hover;
|
||||||
}
|
}
|
||||||
&.load-more {
|
&.load-more {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import "colors";
|
@import "effects";
|
||||||
|
|
||||||
.vn-dialog {
|
.vn-dialog {
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -10,7 +10,7 @@
|
||||||
top: 0;
|
top: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: rgba(1, 1, 1, .6);
|
background-color: rgba(0, 0, 0, .6);
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity 300ms ease-in-out;
|
transition: opacity 300ms ease-in-out;
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
}
|
}
|
||||||
& > div {
|
& > div {
|
||||||
position: relative;
|
position: relative;
|
||||||
box-shadow: 0 0 .4em rgba(1,1,1,.4);
|
box-shadow: 0 0 .4em rgba(0, 0, 0, .4);
|
||||||
background-color: white;
|
background-color: white;
|
||||||
border-radius: .2em;
|
border-radius: .2em;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
@ -34,16 +34,11 @@
|
||||||
input[type="button"],
|
input[type="button"],
|
||||||
input[type="submit"],
|
input[type="submit"],
|
||||||
input[type="reset"] {
|
input[type="reset"] {
|
||||||
|
@extend %clickable;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
cursor: pointer;
|
|
||||||
transition: background-color 250ms;
|
|
||||||
border-radius: .1em;
|
border-radius: .1em;
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(1,1,1,.1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
& > button.close {
|
& > button.close {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<vn-model
|
<vn-rest-model
|
||||||
vn-id="model"
|
vn-id="model"
|
||||||
on-data-change="$ctrl.onModelDataChange()">
|
on-data-change="$ctrl.onModelDataChange()">
|
||||||
</vn-model>
|
</vn-rest-model>
|
||||||
<vn-popover
|
<vn-popover
|
||||||
vn-id="popover"
|
vn-id="popover"
|
||||||
on-open="$ctrl.onOpen()"
|
on-open="$ctrl.onOpen()"
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import ngModule from '../../module';
|
import ngModule from '../../module';
|
||||||
import Component from '../../lib/component';
|
import Component from '../../lib/component';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
import './model';
|
|
||||||
|
|
||||||
export default class DropDown extends Component {
|
export default class DropDown extends Component {
|
||||||
constructor($element, $scope, $transclude, $timeout, $http) {
|
constructor($element, $scope, $transclude, $timeout, $http) {
|
||||||
|
@ -366,14 +365,18 @@ ngModule.component('vnDropDown', {
|
||||||
template: require('./drop-down.html'),
|
template: require('./drop-down.html'),
|
||||||
controller: DropDown,
|
controller: DropDown,
|
||||||
bindings: {
|
bindings: {
|
||||||
|
showField: '@?',
|
||||||
|
valueField: '@?',
|
||||||
|
where: '@?',
|
||||||
|
order: '@?',
|
||||||
|
limit: '<?',
|
||||||
|
showFilter: '<?',
|
||||||
|
multiple: '<?',
|
||||||
field: '=?',
|
field: '=?',
|
||||||
data: '<?',
|
data: '<?',
|
||||||
selection: '=?',
|
selection: '=?',
|
||||||
search: '<?',
|
search: '<?',
|
||||||
limit: '<?',
|
|
||||||
showFilter: '<?',
|
|
||||||
parent: '<?',
|
parent: '<?',
|
||||||
multiple: '<?',
|
|
||||||
onSelect: '&?'
|
onSelect: '&?'
|
||||||
},
|
},
|
||||||
transclude: {
|
transclude: {
|
||||||
|
|
|
@ -32,7 +32,7 @@ describe('Component vnDropDown', () => {
|
||||||
$scope.popover = $componentController('vnPopover', {$element: $popover, $scope, $timeout, $transitions});
|
$scope.popover = $componentController('vnPopover', {$element: $popover, $scope, $timeout, $transitions});
|
||||||
$scope.popover.$postLink();
|
$scope.popover.$postLink();
|
||||||
|
|
||||||
$scope.model = $componentController('vnModel', {$httpBackend, $q, $filter});
|
$scope.model = $componentController('vnRestModel', {$httpBackend, $q, $filter});
|
||||||
controller = $componentController('vnDropDown', {$element, $scope, $transclude: null, $timeout, $httpBackend, $translate: null});
|
controller = $componentController('vnDropDown', {$element, $scope, $transclude: null, $timeout, $httpBackend, $translate: null});
|
||||||
controller.$postLink();
|
controller.$postLink();
|
||||||
controller.parent = angular.element('<vn-parent></vn-parent>')[0];
|
controller.parent = angular.element('<vn-parent></vn-parent>')[0];
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import "colors";
|
@import "effects";
|
||||||
|
|
||||||
vn-drop-down {
|
vn-drop-down {
|
||||||
.dropdown {
|
.dropdown {
|
||||||
|
@ -47,19 +47,15 @@ vn-drop-down {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
li, .status {
|
li, .status {
|
||||||
|
@extend %clickable;
|
||||||
padding: .6em;
|
padding: .6em;
|
||||||
cursor: pointer;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
transition: background-color 250ms ease-out;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
& > input[type=checkbox] {
|
& > input[type=checkbox] {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
margin-right: .6em;
|
margin-right: .6em;
|
||||||
}
|
}
|
||||||
&:hover {
|
|
||||||
background-color: rgba(0, 0, 0, .1);
|
|
||||||
}
|
|
||||||
&.active {
|
&.active {
|
||||||
background-color: #3D3A3B;
|
background-color: #3D3A3B;
|
||||||
color: white;
|
color: white;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import "colors";
|
@import "effects";
|
||||||
|
|
||||||
.vn-grid {
|
.vn-grid {
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
|
@ -26,13 +26,8 @@
|
||||||
transition: background-color 200ms ease-in-out;
|
transition: background-color 200ms ease-in-out;
|
||||||
|
|
||||||
&.clickable {
|
&.clickable {
|
||||||
cursor: pointer;
|
@extend %clickable;
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: $hover;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
&.success {
|
&.success {
|
||||||
background-color: rgba(163, 209, 49, 0.3);
|
background-color: rgba(163, 209, 49, 0.3);
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ vn-icon-button {
|
||||||
color: rgba($main-01, 0.7);
|
color: rgba($main-01, 0.7);
|
||||||
transition: color 200ms ease-in-out;
|
transition: color 200ms ease-in-out;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&.button {
|
&.button {
|
||||||
background-color: $main-01;
|
background-color: $main-01;
|
||||||
color: white;
|
color: white;
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
import './icon-menu.js';
|
|
||||||
|
|
||||||
describe('Component vnIconMenu', () => {
|
|
||||||
let $componentController;
|
|
||||||
let $element;
|
|
||||||
let $httpBackend;
|
|
||||||
let $timeout;
|
|
||||||
let $scope;
|
|
||||||
let controller;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
angular.mock.module('client');
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$httpBackend_, _$timeout_) => {
|
|
||||||
$componentController = _$componentController_;
|
|
||||||
$httpBackend = _$httpBackend_;
|
|
||||||
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
|
||||||
$timeout = _$timeout_;
|
|
||||||
$scope = $rootScope.$new();
|
|
||||||
$element = angular.element('<div></div>');
|
|
||||||
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`, () => {
|
|
||||||
controller.url = undefined;
|
|
||||||
controller.items = undefined;
|
|
||||||
let result = controller.findItems('some search value');
|
|
||||||
|
|
||||||
expect(result).toEqual([]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should return items array if the controller does not provide a url`, () => {
|
|
||||||
controller.url = undefined;
|
|
||||||
controller.items = ['Batman', 'Bruce Wayne'];
|
|
||||||
controller.findItems('some search value');
|
|
||||||
|
|
||||||
expect(controller.items.length).toEqual(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it(`should perform a search and store the result in controller items`, () => {
|
|
||||||
let search = 'The Joker';
|
|
||||||
let json = JSON.stringify({where: {name: {regexp: search}}});
|
|
||||||
$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 call getItems function if there's no search value`, () => {
|
|
||||||
spyOn(controller, 'getItems');
|
|
||||||
controller.findItems();
|
|
||||||
|
|
||||||
expect(controller.getItems).toHaveBeenCalledWith();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
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();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,5 +1,8 @@
|
||||||
import './textfield/textfield';
|
import './model-proxy/model-proxy';
|
||||||
|
import './rest-model/crud-model';
|
||||||
|
import './rest-model/rest-model';
|
||||||
import './watcher/watcher';
|
import './watcher/watcher';
|
||||||
|
import './textfield/textfield';
|
||||||
import './paging/paging';
|
import './paging/paging';
|
||||||
import './icon/icon';
|
import './icon/icon';
|
||||||
import './dialog/dialog';
|
import './dialog/dialog';
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
import ngModule from '../../module';
|
||||||
|
|
||||||
|
export default class ModelProxy {
|
||||||
|
constructor() {
|
||||||
|
this._data = [];
|
||||||
|
this.resetChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
get orgData() {
|
||||||
|
return this._orgData;
|
||||||
|
}
|
||||||
|
|
||||||
|
set orgData(value) {
|
||||||
|
this._orgData = value;
|
||||||
|
this._data = [];
|
||||||
|
// this._data.splice(0, this._data.length);
|
||||||
|
|
||||||
|
for (let i = 0; i < value.length; i++) {
|
||||||
|
let row = new this.Row(value[i], i);
|
||||||
|
this._data.push(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.resetChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
get data() {
|
||||||
|
return this._data;
|
||||||
|
}
|
||||||
|
|
||||||
|
set data(value) {}
|
||||||
|
|
||||||
|
get fields() {
|
||||||
|
return this._fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
set fields(value) {
|
||||||
|
this._fields = value;
|
||||||
|
|
||||||
|
let Row = function(data, index) {
|
||||||
|
this.$data = data;
|
||||||
|
this.$index = index;
|
||||||
|
this.$oldData = null;
|
||||||
|
this.$isNew = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
for (let prop of value) {
|
||||||
|
Object.defineProperty(Row.prototype, prop, {
|
||||||
|
enumerable: true,
|
||||||
|
configurable: false,
|
||||||
|
set: function(value) {
|
||||||
|
if (!this.$isNew) {
|
||||||
|
if (!this.$oldData)
|
||||||
|
this.$oldData = {};
|
||||||
|
if (!this.$oldData[prop])
|
||||||
|
this.$oldData[prop] = this.$data[prop];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$data[prop] = value;
|
||||||
|
},
|
||||||
|
get: function() {
|
||||||
|
return this.$data[prop];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Row = Row;
|
||||||
|
}
|
||||||
|
|
||||||
|
remove(index) {
|
||||||
|
let data = this._data;
|
||||||
|
|
||||||
|
let item;
|
||||||
|
[item] = data.splice(index, 1);
|
||||||
|
|
||||||
|
for (let i = index; i < data.length; i++)
|
||||||
|
data[i].$index = i;
|
||||||
|
|
||||||
|
if (!item.$isNew)
|
||||||
|
this.removed.push(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
insert(data) {
|
||||||
|
data = Object.assign(data || {}, this.link);
|
||||||
|
let newRow = new this.Row(data, this._data.length);
|
||||||
|
newRow.$isNew = true;
|
||||||
|
return this._data.push(newRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
resetChanges() {
|
||||||
|
this.removed = [];
|
||||||
|
|
||||||
|
for (let row of this._data) {
|
||||||
|
row.$oldData = null;
|
||||||
|
row.$isNew = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
undoChanges() {
|
||||||
|
let data = this._data;
|
||||||
|
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
let row = data[i];
|
||||||
|
|
||||||
|
if (row.$oldData)
|
||||||
|
Object.assign(row.$data, row.$oldData);
|
||||||
|
if (row.$isNew)
|
||||||
|
data.splice(i--, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let row of this.removed)
|
||||||
|
data.splice(row.$index, 0, row);
|
||||||
|
|
||||||
|
this.resetChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ngModule.component('vnModelProxy', {
|
||||||
|
controller: ModelProxy,
|
||||||
|
bindings: {
|
||||||
|
orgData: '<?',
|
||||||
|
data: '=?',
|
||||||
|
fields: '<?',
|
||||||
|
link: '<?'
|
||||||
|
}
|
||||||
|
});
|
|
@ -0,0 +1,103 @@
|
||||||
|
import ngModule from '../../module';
|
||||||
|
import ModelProxy from '../model-proxy/model-proxy';
|
||||||
|
|
||||||
|
export default class CrudModel extends ModelProxy {
|
||||||
|
constructor($http, $q) {
|
||||||
|
super();
|
||||||
|
this.$http = $http;
|
||||||
|
this.$q = $q;
|
||||||
|
this.primaryKey = 'id';
|
||||||
|
this.autoLoad = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$onInit() {
|
||||||
|
if (this.autoLoad)
|
||||||
|
this.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
refresh() {
|
||||||
|
if (!this.url) return;
|
||||||
|
|
||||||
|
let filter = this.filter;
|
||||||
|
|
||||||
|
if (!filter) {
|
||||||
|
let where = Object.assign({}, this.link, this.where);
|
||||||
|
filter = {
|
||||||
|
fields: this.fields,
|
||||||
|
where: where,
|
||||||
|
include: this.include,
|
||||||
|
order: this.order,
|
||||||
|
limit: this.limit
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let urlFilter = encodeURIComponent(JSON.stringify(filter));
|
||||||
|
|
||||||
|
return this.$http.get(`${this.url}?filter=${urlFilter}`).then(res => {
|
||||||
|
this.orgData = res.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getChanges() {
|
||||||
|
let create = [];
|
||||||
|
let update = [];
|
||||||
|
let remove = [];
|
||||||
|
|
||||||
|
for (let row of this.removed)
|
||||||
|
remove.push(row.$data[this.primaryKey]);
|
||||||
|
|
||||||
|
for (let row of this._data) {
|
||||||
|
if (row.$isNew)
|
||||||
|
create.push(row.$data);
|
||||||
|
else if (row.$oldData)
|
||||||
|
update.push(row.$data);
|
||||||
|
}
|
||||||
|
|
||||||
|
let isChanged =
|
||||||
|
create.length > 0 ||
|
||||||
|
update.length > 0 ||
|
||||||
|
remove.length > 0;
|
||||||
|
|
||||||
|
if (!isChanged)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
let changes = {
|
||||||
|
create: create,
|
||||||
|
update: update,
|
||||||
|
delete: remove
|
||||||
|
};
|
||||||
|
|
||||||
|
return changes;
|
||||||
|
}
|
||||||
|
|
||||||
|
save(ignoreChanges) {
|
||||||
|
let changes = this.getChanges();
|
||||||
|
|
||||||
|
if (!changes)
|
||||||
|
return this.$q.resolve();
|
||||||
|
|
||||||
|
let url = this.saveUrl ? this.saveUrl : `${this.url}/crud`;
|
||||||
|
return this.$http.post(url, changes)
|
||||||
|
.then(() => this.resetChanges);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CrudModel.$inject = ['$http', '$q'];
|
||||||
|
|
||||||
|
ngModule.component('vnCrudModel', {
|
||||||
|
controller: CrudModel,
|
||||||
|
bindings: {
|
||||||
|
orgData: '<?',
|
||||||
|
data: '=?',
|
||||||
|
fields: '<?',
|
||||||
|
link: '<?',
|
||||||
|
url: '@?',
|
||||||
|
saveUrl: '@?',
|
||||||
|
where: '<?',
|
||||||
|
include: '<?',
|
||||||
|
order: '@?',
|
||||||
|
limit: '<?',
|
||||||
|
filter: '<?',
|
||||||
|
primaryKey: '@?',
|
||||||
|
autoLoad: '<?'
|
||||||
|
}
|
||||||
|
});
|
|
@ -1,6 +1,6 @@
|
||||||
import ngModule from '../../module';
|
import ngModule from '../../module';
|
||||||
|
|
||||||
export default class Model {
|
export default class RestModel {
|
||||||
constructor($http, $q, $filter) {
|
constructor($http, $q, $filter) {
|
||||||
this.$http = $http;
|
this.$http = $http;
|
||||||
this.$q = $q;
|
this.$q = $q;
|
||||||
|
@ -104,10 +104,10 @@ export default class Model {
|
||||||
this.onDataChange();
|
this.onDataChange();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Model.$inject = ['$http', '$q', '$filter'];
|
RestModel.$inject = ['$http', '$q', '$filter'];
|
||||||
|
|
||||||
ngModule.component('vnModel', {
|
ngModule.component('vnRestModel', {
|
||||||
controller: Model,
|
controller: RestModel,
|
||||||
bindings: {
|
bindings: {
|
||||||
url: '@?',
|
url: '@?',
|
||||||
staticData: '<?',
|
staticData: '<?',
|
|
@ -1,6 +1,6 @@
|
||||||
import './model.js';
|
import './rest-model.js';
|
||||||
|
|
||||||
describe('Component vnModel', () => {
|
describe('Component vnRestModel', () => {
|
||||||
let $componentController;
|
let $componentController;
|
||||||
let $httpBackend;
|
let $httpBackend;
|
||||||
let controller;
|
let controller;
|
||||||
|
@ -11,7 +11,7 @@ describe('Component vnModel', () => {
|
||||||
|
|
||||||
beforeEach(angular.mock.inject((_$componentController_, _$httpBackend_) => {
|
beforeEach(angular.mock.inject((_$componentController_, _$httpBackend_) => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
controller = $componentController('vnModel', {$httpBackend});
|
controller = $componentController('vnRestModel', {$httpBackend});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('set url', () => {
|
describe('set url', () => {
|
|
@ -41,9 +41,8 @@ vn-snackbar > div {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: $main-01;
|
color: $main-01;
|
||||||
padding: 1em;
|
padding: .5em;
|
||||||
margin: -1em;
|
margin: -.5em;
|
||||||
padding-left: 1.5em;
|
margin-left: .5em;
|
||||||
margin-left: 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -26,7 +26,8 @@ export default class Tooltip extends Component {
|
||||||
this.parent = parent;
|
this.parent = parent;
|
||||||
this.$element.addClass('show');
|
this.$element.addClass('show');
|
||||||
this.relocate();
|
this.relocate();
|
||||||
this.relocateTimeout = this.$timeout(() => this.relocate(), 200);
|
this.cancelTimeout();
|
||||||
|
this.relocateTimeout = this.$timeout(() => this.relocate(), 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,7 +35,10 @@ export default class Tooltip extends Component {
|
||||||
*/
|
*/
|
||||||
hide() {
|
hide() {
|
||||||
this.$element.removeClass('show');
|
this.$element.removeClass('show');
|
||||||
|
this.cancelTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
cancelTimeout() {
|
||||||
if (this.relocateTimeout) {
|
if (this.relocateTimeout) {
|
||||||
this.$timeout.cancel(this.relocateTimeout);
|
this.$timeout.cancel(this.relocateTimeout);
|
||||||
this.relocateTimeout = null;
|
this.relocateTimeout = null;
|
||||||
|
@ -102,6 +106,8 @@ export default class Tooltip extends Component {
|
||||||
}
|
}
|
||||||
calcCoords();
|
calcCoords();
|
||||||
|
|
||||||
|
// Overflow
|
||||||
|
|
||||||
let axisOverflow =
|
let axisOverflow =
|
||||||
axis == 'x' && (left < min || left > maxLeft) ||
|
axis == 'x' && (left < min || left > maxLeft) ||
|
||||||
axis == 'y' && (top < min || top > maxTop);
|
axis == 'y' && (top < min || top > maxTop);
|
||||||
|
@ -124,8 +130,6 @@ export default class Tooltip extends Component {
|
||||||
calcCoords();
|
calcCoords();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overflow
|
|
||||||
|
|
||||||
function range(coord, min, max) {
|
function range(coord, min, max) {
|
||||||
return Math.min(Math.max(coord, min), max);
|
return Math.min(Math.max(coord, min), max);
|
||||||
}
|
}
|
||||||
|
@ -186,7 +190,7 @@ export default class Tooltip extends Component {
|
||||||
this.arrow = arrow;
|
this.arrow = arrow;
|
||||||
}
|
}
|
||||||
|
|
||||||
$destroy() {
|
$onDestroy() {
|
||||||
this.hide();
|
this.hide();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import getModifiedData from '../../lib/modified';
|
||||||
import copyObject from '../../lib/copy';
|
import copyObject from '../../lib/copy';
|
||||||
import isEqual from '../../lib/equals';
|
import isEqual from '../../lib/equals';
|
||||||
import isFullEmpty from '../../lib/full-empty';
|
import isFullEmpty from '../../lib/full-empty';
|
||||||
|
import UserError from '../../lib/user-error';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that checks for changes on a specific model property and
|
* Component that checks for changes on a specific model property and
|
||||||
|
@ -12,14 +13,15 @@ import isFullEmpty from '../../lib/full-empty';
|
||||||
* properties are provided.
|
* properties are provided.
|
||||||
*/
|
*/
|
||||||
export default class Watcher extends Component {
|
export default class Watcher extends Component {
|
||||||
constructor($element, $scope, $state, $transitions, $http, vnApp, $translate, $attrs) {
|
constructor($element, $scope, $state, $transitions, $http, vnApp, $translate, $attrs, $q) {
|
||||||
super($element);
|
super($element);
|
||||||
this.$scope = $scope;
|
this.$ = $scope;
|
||||||
this.$state = $state;
|
this.$state = $state;
|
||||||
this.$http = $http;
|
this.$http = $http;
|
||||||
this.$translate = $translate;
|
this._ = $translate;
|
||||||
this.$attrs = $attrs;
|
this.$attrs = $attrs;
|
||||||
this.vnApp = vnApp;
|
this.vnApp = vnApp;
|
||||||
|
this.$q = $q;
|
||||||
|
|
||||||
this.state = null;
|
this.state = null;
|
||||||
this.deregisterCallback = $transitions.onStart({},
|
this.deregisterCallback = $transitions.onStart({},
|
||||||
|
@ -28,34 +30,38 @@ export default class Watcher extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
$onInit() {
|
||||||
if (this.get && this.url) {
|
if (this.get && this.url)
|
||||||
this.fetchData();
|
this.fetchData();
|
||||||
} else if (this.get && !this.url) {
|
else if (this.get && !this.url)
|
||||||
throw new Error('Error: Parameter url ommitted');
|
throw new Error('URL parameter ommitted');
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$onChanges(changes) {
|
$onChanges(changes) {
|
||||||
if (this.data) {
|
if (this.data)
|
||||||
this.updateOriginalData();
|
this.updateOriginalData();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
$onDestroy() {
|
$onDestroy() {
|
||||||
this.deregisterCallback();
|
this.deregisterCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get dirty() {
|
||||||
|
return this.form && this.form.$dirty || this.dataChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
dataChanged() {
|
||||||
|
let data = this.copyInNewObject(this.data);
|
||||||
|
return !isEqual(data, this.orgData);
|
||||||
|
}
|
||||||
|
|
||||||
fetchData() {
|
fetchData() {
|
||||||
let id = this.data[this.idField];
|
let id = this.data[this.idField];
|
||||||
// return new Promise((resolve, reject) => {
|
return this.$http.get(`${this.url}/${id}`).then(
|
||||||
this.$http.get(`${this.url}/${id}`).then(
|
|
||||||
json => {
|
json => {
|
||||||
this.data = copyObject(json.data);
|
this.data = copyObject(json.data);
|
||||||
this.updateOriginalData();
|
this.updateOriginalData();
|
||||||
}
|
}
|
||||||
// json => reject(json)
|
|
||||||
);
|
);
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,9 +70,10 @@ export default class Watcher extends Component {
|
||||||
* @return {Promise} The request promise
|
* @return {Promise} The request promise
|
||||||
*/
|
*/
|
||||||
submitBack() {
|
submitBack() {
|
||||||
return this.submit().then(
|
return this.submit().then(res => {
|
||||||
() => this.window.history.back()
|
this.window.history.back();
|
||||||
);
|
return res;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -77,9 +84,10 @@ export default class Watcher extends Component {
|
||||||
* @return {Promise} The request promise
|
* @return {Promise} The request promise
|
||||||
*/
|
*/
|
||||||
submitGo(state, params) {
|
submitGo(state, params) {
|
||||||
return this.submit().then(
|
return this.submit().then(res => {
|
||||||
() => this.$state.go(state, params || {})
|
this.$state.go(state, params || {});
|
||||||
);
|
return res;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,89 +96,107 @@ export default class Watcher extends Component {
|
||||||
* @return {Promise} The http request promise
|
* @return {Promise} The http request promise
|
||||||
*/
|
*/
|
||||||
submit() {
|
submit() {
|
||||||
if (this.form) {
|
try {
|
||||||
|
this.check();
|
||||||
|
} catch (err) {
|
||||||
|
return this.$q.reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.realSubmit().then(res => {
|
||||||
|
this.notifySaved();
|
||||||
|
return res;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submits the data without checking data validity or changes.
|
||||||
|
*
|
||||||
|
* @return {Promise} The http request promise
|
||||||
|
*/
|
||||||
|
realSubmit() {
|
||||||
|
if (this.form)
|
||||||
this.form.$setSubmitted();
|
this.form.$setSubmitted();
|
||||||
|
|
||||||
if (!this.form.$valid)
|
|
||||||
return new Promise(
|
|
||||||
(resolve, reject) => this.invalidForm(reject)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (!this.dataChanged()) {
|
if (!this.dataChanged()) {
|
||||||
return new Promise(
|
this.updateOriginalData();
|
||||||
(resolve, reject) => this.noChanges(reject)
|
return this.$q.resolve();
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let isPost = (this.$attrs.save && this.$attrs.save.toLowerCase() === 'post');
|
let isPost = (this.$attrs.save && this.$attrs.save.toLowerCase() === 'post');
|
||||||
let changedData = isPost
|
let changedData = isPost
|
||||||
? this.data
|
? this.data
|
||||||
: getModifiedData(this.data, this.orgData);
|
: getModifiedData(this.data, this.orgData);
|
||||||
|
|
||||||
if (this.requiredField && !changedData[this.requiredField]) {
|
|
||||||
let required = this.data[this.requiredField] || this.orgData[this.requiredField];
|
|
||||||
if (required === undefined) {
|
|
||||||
return new Promise(
|
|
||||||
(resolve, reject) => this.invalidForm(reject)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
changedData[this.requiredField] = required;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.save && this.save.accept) {
|
|
||||||
this.save.model = changedData; // this.copyInNewObject(changedData);
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.save.accept().then(
|
|
||||||
json => this.writeData({data: json}, resolve),
|
|
||||||
json => reject(json)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// XXX: Alternative when mgCrud is not used
|
|
||||||
|
|
||||||
let id = this.idField ? this.orgData[this.idField] : null;
|
let id = this.idField ? this.orgData[this.idField] : null;
|
||||||
|
|
||||||
if (id) {
|
// If watcher is associated to mgCrud
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
this.$http.patch(`${this.url}/${id}`, changedData).then(
|
if (this.save && this.save.accept) {
|
||||||
json => this.writeData(json, resolve),
|
if (id)
|
||||||
json => reject(json)
|
changedData[this.idField] = id;
|
||||||
|
|
||||||
|
this.save.model = changedData;
|
||||||
|
return this.$q((resolve, reject) => {
|
||||||
|
this.save.accept().then(
|
||||||
|
json => this.writeData({data: json}, resolve),
|
||||||
|
reject
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
// When mgCrud is not used
|
||||||
this.$http.post(this.url, changedData).then(
|
|
||||||
|
if (id) {
|
||||||
|
return this.$q((resolve, reject) => {
|
||||||
|
this.$http.patch(`${this.url}/${id}`, changedData).then(
|
||||||
json => this.writeData(json, resolve),
|
json => this.writeData(json, resolve),
|
||||||
json => reject(json)
|
reject
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return this.$q((resolve, reject) => {
|
||||||
|
this.$http.post(this.url, changedData).then(
|
||||||
|
json => this.writeData(json, resolve),
|
||||||
|
reject
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if data is ready to send.
|
||||||
|
*/
|
||||||
|
check() {
|
||||||
|
if (this.form && this.form.$invalid)
|
||||||
|
throw new UserError(this._.instant('Some fields are invalid'));
|
||||||
|
if (!this.dirty)
|
||||||
|
throw new UserError(this._.instant('No changes to save'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the user that the data has been saved.
|
||||||
|
*/
|
||||||
|
notifySaved() {
|
||||||
|
this.vnApp.showMessage(this._.instant('Data saved!'));
|
||||||
|
}
|
||||||
|
|
||||||
writeData(json, resolve) {
|
writeData(json, resolve) {
|
||||||
Object.assign(this.data, json.data);
|
Object.assign(this.data, json.data);
|
||||||
this.updateOriginalData();
|
this.updateOriginalData();
|
||||||
resolve(json);
|
resolve(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
noChanges(reject) {
|
|
||||||
this.vnApp.showMessage(
|
|
||||||
this.$translate.instant('No changes to save')
|
|
||||||
);
|
|
||||||
reject(new Error('No changes to save'));
|
|
||||||
}
|
|
||||||
|
|
||||||
invalidForm(reject) {
|
|
||||||
this.vnApp.showMessage(
|
|
||||||
this.$translate.instant('Some fields are invalid')
|
|
||||||
);
|
|
||||||
reject(new Error('Some fields are invalid'));
|
|
||||||
}
|
|
||||||
|
|
||||||
updateOriginalData() {
|
updateOriginalData() {
|
||||||
this.orgData = this.copyInNewObject(this.data);
|
this.orgData = this.copyInNewObject(this.data);
|
||||||
if (this.form && this.form.$dirty)
|
this.setPristine();
|
||||||
this.form.$setPristine();
|
}
|
||||||
|
|
||||||
|
setPristine() {
|
||||||
|
if (this.form) this.form.$setPristine();
|
||||||
|
}
|
||||||
|
|
||||||
|
setDirty() {
|
||||||
|
if (this.form) this.form.$setDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
copyInNewObject(data) {
|
copyInNewObject(data) {
|
||||||
|
@ -192,22 +218,15 @@ export default class Watcher extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(transition) {
|
callback(transition) {
|
||||||
let dataChanged = this.dataChanged();
|
if (!this.state && this.dirty) {
|
||||||
if (!this.state && dataChanged) {
|
|
||||||
this.state = transition.to().name;
|
this.state = transition.to().name;
|
||||||
this.$scope.confirm.show();
|
this.$.confirm.show();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
dataChanged() {
|
|
||||||
let newData = this.copyInNewObject(this.data);
|
|
||||||
if (this.form && this.form.$dirty) return !isEqual(newData, this.orgData);
|
|
||||||
return !isEqual(newData, this.orgData);
|
|
||||||
}
|
|
||||||
|
|
||||||
onConfirmResponse(response) {
|
onConfirmResponse(response) {
|
||||||
if (response === 'ACCEPT') {
|
if (response === 'ACCEPT') {
|
||||||
if (this.data)
|
if (this.data)
|
||||||
|
@ -218,18 +237,17 @@ export default class Watcher extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Watcher.$inject = ['$element', '$scope', '$state', '$transitions', '$http', 'vnApp', '$translate', '$attrs'];
|
Watcher.$inject = ['$element', '$scope', '$state', '$transitions', '$http', 'vnApp', '$translate', '$attrs', '$q'];
|
||||||
|
|
||||||
ngModule.component('vnWatcher', {
|
ngModule.component('vnWatcher', {
|
||||||
template: require('./watcher.html'),
|
template: require('./watcher.html'),
|
||||||
bindings: {
|
bindings: {
|
||||||
url: '@?',
|
url: '@?',
|
||||||
idField: '@?',
|
idField: '@?',
|
||||||
requiredField: '@?',
|
|
||||||
data: '<',
|
data: '<',
|
||||||
form: '<',
|
form: '<',
|
||||||
save: '<',
|
save: '<',
|
||||||
get: '=?'
|
get: '<?'
|
||||||
},
|
},
|
||||||
controller: Watcher
|
controller: Watcher
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,6 +3,7 @@ import getModifiedData from '../../lib/modified';
|
||||||
|
|
||||||
describe('Component vnWatcher', () => {
|
describe('Component vnWatcher', () => {
|
||||||
let $componentController;
|
let $componentController;
|
||||||
|
let $rootScope;
|
||||||
let $scope;
|
let $scope;
|
||||||
let $element;
|
let $element;
|
||||||
let $state;
|
let $state;
|
||||||
|
@ -12,25 +13,28 @@ describe('Component vnWatcher', () => {
|
||||||
let $translate;
|
let $translate;
|
||||||
let controller;
|
let controller;
|
||||||
let $attrs;
|
let $attrs;
|
||||||
|
let $q;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
angular.mock.module('client');
|
angular.mock.module('client');
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$state_, _$transitions_, _$httpBackend_, _vnApp_, _$translate_) => {
|
beforeEach(angular.mock.inject((_$componentController_, _$rootScope_, _$state_, _$transitions_, _$httpBackend_, _vnApp_, _$translate_, _$q_) => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
|
$rootScope = _$rootScope_;
|
||||||
$scope = $rootScope.$new();
|
$scope = $rootScope.$new();
|
||||||
$element = angular.element('<div></div>');
|
$element = angular.element('<div></div>');
|
||||||
$state = _$state_;
|
$state = _$state_;
|
||||||
vnApp = _vnApp_;
|
vnApp = _vnApp_;
|
||||||
$transitions = _$transitions_;
|
$transitions = _$transitions_;
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
|
||||||
$translate = _$translate_;
|
$translate = _$translate_;
|
||||||
|
$q = _$q_;
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
$attrs = {
|
$attrs = {
|
||||||
save: "patch"
|
save: "patch"
|
||||||
};
|
};
|
||||||
controller = $componentController('vnWatcher', {$scope, $element, $state, vnApp, $transitions, $httpBackend, $translate, $attrs});
|
controller = $componentController('vnWatcher', {$scope, $element, $state, vnApp, $transitions, $httpBackend, $translate, $attrs, $q});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('$onInit()', () => {
|
describe('$onInit()', () => {
|
||||||
|
@ -48,26 +52,7 @@ describe('Component vnWatcher', () => {
|
||||||
|
|
||||||
expect(function() {
|
expect(function() {
|
||||||
controller.$onInit();
|
controller.$onInit();
|
||||||
}).toThrow(new Error('Error: Parameter url ommitted'));
|
}).toThrowError(/parameter/);
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
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();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -115,61 +100,51 @@ describe('Component vnWatcher', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('submit()', () => {
|
describe('check()', () => {
|
||||||
|
it(`should throw error if controller.form is invalid`, () => {
|
||||||
|
controller.form = {$invalid: true};
|
||||||
|
|
||||||
|
expect(function() {
|
||||||
|
controller.check();
|
||||||
|
}).toThrowError();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should throw error if controller.dirty is true`, () => {
|
||||||
|
controller.form = {$invalid: true};
|
||||||
|
|
||||||
|
expect(function() {
|
||||||
|
controller.check();
|
||||||
|
}).toThrowError();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('realSubmit()', () => {
|
||||||
describe('when controller.form', () => {
|
describe('when controller.form', () => {
|
||||||
it(`should call controller.form.setSubminted if controller.form is defined`, () => {
|
it(`should call controller.form.setSubmited if controller.form is defined`, () => {
|
||||||
controller.form = {$setSubmitted: () => {}};
|
controller.form = {
|
||||||
|
$setSubmitted: () => {},
|
||||||
|
$setPristine: () => {}
|
||||||
|
};
|
||||||
spyOn(controller.form, '$setSubmitted');
|
spyOn(controller.form, '$setSubmitted');
|
||||||
controller.submit();
|
controller.realSubmit();
|
||||||
|
|
||||||
expect(controller.form.$setSubmitted).toHaveBeenCalledWith();
|
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()', () => {
|
describe('when controller.save()', () => {
|
||||||
it(`should set controller.save.model property`, () => {
|
it(`should set controller.save.model property`, () => {
|
||||||
controller.save = {accept: () => {}};
|
controller.save = {accept: () => $q.resolve()};
|
||||||
controller.data = {originalInfo: 'original data', info: 'new data'};
|
controller.data = {originalInfo: 'original data', info: 'new data'};
|
||||||
controller.orgData = {originalInfo: 'original data'};
|
controller.orgData = {originalInfo: 'original data'};
|
||||||
controller.submit();
|
controller.realSubmit();
|
||||||
|
|
||||||
expect(controller.save.model).toEqual({info: 'new data'});
|
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', () => {
|
describe('when id is defined', () => {
|
||||||
it(`should perform a query then call controller.writeData()`, () => {
|
it(`should perform a query then call controller.writeData()`, done => {
|
||||||
controller.dataChanged = () => {
|
controller.dataChanged = () => {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
@ -182,7 +157,7 @@ describe('Component vnWatcher', () => {
|
||||||
spyOn(controller, 'writeData').and.callThrough();
|
spyOn(controller, 'writeData').and.callThrough();
|
||||||
$httpBackend.whenPATCH(`${controller.url}/1`, changedData).respond(json);
|
$httpBackend.whenPATCH(`${controller.url}/1`, changedData).respond(json);
|
||||||
$httpBackend.expectPATCH(`${controller.url}/1`);
|
$httpBackend.expectPATCH(`${controller.url}/1`);
|
||||||
controller.submit()
|
controller.realSubmit()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
expect(controller.writeData).toHaveBeenCalledWith(jasmine.any(Object), jasmine.any(Function));
|
expect(controller.writeData).toHaveBeenCalledWith(jasmine.any(Object), jasmine.any(Function));
|
||||||
done();
|
done();
|
||||||
|
@ -191,7 +166,7 @@ describe('Component vnWatcher', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should perform a POST query then call controller.writeData()`, () => {
|
it(`should perform a POST query then call controller.writeData()`, done => {
|
||||||
controller.dataChanged = () => {
|
controller.dataChanged = () => {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
@ -202,7 +177,7 @@ describe('Component vnWatcher', () => {
|
||||||
spyOn(controller, 'writeData').and.callThrough();
|
spyOn(controller, 'writeData').and.callThrough();
|
||||||
$httpBackend.whenPOST(`${controller.url}`, controller.data).respond(json);
|
$httpBackend.whenPOST(`${controller.url}`, controller.data).respond(json);
|
||||||
$httpBackend.expectPOST(`${controller.url}`, controller.data);
|
$httpBackend.expectPOST(`${controller.url}`, controller.data);
|
||||||
controller.submit()
|
controller.realSubmit()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
expect(controller.writeData).toHaveBeenCalledWith(jasmine.any(Object), jasmine.any(Function));
|
expect(controller.writeData).toHaveBeenCalledWith(jasmine.any(Object), jasmine.any(Function));
|
||||||
done();
|
done();
|
||||||
|
@ -224,18 +199,9 @@ describe('Component vnWatcher', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
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('callback()', () => {
|
||||||
describe(`when dataChanged() returns true and there's no state in the controller`, () => {
|
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`, () => {
|
it(`should define controller.state, call controller.$.confirm.show() and return false`, () => {
|
||||||
$scope.confirm = {show: jasmine.createSpy('show')};
|
$scope.confirm = {show: jasmine.createSpy('show')};
|
||||||
controller.dataChanged = () => {
|
controller.dataChanged = () => {
|
||||||
return true;
|
return true;
|
||||||
|
@ -247,7 +213,7 @@ describe('Component vnWatcher', () => {
|
||||||
let result = controller.callback(transition);
|
let result = controller.callback(transition);
|
||||||
|
|
||||||
expect(controller.state).toEqual('Batman');
|
expect(controller.state).toEqual('Batman');
|
||||||
expect(controller.$scope.confirm.show).toHaveBeenCalledWith();
|
expect(controller.$.confirm.show).toHaveBeenCalledWith();
|
||||||
expect(result).toBeFalsy();
|
expect(result).toBeFalsy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,9 +9,10 @@ describe('Directive zoomImage', () => {
|
||||||
angular.mock.module('client');
|
angular.mock.module('client');
|
||||||
});
|
});
|
||||||
|
|
||||||
beforeEach(angular.mock.inject(($compile, $rootScope) => {
|
beforeEach(angular.mock.inject(($compile, $rootScope, $httpBackend) => {
|
||||||
compile = $compile;
|
compile = $compile;
|
||||||
scope = $rootScope.$new();
|
scope = $rootScope.$new();
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|
|
@ -7,9 +7,9 @@ import ngModule from '../module';
|
||||||
* @property {Snackbar} snackbar The main object to show messages.
|
* @property {Snackbar} snackbar The main object to show messages.
|
||||||
*/
|
*/
|
||||||
export default class App {
|
export default class App {
|
||||||
constructor($rootScope) {
|
constructor() {
|
||||||
this.loaderStatus = 0;
|
this.loaderStatus = 0;
|
||||||
this.$rootScope = $rootScope;
|
this.loading = false;
|
||||||
}
|
}
|
||||||
showMessage(message) {
|
showMessage(message) {
|
||||||
if (this.snackbar)
|
if (this.snackbar)
|
||||||
|
@ -22,14 +22,13 @@ export default class App {
|
||||||
pushLoader() {
|
pushLoader() {
|
||||||
this.loaderStatus++;
|
this.loaderStatus++;
|
||||||
if (this.loaderStatus === 1)
|
if (this.loaderStatus === 1)
|
||||||
this.$rootScope.loading = true;
|
this.loading = true;
|
||||||
}
|
}
|
||||||
popLoader() {
|
popLoader() {
|
||||||
this.loaderStatus--;
|
this.loaderStatus--;
|
||||||
if (this.loaderStatus === 0)
|
if (this.loaderStatus === 0)
|
||||||
this.$rootScope.loading = false;
|
this.loading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
App.$inject = ['$rootScope'];
|
|
||||||
|
|
||||||
ngModule.service('vnApp', App);
|
ngModule.service('vnApp', App);
|
||||||
|
|
|
@ -12,10 +12,10 @@ export function toJsonDate(date) {
|
||||||
let year = date.getFullYear();
|
let year = date.getFullYear();
|
||||||
|
|
||||||
if (day < 10)
|
if (day < 10)
|
||||||
day = `0${day}`
|
day = `0${day}`;
|
||||||
|
|
||||||
if (month < 10)
|
if (month < 10)
|
||||||
month = `0${month}`
|
month = `0${month}`;
|
||||||
|
|
||||||
return new Date(`${year}-${month}-${day}`);
|
return new Date(`${year}-${month}-${day}`);
|
||||||
}
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
/**
|
||||||
|
* Wraps $http error responses. This class is mainly used to
|
||||||
|
* avoid the default AngularJS behaviour, that is, stringifying all
|
||||||
|
* unhandled rejections that aren't @Error objects. More info at:
|
||||||
|
* - https://github.com/angular/angular.js/issues/14631
|
||||||
|
*/
|
||||||
|
export default class HttpError extends Error {
|
||||||
|
constructor(message, fileName, lineNumber) {
|
||||||
|
super(message, fileName, lineNumber);
|
||||||
|
this.name = 'HttpError';
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,3 +13,5 @@ import './equals';
|
||||||
import './modified';
|
import './modified';
|
||||||
import './key-codes';
|
import './key-codes';
|
||||||
import './get-watchers';
|
import './get-watchers';
|
||||||
|
import './http-error';
|
||||||
|
import './user-error';
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
|
import HttpError from './http-error';
|
||||||
|
|
||||||
interceptor.$inject = ['$q', '$window', 'vnApp', '$translate', '$cookies'];
|
interceptor.$inject = ['$q', 'vnApp', '$cookies'];
|
||||||
function interceptor($q, $window, vnApp, $translate, $cookies) {
|
function interceptor($q, vnApp, $cookies) {
|
||||||
return {
|
return {
|
||||||
request: function(config) {
|
request: function(config) {
|
||||||
vnApp.pushLoader();
|
vnApp.pushLoader();
|
||||||
|
@ -16,42 +17,14 @@ function interceptor($q, $window, vnApp, $translate, $cookies) {
|
||||||
return $q.reject(rejection);
|
return $q.reject(rejection);
|
||||||
},
|
},
|
||||||
response: function(response) {
|
response: function(response) {
|
||||||
switch (response.config.method) {
|
|
||||||
case 'PUT':
|
|
||||||
case 'POST':
|
|
||||||
case 'PATCH':
|
|
||||||
vnApp.showMessage($translate.instant('Data saved!'));
|
|
||||||
}
|
|
||||||
vnApp.popLoader();
|
vnApp.popLoader();
|
||||||
return response;
|
return response;
|
||||||
},
|
},
|
||||||
responseError: function(rejection) {
|
responseError: function(rejection) {
|
||||||
vnApp.popLoader();
|
vnApp.popLoader();
|
||||||
let data = rejection.data;
|
let err = new HttpError(rejection.statusText);
|
||||||
let error;
|
Object.assign(err, rejection);
|
||||||
|
return $q.reject(err);
|
||||||
switch (rejection.xhrStatus) {
|
|
||||||
case 'timeout':
|
|
||||||
case 'abort':
|
|
||||||
return $q.reject(rejection);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data && data.error instanceof Object)
|
|
||||||
error = data.error.message;
|
|
||||||
else if (rejection.status === -1)
|
|
||||||
error = $translate.instant(`Can't contact with server`);
|
|
||||||
else
|
|
||||||
error = `${rejection.status}: ${rejection.statusText}`;
|
|
||||||
|
|
||||||
if (rejection.status === 401) {
|
|
||||||
let location = $window.location;
|
|
||||||
let continueUrl = location.pathname + location.search + location.hash;
|
|
||||||
continueUrl = encodeURIComponent(continueUrl);
|
|
||||||
$window.location = `/auth/?apiKey=${vnApp.name}&continue=${continueUrl}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
vnApp.showError(error);
|
|
||||||
return $q.reject(rejection);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
/**
|
||||||
|
* Errors that can be visible and understood by the end user.
|
||||||
|
* Used mainly in the global error handler.
|
||||||
|
*/
|
||||||
|
export default class UserError extends Error {
|
||||||
|
constructor(message, fileName, lineNumber) {
|
||||||
|
super(message, fileName, lineNumber);
|
||||||
|
this.name = 'UserError';
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,8 +15,12 @@ describe('Item', () => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$state = _$state_;
|
$state = _$state_;
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
$state.params.id = '1';
|
$state.params.id = '1';
|
||||||
controller = $componentController('vnItemBarcode', {$state: $state});
|
controller = $componentController('vnItemBarcode', {$state: $state});
|
||||||
|
controller.$scope.watcher = {
|
||||||
|
notifySaved: () => {}
|
||||||
|
};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('add / remove barcode()', () => {
|
describe('add / remove barcode()', () => {
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
<vn-watcher
|
||||||
|
vn-id="watcher"
|
||||||
|
form="form">
|
||||||
|
</vn-watcher>
|
||||||
<form name="form" ng-submit="$ctrl.submit()">
|
<form name="form" ng-submit="$ctrl.submit()">
|
||||||
<vn-card pad-large>
|
<vn-card pad-large>
|
||||||
<vn-title>Item barcode</vn-title>
|
<vn-title>Item barcode</vn-title>
|
||||||
|
|
|
@ -95,6 +95,7 @@ export default class Controller {
|
||||||
return this.$http.post(`/item/api/ItemBarcodes/crudItemBarcodes`, barcodesObj).then(() => {
|
return this.$http.post(`/item/api/ItemBarcodes/crudItemBarcodes`, barcodesObj).then(() => {
|
||||||
this.getBarcodes();
|
this.getBarcodes();
|
||||||
this._unsetDirtyForm();
|
this._unsetDirtyForm();
|
||||||
|
this.$scope.watcher.notifySaved();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.vnApp.showMessage(this.$translate.instant('No changes to save'));
|
this.vnApp.showMessage(this.$translate.instant('No changes to save'));
|
||||||
|
|
|
@ -14,6 +14,7 @@ describe('ItemBotanical', () => {
|
||||||
beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => {
|
beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
$state = {
|
$state = {
|
||||||
params: {
|
params: {
|
||||||
id: 123
|
id: 123
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
vn-id="watcher"
|
vn-id="watcher"
|
||||||
data="$ctrl.botanical"
|
data="$ctrl.botanical"
|
||||||
id-field="itemFk"
|
id-field="itemFk"
|
||||||
required-field="itemFk"
|
|
||||||
form="form"
|
form="form"
|
||||||
save="patch">
|
save="patch">
|
||||||
</vn-watcher>
|
</vn-watcher>
|
||||||
|
|
|
@ -4,6 +4,9 @@ class Controller {
|
||||||
constructor($http, $state) {
|
constructor($http, $state) {
|
||||||
this.$http = $http;
|
this.$http = $http;
|
||||||
this.$state = $state;
|
this.$state = $state;
|
||||||
|
this.botanical = {
|
||||||
|
itemFk: this.$state.params.id
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
_getBotanical() {
|
_getBotanical() {
|
||||||
|
@ -13,16 +16,8 @@ class Controller {
|
||||||
};
|
};
|
||||||
this.$http.get(`/item/api/ItemBotanicals?filter=${JSON.stringify(filter)}`)
|
this.$http.get(`/item/api/ItemBotanicals?filter=${JSON.stringify(filter)}`)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
if (res.data.length) {
|
if (res.data.length)
|
||||||
this.botanical = res.data[0];
|
this.botanical = res.data[0];
|
||||||
} else {
|
|
||||||
this.botanical = {
|
|
||||||
itemFk: this.$state.params.id,
|
|
||||||
botanical: null,
|
|
||||||
genusFk: null,
|
|
||||||
specieFk: null
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ describe('Item', () => {
|
||||||
beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => {
|
beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
$state = {
|
$state = {
|
||||||
params: {
|
params: {
|
||||||
id: 123
|
id: 123
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
save="post">
|
save="post">
|
||||||
</vn-watcher>
|
</vn-watcher>
|
||||||
<form name="form" ng-submit="$ctrl.onSubmit()" margin-medium>
|
<form name="form" ng-submit="$ctrl.onSubmit()" margin-medium>
|
||||||
<div style="max-width: 70em; margin: 0 auto;">
|
<div style="max-width: 50em; margin: 0 auto;">
|
||||||
<vn-card pad-large>
|
<vn-card pad-large>
|
||||||
<vn-title>New item</vn-title>
|
<vn-title>New item</vn-title>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
|
@ -20,7 +20,10 @@
|
||||||
value-field="id"
|
value-field="id"
|
||||||
field="$ctrl.item.typeFk"
|
field="$ctrl.item.typeFk"
|
||||||
where="{or: [{code: {regexp: 'search'}}, {name: {regexp: 'search'}}]}">
|
where="{or: [{code: {regexp: 'search'}}, {name: {regexp: 'search'}}]}">
|
||||||
<tpl-item>{{code}} : {{name}}</tpl-item>
|
<tpl-item style="display: flex;">
|
||||||
|
<div style="width: 3em; padding-right: 1em;">{{::code}}</div>
|
||||||
|
<div>{{::name}}</div>
|
||||||
|
</tpl-item>
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
<vn-autocomplete vn-one
|
<vn-autocomplete vn-one
|
||||||
url="/item/api/Intrastats"
|
url="/item/api/Intrastats"
|
||||||
|
@ -29,7 +32,10 @@
|
||||||
value-field="id"
|
value-field="id"
|
||||||
field="$ctrl.item.intrastatFk"
|
field="$ctrl.item.intrastatFk"
|
||||||
where="{or: [{id: {regexp: 'search'}}, {description: {regexp: 'search'}}]}">
|
where="{or: [{id: {regexp: 'search'}}, {description: {regexp: 'search'}}]}">
|
||||||
<tpl-item>{{id}} : {{description}}</tpl-item>
|
<tpl-item style="display: flex;">
|
||||||
|
<div style="width: 6em; text-align: right; padding-right: 1em;">{{::id}}</div>
|
||||||
|
<div>{{::description}}</div>
|
||||||
|
</tpl-item>
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-horizontal>
|
<vn-horizontal>
|
||||||
|
|
|
@ -32,7 +32,10 @@
|
||||||
field="$ctrl.item.intrastatFk"
|
field="$ctrl.item.intrastatFk"
|
||||||
where="{or: [{id: {regexp: 'search'}}, {description: {regexp: 'search'}}]}"
|
where="{or: [{id: {regexp: 'search'}}, {description: {regexp: 'search'}}]}"
|
||||||
initial-data="$ctrl.item.intrastat">
|
initial-data="$ctrl.item.intrastat">
|
||||||
<tpl-item>{{id}} : {{description}}</tpl-item>
|
<tpl-item style="display: flex;">
|
||||||
|
<div style="width: 6em; text-align: right; padding-right: 1em;">{{::id}}</div>
|
||||||
|
<div>{{::description}}</div>
|
||||||
|
</tpl-item>
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
<vn-textfield vn-one label="Relevancy" field="$ctrl.item.relevancy" type="number"></vn-textfield>
|
<vn-textfield vn-one label="Relevancy" field="$ctrl.item.relevancy" type="number"></vn-textfield>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
|
@ -45,13 +48,19 @@
|
||||||
field="$ctrl.item.originFk"
|
field="$ctrl.item.originFk"
|
||||||
initial-data="$ctrl.item.origin">
|
initial-data="$ctrl.item.origin">
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
|
<vn-textfield
|
||||||
|
vn-one
|
||||||
|
label="Reference"
|
||||||
|
field="$ctrl.item.description">
|
||||||
|
</vn-textfield>
|
||||||
|
</vn-horizontal>
|
||||||
|
<vn-horizontal>
|
||||||
<vn-autocomplete vn-one
|
<vn-autocomplete vn-one
|
||||||
url="/item/api/Expences"
|
url="/item/api/Expences"
|
||||||
label="Expence"
|
label="Expence"
|
||||||
field="$ctrl.item.expenceFk"
|
field="$ctrl.item.expenceFk"
|
||||||
initial-data="$ctrl.item.expence">
|
initial-data="$ctrl.item.expence">
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
<vn-textfield vn-one label="Reference" field="$ctrl.item.description"></vn-textfield>
|
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
<vn-button-bar>
|
<vn-button-bar>
|
||||||
|
|
|
@ -14,6 +14,11 @@ export default class Controller {
|
||||||
this.oldNiches = {};
|
this.oldNiches = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$onInit() {
|
||||||
|
this.getNiches();
|
||||||
|
this.getWarehouses();
|
||||||
|
}
|
||||||
|
|
||||||
_setIconAdd() {
|
_setIconAdd() {
|
||||||
if (this.niches.length) {
|
if (this.niches.length) {
|
||||||
this.niches.map(element => {
|
this.niches.map(element => {
|
||||||
|
@ -130,15 +135,11 @@ export default class Controller {
|
||||||
return this.$http.post(`/item/api/ItemNiches/crudItemNiches`, nichesObj).then(() => {
|
return this.$http.post(`/item/api/ItemNiches/crudItemNiches`, nichesObj).then(() => {
|
||||||
this.getNiches();
|
this.getNiches();
|
||||||
this._unsetDirtyForm();
|
this._unsetDirtyForm();
|
||||||
|
this.$scope.watcher.notifySaved();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.vnApp.showMessage(this.$translate.instant('No changes to save'));
|
this.vnApp.showMessage(this.$translate.instant('No changes to save'));
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
|
||||||
this.getNiches();
|
|
||||||
this.getWarehouses();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$stateParams', '$scope', '$http', '$translate', 'vnApp'];
|
Controller.$inject = ['$stateParams', '$scope', '$http', '$translate', 'vnApp'];
|
||||||
|
|
|
@ -15,7 +15,11 @@ describe('Item', () => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$state = _$state_;
|
$state = _$state_;
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
controller = $componentController('vnItemNiche', {$state: $state});
|
controller = $componentController('vnItemNiche', {$state: $state});
|
||||||
|
controller.$scope.watcher = {
|
||||||
|
notifySaved: () => {}
|
||||||
|
};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('add / remove niche', () => {
|
describe('add / remove niche', () => {
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<form name="form" ng-submit="$ctrl.submit()">
|
<form name="form" ng-submit="$ctrl.submit()">
|
||||||
<vn-card pad-large>
|
<vn-card pad-large>
|
||||||
<vn-title>Item tags</vn-title>
|
<vn-title>Item tags</vn-title>
|
||||||
<vn-horizontal ng-repeat="itemTag in $ctrl.instancedItemTags">
|
<vn-horizontal ng-repeat="itemTag in $ctrl.tags">
|
||||||
<vn-autocomplete
|
<vn-autocomplete
|
||||||
vn-id="tag"
|
vn-id="tag"
|
||||||
vn-one
|
vn-one
|
||||||
|
@ -15,7 +15,7 @@
|
||||||
data="tags.model"
|
data="tags.model"
|
||||||
show-field="name"
|
show-field="name"
|
||||||
label="Tag"
|
label="Tag"
|
||||||
on-change="$ctrl.checkAutocompleteChanges(itemTag)"
|
on-change="itemTag.value = null"
|
||||||
vn-acl="buyer"
|
vn-acl="buyer"
|
||||||
vn-focus
|
vn-focus
|
||||||
disabled="itemTag.id != null">
|
disabled="itemTag.id != null">
|
||||||
|
@ -54,7 +54,7 @@
|
||||||
medium-grey
|
medium-grey
|
||||||
vn-tooltip="Remove tag"
|
vn-tooltip="Remove tag"
|
||||||
icon="remove_circle_outline"
|
icon="remove_circle_outline"
|
||||||
ng-click="$ctrl.removeItemTag($index)">
|
ng-click="$ctrl.removeTag($index)">
|
||||||
</vn-icon>
|
</vn-icon>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<vn-one>
|
<vn-one>
|
||||||
|
@ -62,7 +62,7 @@
|
||||||
vn-bind="+"
|
vn-bind="+"
|
||||||
vn-tooltip="Add tag"
|
vn-tooltip="Add tag"
|
||||||
icon="add_circle"
|
icon="add_circle"
|
||||||
ng-click="$ctrl.addItemTag()">
|
ng-click="$ctrl.addTag()">
|
||||||
</vn-icon-button>
|
</vn-icon-button>
|
||||||
</vn-one>
|
</vn-one>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
|
|
|
@ -1,71 +1,63 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
|
|
||||||
class Controller {
|
class Controller {
|
||||||
constructor($stateParams, $scope, $http, $translate, vnApp) {
|
constructor($stateParams, $scope, $http) {
|
||||||
this.params = $stateParams;
|
this.params = $stateParams;
|
||||||
this.$scope = $scope;
|
this.$ = $scope;
|
||||||
this.$http = $http;
|
this.$http = $http;
|
||||||
this.$translate = $translate;
|
this.tags = [];
|
||||||
this.vnApp = vnApp;
|
this.removedTags = [];
|
||||||
|
|
||||||
this.itemTagTypes = [];
|
|
||||||
this.removedItemTags = [];
|
|
||||||
this.oldItemTags = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_setIconAdd() {
|
$onInit() {
|
||||||
if (this.instancedItemTags && this.instancedItemTags.length) {
|
this.getTags();
|
||||||
this.instancedItemTags.map(element => {
|
}
|
||||||
element.showAddIcon = false;
|
|
||||||
return true;
|
getTags() {
|
||||||
|
let filter = {
|
||||||
|
where: {itemFk: this.params.id},
|
||||||
|
order: "priority ASC",
|
||||||
|
include: {relation: "tag"}
|
||||||
|
};
|
||||||
|
this.$http.get(`/item/api/ItemTags?filter=${JSON.stringify(filter)}`).then(response => {
|
||||||
|
this.removedTags = [];
|
||||||
|
|
||||||
|
this.itemTags = JSON.parse(JSON.stringify(this.tags));
|
||||||
|
this.tags = response.data;
|
||||||
|
this.orgTags = {};
|
||||||
|
this.tags.forEach(tag => {
|
||||||
|
this.orgTags[tag.id] = Object.assign({}, tag);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$.form.$setPristine();
|
||||||
});
|
});
|
||||||
this.instancedItemTags[this.instancedItemTags.length - 1].showAddIcon = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_setDirtyForm() {
|
addTag() {
|
||||||
if (this.$scope.form) {
|
this.tags.push({
|
||||||
this.$scope.form.$setDirty();
|
itemFk: this.params.id,
|
||||||
}
|
priority: this.getHighestPriority(this.tags)
|
||||||
}
|
});
|
||||||
_unsetDirtyForm() {
|
|
||||||
if (this.$scope.form) {
|
|
||||||
this.$scope.form.$setPristine();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
checkAutocompleteChanges(itemTag) {
|
getHighestPriority(tags) {
|
||||||
itemTag.value = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
addItemTag() {
|
|
||||||
if (this.instancedItemTags) {
|
|
||||||
this.instancedItemTags.push({value: null, itemFk: this.params.id, tagFk: null, priority: this.getHighestPriority(this.instancedItemTags), showAddIcon: true});
|
|
||||||
this._setIconAdd();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
removeItemTag(index) {
|
|
||||||
let item = this.instancedItemTags[index];
|
|
||||||
if (item) {
|
|
||||||
this.instancedItemTags.splice(index, 1);
|
|
||||||
this._setIconAdd();
|
|
||||||
if (item.id) {
|
|
||||||
this.removedItemTags.push(item.id);
|
|
||||||
this._setDirtyForm();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getHighestPriority(instancedItemTags) {
|
|
||||||
let max = 0;
|
let max = 0;
|
||||||
instancedItemTags.forEach(tag => {
|
tags.forEach(tag => {
|
||||||
if (tag.priority > max)
|
if (tag.priority > max)
|
||||||
max = tag.priority;
|
max = tag.priority;
|
||||||
});
|
});
|
||||||
return max + 1;
|
return max + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
removeTag(index) {
|
||||||
|
let item = this.tags[index];
|
||||||
|
this.tags.splice(index, 1);
|
||||||
|
if (item.id) {
|
||||||
|
this.removedTags.push(item.id);
|
||||||
|
this.$.form.$setDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getSourceTable(selection) {
|
getSourceTable(selection) {
|
||||||
if (!selection || selection.isFree === true)
|
if (!selection || selection.isFree === true)
|
||||||
return null;
|
return null;
|
||||||
|
@ -78,86 +70,38 @@ class Controller {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_equalItemTags(oldTag, newTag) {
|
tagIsEqual(oldTag, newTag) {
|
||||||
return oldTag.tagFk === newTag.tagFk && oldTag.value === newTag.value && oldTag.priority === newTag.priority;
|
return oldTag.tagFk === newTag.tagFk &&
|
||||||
}
|
oldTag.value === newTag.value &&
|
||||||
|
oldTag.priority === newTag.priority;
|
||||||
_setOlTags(instancedItemTags) {
|
|
||||||
this._setIconAdd();
|
|
||||||
instancedItemTags.forEach(tag => {
|
|
||||||
this.oldItemTags[tag.id] = Object.assign({}, tag);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_getItemTags() {
|
|
||||||
let filter = {
|
|
||||||
where: {itemFk: this.params.id},
|
|
||||||
order: "priority ASC",
|
|
||||||
include: {relation: "tag"}
|
|
||||||
};
|
|
||||||
this.$http.get(`/item/api/ItemTags?filter=${JSON.stringify(filter)}`).then(response => {
|
|
||||||
this.instancedItemTags = response.data;
|
|
||||||
this.itemTags = JSON.parse(JSON.stringify(this.instancedItemTags));
|
|
||||||
this._setOlTags(response.data);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
let itemTagsDefined = [];
|
this.$.watcher.check();
|
||||||
let repeatedItemTags = false;
|
|
||||||
let canSubmit;
|
let changes = {
|
||||||
let tagsObj = {
|
delete: this.removedTags,
|
||||||
delete: this.removedItemTags,
|
|
||||||
create: [],
|
create: [],
|
||||||
update: []
|
update: []
|
||||||
};
|
};
|
||||||
this.instancedItemTags.forEach(tag => {
|
this.tags.forEach(tag => {
|
||||||
let isNewTag = !tag.id;
|
if (!tag.id)
|
||||||
|
changes.create.push(tag);
|
||||||
if (itemTagsDefined.indexOf(tag.tagFk) !== -1) {
|
else if (!this.tagIsEqual(this.orgTags[tag.id], tag)) {
|
||||||
repeatedItemTags = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
itemTagsDefined.push(tag.tagFk);
|
|
||||||
|
|
||||||
if (isNewTag) {
|
|
||||||
tagsObj.create.push(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isNewTag && !this._equalItemTags(this.oldItemTags[tag.id], tag)) {
|
|
||||||
let tagToUpdate = Object.assign({}, tag);
|
let tagToUpdate = Object.assign({}, tag);
|
||||||
delete tagToUpdate.tag;
|
delete tagToUpdate.tag;
|
||||||
delete tagToUpdate.showAddIcon;
|
changes.update.push(tagToUpdate);
|
||||||
tagsObj.update.push(tagToUpdate);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.$scope.form.$invalid) {
|
this.$http.post(`/item/api/ItemTags/crud`, changes).then(() => {
|
||||||
return this.vnApp.showMessage(this.$translate.instant('Some fields are invalid'));
|
this.getTags();
|
||||||
}
|
this.$.watcher.notifySaved();
|
||||||
|
|
||||||
if (repeatedItemTags) {
|
|
||||||
return this.vnApp.showMessage(this.$translate.instant('The tag must be unique'));
|
|
||||||
}
|
|
||||||
|
|
||||||
canSubmit = tagsObj.update.length > 0 || tagsObj.create.length > 0 || tagsObj.delete.length > 0;
|
|
||||||
|
|
||||||
if (canSubmit) {
|
|
||||||
return this.$http.post(`/item/api/ItemTags/crudItemTags`, tagsObj).then(() => {
|
|
||||||
// this.itemTags = JSON.parse(JSON.stringify(this.instancedItemTags));
|
|
||||||
this._getItemTags();
|
|
||||||
this._unsetDirtyForm();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.vnApp.showMessage(this.$translate.instant('No changes to save'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
Controller.$inject = ['$stateParams', '$scope', '$http'];
|
||||||
this._getItemTags();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Controller.$inject = ['$stateParams', '$scope', '$http', '$translate', 'vnApp'];
|
|
||||||
|
|
||||||
ngModule.component('vnItemTags', {
|
ngModule.component('vnItemTags', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
|
|
|
@ -15,38 +15,43 @@ describe('Item', () => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$state = _$state_;
|
$state = _$state_;
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
controller = $componentController('vnItemTags', {$state: $state});
|
controller = $componentController('vnItemTags', {$state: $state});
|
||||||
|
controller.$.form = {
|
||||||
|
$setPristine: () => {},
|
||||||
|
$dirty: true
|
||||||
|
};
|
||||||
|
controller.$.watcher = {
|
||||||
|
notifySaved: () => {},
|
||||||
|
check: () => {}
|
||||||
|
};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('add / remove tags', () => {
|
describe('add / remove tags', () => {
|
||||||
it('should add one empty tag into controller tags collection and call _setIconAdd()', () => {
|
it('should add one empty tag into controller tags collection', () => {
|
||||||
controller.instancedItemTags = [];
|
controller.tags = [];
|
||||||
spyOn(controller, '_setIconAdd').and.callThrough();
|
controller.addTag();
|
||||||
controller.addItemTag();
|
|
||||||
|
|
||||||
expect(controller._setIconAdd).toHaveBeenCalledWith();
|
expect(controller.tags.length).toEqual(1);
|
||||||
expect(controller.instancedItemTags.length).toEqual(1);
|
expect(controller.tags[0].id).toBe(undefined);
|
||||||
expect(controller.instancedItemTags[0].id).toBe(undefined);
|
|
||||||
expect(controller.instancedItemTags[0].showAddIcon).toBeTruthy();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should remove a tag that occupies the position in the index given and call _setIconAdd()', () => {
|
it('should remove a tag that occupies the position in the index', () => {
|
||||||
|
controller.$.form = {$setDirty: () => {}};
|
||||||
|
spyOn(controller.$.form, '$setDirty');
|
||||||
|
|
||||||
let index = 2;
|
let index = 2;
|
||||||
controller.instancedItemTags = [
|
controller.tags = [
|
||||||
{id: 1, typeFk: 1, value: '1111', showAddIcon: false},
|
{id: 1, typeFk: 1, value: '1111', showAddIcon: false},
|
||||||
{id: 2, typeFk: 2, value: '2222', showAddIcon: false},
|
{id: 2, typeFk: 2, value: '2222', showAddIcon: false},
|
||||||
{id: 3, typeFk: 3, value: '3333', showAddIcon: true}
|
{id: 3, typeFk: 3, value: '3333', showAddIcon: true}
|
||||||
];
|
];
|
||||||
|
|
||||||
spyOn(controller, '_setIconAdd').and.callThrough();
|
controller.removeTag(index);
|
||||||
|
|
||||||
controller.removeItemTag(index);
|
expect(controller.tags.length).toEqual(2);
|
||||||
|
expect(controller.tags[index]).toBe(undefined);
|
||||||
expect(controller._setIconAdd).toHaveBeenCalledWith();
|
expect(controller.$.form.$setDirty).toHaveBeenCalledWith();
|
||||||
expect(controller.instancedItemTags.length).toEqual(2);
|
|
||||||
expect(controller.instancedItemTags[0].showAddIcon).toBeFalsy();
|
|
||||||
expect(controller.instancedItemTags[1].showAddIcon).toBeTruthy();
|
|
||||||
expect(controller.instancedItemTags[index]).toBe(undefined);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -89,11 +94,11 @@ describe('Item', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('_equalItemTags()', () => {
|
describe('tagIsEqual()', () => {
|
||||||
it('should return true if two tags are equals independent of control attributes', () => {
|
it('should return true if two tags are equals independent of control attributes', () => {
|
||||||
let tag1 = {id: 1, typeFk: 1, value: '1111', showAddIcon: true};
|
let tag1 = {id: 1, typeFk: 1, value: '1111', showAddIcon: true};
|
||||||
let tag2 = {id: 1, typeFk: 1, value: '1111', showAddIcon: false};
|
let tag2 = {id: 1, typeFk: 1, value: '1111', showAddIcon: false};
|
||||||
let equals = controller._equalItemTags(tag2, tag1);
|
let equals = controller.tagIsEqual(tag2, tag1);
|
||||||
|
|
||||||
expect(equals).toBeTruthy();
|
expect(equals).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
@ -101,7 +106,7 @@ describe('Item', () => {
|
||||||
it('should return false if two tags aint equal independent of control attributes', () => {
|
it('should return false if two tags aint equal independent of control attributes', () => {
|
||||||
let tag1 = {id: 1, typeFk: 1, value: '1111', showAddIcon: true};
|
let tag1 = {id: 1, typeFk: 1, value: '1111', showAddIcon: true};
|
||||||
let tag2 = {id: 1, typeFk: 1, value: '2222', showAddIcon: true};
|
let tag2 = {id: 1, typeFk: 1, value: '2222', showAddIcon: true};
|
||||||
let equals = controller._equalItemTags(tag2, tag1);
|
let equals = controller.tagIsEqual(tag2, tag1);
|
||||||
|
|
||||||
expect(equals).toBeFalsy();
|
expect(equals).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
@ -109,73 +114,78 @@ describe('Item', () => {
|
||||||
|
|
||||||
describe('get itemTags', () => {
|
describe('get itemTags', () => {
|
||||||
it('should perform a GET query to receive the item tags', () => {
|
it('should perform a GET query to receive the item tags', () => {
|
||||||
|
controller.$.form = {$setPristine: () => {}};
|
||||||
|
spyOn(controller.$.form, '$setPristine');
|
||||||
|
|
||||||
let res = [{id: 1, typeFk: 1, value: '1111'}];
|
let res = [{id: 1, typeFk: 1, value: '1111'}];
|
||||||
|
|
||||||
$httpBackend.whenGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`).respond(res);
|
$httpBackend.whenGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`).respond(res);
|
||||||
$httpBackend.expectGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`);
|
$httpBackend.expectGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`);
|
||||||
controller._getItemTags();
|
controller.getTags();
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.$.form.$setPristine).toHaveBeenCalledWith();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('submit()', () => {
|
describe('submit()', () => {
|
||||||
it("should return an error message 'The tag must be unique' when the tag value isnt unique", () => {
|
// TODO: Server validation should be implemented
|
||||||
controller.$scope.form = [];
|
xit("should return an error message 'The tag must be unique' when the tag value isnt unique", () => {
|
||||||
|
controller.$.form = [];
|
||||||
spyOn(controller.vnApp, 'showMessage').and.callThrough();
|
spyOn(controller.vnApp, 'showMessage').and.callThrough();
|
||||||
controller.instancedItemTags = [
|
controller.tags = [
|
||||||
{typeFk: 1, value: 123454, itemFk: 1, id: 1},
|
{typeFk: 1, value: 123454, itemFk: 1, id: 1},
|
||||||
{typeFk: 1, value: 123454, itemFk: 1}
|
{typeFk: 1, value: 123454, itemFk: 1}
|
||||||
];
|
];
|
||||||
controller.oldItemTags = {1: {typeFk: 1, id: 1, value: 123454, itemFk: 1}};
|
controller.orgTags = {1: {typeFk: 1, id: 1, value: 123454, itemFk: 1}};
|
||||||
controller.submit();
|
controller.submit();
|
||||||
|
|
||||||
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('The tag must be unique');
|
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('The tag must be unique');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should perfom a query to delete tags", () => {
|
it("should perfom a query to delete tags", () => {
|
||||||
controller.$scope.form = {$setPristine: () => {}};
|
controller.orgTags = {1: {id: 1, typeFk: 1, value: '1111'}};
|
||||||
controller.oldItemTags = {1: {id: 1, typeFk: 1, value: '1111'}};
|
controller.tags = [];
|
||||||
controller.instancedItemTags = [];
|
controller.removedTags = [1];
|
||||||
controller.removedItemTags = [1];
|
|
||||||
|
|
||||||
$httpBackend.whenGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`).respond([]);
|
$httpBackend.whenGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`).respond([]);
|
||||||
$httpBackend.expectPOST(`/item/api/ItemTags/crudItemTags`).respond('ok!');
|
$httpBackend.expectPOST(`/item/api/ItemTags/crud`).respond('ok!');
|
||||||
controller.submit();
|
controller.submit();
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should perfom a query to update tags", () => {
|
it("should perfom a query to update tags", () => {
|
||||||
controller.$scope.form = {$setPristine: () => {}};
|
controller.tags = [{id: 1, typeFk: 1, value: '2222'}];
|
||||||
controller.instancedItemTags = [{id: 1, typeFk: 1, value: '2222'}];
|
controller.orgTags = {1: {id: 1, typeFk: 1, value: '1111'}};
|
||||||
controller.oldItemTags = {1: {id: 1, typeFk: 1, value: '1111'}};
|
|
||||||
|
|
||||||
$httpBackend.whenGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`).respond([]);
|
$httpBackend.whenGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`).respond([]);
|
||||||
$httpBackend.expectPOST(`/item/api/ItemTags/crudItemTags`).respond('ok!');
|
$httpBackend.expectPOST(`/item/api/ItemTags/crud`).respond('ok!');
|
||||||
controller.submit();
|
controller.submit();
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should perfom a query to create new tag", () => {
|
it("should perfom a query to create new tag", () => {
|
||||||
controller.$scope.form = {$setPristine: () => {}};
|
controller.tags = [{typeFk: 1, value: 1111, itemFk: 1}];
|
||||||
controller.instancedItemTags = [{typeFk: 1, value: 1111, itemFk: 1}];
|
|
||||||
|
|
||||||
$httpBackend.whenGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`).respond([]);
|
$httpBackend.whenGET(`/item/api/ItemTags?filter={"where":{},"order":"priority ASC","include":{"relation":"tag"}}`).respond([]);
|
||||||
$httpBackend.expectPOST(`/item/api/ItemTags/crudItemTags`).respond('ok!');
|
$httpBackend.expectPOST(`/item/api/ItemTags/crud`).respond('ok!');
|
||||||
controller.submit();
|
controller.submit();
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return a message 'No changes to save' when there are no changes to apply", () => {
|
it("should throw 'No changes to save' error when there are no changes to apply", () => {
|
||||||
controller.$scope.form = {$setPristine: () => {}};
|
controller.$.watcher = {
|
||||||
spyOn(controller.vnApp, 'showMessage').and.callThrough();
|
check: () => {
|
||||||
controller.oldItemTags = [
|
throw new Error('No changes to save');
|
||||||
{typeFk: 1, value: 1, itemFk: 1, id: 1},
|
}
|
||||||
{typeFk: 2, value: 2, itemFk: 1, id: 2}
|
};
|
||||||
];
|
|
||||||
controller.instancedItemTags = [];
|
|
||||||
controller.submit();
|
|
||||||
|
|
||||||
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('No changes to save');
|
controller.orgTags = [];
|
||||||
|
controller.tags = [];
|
||||||
|
|
||||||
|
expect(function() {
|
||||||
|
controller.submit();
|
||||||
|
}).toThrowError();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
<vn-crud-model
|
||||||
|
url="/item/api/TaxClasses"
|
||||||
|
fields="['id', 'description', 'code']"
|
||||||
|
data="classes">
|
||||||
|
</vn-crud-model>
|
||||||
<form name="form" ng-submit="$ctrl.submit()">
|
<form name="form" ng-submit="$ctrl.submit()">
|
||||||
<vn-card pad-large>
|
<vn-card pad-large>
|
||||||
<vn-title>Item tax</vn-title>
|
<vn-title>Item tax</vn-title>
|
||||||
|
@ -10,8 +15,7 @@
|
||||||
<vn-autocomplete vn-one
|
<vn-autocomplete vn-one
|
||||||
label="Class"
|
label="Class"
|
||||||
field="tax.taxClassFk"
|
field="tax.taxClassFk"
|
||||||
initial-data="tax.taxClass"
|
data="classes"
|
||||||
data="$ctrl.classes"
|
|
||||||
value-field="id"
|
value-field="id"
|
||||||
show-field="description">
|
show-field="description">
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
|
|
|
@ -1,18 +1,17 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
|
|
||||||
export default class Controller {
|
export default class Controller {
|
||||||
constructor($stateParams, $http) {
|
constructor($stateParams, $http, $translate, vnApp) {
|
||||||
this.$http = $http;
|
this.$http = $http;
|
||||||
this.$stateParams = $stateParams;
|
this.$stateParams = $stateParams;
|
||||||
|
this._ = $translate;
|
||||||
|
this.vnApp = vnApp;
|
||||||
|
|
||||||
let filter = {
|
let filter = {
|
||||||
fields: ['id', 'countryFk', 'taxClassFk'],
|
fields: ['id', 'countryFk', 'taxClassFk'],
|
||||||
include: [{
|
include: [{
|
||||||
relation: 'country',
|
relation: 'country',
|
||||||
scope: {fields: ['country']}
|
scope: {fields: ['country']}
|
||||||
}, {
|
|
||||||
relation: 'taxClass',
|
|
||||||
scope: {fields: ['id', 'description']}
|
|
||||||
}]
|
}]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -21,10 +20,6 @@ export default class Controller {
|
||||||
$http.get(url).then(json => {
|
$http.get(url).then(json => {
|
||||||
this.taxes = json.data;
|
this.taxes = json.data;
|
||||||
});
|
});
|
||||||
|
|
||||||
$http.get(`/item/api/TaxClasses`).then(json => {
|
|
||||||
this.classes = json.data;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
|
@ -33,11 +28,13 @@ export default class Controller {
|
||||||
data.push({id: tax.id, taxClassFk: tax.taxClassFk});
|
data.push({id: tax.id, taxClassFk: tax.taxClassFk});
|
||||||
|
|
||||||
let url = `/item/api/Items/${this.$stateParams.id}/updateTaxes`;
|
let url = `/item/api/Items/${this.$stateParams.id}/updateTaxes`;
|
||||||
this.$http.post(url, data);
|
this.$http.post(url, data).then(
|
||||||
|
() => this.vnApp.showMessage(this._.instant('Data saved!'))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$stateParams', '$http'];
|
Controller.$inject = ['$stateParams', '$http', '$translate', 'vnApp'];
|
||||||
|
|
||||||
ngModule.component('vnItemTax', {
|
ngModule.component('vnItemTax', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
<a ui-sref="home" title="{{'Home' | translate}}">
|
<a ui-sref="home" title="{{'Home' | translate}}">
|
||||||
<img class="logo" src="./logo.svg" alt="Logo"></img>
|
<img class="logo" src="./logo.svg" alt="Logo"></img>
|
||||||
</a>
|
</a>
|
||||||
<vn-spinner enable="$root.loading"></vn-spinner>
|
<vn-spinner enable="$ctrl.vnApp.loading"></vn-spinner>
|
||||||
<vn-main-menu></vn-main-menu>
|
<vn-main-menu></vn-main-menu>
|
||||||
</vn-topbar>
|
</vn-topbar>
|
||||||
<vn-vertical vn-one ui-view scrollable class="main-view">
|
<vn-vertical vn-one ui-view scrollable class="main-view">
|
||||||
|
|
|
@ -14,7 +14,7 @@ vn-app {
|
||||||
}
|
}
|
||||||
vn-spinner {
|
vn-spinner {
|
||||||
float: left;
|
float: left;
|
||||||
padding: .4em;
|
padding: 1em .4em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.main-view {
|
.main-view {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import "colors";
|
@import "effects";
|
||||||
|
|
||||||
vn-home {
|
vn-home {
|
||||||
padding: 2em;
|
padding: 2em;
|
||||||
|
@ -17,6 +17,7 @@ vn-home {
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|
||||||
& > a {
|
& > a {
|
||||||
|
@extend %clickable-light;
|
||||||
overflow:hidden;
|
overflow:hidden;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
background-color: $main-01;
|
background-color: $main-01;
|
||||||
|
@ -29,11 +30,6 @@ vn-home {
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
transition: opacity 250ms ease-out;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: $hover;
|
|
||||||
}
|
|
||||||
& > vn-icon {
|
& > vn-icon {
|
||||||
font-size: 4em;
|
font-size: 4em;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
@import "colors";
|
@import "effects";
|
||||||
|
|
||||||
vn-menu-item {
|
vn-menu-item {
|
||||||
& > li.active {
|
& > li {
|
||||||
|
@extend %clickable;
|
||||||
|
|
||||||
|
&.active {
|
||||||
background-color: $main-header;
|
background-color: $main-header;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@import "colors";
|
@import "effects";
|
||||||
|
|
||||||
vn-main-menu {
|
vn-main-menu {
|
||||||
#user {
|
#user {
|
||||||
|
@ -25,9 +25,9 @@ vn-main-menu {
|
||||||
color: white;
|
color: white;
|
||||||
|
|
||||||
li {
|
li {
|
||||||
|
@extend %clickable-light;
|
||||||
background-color: $main-01;
|
background-color: $main-01;
|
||||||
margin-bottom: .6em;
|
margin-bottom: .6em;
|
||||||
cursor: pointer;
|
|
||||||
padding: .8em;
|
padding: .8em;
|
||||||
border-radius: .1em;
|
border-radius: .1em;
|
||||||
min-width: 8em;
|
min-width: 8em;
|
||||||
|
@ -36,9 +36,6 @@ vn-main-menu {
|
||||||
padding-right: .3em;
|
padding-right: .3em;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
&:hover {
|
|
||||||
background-color: $hover;
|
|
||||||
}
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,29 +6,6 @@ export const appName = 'salix';
|
||||||
const ngModule = ng.module('salix', ['vnCore']);
|
const ngModule = ng.module('salix', ['vnCore']);
|
||||||
export default ngModule;
|
export default ngModule;
|
||||||
|
|
||||||
config.$inject = ['$translatePartialLoaderProvider', '$httpProvider', '$qProvider'];
|
|
||||||
export function config($translatePartialLoaderProvider, $httpProvider, $qProvider) {
|
|
||||||
$translatePartialLoaderProvider.addPart(appName);
|
|
||||||
$httpProvider.interceptors.push('vnInterceptor');
|
|
||||||
|
|
||||||
// TODO: Handle or remove unhandled rejections
|
|
||||||
// $qProvider.errorOnUnhandledRejections(false);
|
|
||||||
}
|
|
||||||
ngModule.config(config);
|
|
||||||
|
|
||||||
/*
|
|
||||||
// FIXME: Handle unhandled exceptions
|
|
||||||
exceptionHandler.$inject = ['vnApp'];
|
|
||||||
function exceptionHandler(vnApp) {
|
|
||||||
return function(exception, cause) {
|
|
||||||
console.error(exception);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
ngModule.factory('$exceptionHandler', exceptionHandler);
|
|
||||||
*/
|
|
||||||
|
|
||||||
const HOOK_ABORTED_TRANSITION = 3;
|
|
||||||
|
|
||||||
run.$inject = ['$window', '$rootScope', 'vnApp', '$state'];
|
run.$inject = ['$window', '$rootScope', 'vnApp', '$state'];
|
||||||
export function run($window, $rootScope, vnApp, $state) {
|
export function run($window, $rootScope, vnApp, $state) {
|
||||||
$window.validations = {};
|
$window.validations = {};
|
||||||
|
@ -37,8 +14,56 @@ export function run($window, $rootScope, vnApp, $state) {
|
||||||
$rootScope.$on('$viewContentLoaded', () => {});
|
$rootScope.$on('$viewContentLoaded', () => {});
|
||||||
window.myAppErrorLog = [];
|
window.myAppErrorLog = [];
|
||||||
$state.defaultErrorHandler(function(error) {
|
$state.defaultErrorHandler(function(error) {
|
||||||
if (error.type === HOOK_ABORTED_TRANSITION)
|
if (error.type === 3) // ABORTED_TRANSITION
|
||||||
window.myAppErrorLog.push(error);
|
window.myAppErrorLog.push(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
ngModule.run(run);
|
ngModule.run(run);
|
||||||
|
|
||||||
|
config.$inject = ['$translatePartialLoaderProvider', '$httpProvider'];
|
||||||
|
export function config($translatePartialLoaderProvider, $httpProvider) {
|
||||||
|
$translatePartialLoaderProvider.addPart(appName);
|
||||||
|
$httpProvider.interceptors.push('vnInterceptor');
|
||||||
|
}
|
||||||
|
ngModule.config(config);
|
||||||
|
|
||||||
|
// Unhandled exceptions
|
||||||
|
|
||||||
|
$exceptionHandler.$inject = ['vnApp', '$window'];
|
||||||
|
function $exceptionHandler(vnApp, $window) {
|
||||||
|
return function(exception, cause) {
|
||||||
|
let message;
|
||||||
|
|
||||||
|
if (exception.name == 'HttpError') {
|
||||||
|
switch (exception.xhrStatus) {
|
||||||
|
case 'timeout':
|
||||||
|
case 'abort':
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = exception.data;
|
||||||
|
|
||||||
|
if (data && data.error instanceof Object)
|
||||||
|
message = data.error.message;
|
||||||
|
else if (exception.status === -1)
|
||||||
|
message = `Can't contact with server`;
|
||||||
|
else
|
||||||
|
message = `${exception.status}: ${exception.statusText}`;
|
||||||
|
|
||||||
|
if (exception.status === 401) {
|
||||||
|
let location = $window.location;
|
||||||
|
let continueUrl = location.pathname + location.search + location.hash;
|
||||||
|
continueUrl = encodeURIComponent(continueUrl);
|
||||||
|
$window.location = `/auth/?apiKey=${vnApp.name}&continue=${continueUrl}`;
|
||||||
|
}
|
||||||
|
} else if (exception.name == 'UserError') {
|
||||||
|
message = exception.message;
|
||||||
|
} else {
|
||||||
|
message = 'Ups! Something went wrong';
|
||||||
|
console.error(exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
vnApp.showError(message);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
ngModule.factory('$exceptionHandler', $exceptionHandler);
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
$main-font-color :#222222;
|
$main-font-color :#222222;
|
||||||
$secondary-font-color: #9b9b9b;
|
$secondary-font-color: #9b9b9b;
|
||||||
$main-header: #3d3d3d;
|
$main-header: #3d3d3d;
|
||||||
$hover: #c4c4c4;
|
$hover: rgba(0, 0, 0, 0.1);
|
||||||
|
$hover-opacity: .7;
|
||||||
$main-bg: #e5e5e5;
|
$main-bg: #e5e5e5;
|
||||||
$main-01: #f7931e;
|
$main-01: #f7931e;
|
||||||
$main-01-05: rgba($main-01, 0.5);
|
$main-01-05: rgba($main-01, 0.5);
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
@import "./colors";
|
||||||
|
|
||||||
|
%clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 250ms ease-out;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $hover;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
%clickable-light {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: opacity 250ms ease-out;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: $hover-opacity;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
@import "colors";
|
@import "colors";
|
||||||
@import "font-family";
|
@import "font-family";
|
||||||
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
color: $main-font-color;
|
color: $main-font-color;
|
||||||
font-family: vn-font;
|
font-family: vn-font;
|
||||||
|
|
|
@ -9,3 +9,4 @@ import './font-style.scss';
|
||||||
import './misc.scss';
|
import './misc.scss';
|
||||||
import './summary.scss';
|
import './summary.scss';
|
||||||
import './colors.scss';
|
import './colors.scss';
|
||||||
|
import './effects.scss';
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
@import "padding";
|
@import "./padding";
|
||||||
@import "margin";
|
@import "./margin";
|
||||||
@import "colors";
|
@import "./colors";
|
||||||
@import "border";
|
@import "./border";
|
||||||
|
@import "./effects";
|
||||||
|
|
||||||
a:focus,
|
a:focus,
|
||||||
input:focus,
|
input:focus,
|
||||||
|
@ -116,17 +116,8 @@ a {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.vn-clickable {
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background-color 250ms ease-out;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: $hover;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
button {
|
||||||
@extend .vn-clickable;
|
@extend %clickable;
|
||||||
}
|
}
|
||||||
|
|
||||||
vn-button-bar {
|
vn-button-bar {
|
||||||
|
@ -168,14 +159,12 @@ vn-main-block {
|
||||||
font-size: 2.5em;
|
font-size: 2.5em;
|
||||||
}
|
}
|
||||||
& > a {
|
& > a {
|
||||||
@extend .vn-clickable;
|
@extend %clickable;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: .5em;
|
padding: .5em;
|
||||||
color: white;
|
color: white;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
transition: background-color 250ms ease-out;
|
|
||||||
|
|
||||||
& > vn-icon {
|
& > vn-icon {
|
||||||
font-size: 1.8em;
|
font-size: 1.8em;
|
||||||
|
@ -205,7 +194,7 @@ vn-main-block {
|
||||||
.vn-list-item {
|
.vn-list-item {
|
||||||
@extend .pad-medium;
|
@extend .pad-medium;
|
||||||
@extend .border-solid-bottom;
|
@extend .border-solid-bottom;
|
||||||
@extend .vn-clickable;
|
@extend %clickable;
|
||||||
|
|
||||||
display: block;
|
display: block;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
@ -220,21 +209,28 @@ vn-main-block {
|
||||||
margin-left: .5em;
|
margin-left: .5em;
|
||||||
transition: opacity 250ms ease-out;
|
transition: opacity 250ms ease-out;
|
||||||
font-size: 2em;
|
font-size: 2em;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** START - FORM ELEMENTS DISABLED **/
|
/** START - FORM ELEMENTS DISABLED **/
|
||||||
fieldset[disabled] .mdl-textfield .mdl-textfield__input, .mdl-textfield.is-disabled .mdl-textfield__input,
|
|
||||||
fieldset[disabled] .mdl-checkbox .mdl-checkbox__label, .mdl-checkbox.is-disabled .mdl-checkbox__label {
|
fieldset[disabled] .mdl-textfield .mdl-textfield__input,
|
||||||
|
fieldset[disabled] .mdl-checkbox .mdl-checkbox__label,
|
||||||
|
.mdl-textfield.is-disabled .mdl-textfield__input,
|
||||||
|
.mdl-checkbox.is-disabled .mdl-checkbox__label {
|
||||||
border: none !important;
|
border: none !important;
|
||||||
color: inherit !important;
|
color: inherit !important;
|
||||||
}
|
}
|
||||||
fieldset[disabled] .mdl-textfield .mdl-textfield__label, .mdl-textfield.is-disabled.is-disabled .mdl-textfield__label {
|
fieldset[disabled] .mdl-textfield .mdl-textfield__label,
|
||||||
|
.mdl-textfield.is-disabled.is-disabled .mdl-textfield__label {
|
||||||
color: $main-01 !important;
|
color: $main-01 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** END - FORM ELEMENTS DISABLED **/
|
/** END - FORM ELEMENTS DISABLED **/
|
||||||
|
|
||||||
.ellipsize {
|
.ellipsize {
|
||||||
|
|
|
@ -15,6 +15,7 @@ describe('ticket', () => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$state = _$state_;
|
$state = _$state_;
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
controller = $componentController('vnTicketDataStepOne', {$state: $state});
|
controller = $componentController('vnTicketDataStepOne', {$state: $state});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -37,6 +38,9 @@ describe('ticket', () => {
|
||||||
|
|
||||||
describe('onStepChange()', () => {
|
describe('onStepChange()', () => {
|
||||||
it('should call onStepChange method and return a NO_AGENCY_AVAILABLE signal error', async () => {
|
it('should call onStepChange method and return a NO_AGENCY_AVAILABLE signal error', async () => {
|
||||||
|
let landed = new Date();
|
||||||
|
landed.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
controller.ticket = {
|
controller.ticket = {
|
||||||
id: 1,
|
id: 1,
|
||||||
clientFk: 1,
|
clientFk: 1,
|
||||||
|
@ -45,20 +49,14 @@ describe('ticket', () => {
|
||||||
companyFk: 442,
|
companyFk: 442,
|
||||||
warehouseFk: 1,
|
warehouseFk: 1,
|
||||||
shipped: new Date(),
|
shipped: new Date(),
|
||||||
landed: new Date()
|
landed: landed
|
||||||
};
|
};
|
||||||
|
|
||||||
let data = {
|
let response = {error: new Error('NO_AGENCY_AVAILABLE')};
|
||||||
addressFk: 121,
|
|
||||||
agencyModeFk: 1,
|
|
||||||
warehouseFk: 1,
|
|
||||||
landed: new Date()
|
|
||||||
};
|
|
||||||
let response = {data: {error: new Error('NO_AGENCY_AVAILABLE')}};
|
|
||||||
|
|
||||||
$httpBackend.whenPOST(`/ticket/api/sales/1/priceDifference`, data).respond(400, response);
|
$httpBackend.whenPOST(`/ticket/api/sales/1/priceDifference`).respond(400, response);
|
||||||
$httpBackend.expectPOST(`/ticket/api/sales/1/priceDifference`, data);
|
$httpBackend.expectPOST(`/ticket/api/sales/1/priceDifference`);
|
||||||
await controller.onStepChange();
|
controller.onStepChange();
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -119,6 +119,7 @@ class Controller {
|
||||||
return this.$http.post(`/ticket/api/TicketObservations/crudTicketObservation`, observationsObj).then(() => {
|
return this.$http.post(`/ticket/api/TicketObservations/crudTicketObservation`, observationsObj).then(() => {
|
||||||
this.getObservations();
|
this.getObservations();
|
||||||
this._unsetDirtyForm();
|
this._unsetDirtyForm();
|
||||||
|
this.$scope.watcher.notifySaved();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.vnApp.showMessage(this.$translate.instant('No changes to save'));
|
this.vnApp.showMessage(this.$translate.instant('No changes to save'));
|
||||||
|
|
|
@ -15,7 +15,11 @@ describe('ticket', () => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$state = _$state_;
|
$state = _$state_;
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
controller = $componentController('vnTicketObservation', {$state: $state});
|
controller = $componentController('vnTicketObservation', {$state: $state});
|
||||||
|
controller.$scope.watcher = {
|
||||||
|
notifySaved: () => {}
|
||||||
|
};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('add / remove observation', () => {
|
describe('add / remove observation', () => {
|
||||||
|
|
|
@ -14,6 +14,7 @@ describe('Ticket', () => {
|
||||||
beforeEach(angular.mock.inject((_$componentController_, _$httpBackend_, $rootScope) => {
|
beforeEach(angular.mock.inject((_$componentController_, _$httpBackend_, $rootScope) => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
$scope = {
|
$scope = {
|
||||||
index: {
|
index: {
|
||||||
accept: function() {}
|
accept: function() {}
|
||||||
|
@ -35,11 +36,6 @@ describe('Ticket', () => {
|
||||||
describe('submit()', () => {
|
describe('submit()', () => {
|
||||||
it('should perform a post', () => {
|
it('should perform a post', () => {
|
||||||
spyOn(controller.$.index, 'accept');
|
spyOn(controller.$.index, 'accept');
|
||||||
let packagesObj = {
|
|
||||||
delete: controller.removedPackages,
|
|
||||||
create: [],
|
|
||||||
update: []
|
|
||||||
};
|
|
||||||
let query = '/ticket/api/TicketPackagings/crudTicketPackaging';
|
let query = '/ticket/api/TicketPackagings/crudTicketPackaging';
|
||||||
controller.removedPackages = [];
|
controller.removedPackages = [];
|
||||||
controller.oldPackages = [];
|
controller.oldPackages = [];
|
||||||
|
|
|
@ -15,6 +15,7 @@ describe('Ticket', () => {
|
||||||
beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_, $rootScope) => {
|
beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_, $rootScope) => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
$scope = $rootScope.$new();
|
$scope = $rootScope.$new();
|
||||||
$scope.index = {model: {instances: [{id: 1}, {id: 2}]}, accept: () => {
|
$scope.index = {model: {instances: [{id: 1}, {id: 2}]}, accept: () => {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -7,8 +7,7 @@ class Controller {
|
||||||
this.vnApp = vnApp;
|
this.vnApp = vnApp;
|
||||||
this.$translate = $translate;
|
this.$translate = $translate;
|
||||||
this.ticket = {
|
this.ticket = {
|
||||||
ticketFk: $state.params.id,
|
ticketFk: $state.params.id
|
||||||
text: null
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
onSubmit() {
|
onSubmit() {
|
||||||
|
|
|
@ -15,6 +15,7 @@ describe('ticket', () => {
|
||||||
beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_, $rootScope) => {
|
beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_, $rootScope) => {
|
||||||
$componentController = _$componentController_;
|
$componentController = _$componentController_;
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
$scope = $rootScope.$new();
|
$scope = $rootScope.$new();
|
||||||
$scope.index = {model: {instances: [{id: 1}, {id: 2}]}, accept: () => {
|
$scope.index = {model: {instances: [{id: 1}, {id: 2}]}, accept: () => {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -4,16 +4,6 @@
|
||||||
// delete me, this comment is to add a commit
|
// delete me, this comment is to add a commit
|
||||||
export default {
|
export default {
|
||||||
vnTextfield: 'vn-textfield > div > input',
|
vnTextfield: 'vn-textfield > div > input',
|
||||||
vnTextarea: 'vn-textarea',
|
|
||||||
vnSubmit: 'vn-submit > input',
|
vnSubmit: 'vn-submit > input',
|
||||||
vnTopbar: 'vn-topbar > header',
|
vnFloatButton: 'vn-float-button > button'
|
||||||
vnIcon: 'vn-icon',
|
|
||||||
vnSearchBar: 'vn-searchbar > form > vn-horizontal',
|
|
||||||
vnFloatButton: 'vn-float-button > button',
|
|
||||||
vnMenuItem: 'vn-menu-item > li > a',
|
|
||||||
vnAutocomplete: 'vn-autocomplete',
|
|
||||||
vnCheck: 'vn-check',
|
|
||||||
vnIconButton: 'vn-icon-button',
|
|
||||||
vnItemSummary: 'vn-item-summary > vn-card > div > vn-vertical',
|
|
||||||
vnLabelValue: 'vn-label-value'
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,7 +17,7 @@ export default {
|
||||||
},
|
},
|
||||||
clientsIndex: {
|
clientsIndex: {
|
||||||
searchClientInput: `${components.vnTextfield}`,
|
searchClientInput: `${components.vnTextfield}`,
|
||||||
searchButton: `${components.vnSearchBar} > vn-icon-button`,
|
searchButton: `vn-searchbar vn-icon-button[icon="search"]`,
|
||||||
searchResult: `vn-item-client a`,
|
searchResult: `vn-item-client a`,
|
||||||
createClientButton: `${components.vnFloatButton}`
|
createClientButton: `${components.vnFloatButton}`
|
||||||
},
|
},
|
||||||
|
@ -33,122 +33,122 @@ export default {
|
||||||
cancelButton: `button[href="#!/client/index"]`
|
cancelButton: `button[href="#!/client/index"]`
|
||||||
},
|
},
|
||||||
clientBasicData: {
|
clientBasicData: {
|
||||||
basicDataButton: `${components.vnMenuItem}[ui-sref="client.card.basicData"]`,
|
basicDataButton: `vn-menu-item a[ui-sref="client.card.basicData"]`,
|
||||||
nameInput: `${components.vnTextfield}[name="name"]`,
|
nameInput: `${components.vnTextfield}[name="name"]`,
|
||||||
contactInput: `${components.vnTextfield}[name="contact"]`,
|
contactInput: `${components.vnTextfield}[name="contact"]`,
|
||||||
phoneInput: `${components.vnTextfield}[name="phone"]`,
|
phoneInput: `${components.vnTextfield}[name="phone"]`,
|
||||||
mobileInput: `${components.vnTextfield}[name="mobile"]`,
|
mobileInput: `${components.vnTextfield}[name="mobile"]`,
|
||||||
faxInput: `${components.vnTextfield}[name="fax"]`,
|
faxInput: `${components.vnTextfield}[name="fax"]`,
|
||||||
emailInput: `${components.vnTextfield}[name="email"]`,
|
emailInput: `${components.vnTextfield}[name="email"]`,
|
||||||
salesPersonInput: `${components.vnAutocomplete}[field="$ctrl.client.salesPersonFk"] input`,
|
salesPersonInput: `vn-autocomplete[field="$ctrl.client.salesPersonFk"] input`,
|
||||||
salesPersonOptionOne: `${components.vnAutocomplete}[field="$ctrl.client.salesPersonFk"] vn-drop-down ul > li:nth-child(1)`,
|
salesPersonOptionOne: `vn-autocomplete[field="$ctrl.client.salesPersonFk"] vn-drop-down ul > li:nth-child(1)`,
|
||||||
channelInput: `${components.vnAutocomplete}[field="$ctrl.client.contactChannelFk"] input`,
|
channelInput: `vn-autocomplete[field="$ctrl.client.contactChannelFk"] input`,
|
||||||
channelMetropolisOption: `${components.vnAutocomplete}[field="$ctrl.client.contactChannelFk"] vn-drop-down ul > li:nth-child(3)`,
|
channelMetropolisOption: `vn-autocomplete[field="$ctrl.client.contactChannelFk"] vn-drop-down ul > li:nth-child(3)`,
|
||||||
saveButton: `${components.vnSubmit}`
|
saveButton: `${components.vnSubmit}`
|
||||||
},
|
},
|
||||||
clientFiscalData: {
|
clientFiscalData: {
|
||||||
fiscalDataButton: `${components.vnMenuItem}[ui-sref="client.card.fiscalData"]`,
|
fiscalDataButton: `vn-menu-item a[ui-sref="client.card.fiscalData"]`,
|
||||||
socialNameInput: `${components.vnTextfield}[name="socialName"]`,
|
socialNameInput: `${components.vnTextfield}[name="socialName"]`,
|
||||||
fiscalIdInput: `${components.vnTextfield}[name="fi"]`,
|
fiscalIdInput: `${components.vnTextfield}[name="fi"]`,
|
||||||
equalizationTaxCheckboxLabel: `${components.vnCheck}[label='Is equalizated'] > label > input`,
|
equalizationTaxCheckboxLabel: `vn-check[label='Is equalizated'] > label > input`,
|
||||||
acceptPropagationButton: `vn-client-fiscal-data > vn-confirm button[response=ACCEPT]`,
|
acceptPropagationButton: `vn-client-fiscal-data > vn-confirm button[response=ACCEPT]`,
|
||||||
addressInput: `${components.vnTextfield}[name="street"]`,
|
addressInput: `${components.vnTextfield}[name="street"]`,
|
||||||
cityInput: `${components.vnTextfield}[name="city"]`,
|
cityInput: `${components.vnTextfield}[name="city"]`,
|
||||||
postcodeInput: `${components.vnTextfield}[name="postcode"]`,
|
postcodeInput: `${components.vnTextfield}[name="postcode"]`,
|
||||||
provinceInput: `${components.vnAutocomplete}[field="$ctrl.client.provinceFk"] input`,
|
provinceInput: `vn-autocomplete[field="$ctrl.client.provinceFk"] input`,
|
||||||
provinceFifthOption: `${components.vnAutocomplete}[field="$ctrl.client.provinceFk"] vn-drop-down ul > li:nth-child(5)`,
|
provinceFifthOption: `vn-autocomplete[field="$ctrl.client.provinceFk"] vn-drop-down ul > li:nth-child(5)`,
|
||||||
countryInput: `${components.vnAutocomplete}[field="$ctrl.client.countryFk"] input`,
|
countryInput: `vn-autocomplete[field="$ctrl.client.countryFk"] input`,
|
||||||
countryThirdOption: `${components.vnAutocomplete}[field="$ctrl.client.countryFk"] vn-drop-down ul > li:nth-child(3)`,
|
countryThirdOption: `vn-autocomplete[field="$ctrl.client.countryFk"] vn-drop-down ul > li:nth-child(3)`,
|
||||||
activeCheckboxLabel: `${components.vnCheck}[label="Active"] > label`,
|
activeCheckboxLabel: `vn-check[label="Active"] > label`,
|
||||||
frozenCheckboxLabel: `${components.vnCheck}[label="Frozen"] > label`,
|
frozenCheckboxLabel: `vn-check[label="Frozen"] > label`,
|
||||||
invoiceByAddressCheckboxInput: `${components.vnCheck}[label='Invoice by address'] > label > input`,
|
invoiceByAddressCheckboxInput: `vn-check[label='Invoice by address'] > label > input`,
|
||||||
verifiedDataCheckboxInput: `${components.vnCheck}[label="Verified data"] > label > input`,
|
verifiedDataCheckboxInput: `vn-check[label="Verified data"] > label > input`,
|
||||||
hasToInvoiceCheckboxLabel: `${components.vnCheck}[label='Has to invoice'] > label`,
|
hasToInvoiceCheckboxLabel: `vn-check[label='Has to invoice'] > label`,
|
||||||
invoiceByMailCheckboxLabel: `${components.vnCheck}[label='Invoice by mail'] > label`,
|
invoiceByMailCheckboxLabel: `vn-check[label='Invoice by mail'] > label`,
|
||||||
viesCheckboxInput: `${components.vnCheck}[label='Vies'] > label > input`,
|
viesCheckboxInput: `vn-check[label='Vies'] > label > input`,
|
||||||
saveButton: `${components.vnSubmit}`
|
saveButton: `${components.vnSubmit}`
|
||||||
},
|
},
|
||||||
clientPayMethod: {
|
clientPayMethod: {
|
||||||
payMethodButton: `${components.vnMenuItem}[ui-sref="client.card.billingData"]`,
|
payMethodButton: `vn-menu-item a[ui-sref="client.card.billingData"]`,
|
||||||
payMethodInput: `${components.vnAutocomplete}[field="$ctrl.client.payMethodFk"] input`,
|
payMethodInput: `vn-autocomplete[field="$ctrl.client.payMethodFk"] input`,
|
||||||
payMethodIBANOption: `${components.vnAutocomplete}[field="$ctrl.client.payMethodFk"] vn-drop-down ul > li:nth-child(5)`,
|
payMethodIBANOption: `vn-autocomplete[field="$ctrl.client.payMethodFk"] vn-drop-down ul > li:nth-child(5)`,
|
||||||
payMethodOptionOne: `${components.vnAutocomplete}[field="$ctrl.client.payMethodFk"] vn-drop-down ul > li:nth-child(2)`,
|
payMethodOptionOne: `vn-autocomplete[field="$ctrl.client.payMethodFk"] vn-drop-down ul > li:nth-child(2)`,
|
||||||
IBANInput: `${components.vnTextfield}[name="iban"]`,
|
IBANInput: `${components.vnTextfield}[name="iban"]`,
|
||||||
dueDayInput: `${components.vnTextfield}[name="dueDay"]`,
|
dueDayInput: `${components.vnTextfield}[name="dueDay"]`,
|
||||||
receivedCoreVNHCheckbox: `${components.vnCheck}[label='Received core VNH'] > label > input`,
|
receivedCoreVNHCheckbox: `vn-check[label='Received core VNH'] > label > input`,
|
||||||
receivedCoreVNLCheckbox: `${components.vnCheck}[label='Received core VNL'] > label > input`,
|
receivedCoreVNLCheckbox: `vn-check[label='Received core VNL'] > label > input`,
|
||||||
receivedB2BVNLCheckbox: `${components.vnCheck}[label='Received B2B VNL'] > label > input`,
|
receivedB2BVNLCheckbox: `vn-check[label='Received B2B VNL'] > label > input`,
|
||||||
saveButton: `${components.vnSubmit}`
|
saveButton: `${components.vnSubmit}`
|
||||||
},
|
},
|
||||||
clientAddresses: {
|
clientAddresses: {
|
||||||
addressesButton: `${components.vnMenuItem}[ui-sref="client.card.address.index"]`,
|
addressesButton: `vn-menu-item a[ui-sref="client.card.address.index"]`,
|
||||||
createAddress: `vn-client-address-index ${components.vnFloatButton}`,
|
createAddress: `vn-client-address-index ${components.vnFloatButton}`,
|
||||||
defaultCheckboxInput: `${components.vnCheck}[label='Default'] > label > input`,
|
defaultCheckboxInput: `vn-check[label='Default'] > label > input`,
|
||||||
consigneeInput: `${components.vnTextfield}[name="nickname"]`,
|
consigneeInput: `${components.vnTextfield}[name="nickname"]`,
|
||||||
streetAddressInput: `${components.vnTextfield}[name="street"]`,
|
streetAddressInput: `${components.vnTextfield}[name="street"]`,
|
||||||
postcodeInput: `${components.vnTextfield}[name="postalCode"]`,
|
postcodeInput: `${components.vnTextfield}[name="postalCode"]`,
|
||||||
cityInput: `${components.vnTextfield}[name="city"]`,
|
cityInput: `${components.vnTextfield}[name="city"]`,
|
||||||
provinceInput: `${components.vnAutocomplete}[field="$ctrl.address.provinceFk"] input`,
|
provinceInput: `vn-autocomplete[field="$ctrl.address.provinceFk"] input`,
|
||||||
provinceSecondOption: `${components.vnAutocomplete}[field="$ctrl.address.provinceFk"] vn-drop-down ul > li:nth-child(2)`,
|
provinceSecondOption: `vn-autocomplete[field="$ctrl.address.provinceFk"] vn-drop-down ul > li:nth-child(2)`,
|
||||||
agencyInput: `${components.vnAutocomplete}[field="$ctrl.address.agencyModeFk"] input`,
|
agencyInput: `vn-autocomplete[field="$ctrl.address.agencyModeFk"] input`,
|
||||||
agenctySecondOption: `${components.vnAutocomplete}[field="$ctrl.address.agencyModeFk"] vn-drop-down ul > li:nth-child(2)`,
|
agenctySecondOption: `vn-autocomplete[field="$ctrl.address.agencyModeFk"] vn-drop-down ul > li:nth-child(2)`,
|
||||||
phoneInput: `${components.vnTextfield}[name="phone"]`,
|
phoneInput: `${components.vnTextfield}[name="phone"]`,
|
||||||
mobileInput: `${components.vnTextfield}[name="mobile"]`,
|
mobileInput: `${components.vnTextfield}[name="mobile"]`,
|
||||||
defaultAddress: 'vn-client-address-index vn-horizontal:nth-child(2) div[name="street"]',
|
defaultAddress: 'vn-client-address-index vn-horizontal:nth-child(2) div[name="street"]',
|
||||||
secondMakeDefaultStar: 'vn-client-address-index > vn-vertical > vn-card > div > vn-horizontal:nth-child(3) > vn-one > vn-horizontal > vn-none > i',
|
secondMakeDefaultStar: 'vn-client-address-index > vn-vertical > vn-card > div > vn-horizontal:nth-child(3) > vn-one > vn-horizontal > vn-none > i',
|
||||||
firstEditButton: `vn-client-address-index ${components.vnIconButton}[icon='edit']`,
|
firstEditButton: `vn-client-address-index vn-icon-button[icon='edit']`,
|
||||||
secondEditButton: `vn-client-address-index vn-horizontal:nth-child(3) ${components.vnIconButton}[icon='edit']`,
|
secondEditButton: `vn-client-address-index vn-horizontal:nth-child(3) vn-icon-button[icon='edit']`,
|
||||||
activeCheckbox: `${components.vnCheck}[label='Enabled'] > label > input`,
|
activeCheckbox: `vn-check[label='Enabled'] > label > input`,
|
||||||
equalizationTaxCheckboxLabel: `vn-client-address-edit ${components.vnCheck}[label='Is equalizated'] > label > input`,
|
equalizationTaxCheckboxLabel: `vn-client-address-edit vn-check[label='Is equalizated'] > label > input`,
|
||||||
firstObservationTypeSelect: `${components.vnAutocomplete}[field="observation.observationTypeFk"]:nth-child(1) input`,
|
firstObservationTypeSelect: `vn-client-address-edit [name=observations] :nth-child(1) [field="observation.observationTypeFk"] input`,
|
||||||
firstObservationTypeSelectOptionOne: `${components.vnAutocomplete}[field="observation.observationTypeFk"] vn-drop-down ul > li:nth-child(1)`,
|
firstObservationTypeSelectOptionOne: `vn-client-address-edit [name=observations] :nth-child(1) [field="observation.observationTypeFk"] vn-drop-down ul > li:nth-child(1)`,
|
||||||
firstObservationDescriptionInput: `vn-horizontal:nth-child(3) > vn-textfield[label="Description"] > div > input`,
|
firstObservationDescriptionInput: `vn-client-address-edit [name=observations] :nth-child(1) [model="observation.description"] input`,
|
||||||
secondObservationTypeSelect: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="observation.observationTypeFk"] input`,
|
secondObservationTypeSelect: `vn-client-address-edit [name=observations] :nth-child(2) [field="observation.observationTypeFk"] input`,
|
||||||
secondObservationTypeSelectOptionTwo: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="observation.observationTypeFk"] vn-drop-down ul > li:nth-child(2)`,
|
secondObservationTypeSelectOptionTwo: `vn-client-address-edit [name=observations] :nth-child(2) [field="observation.observationTypeFk"] vn-drop-down ul > li:nth-child(2)`,
|
||||||
secondObservationDescriptionInput: `vn-horizontal:nth-child(4) > vn-textfield[label="Description"] > div > input`,
|
secondObservationDescriptionInput: `vn-client-address-edit [name=observations] :nth-child(2) [model="observation.description"] input`,
|
||||||
thirdObservationTypeSelect: `${components.vnAutocomplete}[field="observation.observationTypeFk"]:nth-child(3) input`,
|
thirdObservationTypeSelect: `vn-client-address-edit [name=observations] :nth-child(3) [field="observation.observationTypeFk"] input`,
|
||||||
thirdObservationTypeSelectOptionThree: `${components.vnAutocomplete}[field="observation.observationTypeFk"] vn-drop-down ul > li:nth-child(3)`,
|
thirdObservationTypeSelectOptionThree: `vn-client-address-edit [name=observations] :nth-child(3) [field="observation.observationTypeFk"] vn-drop-down ul > li:nth-child(3)`,
|
||||||
thirdObservationDescriptionInput: `vn-horizontal:nth-child(5) > vn-textfield[label="Description"] > div > input`,
|
thirdObservationDescriptionInput: `vn-client-address-edit [name=observations] :nth-child(3) [model="observation.description"] input`,
|
||||||
addObservationButton: `${components.vnIcon}[icon="add_circle"]`,
|
addObservationButton: `vn-client-address-edit vn-icon-button[icon="add_circle"]`,
|
||||||
saveButton: `${components.vnSubmit}`,
|
saveButton: `${components.vnSubmit}`,
|
||||||
cancelButton: `button[ui-sref="client.card.address.index"]`
|
cancelButton: `button[ui-sref="client.card.address.index"]`
|
||||||
},
|
},
|
||||||
clientWebAccess: {
|
clientWebAccess: {
|
||||||
webAccessButton: `${components.vnMenuItem}[ui-sref="client.card.webAccess"]`,
|
webAccessButton: `vn-menu-item a[ui-sref="client.card.webAccess"]`,
|
||||||
enableWebAccessCheckbox: `${components.vnCheck}[label='Enable web access'] > label > input`,
|
enableWebAccessCheckbox: `vn-check[label='Enable web access'] > label > input`,
|
||||||
userNameInput: `${components.vnTextfield}[name="name"]`,
|
userNameInput: `${components.vnTextfield}[name="name"]`,
|
||||||
saveButton: `${components.vnSubmit}`
|
saveButton: `${components.vnSubmit}`
|
||||||
},
|
},
|
||||||
clientNotes: {
|
clientNotes: {
|
||||||
notesButton: `${components.vnMenuItem}[ui-sref="client.card.note.index"]`,
|
notesButton: `vn-menu-item a[ui-sref="client.card.note.index"]`,
|
||||||
addNoteFloatButton: `${components.vnFloatButton}`,
|
addNoteFloatButton: `${components.vnFloatButton}`,
|
||||||
noteInput: `${components.vnTextarea}[label="Note"]`,
|
noteInput: `vn-textarea[label="Note"]`,
|
||||||
saveButton: `${components.vnSubmit}`,
|
saveButton: `${components.vnSubmit}`,
|
||||||
firstNoteText: 'vn-client-note .text'
|
firstNoteText: 'vn-client-note .text'
|
||||||
},
|
},
|
||||||
clientCredit: {
|
clientCredit: {
|
||||||
creditButton: `${components.vnMenuItem}[ui-sref="client.card.credit.index"]`,
|
creditButton: `vn-menu-item a[ui-sref="client.card.credit.index"]`,
|
||||||
addCreditFloatButton: `${components.vnFloatButton}`,
|
addCreditFloatButton: `${components.vnFloatButton}`,
|
||||||
creditInput: `${components.vnTextfield}[name="credit"]`,
|
creditInput: `${components.vnTextfield}[name="credit"]`,
|
||||||
saveButton: `${components.vnSubmit}`,
|
saveButton: `${components.vnSubmit}`,
|
||||||
firstCreditText: 'vn-client-credit-index .list-element'
|
firstCreditText: 'vn-client-credit-index .list-element'
|
||||||
},
|
},
|
||||||
clientGreuge: {
|
clientGreuge: {
|
||||||
greugeButton: `${components.vnMenuItem}[ui-sref="client.card.greuge.index"]`,
|
greugeButton: `vn-menu-item a[ui-sref="client.card.greuge.index"]`,
|
||||||
addGreugeFloatButton: `${components.vnFloatButton}`,
|
addGreugeFloatButton: `${components.vnFloatButton}`,
|
||||||
amountInput: `${components.vnTextfield}[name="amount"]`,
|
amountInput: `${components.vnTextfield}[name="amount"]`,
|
||||||
descriptionInput: `${components.vnTextfield}[name="description"]`,
|
descriptionInput: `${components.vnTextfield}[name="description"]`,
|
||||||
typeInput: `${components.vnAutocomplete}[field="$ctrl.greuge.greugeTypeFk"] input`,
|
typeInput: `vn-autocomplete[field="$ctrl.greuge.greugeTypeFk"] input`,
|
||||||
typeSecondOption: `${components.vnAutocomplete}[field="$ctrl.greuge.greugeTypeFk"] vn-drop-down ul > li`,
|
typeSecondOption: `vn-autocomplete[field="$ctrl.greuge.greugeTypeFk"] vn-drop-down ul > li`,
|
||||||
saveButton: `${components.vnSubmit}`,
|
saveButton: `${components.vnSubmit}`,
|
||||||
firstGreugeText: 'vn-client-greuge-index .list-element'
|
firstGreugeText: 'vn-client-greuge-index .list-element'
|
||||||
},
|
},
|
||||||
clientMandate: {
|
clientMandate: {
|
||||||
mandateButton: `${components.vnMenuItem}[ui-sref="client.card.mandate"]`,
|
mandateButton: `vn-menu-item a[ui-sref="client.card.mandate"]`,
|
||||||
firstMandateText: 'vn-client-mandate .list-element'
|
firstMandateText: 'vn-client-mandate .list-element'
|
||||||
},
|
},
|
||||||
clientInvoices: {
|
clientInvoices: {
|
||||||
invoicesButton: `${components.vnMenuItem}[ui-sref="client.card.invoice"]`,
|
invoicesButton: `vn-menu-item a[ui-sref="client.card.invoice"]`,
|
||||||
firstInvoiceText: 'vn-client-invoice .list-element'
|
firstInvoiceText: 'vn-client-invoice .list-element'
|
||||||
},
|
},
|
||||||
itemsIndex: {
|
itemsIndex: {
|
||||||
|
@ -158,167 +158,167 @@ export default {
|
||||||
searchResultCloneButton: `vn-item-product .buttons > [icon="icon-clone"]`,
|
searchResultCloneButton: `vn-item-product .buttons > [icon="icon-clone"]`,
|
||||||
acceptClonationAlertButton: `vn-item-index [vn-id="clone"] [response="ACCEPT"]`,
|
acceptClonationAlertButton: `vn-item-index [vn-id="clone"] [response="ACCEPT"]`,
|
||||||
searchItemInput: `${components.vnTextfield}`,
|
searchItemInput: `${components.vnTextfield}`,
|
||||||
searchButton: `${components.vnSearchBar} > vn-icon-button`,
|
searchButton: `vn-searchbar vn-icon-button[icon="search"]`,
|
||||||
closeItemSummaryPreview: 'vn-item-index [vn-id="preview"] button.close'
|
closeItemSummaryPreview: 'vn-item-index [vn-id="preview"] button.close'
|
||||||
},
|
},
|
||||||
itemCreateView: {
|
itemCreateView: {
|
||||||
name: `${components.vnTextfield}[name="name"]`,
|
name: `${components.vnTextfield}[name="name"]`,
|
||||||
typeSelect: `${components.vnAutocomplete}[field="$ctrl.item.typeFk"] input`,
|
typeSelect: `vn-autocomplete[field="$ctrl.item.typeFk"] input`,
|
||||||
typeSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.item.typeFk"] vn-drop-down ul > li:nth-child(2)`,
|
typeSelectOptionOne: `vn-autocomplete[field="$ctrl.item.typeFk"] vn-drop-down ul > li:nth-child(2)`,
|
||||||
intrastatSelect: `${components.vnAutocomplete}[field="$ctrl.item.intrastatFk"] input`,
|
intrastatSelect: `vn-autocomplete[field="$ctrl.item.intrastatFk"] input`,
|
||||||
intrastatSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.item.intrastatFk"] vn-drop-down ul > li:nth-child(2)`,
|
intrastatSelectOptionOne: `vn-autocomplete[field="$ctrl.item.intrastatFk"] vn-drop-down ul > li:nth-child(2)`,
|
||||||
originSelect: `${components.vnAutocomplete}[field="$ctrl.item.originFk"] input`,
|
originSelect: `vn-autocomplete[field="$ctrl.item.originFk"] input`,
|
||||||
originSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.item.originFk"] vn-drop-down ul > li:nth-child(2)`,
|
originSelectOptionOne: `vn-autocomplete[field="$ctrl.item.originFk"] vn-drop-down ul > li:nth-child(2)`,
|
||||||
createButton: `${components.vnSubmit}`,
|
createButton: `${components.vnSubmit}`,
|
||||||
cancelButton: `button[ui-sref="item.index"]`
|
cancelButton: `button[ui-sref="item.index"]`
|
||||||
|
|
||||||
},
|
},
|
||||||
itemBasicData: {
|
itemBasicData: {
|
||||||
goToItemIndexButton: 'vn-item-descriptor [ui-sref="item.index"]',
|
goToItemIndexButton: 'vn-item-descriptor [ui-sref="item.index"]',
|
||||||
basicDataButton: `${components.vnMenuItem}[ui-sref="item.card.data"]`,
|
basicDataButton: `vn-menu-item a[ui-sref="item.card.data"]`,
|
||||||
typeSelect: `${components.vnAutocomplete}[field="$ctrl.item.typeFk"] input`,
|
typeSelect: `vn-autocomplete[field="$ctrl.item.typeFk"] input`,
|
||||||
typeSelectOptionTwo: `${components.vnAutocomplete}[field="$ctrl.item.typeFk"] vn-drop-down ul > li:nth-child(2)`,
|
typeSelectOptionTwo: `vn-autocomplete[field="$ctrl.item.typeFk"] vn-drop-down ul > li:nth-child(2)`,
|
||||||
intrastatSelect: `${components.vnAutocomplete}[field="$ctrl.item.intrastatFk"] input`,
|
intrastatSelect: `vn-autocomplete[field="$ctrl.item.intrastatFk"] input`,
|
||||||
intrastatSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.item.intrastatFk"] vn-drop-down ul > li:nth-child(1)`,
|
intrastatSelectOptionOne: `vn-autocomplete[field="$ctrl.item.intrastatFk"] vn-drop-down ul > li:nth-child(1)`,
|
||||||
nameInput: `vn-horizontal:nth-child(2) > ${components.vnTextfield}`,
|
nameInput: `vn-horizontal:nth-child(2) > ${components.vnTextfield}`,
|
||||||
relevancyInput: `vn-horizontal:nth-child(3) > ${components.vnTextfield}`,
|
relevancyInput: `vn-horizontal:nth-child(3) > ${components.vnTextfield}`,
|
||||||
originSelect: `${components.vnAutocomplete}[field="$ctrl.item.originFk"] input`,
|
originSelect: `vn-autocomplete[field="$ctrl.item.originFk"] input`,
|
||||||
originSelectOptionTwo: `${components.vnAutocomplete}[field="$ctrl.item.originFk"] vn-drop-down ul > li:nth-child(2)`,
|
originSelectOptionTwo: `vn-autocomplete[field="$ctrl.item.originFk"] vn-drop-down ul > li:nth-child(2)`,
|
||||||
expenceSelect: `${components.vnAutocomplete}[field="$ctrl.item.expenceFk"] input`,
|
expenceSelect: `vn-autocomplete[field="$ctrl.item.expenceFk"] input`,
|
||||||
expenceSelectOptionTwo: `${components.vnAutocomplete}[field="$ctrl.item.expenceFk"] vn-drop-down ul > li:nth-child(2)`,
|
expenceSelectOptionTwo: `vn-autocomplete[field="$ctrl.item.expenceFk"] vn-drop-down ul > li:nth-child(2)`,
|
||||||
submitBasicDataButton: `${components.vnSubmit}`
|
submitBasicDataButton: `${components.vnSubmit}`
|
||||||
},
|
},
|
||||||
itemTags: {
|
itemTags: {
|
||||||
goToItemIndexButton: 'vn-item-descriptor [ui-sref="item.index"]',
|
goToItemIndexButton: 'vn-item-descriptor [ui-sref="item.index"]',
|
||||||
tagsButton: `${components.vnMenuItem}[ui-sref="item.card.tags"]`,
|
tagsButton: `vn-menu-item a[ui-sref="item.card.tags"]`,
|
||||||
firstRemoveTagButton: `vn-item-tags vn-horizontal:nth-child(2) > ${components.vnIcon}[icon="remove_circle_outline"]`,
|
firstRemoveTagButton: `vn-item-tags vn-horizontal:nth-child(2) > vn-icon[icon="remove_circle_outline"]`,
|
||||||
firstTagSelect: `vn-item-tags vn-horizontal:nth-child(2) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`,
|
firstTagSelect: `vn-item-tags vn-horizontal:nth-child(2) > vn-autocomplete[field="itemTag.tagFk"] input`,
|
||||||
firstTagDisabled: `vn-item-tags vn-horizontal:nth-child(2) > vn-autocomplete > div > div > input`,
|
firstTagDisabled: `vn-item-tags vn-horizontal:nth-child(2) > vn-autocomplete > div > div > input`,
|
||||||
firstTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(2) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
firstTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(2) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
||||||
firstValueInput: `vn-item-tags vn-horizontal:nth-child(2) > vn-textfield[label="Value"] > div > input`,
|
firstValueInput: `vn-item-tags vn-horizontal:nth-child(2) > vn-textfield[label="Value"] > div > input`,
|
||||||
firstRelevancyInput: `vn-horizontal:nth-child(2) > vn-textfield[label="Relevancy"] > div > input`,
|
firstRelevancyInput: `vn-horizontal:nth-child(2) > vn-textfield[label="Relevancy"] > div > input`,
|
||||||
secondTagSelect: `vn-item-tags vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`,
|
secondTagSelect: `vn-item-tags vn-horizontal:nth-child(3) > vn-autocomplete[field="itemTag.tagFk"] input`,
|
||||||
secondTagDisabled: `vn-item-tags vn-horizontal:nth-child(3) > vn-autocomplete > div > div > input`,
|
secondTagDisabled: `vn-item-tags vn-horizontal:nth-child(3) > vn-autocomplete > div > div > input`,
|
||||||
secondTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
secondTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(3) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
||||||
secondValueInput: `vn-item-tags vn-horizontal:nth-child(3) > vn-textfield[label="Value"] > div > input`,
|
secondValueInput: `vn-item-tags vn-horizontal:nth-child(3) > vn-textfield[label="Value"] > div > input`,
|
||||||
secondRelevancyInput: `vn-horizontal:nth-child(3) > vn-textfield[label="Relevancy"] > div > input`,
|
secondRelevancyInput: `vn-horizontal:nth-child(3) > vn-textfield[label="Relevancy"] > div > input`,
|
||||||
thirdTagSelect: `vn-item-tags vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`,
|
thirdTagSelect: `vn-item-tags vn-horizontal:nth-child(4) > vn-autocomplete[field="itemTag.tagFk"] input`,
|
||||||
thirdTagDisabled: `vn-item-tags vn-horizontal:nth-child(4) > vn-autocomplete > div > div > input`,
|
thirdTagDisabled: `vn-item-tags vn-horizontal:nth-child(4) > vn-autocomplete > div > div > input`,
|
||||||
thirdTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
thirdTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(4) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
||||||
thirdValueInput: `vn-item-tags vn-horizontal:nth-child(4) > vn-textfield[label="Value"] > div > input`,
|
thirdValueInput: `vn-item-tags vn-horizontal:nth-child(4) > vn-textfield[label="Value"] > div > input`,
|
||||||
thirdRelevancyInput: `vn-horizontal:nth-child(4) > vn-textfield[label="Relevancy"] > div > input`,
|
thirdRelevancyInput: `vn-horizontal:nth-child(4) > vn-textfield[label="Relevancy"] > div > input`,
|
||||||
fourthTagSelect: `vn-item-tags vn-horizontal:nth-child(5) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`,
|
fourthTagSelect: `vn-item-tags vn-horizontal:nth-child(5) > vn-autocomplete[field="itemTag.tagFk"] input`,
|
||||||
fourthTagDisabled: `vn-item-tags vn-horizontal:nth-child(5) > vn-autocomplete > div > div > input`,
|
fourthTagDisabled: `vn-item-tags vn-horizontal:nth-child(5) > vn-autocomplete > div > div > input`,
|
||||||
fourthTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(5) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
fourthTagSelectOptionOne: `vn-item-tags vn-horizontal:nth-child(5) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(1)`,
|
||||||
fourthValueInput: `vn-item-tags vn-horizontal:nth-child(5) > vn-textfield[label="Value"] > div > input`,
|
fourthValueInput: `vn-item-tags vn-horizontal:nth-child(5) > vn-textfield[label="Value"] > div > input`,
|
||||||
fourthRelevancyInput: `vn-horizontal:nth-child(5) > vn-textfield[label="Relevancy"] > div > input`,
|
fourthRelevancyInput: `vn-horizontal:nth-child(5) > vn-textfield[label="Relevancy"] > div > input`,
|
||||||
fifthTagSelect: `vn-item-tags vn-horizontal:nth-child(6) > ${components.vnAutocomplete}[field="itemTag.tagFk"] input`,
|
fifthTagSelect: `vn-item-tags vn-horizontal:nth-child(6) > vn-autocomplete[field="itemTag.tagFk"] input`,
|
||||||
fifthTagDisabled: `vn-item-tags vn-horizontal:nth-child(6) > vn-autocomplete > div > div > input`,
|
fifthTagDisabled: `vn-item-tags vn-horizontal:nth-child(6) > vn-autocomplete > div > div > input`,
|
||||||
fifthTagSelectOptionFive: `vn-item-tags vn-horizontal:nth-child(6) > ${components.vnAutocomplete}[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(5)`,
|
fifthTagSelectOptionFive: `vn-item-tags vn-horizontal:nth-child(6) > vn-autocomplete[field="itemTag.tagFk"] vn-drop-down ul > li:nth-child(5)`,
|
||||||
fifthValueInput: `vn-item-tags vn-horizontal:nth-child(6) > vn-textfield[label="Value"] > div > input`,
|
fifthValueInput: `vn-item-tags vn-horizontal:nth-child(6) > vn-textfield[label="Value"] > div > input`,
|
||||||
fifthRelevancyInput: `vn-horizontal:nth-child(6) > vn-textfield[label="Relevancy"] > div > input`,
|
fifthRelevancyInput: `vn-horizontal:nth-child(6) > vn-textfield[label="Relevancy"] > div > input`,
|
||||||
addItemTagButton: `${components.vnIcon}[icon="add_circle"]`,
|
addItemTagButton: `vn-icon[icon="add_circle"]`,
|
||||||
submitItemTagsButton: `${components.vnSubmit}`
|
submitItemTagsButton: `${components.vnSubmit}`
|
||||||
},
|
},
|
||||||
itemTax: {
|
itemTax: {
|
||||||
taxButton: `${components.vnMenuItem}[ui-sref="item.card.tax"]`,
|
taxButton: `vn-menu-item a[ui-sref="item.card.tax"]`,
|
||||||
firstClassSelect: `vn-horizontal:nth-child(2) > ${components.vnAutocomplete}[field="tax.taxClassFk"] input`,
|
firstClassSelect: `vn-horizontal:nth-child(2) > vn-autocomplete[field="tax.taxClassFk"] input`,
|
||||||
firstClassSelectOptionTwo: `vn-horizontal:nth-child(2) > ${components.vnAutocomplete} vn-drop-down ul > li:nth-child(2)`,
|
firstClassSelectOptionTwo: `vn-horizontal:nth-child(2) > vn-autocomplete vn-drop-down ul > li:nth-child(2)`,
|
||||||
secondClassSelect: `vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="tax.taxClassFk"] input`,
|
secondClassSelect: `vn-horizontal:nth-child(3) > vn-autocomplete[field="tax.taxClassFk"] input`,
|
||||||
secondClassSelectOptionOne: `vn-horizontal:nth-child(3) > ${components.vnAutocomplete} vn-drop-down ul > li:nth-child(1)`,
|
secondClassSelectOptionOne: `vn-horizontal:nth-child(3) > vn-autocomplete vn-drop-down ul > li:nth-child(1)`,
|
||||||
thirdClassSelect: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="tax.taxClassFk"] input`,
|
thirdClassSelect: `vn-horizontal:nth-child(4) > vn-autocomplete[field="tax.taxClassFk"] input`,
|
||||||
thirdClassSelectOptionTwo: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete} vn-drop-down ul > li:nth-child(2)`,
|
thirdClassSelectOptionTwo: `vn-horizontal:nth-child(4) > vn-autocomplete vn-drop-down ul > li:nth-child(2)`,
|
||||||
submitTaxButton: `${components.vnSubmit}`
|
submitTaxButton: `${components.vnSubmit}`
|
||||||
},
|
},
|
||||||
itemBarcodes: {
|
itemBarcodes: {
|
||||||
barcodeButton: `${components.vnMenuItem}[ui-sref="item.card.itemBarcode"]`,
|
barcodeButton: `vn-menu-item a[ui-sref="item.card.itemBarcode"]`,
|
||||||
addBarcodeButton: `${components.vnIcon}[icon="add_circle"]`,
|
addBarcodeButton: `vn-icon[icon="add_circle"]`,
|
||||||
thirdCodeInput: `vn-item-barcode vn-horizontal:nth-child(4) > ${components.vnTextfield}`,
|
thirdCodeInput: `vn-item-barcode vn-horizontal:nth-child(4) > ${components.vnTextfield}`,
|
||||||
submitBarcodesButton: `${components.vnSubmit}`,
|
submitBarcodesButton: `${components.vnSubmit}`,
|
||||||
firstCodeRemoveButton: `vn-horizontal:nth-child(2) > ${components.vnIcon}[icon="remove_circle_outline"]`
|
firstCodeRemoveButton: `vn-horizontal:nth-child(2) > vn-icon[icon="remove_circle_outline"]`
|
||||||
},
|
},
|
||||||
itemNiches: {
|
itemNiches: {
|
||||||
nicheButton: `${components.vnMenuItem}[ui-sref="item.card.niche"]`,
|
nicheButton: `vn-menu-item a[ui-sref="item.card.niche"]`,
|
||||||
addNicheButton: `${components.vnIcon}[icon="add_circle"]`,
|
addNicheButton: `vn-icon[icon="add_circle"]`,
|
||||||
firstWarehouseSelect: `${components.vnAutocomplete}[field="itemNiche.warehouseFk"] input`,
|
firstWarehouseSelect: `vn-autocomplete[field="itemNiche.warehouseFk"] input`,
|
||||||
firstWarehouseDisabled: `vn-horizontal:nth-child(2) > vn-textfield[label="Warehouse"] > div > input`,
|
firstWarehouseDisabled: `vn-horizontal:nth-child(2) > vn-textfield[label="Warehouse"] > div > input`,
|
||||||
firstWarehouseSelectSecondOption: `${components.vnAutocomplete}[field="itemNiche.warehouseFk"] vn-drop-down ul > li:nth-child(2)`,
|
firstWarehouseSelectSecondOption: `vn-autocomplete[field="itemNiche.warehouseFk"] vn-drop-down ul > li:nth-child(2)`,
|
||||||
firstCodeInput: `vn-horizontal:nth-child(2) > vn-textfield[label="Code"] > div > input`,
|
firstCodeInput: `vn-horizontal:nth-child(2) > vn-textfield[label="Code"] > div > input`,
|
||||||
secondWarehouseSelect: `vn-horizontal:nth-child(3) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] input`,
|
secondWarehouseSelect: `vn-horizontal:nth-child(3) > vn-autocomplete[field="itemNiche.warehouseFk"] input`,
|
||||||
secondWarehouseDisabled: `vn-horizontal:nth-child(3) > vn-textfield[label="Warehouse"] > div > input`,
|
secondWarehouseDisabled: `vn-horizontal:nth-child(3) > vn-textfield[label="Warehouse"] > div > input`,
|
||||||
secondCodeInput: `vn-horizontal:nth-child(3) > vn-textfield[label="Code"] > div > input`,
|
secondCodeInput: `vn-horizontal:nth-child(3) > vn-textfield[label="Code"] > div > input`,
|
||||||
secondNicheRemoveButton: `vn-horizontal:nth-child(3) > ${components.vnIcon}[icon="remove_circle_outline"]`,
|
secondNicheRemoveButton: `vn-horizontal:nth-child(3) > vn-icon[icon="remove_circle_outline"]`,
|
||||||
thirdWarehouseSelect: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] input`,
|
thirdWarehouseSelect: `vn-horizontal:nth-child(4) > vn-autocomplete[field="itemNiche.warehouseFk"] input`,
|
||||||
thirdWarehouseDisabled: `vn-horizontal:nth-child(4) > vn-textfield[label="Warehouse"] > div > input`,
|
thirdWarehouseDisabled: `vn-horizontal:nth-child(4) > vn-textfield[label="Warehouse"] > div > input`,
|
||||||
thirdWarehouseSelectFourthOption: `vn-horizontal:nth-child(4) > ${components.vnAutocomplete}[field="itemNiche.warehouseFk"] vn-drop-down ul > li:nth-child(4)`,
|
thirdWarehouseSelectFourthOption: `vn-horizontal:nth-child(4) > vn-autocomplete[field="itemNiche.warehouseFk"] vn-drop-down ul > li:nth-child(4)`,
|
||||||
thirdCodeInput: `vn-horizontal:nth-child(4) > vn-textfield[label="Code"] > div > input`,
|
thirdCodeInput: `vn-horizontal:nth-child(4) > vn-textfield[label="Code"] > div > input`,
|
||||||
submitNichesButton: `${components.vnSubmit}`
|
submitNichesButton: `${components.vnSubmit}`
|
||||||
},
|
},
|
||||||
itemBotanical: {
|
itemBotanical: {
|
||||||
botanicalButton: `${components.vnMenuItem}[ui-sref="item.card.botanical"]`,
|
botanicalButton: `vn-menu-item a[ui-sref="item.card.botanical"]`,
|
||||||
botanicalInput: `vn-horizontal:nth-child(2) > ${components.vnTextfield}`,
|
botanicalInput: `vn-horizontal:nth-child(2) > ${components.vnTextfield}`,
|
||||||
genusSelect: `${components.vnAutocomplete}[field="$ctrl.botanical.genusFk"] input`,
|
genusSelect: `vn-autocomplete[field="$ctrl.botanical.genusFk"] input`,
|
||||||
genusSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.botanical.genusFk"] vn-drop-down ul > li:nth-child(1)`,
|
genusSelectOptionOne: `vn-autocomplete[field="$ctrl.botanical.genusFk"] vn-drop-down ul > li:nth-child(1)`,
|
||||||
genusSelectOptionTwo: `${components.vnAutocomplete}[field="$ctrl.botanical.genusFk"] vn-drop-down ul > li:nth-child(2)`,
|
genusSelectOptionTwo: `vn-autocomplete[field="$ctrl.botanical.genusFk"] vn-drop-down ul > li:nth-child(2)`,
|
||||||
speciesSelect: `${components.vnAutocomplete}[field="$ctrl.botanical.specieFk"] input`,
|
speciesSelect: `vn-autocomplete[field="$ctrl.botanical.specieFk"] input`,
|
||||||
speciesSelectOptionOne: `${components.vnAutocomplete}[field="$ctrl.botanical.specieFk"] vn-drop-down ul > li:nth-child(1)`,
|
speciesSelectOptionOne: `vn-autocomplete[field="$ctrl.botanical.specieFk"] vn-drop-down ul > li:nth-child(1)`,
|
||||||
speciesSelectOptionTwo: `${components.vnAutocomplete}[field="$ctrl.botanical.specieFk"] vn-drop-down ul > li:nth-child(2)`,
|
speciesSelectOptionTwo: `vn-autocomplete[field="$ctrl.botanical.specieFk"] vn-drop-down ul > li:nth-child(2)`,
|
||||||
submitBotanicalButton: `${components.vnSubmit}`
|
submitBotanicalButton: `${components.vnSubmit}`
|
||||||
},
|
},
|
||||||
itemSummary: {
|
itemSummary: {
|
||||||
basicData: `${components.vnItemSummary} vn-vertical[name="basicData"]`,
|
basicData: `vn-item-summary vn-vertical[name="basicData"]`,
|
||||||
vat: `${components.vnItemSummary} vn-vertical[name="tax"]`,
|
vat: `vn-item-summary vn-vertical[name="tax"]`,
|
||||||
tags: `${components.vnItemSummary} vn-vertical[name="tags"]`,
|
tags: `vn-item-summary vn-vertical[name="tags"]`,
|
||||||
niche: `${components.vnItemSummary} vn-vertical[name="niche"]`,
|
niche: `vn-item-summary vn-vertical[name="niche"]`,
|
||||||
botanical: `${components.vnItemSummary} vn-vertical[name="botanical"]`,
|
botanical: `vn-item-summary vn-vertical[name="botanical"]`,
|
||||||
barcode: `${components.vnItemSummary} vn-vertical[name="barcode"]`
|
barcode: `vn-item-summary vn-vertical[name="barcode"]`
|
||||||
},
|
},
|
||||||
ticketsIndex: {
|
ticketsIndex: {
|
||||||
createTicketButton: `${components.vnFloatButton}`,
|
createTicketButton: `${components.vnFloatButton}`,
|
||||||
searchResult: `table > tbody > tr`,
|
searchResult: `table > tbody > tr`,
|
||||||
searchTicketInput: `${components.vnTextfield}`,
|
searchTicketInput: `${components.vnTextfield}`,
|
||||||
searchButton: `${components.vnSearchBar} > vn-icon-button`
|
searchButton: `vn-searchbar vn-icon-button[icon="search"]`
|
||||||
},
|
},
|
||||||
ticketNotes: {
|
ticketNotes: {
|
||||||
notesButton: `${components.vnMenuItem}[ui-sref="ticket.card.observation"]`,
|
notesButton: `vn-menu-item a[ui-sref="ticket.card.observation"]`,
|
||||||
firstNoteRemoveButton: `${components.vnIcon}[icon="remove_circle_outline"]`,
|
firstNoteRemoveButton: `vn-icon[icon="remove_circle_outline"]`,
|
||||||
addNoteButton: `${components.vnIcon}[icon="add_circle"]`,
|
addNoteButton: `vn-icon[icon="add_circle"]`,
|
||||||
firstNoteSelect: `${components.vnAutocomplete}[field="ticketObservation.observationTypeFk"] input`,
|
firstNoteSelect: `vn-autocomplete[field="ticketObservation.observationTypeFk"] input`,
|
||||||
firstNoteSelectSecondOption: `${components.vnAutocomplete}[field="ticketObservation.observationTypeFk"] vn-drop-down ul > li:nth-child(2)`,
|
firstNoteSelectSecondOption: `vn-autocomplete[field="ticketObservation.observationTypeFk"] vn-drop-down ul > li:nth-child(2)`,
|
||||||
firstNoteDisabled: `vn-textfield[label="Observation type"] > div > input`,
|
firstNoteDisabled: `vn-textfield[label="Observation type"] > div > input`,
|
||||||
firstDescriptionInput: `vn-textfield[label="Description"] > div > input`,
|
firstDescriptionInput: `vn-textfield[label="Description"] > div > input`,
|
||||||
submitNotesButton: `${components.vnSubmit}`
|
submitNotesButton: `${components.vnSubmit}`
|
||||||
},
|
},
|
||||||
ticketExpedition: {
|
ticketExpedition: {
|
||||||
expeditionButton: `${components.vnMenuItem}[ui-sref="ticket.card.expedition"]`,
|
expeditionButton: `vn-menu-item a[ui-sref="ticket.card.expedition"]`,
|
||||||
secondExpeditionRemoveButton: `body > vn-app > vn-vertical > vn-vertical > ui-view > vn-ticket-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-ticket-expedition > vn-vertical > vn-card > div > vn-vertical > vn-one > vn-horizontal:nth-child(2) > vn-one:nth-child(1) > i`,
|
secondExpeditionRemoveButton: `body > vn-app > vn-vertical > vn-vertical > ui-view > vn-ticket-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-ticket-expedition > vn-vertical > vn-card > div > vn-vertical > vn-one > vn-horizontal:nth-child(2) > vn-one:nth-child(1) > i`,
|
||||||
secondExpeditionText: `body > vn-app > vn-vertical > vn-vertical > ui-view > vn-ticket-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-ticket-expedition > vn-vertical > vn-card > div > vn-vertical > vn-one > vn-horizontal:nth-child(2)`
|
secondExpeditionText: `body > vn-app > vn-vertical > vn-vertical > ui-view > vn-ticket-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-ticket-expedition > vn-vertical > vn-card > div > vn-vertical > vn-one > vn-horizontal:nth-child(2)`
|
||||||
},
|
},
|
||||||
ticketPackages: {
|
ticketPackages: {
|
||||||
packagesButton: `${components.vnMenuItem}[ui-sref="ticket.card.package.index"]`,
|
packagesButton: `vn-menu-item a[ui-sref="ticket.card.package.index"]`,
|
||||||
firstPackageSelect: `${components.vnAutocomplete}[label="Package"] > div > div > input`,
|
firstPackageSelect: `vn-autocomplete[label="Package"] > div > div > input`,
|
||||||
firstPackageSelectOptionThree: `${components.vnAutocomplete}[label="Package"] vn-drop-down ul > li:nth-child(3)`,
|
firstPackageSelectOptionThree: `vn-autocomplete[label="Package"] vn-drop-down ul > li:nth-child(3)`,
|
||||||
firstQuantityInput: `vn-textfield[label="Quantity"] > div > input`,
|
firstQuantityInput: `vn-textfield[label="Quantity"] > div > input`,
|
||||||
firstRemovePackageButton: `vn-icon[vn-tooltip="Remove package"]`,
|
firstRemovePackageButton: `vn-icon[vn-tooltip="Remove package"]`,
|
||||||
addPackageButton: `vn-icon[vn-tooltip="Add package"]`,
|
addPackageButton: `vn-icon[vn-tooltip="Add package"]`,
|
||||||
clearPackageSelectButton: `${components.vnAutocomplete}[label="Package"] > div > div > div > vn-icon > i`,
|
clearPackageSelectButton: `vn-autocomplete[label="Package"] > div > div > div > vn-icon > i`,
|
||||||
savePackagesButton: `${components.vnSubmit}`
|
savePackagesButton: `${components.vnSubmit}`
|
||||||
},
|
},
|
||||||
ticketSales: {
|
ticketSales: {
|
||||||
saleButton: `${components.vnMenuItem}[ui-sref="ticket.card.sale"]`,
|
saleButton: `vn-menu-item a[ui-sref="ticket.card.sale"]`,
|
||||||
firstSaleText: `table > tbody > tr:nth-child(1)`,
|
firstSaleText: `table > tbody > tr:nth-child(1)`,
|
||||||
secondSaleText: `table > tbody > tr:nth-child(2)`
|
secondSaleText: `table > tbody > tr:nth-child(2)`
|
||||||
},
|
},
|
||||||
ticketTracking: {
|
ticketTracking: {
|
||||||
trackingButton: `${components.vnMenuItem}[ui-sref="ticket.card.tracking.index"]`,
|
trackingButton: `vn-menu-item a[ui-sref="ticket.card.tracking.index"]`,
|
||||||
createStateButton: `${components.vnFloatButton}`,
|
createStateButton: `${components.vnFloatButton}`,
|
||||||
firstSaleText: `table > tbody > tr:nth-child(1)`,
|
firstSaleText: `table > tbody > tr:nth-child(1)`,
|
||||||
secondSaleText: `table > tbody > tr:nth-child(2)`
|
secondSaleText: `table > tbody > tr:nth-child(2)`
|
||||||
},
|
},
|
||||||
createStateView: {
|
createStateView: {
|
||||||
stateInput: `${components.vnAutocomplete}[field="$ctrl.ticket.stateFk"] > div > div > input`,
|
stateInput: `vn-autocomplete[field="$ctrl.ticket.stateFk"] > div > div > input`,
|
||||||
stateInputOptionOne: `${components.vnAutocomplete}[field="$ctrl.ticket.stateFk"] vn-drop-down ul > li:nth-child(1)`,
|
stateInputOptionOne: `vn-autocomplete[field="$ctrl.ticket.stateFk"] vn-drop-down ul > li:nth-child(1)`,
|
||||||
clearStateInputButton: `${components.vnAutocomplete}[field="$ctrl.ticket.stateFk"] > div > div > div > vn-icon > i`,
|
clearStateInputButton: `vn-autocomplete[field="$ctrl.ticket.stateFk"] > div > div > div > vn-icon > i`,
|
||||||
saveStateButton: `${components.vnSubmit}`
|
saveStateButton: `${components.vnSubmit}`
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -67,7 +67,7 @@ describe('Client', () => {
|
||||||
.click(selectors.createClientView.createButton)
|
.click(selectors.createClientView.createButton)
|
||||||
.waitForSnackbar()
|
.waitForSnackbar()
|
||||||
.then(result => {
|
.then(result => {
|
||||||
expect(result).toEqual('Some fields are invalid');
|
expect(result).toContain('Some fields are invalid');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ describe('Client', () => {
|
||||||
.waitToClick(selectors.clientAddresses.saveButton)
|
.waitToClick(selectors.clientAddresses.saveButton)
|
||||||
.waitForSnackbar()
|
.waitForSnackbar()
|
||||||
.then(result => {
|
.then(result => {
|
||||||
expect(result).toContain('No field can be blank');
|
expect(result).toContain('type cannot be blank');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ describe('Ticket', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`should attempt create a new state but receive an error if state have been cleared`, () => {
|
it(`should attempt create a new state then clear and save it`, () => {
|
||||||
return nightmare
|
return nightmare
|
||||||
.waitToClick(selectors.createStateView.stateInput)
|
.waitToClick(selectors.createStateView.stateInput)
|
||||||
.waitToClick(selectors.createStateView.stateInputOptionOne)
|
.waitToClick(selectors.createStateView.stateInputOptionOne)
|
||||||
|
@ -73,7 +73,17 @@ describe('Ticket', () => {
|
||||||
.click(selectors.createStateView.saveStateButton)
|
.click(selectors.createStateView.saveStateButton)
|
||||||
.waitForSnackbar()
|
.waitForSnackbar()
|
||||||
.then(result => {
|
.then(result => {
|
||||||
expect(result).toContain('No changes to save');
|
expect(result).toContain('Data saved!');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should access to the create state view by clicking the create floating button', () => {
|
||||||
|
return nightmare
|
||||||
|
.click(selectors.ticketTracking.createStateButton)
|
||||||
|
.wait(selectors.createStateView.stateInput)
|
||||||
|
.parsedUrl()
|
||||||
|
.then(url => {
|
||||||
|
expect(url.hash).toContain('tracking/edit');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -103,19 +103,19 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"angular": {
|
"angular": {
|
||||||
"version": "1.6.8",
|
"version": "1.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/angular/-/angular-1.6.8.tgz",
|
"resolved": "https://registry.npmjs.org/angular/-/angular-1.7.0.tgz",
|
||||||
"integrity": "sha512-9WErZIOw1Cu1V5Yxdvxz/6YpND8ntdP71fdPpufPFJvZodZXqCjQBYrHqEoMZreO5i84O3D/Jw/vepoFt68Azw=="
|
"integrity": "sha512-3LboCLjrOuC7dWh953O0+dI3dJ7PexYRSCIrfqoN5qoHyja/wak3eWoxPKb2Sl2qwiPbrUV5KJXwgpUQ48McBQ=="
|
||||||
},
|
},
|
||||||
"angular-cookies": {
|
"angular-cookies": {
|
||||||
"version": "1.6.4",
|
"version": "1.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/angular-cookies/-/angular-cookies-1.6.4.tgz",
|
"resolved": "https://registry.npmjs.org/angular-cookies/-/angular-cookies-1.7.0.tgz",
|
||||||
"integrity": "sha1-wo8/aqx6mCbB5F8daAckADblsm0="
|
"integrity": "sha512-bxY7SAl7M+P+DazcDq4OVSFhmR0QET6KWw7bsxh4V22Ky+NcGbdyFySRNqu0TtWB5LkiGvo0wCFLd/vDyuMQOQ=="
|
||||||
},
|
},
|
||||||
"angular-mocks": {
|
"angular-mocks": {
|
||||||
"version": "1.6.6",
|
"version": "1.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/angular-mocks/-/angular-mocks-1.6.6.tgz",
|
"resolved": "https://registry.npmjs.org/angular-mocks/-/angular-mocks-1.7.0.tgz",
|
||||||
"integrity": "sha1-yTAY54OMbcXOrxprz5vhPIMOpRU=",
|
"integrity": "sha512-tBlj9jIEpbgiYY1VpV6XAi+5JSAO0AXFziVW4TSIFETB23fautoREI7XbOeRgy/QmOhZA4P320gs2XgpbvLd0w==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"angular-paging": {
|
"angular-paging": {
|
||||||
|
@ -124,19 +124,19 @@
|
||||||
"integrity": "sha1-cC9XTW0UBpADXqxkOV/jEfeYf7s="
|
"integrity": "sha1-cC9XTW0UBpADXqxkOV/jEfeYf7s="
|
||||||
},
|
},
|
||||||
"angular-translate": {
|
"angular-translate": {
|
||||||
"version": "2.17.0",
|
"version": "2.18.1",
|
||||||
"resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/angular-translate/-/angular-translate-2.18.1.tgz",
|
||||||
"integrity": "sha512-SudfI0R0Hhtvngc0X3wFChXQGmw90o95i+QPZ11LhJJryneTq8LR3+3E4E7jgHA4fu6TcswgcfZ9+cp5ckbUHw==",
|
"integrity": "sha512-Mw0kFBqsv5j8ItL9IhRZunIlVmIRW6iFsiTmRs9wGr2QTt8z4rehYlWyHos8qnXc/kyOYJiW50iH50CSNHGB9A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"angular": "1.6.8"
|
"angular": "1.7.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"angular-translate-loader-partial": {
|
"angular-translate-loader-partial": {
|
||||||
"version": "2.17.0",
|
"version": "2.18.1",
|
||||||
"resolved": "https://registry.npmjs.org/angular-translate-loader-partial/-/angular-translate-loader-partial-2.17.0.tgz",
|
"resolved": "https://registry.npmjs.org/angular-translate-loader-partial/-/angular-translate-loader-partial-2.18.1.tgz",
|
||||||
"integrity": "sha512-pyRJcRc93iwiUnRnh9ZfehbQE/yxO5T6jmEqIvLEVz8gKLjDqDLKcaQFgPef9wCIN2n3e531YbStkkbSH3LYmQ==",
|
"integrity": "sha512-+bPzY3+F2I1tb+X5bscvZq0OGoVEVkHwPGZvaY4nhbktpshArYpvIEV+RQFUa/QNj8vQc3iQ/pruJDb8w3zIdw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"angular-translate": "2.17.0"
|
"angular-translate": "2.18.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ansi-align": {
|
"ansi-align": {
|
||||||
|
@ -1383,7 +1383,7 @@
|
||||||
"bluebird": {
|
"bluebird": {
|
||||||
"version": "3.5.1",
|
"version": "3.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz",
|
||||||
"integrity": "sha1-2VUfnemPH82h5oPRfukaBgLuLrk=",
|
"integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"bn.js": {
|
"bn.js": {
|
||||||
|
@ -10785,7 +10785,7 @@
|
||||||
"jasmine-spec-reporter": {
|
"jasmine-spec-reporter": {
|
||||||
"version": "4.2.1",
|
"version": "4.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/jasmine-spec-reporter/-/jasmine-spec-reporter-4.2.1.tgz",
|
||||||
"integrity": "sha1-HWMq7ANBZwrTJPkrqEtLMrNeniI=",
|
"integrity": "sha512-FZBoZu7VE5nR7Nilzy+Np8KuVIOxF4oXDPDknehCYBDE080EnlPu0afdZNmpGDBRCUBv3mj5qgqCRmk6W/K8vg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"colors": "1.1.2"
|
"colors": "1.1.2"
|
||||||
|
@ -10933,7 +10933,7 @@
|
||||||
"karma": {
|
"karma": {
|
||||||
"version": "1.7.1",
|
"version": "1.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/karma/-/karma-1.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/karma/-/karma-1.7.1.tgz",
|
||||||
"integrity": "sha1-hcwI6eCiLXzpzKN8ShvoJPaisa4=",
|
"integrity": "sha512-k5pBjHDhmkdaUccnC7gE3mBzZjcxyxYsYVaqiL2G5AqlfLyBO5nw2VdNK+O16cveEPd/gIOWULH7gkiYYwVNHg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"bluebird": "3.5.1",
|
"bluebird": "3.5.1",
|
||||||
|
@ -10985,7 +10985,7 @@
|
||||||
"karma-chrome-launcher": {
|
"karma-chrome-launcher": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/karma-chrome-launcher/-/karma-chrome-launcher-2.2.0.tgz",
|
||||||
"integrity": "sha1-zxudBxNswY/iOTJ9JGVMPbw2is8=",
|
"integrity": "sha512-uf/ZVpAabDBPvdPdveyk1EPgbnloPvFFGgmRhYLTDH7gEB4nZdSBk8yTU47w1g/drLSx5uMOkjKk7IWKfWg/+w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"fs-access": "1.0.1",
|
"fs-access": "1.0.1",
|
||||||
|
@ -11822,7 +11822,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/mg-crud/-/mg-crud-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/mg-crud/-/mg-crud-1.1.2.tgz",
|
||||||
"integrity": "sha1-p6AWGzWSPK7/8ZpIBpS2V1vDggw=",
|
"integrity": "sha1-p6AWGzWSPK7/8ZpIBpS2V1vDggw=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"angular": "1.6.8"
|
"angular": "1.7.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"micromatch": {
|
"micromatch": {
|
||||||
|
@ -19992,7 +19992,7 @@
|
||||||
"useragent": {
|
"useragent": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz",
|
||||||
"integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=",
|
"integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"lru-cache": "4.1.1",
|
"lru-cache": "4.1.1",
|
||||||
|
|
10
package.json
10
package.json
|
@ -10,11 +10,11 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@uirouter/angularjs": "^1.0.3",
|
"@uirouter/angularjs": "^1.0.3",
|
||||||
"angular": "^1.6.8",
|
"angular": "^1.7.0",
|
||||||
"angular-cookies": "^1.6.4",
|
"angular-cookies": "^1.7.0",
|
||||||
"angular-paging": "^2.2.2",
|
"angular-paging": "^2.2.2",
|
||||||
"angular-translate": "^2.17.0",
|
"angular-translate": "^2.18.1",
|
||||||
"angular-translate-loader-partial": "^2.17.0",
|
"angular-translate-loader-partial": "^2.18.1",
|
||||||
"flatpickr": "^4.4.6",
|
"flatpickr": "^4.4.6",
|
||||||
"fs-extra": "^5.0.0",
|
"fs-extra": "^5.0.0",
|
||||||
"material-design-lite": "^1.3.0",
|
"material-design-lite": "^1.3.0",
|
||||||
|
@ -25,7 +25,7 @@
|
||||||
"validator": "^6.2.1"
|
"validator": "^6.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"angular-mocks": "^1.6.6",
|
"angular-mocks": "^1.7.0",
|
||||||
"assets-webpack-plugin": "^3.5.1",
|
"assets-webpack-plugin": "^3.5.1",
|
||||||
"babel": "^6.23.0",
|
"babel": "^6.23.0",
|
||||||
"babel-core": "^6.26.0",
|
"babel-core": "^6.26.0",
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
module.exports = Self => {
|
|
||||||
Self.installCrudModel('crudAddressObservations');
|
|
||||||
};
|
|
|
@ -1,3 +1,25 @@
|
||||||
module.exports = function(Self) {
|
module.exports = function(Self) {
|
||||||
require('../methods/address/crudAddressObservations')(Self);
|
Self.validatesPresenceOf('observationTypeFk', {
|
||||||
|
message: 'Observation type cannot be blank'
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.validateAsync('typeUnique', typeIsUnique, {
|
||||||
|
message: 'Observation type must be unique'
|
||||||
|
});
|
||||||
|
async function typeIsUnique(err, done) {
|
||||||
|
let filter = {
|
||||||
|
fields: ['id'],
|
||||||
|
where: {
|
||||||
|
observationTypeFk: this.observationTypeFk,
|
||||||
|
addressFk: this.addressFk
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.id)
|
||||||
|
filter.where.id = {neq: this.id};
|
||||||
|
|
||||||
|
if (await Self.findOne(filter))
|
||||||
|
err();
|
||||||
|
done();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,5 +17,6 @@
|
||||||
"The IBAN does not have the correct format": "The IBAN does not have the correct format",
|
"The IBAN does not have the correct format": "The IBAN does not have the correct format",
|
||||||
"That payment method requires an IBAN": "That payment method requires an IBAN",
|
"That payment method requires an IBAN": "That payment method requires an IBAN",
|
||||||
"State cannot be blank": "State cannot be blank",
|
"State cannot be blank": "State cannot be blank",
|
||||||
"Cannot change the payment method if no salesperson": "Cannot change the payment method if no salesperson"
|
"Cannot change the payment method if no salesperson": "Cannot change the payment method if no salesperson",
|
||||||
|
"Observation type cannot be blank": "Observation type cannot be blank"
|
||||||
}
|
}
|
|
@ -18,7 +18,9 @@
|
||||||
"That payment method requires an IBAN": "El método de pago seleccionado requiere que se especifique el IBAN",
|
"That payment method requires an IBAN": "El método de pago seleccionado requiere que se especifique el IBAN",
|
||||||
"State cannot be blank": "El estado no puede estar en blanco",
|
"State cannot be blank": "El estado no puede estar en blanco",
|
||||||
"Cannot change the payment method if no salesperson": "No se puede cambiar la forma de pago si no hay comercial asignado",
|
"Cannot change the payment method if no salesperson": "No se puede cambiar la forma de pago si no hay comercial asignado",
|
||||||
"NO_AGENCY_AVAILABLE": "NO_AGENCY_AVAILABLE",
|
"can't be blank": "El campo no puede estar vacío",
|
||||||
|
"Observation type cannot be blank": "El tipo de observación no puede estar en blanco",
|
||||||
|
"Observation type must be unique": "El tipo de observación no puede repetirse",
|
||||||
"The credit must be an integer greater than or equal to zero": "The credit must be an integer greater than or equal to zero",
|
"The credit must be an integer greater than or equal to zero": "The credit must be an integer greater than or equal to zero",
|
||||||
"The grade must be similar to the last one": "El grado debe ser similar al último crédito"
|
"The grade must be similar to the last one": "El grado debe ser similar al último crédito"
|
||||||
}
|
}
|
|
@ -1,3 +0,0 @@
|
||||||
module.exports = Self => {
|
|
||||||
Self.installCrudModel('crudItemTags');
|
|
||||||
};
|
|
|
@ -8,15 +8,13 @@ module.exports = Self => {
|
||||||
required: true,
|
required: true,
|
||||||
description: 'ticket id',
|
description: 'ticket id',
|
||||||
http: {source: 'path'}
|
http: {source: 'path'}
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
arg: 'data',
|
arg: 'data',
|
||||||
type: 'Object',
|
type: 'Object',
|
||||||
required: true,
|
required: true,
|
||||||
description: 'landed, addressFk, agencyModeFk, warehouseFk',
|
description: 'landed, addressFk, agencyModeFk, warehouseFk',
|
||||||
http: {source: 'body'}
|
http: {source: 'body'}
|
||||||
},
|
}, {
|
||||||
{
|
|
||||||
arg: 'context',
|
arg: 'context',
|
||||||
type: 'object',
|
type: 'object',
|
||||||
http: function(ctx) {
|
http: function(ctx) {
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
module.exports = function(Self) {
|
|
||||||
Self.installCrudModel = function(methodName) {
|
|
||||||
let Model = this;
|
|
||||||
Model.remoteMethod(methodName, {
|
|
||||||
description: 'create, update or delete model',
|
|
||||||
accessType: 'WRITE',
|
|
||||||
accepts: [
|
|
||||||
{
|
|
||||||
arg: 'crudStruct',
|
|
||||||
type: 'Object',
|
|
||||||
require: true,
|
|
||||||
description: 'object with instances of model to create, update or delete, Example: {create: [], update: [], delete: []}',
|
|
||||||
http: {source: 'body'}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
http: {
|
|
||||||
path: `/${methodName}`,
|
|
||||||
verb: 'post'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
Model[methodName] = async crudObject => {
|
|
||||||
let promises = [];
|
|
||||||
let transaction = await Model.beginTransaction({});
|
|
||||||
let options = {transaction: transaction};
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (crudObject.delete && crudObject.delete.length) {
|
|
||||||
promises.push(Model.destroyAll({id: {inq: crudObject.delete}}, options));
|
|
||||||
}
|
|
||||||
if (crudObject.create && crudObject.create.length) {
|
|
||||||
promises.push(Model.create(crudObject.create, options));
|
|
||||||
}
|
|
||||||
if (crudObject.update) {
|
|
||||||
crudObject.update.forEach(toUpdate => {
|
|
||||||
promises.push(Model.upsert(toUpdate, options));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
await Promise.all(promises);
|
|
||||||
await transaction.commit();
|
|
||||||
} catch (error) {
|
|
||||||
await transaction.rollback();
|
|
||||||
throw Array.isArray(error) ? error[0] : error;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,4 +1,3 @@
|
||||||
module.exports = Self => {
|
module.exports = Self => {
|
||||||
require('../methods/item-tag/crudItemTags')(Self);
|
|
||||||
require('../methods/item-tag/filterItemTags')(Self);
|
require('../methods/item-tag/filterItemTags')(Self);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
module.exports = function(Self) {
|
module.exports = function(Self) {
|
||||||
Self.setup = function() {
|
Self.setup = function() {
|
||||||
Self.super_.setup.call(this);
|
Self.super_.setup.call(this);
|
||||||
|
/*
|
||||||
/* let disableMethods = {
|
let disableMethods = {
|
||||||
create: true,
|
create: true,
|
||||||
replaceOrCreate: true,
|
replaceOrCreate: true,
|
||||||
patchOrCreate: true,
|
patchOrCreate: true,
|
||||||
|
@ -22,7 +22,9 @@ module.exports = function(Self) {
|
||||||
};
|
};
|
||||||
for (let method in disableMethods) {
|
for (let method in disableMethods) {
|
||||||
// this.disableRemoteMethod(method, disableMethods[method]);
|
// this.disableRemoteMethod(method, disableMethods[method]);
|
||||||
} */
|
}
|
||||||
|
*/
|
||||||
|
this.installCrudModel('crud');
|
||||||
};
|
};
|
||||||
|
|
||||||
Self.defineScope = function(serverFilter) {
|
Self.defineScope = function(serverFilter) {
|
||||||
|
@ -116,8 +118,51 @@ module.exports = function(Self) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
require('../methods/vnModel/rawSql')(Self);
|
Self.installCrudModel = function(methodName) {
|
||||||
require('../methods/vnModel/installMethod')(Self);
|
this.remoteMethod(methodName, {
|
||||||
require('../methods/vnModel/validateBinded')(Self);
|
description: 'Create, update or/and delete instances from model in a single request',
|
||||||
require('../methods/vnModel/installCrudModel')(Self);
|
accessType: 'WRITE',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'actions',
|
||||||
|
type: 'Object',
|
||||||
|
require: true,
|
||||||
|
description: 'Instances to update, example: {create: [instances], update: [instances], delete: [ids]}',
|
||||||
|
http: {source: 'body'}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
http: {
|
||||||
|
path: `/${methodName}`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this[methodName] = async actions => {
|
||||||
|
let promises = [];
|
||||||
|
let transaction = await this.beginTransaction({});
|
||||||
|
let options = {transaction: transaction};
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (actions.delete && actions.delete.length) {
|
||||||
|
promises.push(this.destroyAll({id: {inq: actions.delete}}, options));
|
||||||
|
}
|
||||||
|
if (actions.create && actions.create.length) {
|
||||||
|
promises.push(this.create(actions.create, options));
|
||||||
|
}
|
||||||
|
if (actions.update) {
|
||||||
|
actions.update.forEach(toUpdate => {
|
||||||
|
promises.push(this.upsert(toUpdate, options));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
await Promise.all(promises);
|
||||||
|
await transaction.commit();
|
||||||
|
} catch (error) {
|
||||||
|
await transaction.rollback();
|
||||||
|
throw Array.isArray(error) ? error[0] : error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
require('../methods/vn-model/rawSql')(Self);
|
||||||
|
require('../methods/vn-model/installMethod')(Self);
|
||||||
|
require('../methods/vn-model/validateBinded')(Self);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue