Merge conflicts
This commit is contained in:
commit
81b374d744
|
@ -9,16 +9,19 @@
|
||||||
"state": "clients",
|
"state": "clients",
|
||||||
"component": "vn-client-index",
|
"component": "vn-client-index",
|
||||||
"acl": ["employee"]
|
"acl": ["employee"]
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/create",
|
"url": "/create",
|
||||||
"state": "create",
|
"state": "create",
|
||||||
"component": "vn-client-create"
|
"component": "vn-client-create"
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/clients/:id",
|
"url": "/clients/:id",
|
||||||
"state": "clientCard",
|
"state": "clientCard",
|
||||||
"abstract": true,
|
"abstract": true,
|
||||||
"component": "vn-client-card"
|
"component": "vn-client-card"
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/basic-data",
|
"url": "/basic-data",
|
||||||
"state": "clientCard.basicData",
|
"state": "clientCard.basicData",
|
||||||
"component": "vn-client-basic-data",
|
"component": "vn-client-basic-data",
|
||||||
|
@ -29,7 +32,8 @@
|
||||||
"description": "Basic data",
|
"description": "Basic data",
|
||||||
"icon": "person"
|
"icon": "person"
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/fiscal-data",
|
"url": "/fiscal-data",
|
||||||
"state": "clientCard.fiscalData",
|
"state": "clientCard.fiscalData",
|
||||||
"component": "vn-client-fiscal-data",
|
"component": "vn-client-fiscal-data",
|
||||||
|
@ -40,7 +44,8 @@
|
||||||
"description": "Fiscal data",
|
"description": "Fiscal data",
|
||||||
"icon": "account_balance"
|
"icon": "account_balance"
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/billing-data",
|
"url": "/billing-data",
|
||||||
"state": "clientCard.billingData",
|
"state": "clientCard.billingData",
|
||||||
"component": "vn-client-billing-data",
|
"component": "vn-client-billing-data",
|
||||||
|
@ -51,12 +56,14 @@
|
||||||
"description": "Pay method",
|
"description": "Pay method",
|
||||||
"icon": "assignment"
|
"icon": "assignment"
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/addresses",
|
"url": "/addresses",
|
||||||
"state": "clientCard.addresses",
|
"state": "clientCard.addresses",
|
||||||
"component": "ui-view",
|
"component": "ui-view",
|
||||||
"abstract": true
|
"abstract": true
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/list",
|
"url": "/list",
|
||||||
"state": "clientCard.addresses.list",
|
"state": "clientCard.addresses.list",
|
||||||
"component": "vn-client-addresses",
|
"component": "vn-client-addresses",
|
||||||
|
@ -67,15 +74,18 @@
|
||||||
"description": "Addresses",
|
"description": "Addresses",
|
||||||
"icon": "local_shipping"
|
"icon": "local_shipping"
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/create",
|
"url": "/create",
|
||||||
"state": "clientCard.addresses.create",
|
"state": "clientCard.addresses.create",
|
||||||
"component": "vn-address-create"
|
"component": "vn-address-create"
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/:addressId/edit",
|
"url": "/:addressId/edit",
|
||||||
"state": "clientCard.addresses.edit",
|
"state": "clientCard.addresses.edit",
|
||||||
"component": "vn-address-edit"
|
"component": "vn-address-edit"
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/web-access",
|
"url": "/web-access",
|
||||||
"state": "clientCard.webAccess",
|
"state": "clientCard.webAccess",
|
||||||
"component": "vn-client-web-access",
|
"component": "vn-client-web-access",
|
||||||
|
@ -86,12 +96,14 @@
|
||||||
"description": "Web access",
|
"description": "Web access",
|
||||||
"icon": "language"
|
"icon": "language"
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/notes",
|
"url": "/notes",
|
||||||
"state": "clientCard.notes",
|
"state": "clientCard.notes",
|
||||||
"component": "ui-view",
|
"component": "ui-view",
|
||||||
"abstract": true
|
"abstract": true
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/list",
|
"url": "/list",
|
||||||
"state": "clientCard.notes.list",
|
"state": "clientCard.notes.list",
|
||||||
"component": "vn-client-notes",
|
"component": "vn-client-notes",
|
||||||
|
@ -102,16 +114,19 @@
|
||||||
"description": "Notes",
|
"description": "Notes",
|
||||||
"icon": "insert_drive_file"
|
"icon": "insert_drive_file"
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/create",
|
"url": "/create",
|
||||||
"state": "clientCard.notes.create",
|
"state": "clientCard.notes.create",
|
||||||
"component": "vn-note-create"
|
"component": "vn-note-create"
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/credit",
|
"url": "/credit",
|
||||||
"abstract": true,
|
"abstract": true,
|
||||||
"state": "clientCard.credit",
|
"state": "clientCard.credit",
|
||||||
"component": "ui-view"
|
"component": "ui-view"
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/list",
|
"url": "/list",
|
||||||
"state": "clientCard.credit.list",
|
"state": "clientCard.credit.list",
|
||||||
"component": "vn-client-credit-list",
|
"component": "vn-client-credit-list",
|
||||||
|
@ -123,19 +138,22 @@
|
||||||
"icon": "credit_card"
|
"icon": "credit_card"
|
||||||
},
|
},
|
||||||
"acl": ["manager", "salesAssistant", "teamBoss", "teamManager"]
|
"acl": ["manager", "salesAssistant", "teamBoss", "teamManager"]
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/create",
|
"url": "/create",
|
||||||
"state": "clientCard.credit.create",
|
"state": "clientCard.credit.create",
|
||||||
"component": "vn-client-credit-create",
|
"component": "vn-client-credit-create",
|
||||||
"params": {
|
"params": {
|
||||||
"client": "$ctrl.client"
|
"client": "$ctrl.client"
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/greuge",
|
"url": "/greuge",
|
||||||
"abstract": true,
|
"abstract": true,
|
||||||
"state": "clientCard.greuge",
|
"state": "clientCard.greuge",
|
||||||
"component": "ui-view"
|
"component": "ui-view"
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/list",
|
"url": "/list",
|
||||||
"state": "clientCard.greuge.list",
|
"state": "clientCard.greuge.list",
|
||||||
"component": "vn-client-greuge-list",
|
"component": "vn-client-greuge-list",
|
||||||
|
@ -146,14 +164,16 @@
|
||||||
"description": "Greuge",
|
"description": "Greuge",
|
||||||
"icon": "work"
|
"icon": "work"
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/create",
|
"url": "/create",
|
||||||
"state": "clientCard.greuge.create",
|
"state": "clientCard.greuge.create",
|
||||||
"component": "vn-client-greuge-create",
|
"component": "vn-client-greuge-create",
|
||||||
"params": {
|
"params": {
|
||||||
"client": "$ctrl.client"
|
"client": "$ctrl.client"
|
||||||
}
|
}
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/mandate",
|
"url": "/mandate",
|
||||||
"state": "clientCard.mandate",
|
"state": "clientCard.mandate",
|
||||||
"component": "vn-client-mandate",
|
"component": "vn-client-mandate",
|
||||||
|
|
|
@ -5,3 +5,4 @@ import './validation';
|
||||||
import './acl';
|
import './acl';
|
||||||
import './on-error-src';
|
import './on-error-src';
|
||||||
import './zoom-image';
|
import './zoom-image';
|
||||||
|
import './visible-by';
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
import ngModule from '../module';
|
||||||
|
|
||||||
|
function vnVisibleBy(aclService) {
|
||||||
|
return {
|
||||||
|
restrict: 'A',
|
||||||
|
priority: -1,
|
||||||
|
link: function($scope, $element, $attrs) {
|
||||||
|
let acls = $attrs.vnVisibleBy.split(',');
|
||||||
|
if (!aclService.aclPermission(acls)) {
|
||||||
|
$element[0].style.visibility = 'hidden';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
vnVisibleBy.$inject = ['aclService'];
|
||||||
|
|
||||||
|
ngModule.directive('vnVisibleBy', vnVisibleBy);
|
|
@ -15,16 +15,19 @@
|
||||||
"state": "item.index",
|
"state": "item.index",
|
||||||
"component": "vn-item-list",
|
"component": "vn-item-list",
|
||||||
"acl": ["developer"]
|
"acl": ["developer"]
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/create",
|
"url": "/create",
|
||||||
"state": "item.create",
|
"state": "item.create",
|
||||||
"component": "vn-item-create"
|
"component": "vn-item-create"
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url": "/:id",
|
"url": "/:id",
|
||||||
"state": "item.card",
|
"state": "item.card",
|
||||||
"abstract": true,
|
"abstract": true,
|
||||||
"component": "vn-item-card"
|
"component": "vn-item-card"
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"url" : "/data",
|
"url" : "/data",
|
||||||
"state": "item.card.data",
|
"state": "item.card.data",
|
||||||
"component": "vn-item-data",
|
"component": "vn-item-data",
|
||||||
|
@ -35,7 +38,8 @@
|
||||||
"description": "Basic data",
|
"description": "Basic data",
|
||||||
"icon": "folder"
|
"icon": "folder"
|
||||||
}
|
}
|
||||||
},{
|
},
|
||||||
|
{
|
||||||
"url" : "/tags",
|
"url" : "/tags",
|
||||||
"state": "item.card.tags",
|
"state": "item.card.tags",
|
||||||
"component": "vn-item-tags",
|
"component": "vn-item-tags",
|
||||||
|
@ -46,7 +50,8 @@
|
||||||
"description": "Tags",
|
"description": "Tags",
|
||||||
"icon": "folder"
|
"icon": "folder"
|
||||||
}
|
}
|
||||||
},{
|
},
|
||||||
|
{
|
||||||
"url" : "/history",
|
"url" : "/history",
|
||||||
"state": "item.card.history",
|
"state": "item.card.history",
|
||||||
"component": "vn-item-history",
|
"component": "vn-item-history",
|
||||||
|
@ -57,7 +62,8 @@
|
||||||
"description": "History",
|
"description": "History",
|
||||||
"icon": "folder"
|
"icon": "folder"
|
||||||
}
|
}
|
||||||
},{
|
},
|
||||||
|
{
|
||||||
"url" : "/niche",
|
"url" : "/niche",
|
||||||
"state": "item.card.niche",
|
"state": "item.card.niche",
|
||||||
"component": "vn-item-niche",
|
"component": "vn-item-niche",
|
||||||
|
@ -68,7 +74,8 @@
|
||||||
"description": "Niche",
|
"description": "Niche",
|
||||||
"icon": "folder"
|
"icon": "folder"
|
||||||
}
|
}
|
||||||
},{
|
},
|
||||||
|
{
|
||||||
"url" : "/botanical",
|
"url" : "/botanical",
|
||||||
"state": "item.card.botanical",
|
"state": "item.card.botanical",
|
||||||
"component": "vn-item-botanical",
|
"component": "vn-item-botanical",
|
||||||
|
@ -80,19 +87,8 @@
|
||||||
"icon": "folder"
|
"icon": "folder"
|
||||||
}
|
}
|
||||||
},{
|
},{
|
||||||
"url" : "/picture",
|
|
||||||
"state": "item.card.picture",
|
|
||||||
"component": "vn-item-picture",
|
|
||||||
"params": {
|
|
||||||
"item": "$ctrl.item"
|
|
||||||
},
|
|
||||||
"menu": {
|
|
||||||
"description": "Picture",
|
|
||||||
"icon": "folder"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"url" : "/barcode",
|
"url" : "/barcode",
|
||||||
"state": "item.card.barcode",
|
"state": "item.card.itemBarcode",
|
||||||
"component": "vn-item-barcode",
|
"component": "vn-item-barcode",
|
||||||
"params": {
|
"params": {
|
||||||
"item": "$ctrl.item"
|
"item": "$ctrl.item"
|
||||||
|
|
|
@ -1,5 +1,34 @@
|
||||||
<vn-card>
|
<form name="form" ng-submit="$ctrl.submit()">
|
||||||
<vn-vertical pad-large>
|
<vn-card>
|
||||||
<vn-title>Item barcode</vn-title>
|
<vn-vertical pad-large>
|
||||||
</vn-vertical>
|
<vn-one margin-medium-top>
|
||||||
</vn-card>
|
<vn-title>Item Barcodes</vn-title>
|
||||||
|
<mg-ajax path="/item/api/ItemBarcodes" options="mgIndex as barcodes"></mg-ajax>
|
||||||
|
<vn-horizontal ng-repeat="barcode in $ctrl.barcodes track by $index">
|
||||||
|
<vn-textfield vn-three label="code" model="barcode.code" vn-acl="buyer, replenisher"></vn-textfield>
|
||||||
|
<vn-one pad-medium-top>
|
||||||
|
<vn-icon
|
||||||
|
vn-acl="buyer, replenisher"
|
||||||
|
pointer
|
||||||
|
medium-grey
|
||||||
|
icon="remove_circle_outline"
|
||||||
|
ng-click="$ctrl.removeBarcode($index)">
|
||||||
|
</vn-icon>
|
||||||
|
<vn-icon
|
||||||
|
vn-acl="buyer, replenisher"
|
||||||
|
pointer
|
||||||
|
margin-medium-left
|
||||||
|
orange
|
||||||
|
icon="add_circle"
|
||||||
|
ng-if = "barcode.showAddIcon"
|
||||||
|
ng-click="$ctrl.addBarcode()"
|
||||||
|
></vn-icon>
|
||||||
|
</vn-one>
|
||||||
|
</vn-horizontal>
|
||||||
|
</vn-one>
|
||||||
|
</vn-vertical>
|
||||||
|
</vn-card>
|
||||||
|
<vn-button-bar>
|
||||||
|
<vn-submit label="Save"></vn-submit>
|
||||||
|
</vn-button-bar>
|
||||||
|
</form>
|
||||||
|
|
|
@ -1,5 +1,127 @@
|
||||||
import ngModule from '../module';
|
import ngModule from '../module';
|
||||||
|
|
||||||
|
export default class Controller {
|
||||||
|
constructor($state, $scope, $http, $q, $translate, vnApp) {
|
||||||
|
this.$state = $state;
|
||||||
|
this.$scope = $scope;
|
||||||
|
this.$http = $http;
|
||||||
|
this.$q = $q;
|
||||||
|
this.$translate = $translate;
|
||||||
|
this.vnApp = vnApp;
|
||||||
|
|
||||||
|
this.barcodes = [];
|
||||||
|
this.removedBarcodes = [];
|
||||||
|
this.oldBarcodes = {};
|
||||||
|
}
|
||||||
|
_setIconAdd() {
|
||||||
|
if (this.barcodes.length) {
|
||||||
|
this.barcodes.map(element => {
|
||||||
|
element.showAddIcon = false;
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
this.barcodes[this.barcodes.length - 1].showAddIcon = true;
|
||||||
|
} else {
|
||||||
|
this.addBarcode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_setDirtyForm() {
|
||||||
|
if (this.$scope.form) {
|
||||||
|
this.$scope.form.$setDirty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_unsetDirtyForm() {
|
||||||
|
if (this.$scope.form) {
|
||||||
|
this.$scope.form.$setPristine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_equalBarcodes(oldBarcode, newBarcode) {
|
||||||
|
return oldBarcode.id === newBarcode.id && oldBarcode.code === newBarcode.code;
|
||||||
|
}
|
||||||
|
|
||||||
|
addBarcode() {
|
||||||
|
this.barcodes.push({code: null, itemFk: this.$state.params.id, showAddIcon: true});
|
||||||
|
this._setIconAdd();
|
||||||
|
}
|
||||||
|
|
||||||
|
removeBarcode(index) {
|
||||||
|
let item = this.barcodes[index];
|
||||||
|
if (item) {
|
||||||
|
this.barcodes.splice(index, 1);
|
||||||
|
this._setIconAdd();
|
||||||
|
if (item.id) {
|
||||||
|
this.removedBarcodes.push(item.id);
|
||||||
|
this._setDirtyForm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
submit() {
|
||||||
|
let codes = [];
|
||||||
|
let repeatedBarcodes = false;
|
||||||
|
let canSubmit;
|
||||||
|
let barcodesObj = {
|
||||||
|
delete: this.removedBarcodes,
|
||||||
|
create: [],
|
||||||
|
update: []
|
||||||
|
};
|
||||||
|
for (let i = 0; i < this.barcodes.length; i++) {
|
||||||
|
let barcode = this.barcodes[i];
|
||||||
|
let isNewBarcode = barcode.id === undefined;
|
||||||
|
|
||||||
|
if (barcode.code && codes.indexOf(barcode.code) !== -1) {
|
||||||
|
repeatedBarcodes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (barcode.code) codes.push(barcode.code);
|
||||||
|
|
||||||
|
if (isNewBarcode && barcode.code) {
|
||||||
|
barcodesObj.create.push(barcode);
|
||||||
|
} else if (!isNewBarcode && !this._equalBarcodes(this.oldBarcodes[barcode.id], barcode)) {
|
||||||
|
barcodesObj.update.push(barcode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (repeatedBarcodes) {
|
||||||
|
return this.vnApp.showMessage(this.$translate.instant('The barcode must be unique'));
|
||||||
|
}
|
||||||
|
|
||||||
|
canSubmit = barcodesObj.update.length > 0 || barcodesObj.create.length > 0 || barcodesObj.delete.length > 0;
|
||||||
|
|
||||||
|
if (canSubmit) {
|
||||||
|
return this.$http.post(`/item/api/ItemBarcodes/crudItemBarcodes`, barcodesObj).then(() => {
|
||||||
|
this.getBarcodes();
|
||||||
|
this._unsetDirtyForm();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.vnApp.showMessage(this.$translate.instant('No changes to save'));
|
||||||
|
}
|
||||||
|
|
||||||
|
setOldBarcodes(response) {
|
||||||
|
this._setIconAdd();
|
||||||
|
response.data.forEach(barcode => {
|
||||||
|
this.oldBarcodes[barcode.id] = Object.assign({}, barcode);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getBarcodes() {
|
||||||
|
let filter = {
|
||||||
|
where: {itemFk: this.$state.params.id}
|
||||||
|
};
|
||||||
|
this.$http.get(`/item/api/ItemBarcodes?filter=${JSON.stringify(filter)}`).then(response => {
|
||||||
|
this.barcodes = response.data;
|
||||||
|
this.setOldBarcodes(response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
$onInit() {
|
||||||
|
this.getBarcodes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.$inject = ['$state', '$scope', '$http', '$q', '$translate', 'vnApp'];
|
||||||
|
|
||||||
ngModule.component('vnItemBarcode', {
|
ngModule.component('vnItemBarcode', {
|
||||||
template: require('./item-barcode.html')
|
template: require('./item-barcode.html'),
|
||||||
|
controller: Controller
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,142 @@
|
||||||
|
import './item-barcode.js';
|
||||||
|
|
||||||
|
describe('Item', () => {
|
||||||
|
describe('Component vnItemBarcode', () => {
|
||||||
|
let $componentController;
|
||||||
|
let $state;
|
||||||
|
let controller;
|
||||||
|
let $httpBackend;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
angular.mock.module('item');
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject((_$componentController_, _$state_, _$httpBackend_) => {
|
||||||
|
$componentController = _$componentController_;
|
||||||
|
$state = _$state_;
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
$state.params.id = '1';
|
||||||
|
controller = $componentController('vnItemBarcode', {$state: $state});
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('add / remove barcode()', () => {
|
||||||
|
it('should add one empty barcode into controller barcodes collection and call _setIconAdd()', () => {
|
||||||
|
controller.barcodes = [];
|
||||||
|
spyOn(controller, '_setIconAdd').and.callThrough();
|
||||||
|
controller.addBarcode();
|
||||||
|
|
||||||
|
expect(controller._setIconAdd).toHaveBeenCalledWith();
|
||||||
|
expect(controller.barcodes.length).toEqual(1);
|
||||||
|
expect(controller.barcodes[0].id).toBe(undefined);
|
||||||
|
expect(controller.barcodes[0].showAddIcon).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should remove a barcode that occupies the position in the index given and call _setIconAdd()', () => {
|
||||||
|
let index = 2;
|
||||||
|
controller.barcodes = [
|
||||||
|
{id: 1, code: '1111', showAddIcon: false},
|
||||||
|
{id: 2, code: '2222', showAddIcon: false},
|
||||||
|
{id: 3, code: '3333', showAddIcon: true}
|
||||||
|
];
|
||||||
|
|
||||||
|
spyOn(controller, '_setIconAdd').and.callThrough();
|
||||||
|
|
||||||
|
controller.removeBarcode(index);
|
||||||
|
|
||||||
|
expect(controller._setIconAdd).toHaveBeenCalledWith();
|
||||||
|
expect(controller.barcodes.length).toEqual(2);
|
||||||
|
expect(controller.barcodes[0].showAddIcon).toBeFalsy();
|
||||||
|
expect(controller.barcodes[1].showAddIcon).toBeTruthy();
|
||||||
|
expect(controller.barcodes[index]).toBe(undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('_equalBarcodes()', () => {
|
||||||
|
it('should return true if two barcodes are equals independent of control attributes', () => {
|
||||||
|
let code1 = {id: 1, code: '1111', showAddIcon: true};
|
||||||
|
let code2 = {id: 1, code: '1111', showAddIcon: false};
|
||||||
|
let equals = controller._equalBarcodes(code2, code1);
|
||||||
|
|
||||||
|
expect(equals).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false if two barcodes aint equals independent of control attributes', () => {
|
||||||
|
let code1 = {id: 1, code: '1111', showAddIcon: true};
|
||||||
|
let code2 = {id: 1, code: '2222', showAddIcon: true};
|
||||||
|
let equals = controller._equalBarcodes(code2, code1);
|
||||||
|
|
||||||
|
expect(equals).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getBarcodes()', () => {
|
||||||
|
it('should perform a GET query to receive the item barcodes', () => {
|
||||||
|
let filter = {
|
||||||
|
where: {itemFk: '1'}
|
||||||
|
};
|
||||||
|
let res = [{id: 1, code: '1111'}];
|
||||||
|
$httpBackend.when('GET', `/item/api/ItemBarcodes?filter=${JSON.stringify(filter)}`).respond(res);
|
||||||
|
$httpBackend.expectGET(`/item/api/ItemBarcodes?filter=${JSON.stringify(filter)}`);
|
||||||
|
controller.getBarcodes();
|
||||||
|
$httpBackend.flush();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('submit()', () => {
|
||||||
|
it("should return an error message 'The barcode must be unique' when the code isnt unique", () => {
|
||||||
|
spyOn(controller.vnApp, 'showMessage').and.callThrough();
|
||||||
|
controller.barcodes = [
|
||||||
|
{code: 123454, itemFk: 1, id: 1},
|
||||||
|
{code: 123454, itemFk: 1}
|
||||||
|
];
|
||||||
|
controller.oldBarcodes = {1: {id: 1, code: 123454, itemFk: 1}};
|
||||||
|
controller.submit();
|
||||||
|
|
||||||
|
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('The barcode must be unique');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should perfom a query to delete barcodes", () => {
|
||||||
|
controller.removedBarcodes = [1, 2, 3];
|
||||||
|
|
||||||
|
$httpBackend.when('GET', `/item/api/ItemBarcodes?filter={"where":{"itemFk":"1"}}`).respond([{code: 123454, itemFk: 1, id: 1}]);
|
||||||
|
$httpBackend.when('POST', `/item/api/ItemBarcodes/crudItemBarcodes`).respond('ok!');
|
||||||
|
$httpBackend.expectPOST(`/item/api/ItemBarcodes/crudItemBarcodes`);
|
||||||
|
controller.submit();
|
||||||
|
$httpBackend.flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should perfom a query to update barcodes", () => {
|
||||||
|
controller.barcodes = [{code: 2222, itemFk: 1, id: 1}];
|
||||||
|
controller.oldBarcodes = {1: {id: 1, code: 1111, itemFk: 1}};
|
||||||
|
|
||||||
|
$httpBackend.when('GET', `/item/api/ItemBarcodes?filter={"where":{"itemFk":"1"}}`).respond([{}]);
|
||||||
|
$httpBackend.when('POST', `/item/api/ItemBarcodes/crudItemBarcodes`).respond('ok!');
|
||||||
|
$httpBackend.expectPOST(`/item/api/ItemBarcodes/crudItemBarcodes`);
|
||||||
|
controller.submit();
|
||||||
|
$httpBackend.flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should perfom a query to create new barcode", () => {
|
||||||
|
controller.barcodes = [{code: 1111, itemFk: 1}];
|
||||||
|
|
||||||
|
$httpBackend.when('GET', `/item/api/ItemBarcodes?filter={"where":{"itemFk":"1"}}`).respond([{}]);
|
||||||
|
$httpBackend.when('POST', `/item/api/ItemBarcodes/crudItemBarcodes`).respond('ok!');
|
||||||
|
$httpBackend.expectPOST(`/item/api/ItemBarcodes/crudItemBarcodes`);
|
||||||
|
controller.submit();
|
||||||
|
$httpBackend.flush();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return a message 'No changes to save' when there are no changes to apply", () => {
|
||||||
|
spyOn(controller.vnApp, 'showMessage').and.callThrough();
|
||||||
|
controller.oldBarcodes = [
|
||||||
|
{code: 1, itemFk: 1, id: 1},
|
||||||
|
{code: 2, itemFk: 1, id: 2}
|
||||||
|
];
|
||||||
|
controller.barcodes = [];
|
||||||
|
controller.submit();
|
||||||
|
|
||||||
|
expect(controller.vnApp.showMessage).toHaveBeenCalledWith('No changes to save');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -3,10 +3,14 @@
|
||||||
<vn-auto class="descriptor-header pointer" ui-sref="item.index">
|
<vn-auto class="descriptor-header pointer" ui-sref="item.index">
|
||||||
<img ng-src="/static/images/icon_item.png"/>
|
<img ng-src="/static/images/icon_item.png"/>
|
||||||
</vn-auto>
|
</vn-auto>
|
||||||
<vn-auto pad-medium text-center>
|
<vn-auto style="position: relative" pad-medium text-center>
|
||||||
<img
|
<img
|
||||||
ng-src="http://verdnatura.es/vn-image-data/catalog/200x200/{{$ctrl.item.image}}"
|
ng-src="http://verdnatura.es/vn-image-data/catalog/200x200/{{::$ctrl.item.image}}"
|
||||||
zoom-image="http://verdnatura.es/vn-image-data/catalog/900x900/{{$ctrl.item.image}}" on-error-src/>
|
zoom-image="http://verdnatura.es/vn-image-data/catalog/900x900/{{::$ctrl.item.image}}" on-error-src/>
|
||||||
|
<a href="https://www.verdnatura.es/#!form=admin/items&filter={{::$ctrl.item.id}}" target="_blank"><vn-float-button icon="edit"
|
||||||
|
style="position: absolute; bottom: 1em; right: 1em;"
|
||||||
|
vn-visible-by="administrative"></vn-float-button>
|
||||||
|
</a>
|
||||||
</vn-auto>
|
</vn-auto>
|
||||||
<vn-auto pad-medium>
|
<vn-auto pad-medium>
|
||||||
<div><span translate>Id</span>: <b>{{$ctrl.item.id}}</b></div>
|
<div><span translate>Id</span>: <b>{{$ctrl.item.id}}</b></div>
|
||||||
|
|
|
@ -11,6 +11,5 @@ import './tags/item-tags';
|
||||||
import './history/item-history';
|
import './history/item-history';
|
||||||
import './niche/item-niche';
|
import './niche/item-niche';
|
||||||
import './botanical/item-botanical';
|
import './botanical/item-botanical';
|
||||||
import './picture/item-picture';
|
|
||||||
import './barcode/item-barcode';
|
import './barcode/item-barcode';
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,7 @@
|
||||||
on-search="$ctrl.search(index)"
|
on-search="$ctrl.search(index)"
|
||||||
advanced="true"
|
advanced="true"
|
||||||
popover="vn-item-filter-panel"
|
popover="vn-item-filter-panel"
|
||||||
ignore-keys = "['page', 'size', 'search']"
|
ignore-keys = "['page', 'size', 'search']">
|
||||||
>
|
|
||||||
</vn-searchbar>
|
</vn-searchbar>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
|
|
|
@ -13,7 +13,6 @@ Item history: Historial del artículo
|
||||||
Item tags: Tags del artículo
|
Item tags: Tags del artículo
|
||||||
Niche: Nicho
|
Niche: Nicho
|
||||||
Picture: Foto
|
Picture: Foto
|
||||||
Item pictures: Fotos del artículo
|
|
||||||
Barcode: Código barras
|
Barcode: Código barras
|
||||||
Item barcode: Código de barras del artículo
|
Item barcode: Código de barras del artículo
|
||||||
Changed by: Cambiado por
|
Changed by: Cambiado por
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
<vn-card>
|
|
||||||
<vn-vertical pad-large>
|
|
||||||
<vn-title>Item pictures</vn-title>
|
|
||||||
</vn-vertical>
|
|
||||||
</vn-card>
|
|
|
@ -1,5 +0,0 @@
|
||||||
import ngModule from '../module';
|
|
||||||
|
|
||||||
ngModule.component('vnItemPicture', {
|
|
||||||
template: require('./item-picture.html')
|
|
||||||
});
|
|
|
@ -53,7 +53,7 @@ export default {
|
||||||
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: `${components.vnCheck}[label='Is equalizated'] > label > input`,
|
||||||
acceptPropagationButton: `body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-client-fiscal-data > vn-dialog > div > form > div.button-bar > tpl-buttons > button:nth-child(2)`,
|
acceptPropagationButton: `body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-client-fiscal-data > vn-confirm > div > form > div.button-bar > tpl-buttons > button:nth-child(2)`,
|
||||||
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"]`,
|
||||||
|
@ -76,7 +76,7 @@ export default {
|
||||||
payMethodOptionOne: `${components.vnAutocomplete}[field="$ctrl.client.payMethodFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(2)`,
|
payMethodOptionOne: `${components.vnAutocomplete}[field="$ctrl.client.payMethodFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(2)`,
|
||||||
IBANInput: `${components.vnTextfield}[name="iban"]`,
|
IBANInput: `${components.vnTextfield}[name="iban"]`,
|
||||||
dueDayInput: `${components.vnTextfield}[name="dueDay"]`,
|
dueDayInput: `${components.vnTextfield}[name="dueDay"]`,
|
||||||
cancelNotificationButton: 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-client-billing-data > vn-dialog > div > form > div.button-bar > tpl-buttons > button:nth-child(1)',
|
cancelNotificationButton: 'vn-client-billing-data > vn-dialog tpl-buttons > button:nth-child(1)',
|
||||||
receivedCoreVNHCheckbox: `${components.vnCheck}[label='Received core VNH'] > label > input`,
|
receivedCoreVNHCheckbox: `${components.vnCheck}[label='Received core VNH'] > label > input`,
|
||||||
receivedCoreVNLCheckbox: `${components.vnCheck}[label='Received core VNL'] > label > input`,
|
receivedCoreVNLCheckbox: `${components.vnCheck}[label='Received core VNL'] > label > input`,
|
||||||
receivedB2BVNLCheckbox: `${components.vnCheck}[label='Received B2B VNL'] > label > input`,
|
receivedB2BVNLCheckbox: `${components.vnCheck}[label='Received B2B VNL'] > label > input`,
|
||||||
|
@ -115,7 +115,7 @@ export default {
|
||||||
addNoteFloatButton: `${components.vnFloatButton}`,
|
addNoteFloatButton: `${components.vnFloatButton}`,
|
||||||
noteInput: `${components.vnTextarea}[label="Note"]`,
|
noteInput: `${components.vnTextarea}[label="Note"]`,
|
||||||
saveButton: `${components.vnSubmit}`,
|
saveButton: `${components.vnSubmit}`,
|
||||||
firstNoteText: 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > ui-view > vn-client-notes > vn-card > div > vn-vertical > vn-one:nth-child(2) > vn-horizontal:nth-child(2) > b'
|
firstNoteText: 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > ui-view > vn-client-notes > vn-card > div > vn-vertical > vn-one:nth-child(2) > vn-horizontal.ng-binding'
|
||||||
},
|
},
|
||||||
credit: {
|
credit: {
|
||||||
creditButton: `${components.vnMenuItem}[ui-sref="clientCard.credit.list"]`,
|
creditButton: `${components.vnMenuItem}[ui-sref="clientCard.credit.list"]`,
|
||||||
|
|
|
@ -84,9 +84,9 @@ describe('Add address notes path', () => {
|
||||||
.catch(catchErrors(done));
|
.catch(catchErrors(done));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should add as many notes as observation types', done => {
|
// it('should add as many notes as observation types', done => {
|
||||||
nightmare
|
// nightmare
|
||||||
.waitToClick(selectors.addresses.defaultCheckboxInput)
|
// .waitToClick(selectors.addresses.defaultCheckboxInput)
|
||||||
// .waitToClick(selectors.fiscalData.saveButton)
|
// .waitToClick(selectors.fiscalData.saveButton)
|
||||||
// .wait(selectors.globalItems.snackbarIsActive)
|
// .wait(selectors.globalItems.snackbarIsActive)
|
||||||
// .getInnerText(selectors.globalItems.snackbarIsActive)
|
// .getInnerText(selectors.globalItems.snackbarIsActive)
|
||||||
|
@ -94,6 +94,6 @@ describe('Add address notes path', () => {
|
||||||
// expect(result).toContain('Some fields are invalid');
|
// expect(result).toContain('Some fields are invalid');
|
||||||
// done();
|
// done();
|
||||||
// })
|
// })
|
||||||
.catch(catchErrors(done));
|
// .catch(catchErrors(done));
|
||||||
});
|
// });
|
||||||
});
|
});
|
||||||
|
|
|
@ -85,7 +85,7 @@ describe('Add notes path', () => {
|
||||||
|
|
||||||
it(`should create a note`, done => {
|
it(`should create a note`, done => {
|
||||||
nightmare
|
nightmare
|
||||||
.type(selectors.notes.noteInput, 'Meeting with Black Widow 21th 9am')
|
.type(selectors.notes.noteInput, 'Meeting with Black Widow 21st 9am')
|
||||||
.click(selectors.notes.saveButton)
|
.click(selectors.notes.saveButton)
|
||||||
.wait(selectors.globalItems.snackbarIsActive)
|
.wait(selectors.globalItems.snackbarIsActive)
|
||||||
.getInnerText(selectors.globalItems.snackbarIsActive)
|
.getInnerText(selectors.globalItems.snackbarIsActive)
|
||||||
|
@ -102,7 +102,7 @@ describe('Add notes path', () => {
|
||||||
.wait(selectors.notes.firstNoteText)
|
.wait(selectors.notes.firstNoteText)
|
||||||
.getInnerText(selectors.notes.firstNoteText)
|
.getInnerText(selectors.notes.firstNoteText)
|
||||||
.then(value => {
|
.then(value => {
|
||||||
expect(value).toEqual('Meeting with Black Widow 21th 9am');
|
expect(value).toEqual('Meeting with Black Widow 21st 9am');
|
||||||
done();
|
done();
|
||||||
})
|
})
|
||||||
.catch(catchErrors(done));
|
.catch(catchErrors(done));
|
||||||
|
|
18
gulpfile.js
18
gulpfile.js
|
@ -76,6 +76,22 @@ gulp.task('e2e-only', () => {
|
||||||
.pipe(jasmine({reporter: 'none'}));
|
.pipe(jasmine({reporter: 'none'}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the backend tests.
|
||||||
|
*/
|
||||||
|
// gulp.task('test', ['test-only'], async () => {
|
||||||
|
// gulp.watch('./services/**/*', ['test-only']);
|
||||||
|
// gulp.unwatch('./services/node_modules');
|
||||||
|
// });
|
||||||
|
|
||||||
|
// gulp.task('test-only', () => {
|
||||||
|
// const jasmine = require('gulp-jasmine');
|
||||||
|
// gulp.src('./services/loopback/common/**/*[sS]pec.js')
|
||||||
|
// .pipe(jasmine(
|
||||||
|
// require('./services-test.config')
|
||||||
|
// ));
|
||||||
|
// });
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cleans all generated project files.
|
* Cleans all generated project files.
|
||||||
*/
|
*/
|
||||||
|
@ -181,7 +197,7 @@ gulp.task('nginx-start', ['nginx-conf'], async () => {
|
||||||
if (isWindows)
|
if (isWindows)
|
||||||
nginxBin = `start /B ${nginxBin}`;
|
nginxBin = `start /B ${nginxBin}`;
|
||||||
|
|
||||||
log(`Application will be at http://${proxyConf.host}:${proxyConf.port}/`);
|
log(`Application will be available at http://${proxyConf.host}:${proxyConf.port}/`);
|
||||||
await execP(`${nginxBin} -c "${nginxConf}" -p "${nginxDir}"`);
|
await execP(`${nginxBin} -c "${nginxConf}" -p "${nginxDir}"`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,24 @@
|
||||||
|
// const SpecReporter = require('jasmine-spec-reporter').SpecReporter;
|
||||||
|
|
||||||
|
// module.exports = {
|
||||||
|
// reporter: new SpecReporter({
|
||||||
|
// spec: {
|
||||||
|
// // displayStacktrace: 'summary',
|
||||||
|
// displaySuccessful: false,
|
||||||
|
// displayFailedSpec: true,
|
||||||
|
// displaySpecDuration: true
|
||||||
|
// }
|
||||||
|
// }),
|
||||||
|
// config: {
|
||||||
|
// spec_dir: 'services',
|
||||||
|
// spec_files: [
|
||||||
|
// // '**/*.spec.js',
|
||||||
|
// 'auth/server/**/*.spec.js',
|
||||||
|
// 'client/common/**/*.spec.js',
|
||||||
|
// 'loopback/common/**/*.spec.js'
|
||||||
|
// ],
|
||||||
|
// helpers: [
|
||||||
|
// '/services/utils/jasmineHelpers.js'
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
// };
|
|
@ -2,7 +2,7 @@ FROM node:8.9.4
|
||||||
|
|
||||||
COPY auth /app
|
COPY auth /app
|
||||||
COPY loopback /loopback
|
COPY loopback /loopback
|
||||||
COPY nginx/static/webpack-assets.json /loopback/server/
|
COPY nginx/static/webpack-assets.json /loopback/client/
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ module.exports = function(app) {
|
||||||
let applications = app.get('applications');
|
let applications = app.get('applications');
|
||||||
|
|
||||||
app.get('/', function(req, res) {
|
app.get('/', function(req, res) {
|
||||||
res.render('index.ejs');
|
app.renderIndex(res);
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post('/login', function(req, res) {
|
app.post('/login', function(req, res) {
|
||||||
|
|
|
@ -11,9 +11,6 @@ module.exports = Self => {
|
||||||
http: {source: 'body'}
|
http: {source: 'body'}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
returns: {
|
|
||||||
arg: 'sumAmount'
|
|
||||||
},
|
|
||||||
http: {
|
http: {
|
||||||
path: `/crudAddressObservations`,
|
path: `/crudAddressObservations`,
|
||||||
verb: 'post'
|
verb: 'post'
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethod('crudItemBarcodes', {
|
||||||
|
description: 'create, update or delete barcodes',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'barcodes',
|
||||||
|
type: 'Object',
|
||||||
|
require: true,
|
||||||
|
description: 'object with barcodes to create, update or delete, Example: {create: [], update: [], delete: []}',
|
||||||
|
http: {source: 'body'}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
http: {
|
||||||
|
path: `/crudItemBarcodes`,
|
||||||
|
verb: 'post'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.crudItemBarcodes = barcodes => {
|
||||||
|
let promises = [];
|
||||||
|
|
||||||
|
if (barcodes.delete && barcodes.delete.length) {
|
||||||
|
promises.push(Self.destroyAll({id: {inq: barcodes.delete}}));
|
||||||
|
}
|
||||||
|
if (barcodes.create.length) {
|
||||||
|
promises.push(Self.create(barcodes.create));
|
||||||
|
}
|
||||||
|
if (barcodes.update.length) {
|
||||||
|
barcodes.update.forEach(barcode => {
|
||||||
|
promises.push(Self.upsert(barcode));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return Promise.all(promises);
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,51 @@
|
||||||
|
const crudItemBarcodes = require('../crudItemBarcodes');
|
||||||
|
const catchErrors = require('../../../../../../services/utils/jasmineHelpers').catchErrors;
|
||||||
|
|
||||||
|
describe('Item crudItemBarcodes()', () => {
|
||||||
|
it('should call the destroyAll methodif there are ids in delete Array', done => {
|
||||||
|
let self = jasmine.createSpyObj('self', ['remoteMethod', 'crudItemBarcodes', 'destroyAll', 'create', 'upsert']);
|
||||||
|
|
||||||
|
crudItemBarcodes(self);
|
||||||
|
self.crudItemBarcodes({
|
||||||
|
delete: [1],
|
||||||
|
create: [],
|
||||||
|
update: []
|
||||||
|
}).then(result => {
|
||||||
|
expect(self.destroyAll).toHaveBeenCalledWith({id: {inq: [1]}});
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(catchErrors(done));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call the create method if there are ids in create Array', done => {
|
||||||
|
let self = jasmine.createSpyObj('self', ['remoteMethod', 'crudItemBarcodes', 'destroyAll', 'create', 'upsert']);
|
||||||
|
|
||||||
|
crudItemBarcodes(self);
|
||||||
|
self.crudItemBarcodes({
|
||||||
|
delete: [],
|
||||||
|
create: [1],
|
||||||
|
update: []
|
||||||
|
}).then(result => {
|
||||||
|
expect(self.create).toHaveBeenCalledWith([1]);
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(catchErrors(done));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call the upsert method as many times as ids in update Array', done => {
|
||||||
|
let self = jasmine.createSpyObj('self', ['remoteMethod', 'crudItemBarcodes', 'destroyAll', 'create', 'upsert']);
|
||||||
|
|
||||||
|
crudItemBarcodes(self);
|
||||||
|
self.crudItemBarcodes({
|
||||||
|
delete: [],
|
||||||
|
create: [],
|
||||||
|
update: [1, 2]
|
||||||
|
}).then(result => {
|
||||||
|
expect(self.upsert).toHaveBeenCalledWith(1);
|
||||||
|
expect(self.upsert).toHaveBeenCalledWith(2);
|
||||||
|
expect(self.upsert.calls.count()).toEqual(2);
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(catchErrors(done));
|
||||||
|
});
|
||||||
|
});
|
|
@ -79,6 +79,11 @@
|
||||||
"type": "hasMany",
|
"type": "hasMany",
|
||||||
"model": "ItemTag",
|
"model": "ItemTag",
|
||||||
"foreignKey": "itemFk"
|
"foreignKey": "itemFk"
|
||||||
|
},
|
||||||
|
"itemBarcode": {
|
||||||
|
"type": "hasMany",
|
||||||
|
"model": "ItemBarcode",
|
||||||
|
"foreignKey": "itemFk"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
module.exports = function(Self) {
|
||||||
|
require('../methods/item/crudItemBarcodes.js')(Self);
|
||||||
|
};
|
|
@ -0,0 +1,28 @@
|
||||||
|
{
|
||||||
|
"name": "ItemBarcode",
|
||||||
|
"base": "VnModel",
|
||||||
|
"options": {
|
||||||
|
"mysql": {
|
||||||
|
"table": "itemBarcode",
|
||||||
|
"database": "vn"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "Number",
|
||||||
|
"id": true,
|
||||||
|
"description": "Identifier"
|
||||||
|
},
|
||||||
|
"code": {
|
||||||
|
"type": "String",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"relations": {
|
||||||
|
"item": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Item",
|
||||||
|
"foreignKey": "itemFk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,5 +37,8 @@
|
||||||
},
|
},
|
||||||
"ItemLog": {
|
"ItemLog": {
|
||||||
"dataSource": "vn"
|
"dataSource": "vn"
|
||||||
|
},
|
||||||
|
"ItemBarcode": {
|
||||||
|
"dataSource": "vn"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
require('require-yaml');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtains the webpack asset filenames with its hash.
|
|
||||||
*
|
|
||||||
* @param {String} main The main asset name
|
|
||||||
* @param {Array} deps The main asset dependencies
|
|
||||||
* @return {Array} The assets filenames
|
|
||||||
*/
|
|
||||||
function assets(main, deps) {
|
|
||||||
let jsFiles;
|
|
||||||
let env = process.env.NODE_ENV ? process.env.NODE_ENV : 'development';
|
|
||||||
|
|
||||||
if (env === 'development') {
|
|
||||||
const wpConfig = require('../../../webpack.config.yml');
|
|
||||||
let publicPath = wpConfig.publicPath;
|
|
||||||
|
|
||||||
jsFiles = [`${publicPath}/manifest.js`];
|
|
||||||
|
|
||||||
for (let dep of deps)
|
|
||||||
jsFiles.push(`${publicPath}/${dep}.js`);
|
|
||||||
|
|
||||||
jsFiles.push(`${publicPath}/${main}.js`);
|
|
||||||
} else {
|
|
||||||
const wpAssets = require('./webpack-assets.json');
|
|
||||||
|
|
||||||
let jsFiles = [wpAssets.manifest.js];
|
|
||||||
|
|
||||||
for (let dep of deps)
|
|
||||||
jsFiles.push(wpAssets[dep].js);
|
|
||||||
|
|
||||||
jsFiles.push(wpAssets[main].js);
|
|
||||||
}
|
|
||||||
|
|
||||||
return jsFiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = assets;
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
let loopback = require('loopback');
|
let loopback = require('loopback');
|
||||||
let boot = require('loopback-boot');
|
let boot = require('loopback-boot');
|
||||||
let fs = require('fs-extra');
|
let fs = require('fs-extra');
|
||||||
|
@ -26,31 +25,57 @@ function vnBoot(app, rootDir, rootModule) {
|
||||||
|
|
||||||
// View
|
// View
|
||||||
|
|
||||||
|
let wpAssets;
|
||||||
let viewDir = `${rootDir}/../client`;
|
let viewDir = `${rootDir}/../client`;
|
||||||
|
|
||||||
if (fs.existsSync(viewDir)) {
|
if (fs.existsSync(viewDir)) {
|
||||||
|
try {
|
||||||
|
wpAssets = require('../client/webpack-assets.json');
|
||||||
|
} catch (e) {}
|
||||||
|
|
||||||
app.set('view engine', 'ejs');
|
app.set('view engine', 'ejs');
|
||||||
app.set('views', viewDir);
|
app.set('views', viewDir);
|
||||||
app.use(loopback.static(path.resolve(rootDir, '../client')));
|
app.use(loopback.static(path.resolve(rootDir, '../client')));
|
||||||
app.get('/', function(req, res) {
|
|
||||||
res.render(`${viewDir}/index.ejs`, {
|
|
||||||
assets: require('./assets')
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
app.renderIndex = async res => {
|
||||||
|
res.render(`${viewDir}/index.ejs`, {
|
||||||
|
assets: assets
|
||||||
|
});
|
||||||
|
|
||||||
|
function assets(main, deps) {
|
||||||
|
let jsFiles;
|
||||||
|
|
||||||
|
if (wpAssets) {
|
||||||
|
jsFiles = [wpAssets.manifest.js];
|
||||||
|
|
||||||
|
for (let dep of deps)
|
||||||
|
jsFiles.push(wpAssets[dep].js);
|
||||||
|
|
||||||
|
jsFiles.push(wpAssets[main].js);
|
||||||
|
} else {
|
||||||
|
let publicPath = '/static';
|
||||||
|
jsFiles = [`${publicPath}/manifest.js`];
|
||||||
|
|
||||||
|
for (let dep of deps)
|
||||||
|
jsFiles.push(`${publicPath}/${dep}.js`);
|
||||||
|
|
||||||
|
jsFiles.push(`${publicPath}/${main}.js`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsFiles;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
|
|
||||||
app.start = function(port) {
|
app.start = port => {
|
||||||
function onListen() {
|
function onListen() {
|
||||||
app.emit('started');
|
app.emit('started');
|
||||||
|
let packageJson = require(`${rootDir}/../package.json`);
|
||||||
if (require.main === rootModule) {
|
let appName = packageJson.name;
|
||||||
let packageJson = require(`${rootDir}/../package.json`);
|
let baseUrl = app.get('url').replace(/\/$/, '');
|
||||||
let appName = packageJson.name;
|
console.log(`Web server ${appName} listening at: %s`, baseUrl);
|
||||||
let baseUrl = app.get('url').replace(/\/$/, '');
|
|
||||||
console.log(`Web server ${appName} listening at: %s`, baseUrl);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let args = port ? [port, onListen] : [onListen];
|
let args = port ? [port, onListen] : [onListen];
|
||||||
|
|
|
@ -2,7 +2,7 @@ FROM node:8.9.4
|
||||||
|
|
||||||
COPY salix /app
|
COPY salix /app
|
||||||
COPY loopback /loopback
|
COPY loopback /loopback
|
||||||
COPY nginx/static/webpack-assets.json /loopback/server/
|
COPY nginx/static/webpack-assets.json /loopback/client/
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ module.exports = function(app) {
|
||||||
let token = req.cookies.vnToken;
|
let token = req.cookies.vnToken;
|
||||||
validateToken(token, function(isValid) {
|
validateToken(token, function(isValid) {
|
||||||
if (isValid)
|
if (isValid)
|
||||||
res.render('index.ejs');
|
app.renderIndex(res);
|
||||||
else
|
else
|
||||||
redirectToAuth(res, req.get('origin'));
|
redirectToAuth(res, req.get('origin'));
|
||||||
});
|
});
|
||||||
|
|
|
@ -19,6 +19,7 @@ jasmine.loadConfig({
|
||||||
spec_files: [
|
spec_files: [
|
||||||
'auth/server/**/*[sS]pec.js',
|
'auth/server/**/*[sS]pec.js',
|
||||||
'client/common/**/*[sS]pec.js',
|
'client/common/**/*[sS]pec.js',
|
||||||
|
'item/common/**/*[sS]pec.js',
|
||||||
'loopback/common/**/*[sS]pec.js'
|
'loopback/common/**/*[sS]pec.js'
|
||||||
],
|
],
|
||||||
helpers: [
|
helpers: [
|
||||||
|
|
Loading…
Reference in New Issue