itemDiary, filter, grid and new directive repeat-last #346
This commit is contained in:
parent
2ab6eb5e83
commit
86a8ae0322
|
@ -1,8 +1,12 @@
|
||||||
Active: Activo
|
Active: Activo
|
||||||
|
Add contact: Añadir contacto
|
||||||
|
Amount: Importe
|
||||||
Client: Cliente
|
Client: Cliente
|
||||||
Clients: Clientes
|
Clients: Clientes
|
||||||
Comercial Name: Comercial
|
Comercial Name: Comercial
|
||||||
|
Contacts: Contactos
|
||||||
Basic data: Datos básicos
|
Basic data: Datos básicos
|
||||||
|
Back: Volver
|
||||||
Fiscal data: Datos Fiscales
|
Fiscal data: Datos Fiscales
|
||||||
Addresses: Consignatarios
|
Addresses: Consignatarios
|
||||||
Web access: Acceso web
|
Web access: Acceso web
|
||||||
|
@ -21,6 +25,4 @@ Credit : Crédito
|
||||||
Credit contracts: Contratos de crédito
|
Credit contracts: Contratos de crédito
|
||||||
Verified data: Datos comprobados
|
Verified data: Datos comprobados
|
||||||
Mandate: Mandato
|
Mandate: Mandato
|
||||||
Amount: Importe
|
Remove contact: Eliminar
|
||||||
Back: Volver
|
|
||||||
Contacts: Contactos
|
|
|
@ -8,3 +8,4 @@ import './on-error-src';
|
||||||
import './zoom-image';
|
import './zoom-image';
|
||||||
import './visible-by';
|
import './visible-by';
|
||||||
import './bind';
|
import './bind';
|
||||||
|
import './repeat-last';
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import ngModule from '../module';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls a passed function if is the last element from an ng-repeat.
|
||||||
|
*
|
||||||
|
* @attribute {String} onLast - Callback function
|
||||||
|
* @return {Object} The directive
|
||||||
|
*/
|
||||||
|
directive.$inject = ['$parse'];
|
||||||
|
export function directive($parse) {
|
||||||
|
return {
|
||||||
|
restrict: 'A',
|
||||||
|
link: function($scope, $element, $attrs) {
|
||||||
|
if ($scope.$last && $attrs.onLast) {
|
||||||
|
let fn = $parse($attrs.onLast);
|
||||||
|
fn($scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
ngModule.directive('vnRepeatLast', directive);
|
|
@ -110,7 +110,7 @@
|
||||||
"item": "$ctrl.item"
|
"item": "$ctrl.item"
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
"url" : "/diary",
|
"url" : "/diary?q",
|
||||||
"state": "item.card.diary",
|
"state": "item.card.diary",
|
||||||
"component": "vn-item-diary",
|
"component": "vn-item-diary",
|
||||||
"params": {
|
"params": {
|
||||||
|
|
|
@ -25,8 +25,8 @@ describe('Item', () => {
|
||||||
|
|
||||||
describe('_getItem()', () => {
|
describe('_getItem()', () => {
|
||||||
it('should request to get the item', () => {
|
it('should request to get the item', () => {
|
||||||
$httpBackend.whenGET('/item/api/Items/123?filter={"include":[{"relation":"itemType","scope":{"fields":["name","workerFk"],"include":{"relation":"worker","fields":["firstName","name"]}}},{"relation":"origin"},{"relation":"ink"},{"relation":"producer"},{"relation":"intrastat"},{"relation":"expence"}]}').respond({data: 'item'});
|
$httpBackend.whenGET('/item/api/Items/123?filter={"include":[{"relation":"itemType","scope":{"fields":["name","workerFk","warehouseFk"],"include":{"relation":"worker","fields":["firstName","name"]}}},{"relation":"origin"},{"relation":"ink"},{"relation":"producer"},{"relation":"intrastat"},{"relation":"expence"}]}').respond({data: 'item'});
|
||||||
$httpBackend.expectGET('/item/api/Items/123?filter={"include":[{"relation":"itemType","scope":{"fields":["name","workerFk"],"include":{"relation":"worker","fields":["firstName","name"]}}},{"relation":"origin"},{"relation":"ink"},{"relation":"producer"},{"relation":"intrastat"},{"relation":"expence"}]}');
|
$httpBackend.expectGET('/item/api/Items/123?filter={"include":[{"relation":"itemType","scope":{"fields":["name","workerFk","warehouseFk"],"include":{"relation":"worker","fields":["firstName","name"]}}},{"relation":"origin"},{"relation":"ink"},{"relation":"producer"},{"relation":"intrastat"},{"relation":"expence"}]}');
|
||||||
controller._getItem();
|
controller._getItem();
|
||||||
$httpBackend.flush();
|
$httpBackend.flush();
|
||||||
});
|
});
|
||||||
|
|
|
@ -35,7 +35,7 @@ class Controller {
|
||||||
include: [
|
include: [
|
||||||
{relation: "itemType",
|
{relation: "itemType",
|
||||||
scope: {
|
scope: {
|
||||||
fields: ['name', 'workerFk'],
|
fields: ['name', 'workerFk', 'warehouseFk'],
|
||||||
include: {
|
include: {
|
||||||
relation: 'worker',
|
relation: 'worker',
|
||||||
fields: ['firstName', 'name']
|
fields: ['firstName', 'name']
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
<vn-crud-model
|
||||||
|
vn-id="model"
|
||||||
|
url="item/api/Items/getDiary"
|
||||||
|
filter="::$ctrl.filter"
|
||||||
|
data="sales"
|
||||||
|
auto-load="false">
|
||||||
|
</vn-crud-model>
|
||||||
|
|
||||||
<vn-vertical>
|
<vn-vertical>
|
||||||
<vn-card pad-large>
|
<vn-card pad-large>
|
||||||
<vn-vertical>
|
<vn-vertical>
|
||||||
|
@ -8,42 +16,42 @@
|
||||||
url="/item/api/Warehouses"
|
url="/item/api/Warehouses"
|
||||||
show-field="name"
|
show-field="name"
|
||||||
value-field="id"
|
value-field="id"
|
||||||
initial-data="$ctrl.warehouseFk"
|
initial-data="$ctrl.filter.where.warehouseFk"
|
||||||
field="$ctrl.warehouseFk"
|
field="$ctrl.filter.where.warehouseFk"
|
||||||
label="Select warehouse">
|
label="Select warehouse" on-change="$ctrl.onChange(value)">
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
</vn-horizontal>
|
</vn-horizontal>
|
||||||
<table class="vn-grid">
|
<vn-table model="model">
|
||||||
<thead>
|
<vn-thead>
|
||||||
<tr>
|
<vn-tr>
|
||||||
<th number translate>Date</th>
|
<vn-th>Date</vn-th>
|
||||||
<th number translate>State</th>
|
<vn-th number>State</vn-th>
|
||||||
<th number translate>Origin</th>
|
<vn-th number>Origin</vn-th>
|
||||||
<th number translate>Reference</th>
|
<vn-th number>Reference</vn-th>
|
||||||
<th style="text-align: center" translate>Name</th>
|
<vn-th field="name">Worker</vn-th>
|
||||||
<th number translate>In</th>
|
<vn-th number>In</vn-th>
|
||||||
<th number translate>Out</th>
|
<vn-th number>Out</vn-th>
|
||||||
<th number translate>Balance</th>
|
<vn-th number>Balance</vn-th>
|
||||||
</tr>
|
</vn-tr>
|
||||||
</thead>
|
</vn-thead>
|
||||||
<tbody>
|
<vn-tbody>
|
||||||
<tr ng-repeat="diary in $ctrl.diary">
|
<vn-tr ng-class="{'warning': $ctrl.isToday(sale.date)}"
|
||||||
<td number>{{diary.date | date:'dd/MM/yyyy HH:mm' }}</td>
|
ng-repeat="sale in sales" vn-repeat-last on-last="$ctrl.scrollToActive()">
|
||||||
<td number>{{diary.alertLevel | dashIfEmpty}}</td>
|
<vn-td>{{::sale.date | date:'dd/MM/yyyy HH:mm' }}</vn-td>
|
||||||
<td number>{{diary.origin | dashIfEmpty}}</td>
|
<vn-td number>{{::sale.alertLevel | dashIfEmpty}}</vn-td>
|
||||||
<td number>{{diary.reference | dashIfEmpty}}</td>
|
<vn-td number>{{::sale.origin | dashIfEmpty}}</vn-td>
|
||||||
<td style="text-align: center">{{diary.name | dashIfEmpty}}</td>
|
<vn-td number>{{::sale.reference | dashIfEmpty}}</vn-td>
|
||||||
<td number>{{diary.in | dashIfEmpty}}</td>
|
<vn-td>{{sale.name | dashIfEmpty}}</vn-td>
|
||||||
<td number>{{diary.out | dashIfEmpty}}</td>
|
<vn-td number>{{::sale.in | dashIfEmpty}}</vn-td>
|
||||||
<td number>{{diary.balance | dashIfEmpty}}</td>
|
<vn-td number>{{::sale.out | dashIfEmpty}}</vn-td>
|
||||||
</tr>
|
<vn-td number><span class="balance">{{::sale.balance | dashIfEmpty}}</span></vn-td>
|
||||||
<tr ng-if="$ctrl.diary.length === 0" class="list list-element">
|
</vn-tr>
|
||||||
<td colspan="8" style="text-align: center" translate>No results</td>
|
</vn-tbody>
|
||||||
</tr>
|
<vn-empty-rows ng-if="model.data.length === 0" translate>
|
||||||
</tbody>
|
No results
|
||||||
</table>
|
</vn-empty-rows>
|
||||||
|
</vn-table>
|
||||||
</vn-vertical>
|
</vn-vertical>
|
||||||
</vn-card>
|
</vn-card>
|
||||||
<vn-paging margin-large-top vn-one index="$ctrl.diary" total="$ctrl.diary.count"></vn-paging>
|
|
||||||
<!-- <vn-auto-paging margin-large-top vn-one index="index" total="index.model.count" items="$ctrl.instances"></vn-auto-paging> -->
|
|
||||||
</vn-vertical>
|
</vn-vertical>
|
||||||
|
|
|
@ -2,32 +2,96 @@ import ngModule from '../module';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
|
|
||||||
class Controller {
|
class Controller {
|
||||||
constructor($scope, $http) {
|
constructor($scope, $http, $state, $window) {
|
||||||
this.$ = $scope;
|
this.$scope = $scope;
|
||||||
this.$http = $http;
|
this.$http = $http;
|
||||||
this.diary = [];
|
this.$state = $state;
|
||||||
|
this.$window = $window;
|
||||||
}
|
}
|
||||||
|
|
||||||
set warehouseFk(value) {
|
$postLink() {
|
||||||
this._getItemDiary(value);
|
if (this.item)
|
||||||
this._warehouseFk = value;
|
this.filterBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
get warehouseFk() {
|
set item(value) {
|
||||||
return this._warehouseFk;
|
this._item = value;
|
||||||
|
|
||||||
|
if (value && this.$scope.model)
|
||||||
|
this.filterBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
_getItemDiary(warehouse) {
|
get item() {
|
||||||
if (warehouse == null)
|
return this._item;
|
||||||
return;
|
}
|
||||||
let params = {itemFk: this.item.id, warehouseFk: warehouse};
|
|
||||||
this.$http.get(`/item/api/Items/getDiary?params=${JSON.stringify(params)}`).then(res => {
|
get alertLevelIndex() {
|
||||||
this.diary = res.data;
|
let lines = this.$scope.model.data;
|
||||||
});
|
for (let i = 0; i < lines.length; i++) {
|
||||||
|
let isFutureDate = new Date(lines[i].date) > new Date();
|
||||||
|
let isGenreOut = lines[i].alertLevel != 0;
|
||||||
|
|
||||||
|
if (!isFutureDate && !isGenreOut)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onChange(value) {
|
||||||
|
if (!value) return;
|
||||||
|
|
||||||
|
this.filter.where.warehouseFk = value;
|
||||||
|
this.$scope.model.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds a filter with default values
|
||||||
|
* and aplies query params.
|
||||||
|
*/
|
||||||
|
filterBuilder() {
|
||||||
|
this.filter = {
|
||||||
|
where: {
|
||||||
|
itemFk: this.item.id,
|
||||||
|
warehouseFk: this.item.itemType.warehouseFk
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
let where = this.filter.where;
|
||||||
|
|
||||||
|
if (this.$state.params.q) {
|
||||||
|
let queryFilter = JSON.parse(this.$state.params.q);
|
||||||
|
where.warehouseFk = queryFilter.warehouseFk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollToActive() {
|
||||||
|
let body = this.$window.document.body;
|
||||||
|
let lineIndex = this.alertLevelIndex;
|
||||||
|
let lines = body.querySelector('vn-tbody').children;
|
||||||
|
|
||||||
|
if (!lineIndex || !lines.length) return;
|
||||||
|
|
||||||
|
lines[lineIndex].scrollIntoView();
|
||||||
|
lines[lineIndex - 1].querySelector('.balance').classList.add('counter');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares a date with the current one
|
||||||
|
* @param {Object} date - Date to compare
|
||||||
|
* @return {Boolean} - Returns true if the two dates equals
|
||||||
|
*/
|
||||||
|
isToday(date) {
|
||||||
|
let today = new Date();
|
||||||
|
today.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
|
let comparedDate = new Date(date);
|
||||||
|
comparedDate.setHours(0, 0, 0, 0);
|
||||||
|
|
||||||
|
if (!(today - comparedDate))
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Controller.$inject = ['$scope', '$http'];
|
Controller.$inject = ['$scope', '$http', '$state', '$window'];
|
||||||
|
|
||||||
ngModule.component('vnItemDiary', {
|
ngModule.component('vnItemDiary', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
|
|
|
@ -17,25 +17,47 @@ describe('Item', () => {
|
||||||
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
$httpBackend.when('GET', /\/locale\/\w+\/[a-z]{2}\.json/).respond({});
|
||||||
$scope = $rootScope.$new();
|
$scope = $rootScope.$new();
|
||||||
controller = $componentController('vnItemDiary', {$scope: $scope});
|
controller = $componentController('vnItemDiary', {$scope: $scope});
|
||||||
controller.item = {id: 3};
|
controller.$scope.model = {};
|
||||||
}));
|
}));
|
||||||
|
|
||||||
describe('set warehouseFk()', () => {
|
describe('isToday()', () => {
|
||||||
it(`should call _getItemDiary() with 2 and set warehouseFk`, () => {
|
it(`should call isToday() an return true if an specified date is the current date`, () => {
|
||||||
spyOn(controller, '_getItemDiary');
|
let date = new Date();
|
||||||
controller.warehouseFk = 2;
|
|
||||||
|
|
||||||
expect(controller._getItemDiary).toHaveBeenCalledWith(2);
|
let result = controller.isToday(date);
|
||||||
expect(controller.warehouseFk).toEqual(2);
|
|
||||||
|
expect(result).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it(`should call isToday() an return false if an specified date is the current date`, () => {
|
||||||
|
let date = '2018-07-03';
|
||||||
|
|
||||||
|
let result = controller.isToday(date);
|
||||||
|
|
||||||
|
expect(result).toBeFalsy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('_getItemDiary()', () => {
|
describe('alertLevelIndex()', () => {
|
||||||
it(`should make a request to get the diary hwen is called with a number`, () => {
|
it(`should call alertLevelIndex() and return an index from line with alertLevel 0 and current date`, () => {
|
||||||
$httpBackend.whenGET('/item/api/Items/getDiary?params={"itemFk":3,"warehouseFk":2}').respond({data: 'item'});
|
controller.$scope.model = {data: [
|
||||||
$httpBackend.expectGET('/item/api/Items/getDiary?params={"itemFk":3,"warehouseFk":2}');
|
{name: 'My item 1', alertLevel: 3, date: '2018-05-02'},
|
||||||
controller._getItemDiary(2);
|
{name: 'My item 2', alertLevel: 1, date: '2018-05-03'},
|
||||||
$httpBackend.flush();
|
{name: 'My item 3', alertLevel: 0, date: new Date()}]
|
||||||
|
};
|
||||||
|
let result = controller.alertLevelIndex;
|
||||||
|
|
||||||
|
expect(result).toEqual(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('set item()', () => {
|
||||||
|
it(`should call filterBuilder()`, () => {
|
||||||
|
spyOn(controller, 'filterBuilder');
|
||||||
|
controller.item = {id: 1};
|
||||||
|
|
||||||
|
expect(controller.filterBuilder).toHaveBeenCalledWith();
|
||||||
|
expect(controller.item).toEqual({id: 1});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -242,4 +242,15 @@ fieldset[disabled] .mdl-textfield .mdl-textfield__label,
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.counter {
|
||||||
|
background-color: $main-header;
|
||||||
|
color: $color-white;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 5px
|
||||||
|
}
|
||||||
|
|
||||||
|
.counter.small {
|
||||||
|
font-size: 0.7em
|
||||||
}
|
}
|
|
@ -3,12 +3,14 @@ module.exports = Self => {
|
||||||
description: 'Returns the ',
|
description: 'Returns the ',
|
||||||
accessType: 'READ',
|
accessType: 'READ',
|
||||||
accepts: [{
|
accepts: [{
|
||||||
arg: 'params',
|
arg: 'filter',
|
||||||
type: 'object',
|
type: 'Object',
|
||||||
description: 'itemFk, warehouseFk'
|
required: true,
|
||||||
|
description: 'Filter defining where and paginated data',
|
||||||
|
http: {source: 'query'}
|
||||||
}],
|
}],
|
||||||
returns: {
|
returns: {
|
||||||
arg: 'diary',
|
type: ['Object'],
|
||||||
root: true
|
root: true
|
||||||
},
|
},
|
||||||
http: {
|
http: {
|
||||||
|
@ -17,8 +19,9 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Self.getDiary = async params => {
|
Self.getDiary = async filter => {
|
||||||
let [diary] = await Self.rawSql(`CALL vn.itemDiary(?, ?)`, [params.itemFk, params.warehouseFk]);
|
let where = filter.where;
|
||||||
|
let [diary] = await Self.rawSql(`CALL vn.itemDiary(?, ?)`, [where.itemFk, where.warehouseFk]);
|
||||||
return diary;
|
return diary;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,10 +24,15 @@
|
||||||
},
|
},
|
||||||
"relations": {
|
"relations": {
|
||||||
"worker": {
|
"worker": {
|
||||||
"type": "belongsTo",
|
"type": "belongsTo",
|
||||||
"model": "Worker",
|
"model": "Worker",
|
||||||
"foreignKey": "workerFk"
|
"foreignKey": "workerFk"
|
||||||
}
|
},
|
||||||
|
"warehouse": {
|
||||||
|
"type": "belongsTo",
|
||||||
|
"model": "Warehouse",
|
||||||
|
"foreignKey": "warehouseFk"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"acls": [
|
"acls": [
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue